From f7b5bd3e21138bc547ea3d79c41b9f6342900881 Mon Sep 17 00:00:00 2001 From: yinbin8 <862511068@qq.com> Date: Fri, 1 Aug 2025 14:53:14 +0800 Subject: [PATCH] update version to 1.0.3 --- ...remove-unused-dpdk-dynamic-libraries.patch | 93 - ...tat_pkts-gazelle_stat_low_power_info.patch | 49 - ...-when-bind-ip-is-same-as-ip-in-lstac.patch | 27 - 0004-refactoring-preload-module.patch | 158 - ...us-commit-refactoring-preload-module.patch | 99 - 0006-add-lstack_preload.c-to-makefile.patch | 49 - 0007-cosmetic-changes.patch | 67 - ...dd-loongarch64-and-sw64-arch-support.patch | 120 - ...d-the-dpdk-primary-default-parameter.patch | 39 - 0010-suport-clang-build.patch | 26 - ...dev-fix-pbuf-chain-tot_len-incorrect.patch | 25 - ...el-event-thread-report-kernel-events.patch | 105 - 0013-fix-bond-port-reta_size-init.patch | 24 - ...-sem-between-lstack-thread-and-main-.patch | 383 -- ...ernal-api-start-with-do_lwip_-prefix.patch | 941 --- 0016-cfg-nic-rx-tx-queue-size-configure.patch | 140 - ...h-add-del_sock_event-and-add-del_soc.patch | 203 - ...reload-support-thread-hijacking-mode.patch | 646 -- ...add-run-to-completion-mode-configure.patch | 91 - ...oop-in-lstack-thread-is-defined-as-s.patch | 136 - 0021-delete_rule-bug.patch | 25 - ...s-gazelle_setup-adapt-non-ltran-mode.patch | 198 - ...dd-run-to-completion-wakeup-mode-api.patch | 993 --- ...fix-arping-gazelle-return-value-is-1.patch | 25 - ...-in-app-thread-when-app-call-socket-.patch | 169 - ...l-adapt-epoll-interface-for-rtc-mode.patch | 365 -- 0027-clean-useless-code.patch | 27 - ...nicast-packets-cannot-be-transmitted.patch | 55 - ...ore-to-ensure-all-stack-threads-setu.patch | 102 - 0030-ethdev-register-offload-to-netif.patch | 29 - 0031-epoll-fix-epollet-mode-error.patch | 44 - 0032-bond6.patch | 210 - 0033-cfg-fix-bond_mode-null.patch | 28 - 0034-dfx-add-four-snmp-udp-datas.patch | 28 - ...c-queue-size-only-support-power-of-2.patch | 38 - ...le-coredump-when-arp-packet-broadcas.patch | 29 - ...ue-and-skip-rte_pdump_init-for-secon.patch | 53 - ...at-rte_pktmbuf_poll_creat-in-same-nu.patch | 159 - 0040-when-timeout-occurs-process-exits.patch | 83 - 0041-wrap-support-select.patch | 260 - 0042-add-vlan-support.patch | 152 - 0043-slave-mac-addr.patch | 194 - ...relog-info-transfer-to-terminal-at-t.patch | 26 - ...mbuf-data-start-pointer-pbuf-payload.patch | 64 - ...-mempool-lookup-failed-in-ltran-mode.patch | 24 - 0048-add-tx-package-timeout.patch | 29 - 0049-modif-mem.patch | 48 - 0050-enable-ipv6.patch | 734 --- ...-wrap-dont-hijack-select-temporarily.patch | 29 - 0052-ipv6.patch | 25 - 0053-add-gazelle-log.patch | 258 - ...og-info-while-there-are-repeated-ite.patch | 43 - 0055-add-gazelle-log.patch | 100 - ...-wrong-port-after-addr-bind-two-port.patch | 38 - 0057-cfg-rm-ipv6_enable.patch | 88 - 0058-ltran-support-vlan.patch | 102 - 0059-update-src-ltran-ltran_param.c.patch | 33 - 0060-dfx-support-bond-get-dpdk-xstats.patch | 262 - 0061-add-tcp-faste-timer-cnt.patch | 73 - ...ump-caused-by-gazelleclt-in-rtc-mode.patch | 124 - ...xception-and-kernel-event-statistics.patch | 109 - 0064-add-vlan_id-in-netif.patch | 88 - 0065-support-vlan-offload.patch | 89 - ...fix-gazellectl-lstack-show-1-r-error.patch | 487 -- ...ause-sock-closed-before-send-data-fu.patch | 129 - 0068-fix-compilation-error.patch | 39 - ...ause-of-addr-null-in-lwip_fill_sendr.patch | 25 - 0070-add-struct-gz_addr_t.patch | 97 - 0071-wrap-support-shutdown.patch | 305 - ...lem-of-1w-connection-not-being-able-.patch | 395 -- 0073-dfx-gazellectl-c-support-ipv6.patch | 181 - ...s-not-printed-in-the-proactive-exit-.patch | 28 - ...fix-gazellectl-lstack-show-ip-failed.patch | 69 - 0076-gazellectl-add-connect-para.patch | 69 - 0077-log-optimize-lstack-log.patch | 51 - ...upport-show-nic-offload-and-features.patch | 209 - ...here-no-packet-is-sent-or-received-w.patch | 33 - 0080-fix-example-print-error.patch | 46 - 0081-dfx-fix-kernel_events-stat.patch | 24 - 0082-add-keep-alive-info.patch | 111 - 0083-fix-close-can-t-exit.patch | 137 - 0084-mod-unix-time-stamp-to-local-time.patch | 72 - 0085-optimize-gazelle-exit-process.patch | 671 --- 0086-fix-EPOLLIN-event-error.patch | 52 - 0087-mod-time-err.patch | 25 - ...stack-show-ip-r-with-ltran-error-log.patch | 39 - 0089-fix-udp-multicast-bind-error.patch | 29 - 0090-support-netperf.patch | 179 - 0091-fix-alloc-not-free.patch | 49 - ...igaction-fix-deprecated-signal-flags.patch | 59 - 0093-fix-gazellectl-c-msg-error.patch | 38 - ...eck-func-strdup-return-value-is-NULL.patch | 107 - ...parate_str_to_array-overflow-problem.patch | 26 - 0096-use-default-nonblock-mode.patch | 76 - ...-rte_ring_create-free-time-consuming.patch | 128 - 0098-optimize-shutdown-exit-process.patch | 25 - ...parate_str_to_array-overflow-problem.patch | 32 - ...parate_str_to_array-overflow-problem.patch | 28 - ...parate_str_to_array-overflow-problem.patch | 26 - ...parate_str_to_array-overflow-problem.patch | 26 - ...tack_setup_thread-array-doesn-t-init.patch | 25 - 0104-fix-stack_setup_thread-array-range.patch | 21 - ...parate_str_to_array-overflow-problem.patch | 80 - ...ix-dpdk_alloc_pktmbuf-time-consuming.patch | 32 - ...n-optimize-config-file-error-message.patch | 46 - 0108-replace-with-gz_addr_t.patch | 224 - 0109-match_host_addr-func-support-ipv6.patch | 103 - ...add-example-keep-alive-interval-para.patch | 27 - 0111-update-src-common-dpdk_common.c.patch | 68 - 0112-listen_shadow-support-ipv6.patch | 51 - 0113-lstack_dpdk-limit-mbuf-max-num.patch | 78 - ...zellectl-add-tcp_input-empty-ack-cnt.patch | 66 - 0115-add-socket-accept-fail-cnt.patch | 54 - 0116-diff-lstack-and-ltran-dfx-sock.patch | 137 - ...-can-be-assigned-a-multicast-address.patch | 29 - ...udp-do-not-merge-data-into-last-pbuf.patch | 45 - 0119-adpat-dpdk-23.11.patch | 969 --- 0120-modify-conf-vlan-default-vlaue.patch | 24 - ...riables-in-pbuf-and-reduce-mbuf-size.patch | 123 - ...it-process-for-FIN-and-unsupport-SO_.patch | 38 - 0123-remove-expand_send_ring.patch | 371 -- 0124-set-ltran.patch | 25 - 0125-add-bond-doc.patch | 25 - 0126-cfg-host_addr-is-not-mandatory.patch | 61 - 0127-add-bond1-support.patch | 139 - 0128-fix-t_params-double-free.patch | 77 - ...fix-receive-fin-packet-process-error.patch | 155 - ...upport-netperf-UDP_STREAM-and-UDP_RR.patch | 129 - 0131-adapt-lwip-2.2.0.patch | 131 - ...bservable-method-of-data-aggregation.patch | 62 - ...try-to-ensure-arp-packet-can-be-sent.patch | 191 - ...gazellectl-support-send-latency-show.patch | 345 -- ...on-does-not-depend-on-protocol-stack.patch | 1336 ----- ...rrno-is-EAGAIN-when-recvring-no-data.patch | 30 - ...ules-related-functions-into-separate.patch | 1707 ------ ...-when-stack-setup-failed-in-rtc-mode.patch | 66 - 0139-diff-udp-and-tcp-read-from-stack.patch | 277 - ...elle-add-packet-delay-and-packet-dro.patch | 798 --- 0141-recv-support-MSG_DONTWAIT.patch | 36 - ...nction-no-longer-checks-the-results-.patch | 29 - ...INJECT-add-fault-inject-unset-method.patch | 254 - 0144-support-udp-pkglen-mtu.patch | 85 - 0145-add-limit-with-level-for-sockopt.patch | 86 - ...udp-add-restriction-message-too-long.patch | 42 - ...readability-when-connect-ltran-lstac.patch | 269 - ...-fix-rpc_pool-create-failed-coredump.patch | 103 - ...interface-flow_type_rss_offloads-mat.patch | 24 - ...CT-add-duplicate-and-reorder-methods.patch | 315 - 0151-select-timeout-arguments-check.patch | 51 - 0152-recvfrom-support-timeout.patch | 213 - 0153-fix-netperf-setsockopt-fail.patch | 42 - ...TENCY_WRITE-increase-in-recv-process.patch | 134 - 0155-dpdk-add-vlan-filter.patch | 95 - 0156-Correcting-spelling-errors.patch | 25 - 0157-perftool-add-lhist-statstic-tool.patch | 41 - 0158-add-udp-poll.patch | 47 - ...stcase-for-gazellectl-connect-failed.patch | 39 - ...ration-check-with-host_addr-and-serv.patch | 29 - ...cy-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch | 380 -- ...filter-can-be-added-when-vlan_mode-1.patch | 33 - 0163-Add-support-for-arch-ppc64le.patch | 36 - 0164-dfx-support-get-nic-bond-status.patch | 120 - ...ve-dpdk_skip_nic_init-for-dpdk-23.11.patch | 54 - ...azellectl-add-lwip-stats_proto-print.patch | 317 - 0167-fix-port-not-support-vlan-filter.patch | 26 - ...s-not-return-pkg-when-ring-buffer-is.patch | 27 - 0169-add-tuple_fileter-error-info.patch | 24 - 0170-adapt-dpdk-23.11-remove-kni.patch | 80 - 0171-fix-ioctl-set-failed.patch | 49 - 0172-ltran-memset-quintuple.patch | 25 - ...azellectl-add-lwip-stats_proto-print.patch | 69 - 0174-CFG-set-multicast-IP-assert.patch | 28 - ...-be-in-bond_slave_mac-for-BONDING_MO.patch | 47 - 0176-CFG-fix-multicast-IP-assert-error.patch | 25 - ...eak-in-dpdk-23.11-due-to-kni-removed.patch | 82 - 0178-add-riscv64-support.patch | 48 - 0179-dfx-fix-gazellectl-x-for-bond.patch | 59 - ...le_stat_lstack_proto-from-u16-to-u64.patch | 87 - 0181-memary-error-fix-some-memary-error.patch | 45 - ...-initialization-code-in-dpdk_ethdev_.patch | 545 -- ..._msg_max-recv_ring_size-configurable.patch | 169 - ...mp-while-event-count-exceed-maxevent.patch | 46 - 0185-fix-fin-pack-free-coredump.patch | 25 - 0186-fix-MySQL-shutdown-cmd.patch | 95 - ...move-map-perfect-flag-in-lstack.conf.patch | 31 - 0188-redis-perf-add-tx-driver-cache.patch | 255 - ...timized-latency-distribution-dotting.patch | 250 - 0190-rtc-adapt-rtc_close.patch | 51 - 0191-virtio-flow_bifurcation-switch.patch | 59 - 0192-remove-legacy-mem.patch | 30 - ...-cfg-bond_slave_mac-support-pci-addr.patch | 246 - 0194-refactor-tx-cache-module.patch | 340 -- 0195-virtio-create-and-init-virtio_port.patch | 392 -- 0196-refactor-udp-send.patch | 341 -- 0197-solve-compile-err-in-20.03.patch | 39 - 0198-fix-function-call-error.patch | 66 - 0199-perftool-add-latency-tool.patch | 57 - 0200-cfg-del-unnecessary-logs.patch | 88 - 0201-fix-dpdk_bond_primary_set-bug.patch | 72 - 0202-fix-build-failed-in-2003sp4.patch | 25 - 0203-virtio-cfg-ipv4-and-ipv6-addr.patch | 190 - 0204-parse-packages-type-in-rx_poll.patch | 168 - 0205-virtio-distribute-pkg-by-dst_port.patch | 198 - ...ump-when-get-empty-from-udp-sendring.patch | 40 - 0207-fix-poll-init-not-clear-old-fd.patch | 35 - 0208-virtio-mode-actual_queue_num.patch | 29 - ...te-g_rule_port-by-reg_ring_type-enum.patch | 109 - 0210-virtio-dfx-data-of-virtio.patch | 157 - ...ifurcation-switch-in-lstack_cfg-file.patch | 24 - 0212-example-sync-example-update.patch | 3751 ------------ ...ncode-improving-makefile-readability.patch | 1154 ---- 0214-add-.gitignore.patch | 50 - ...eancode-rename-gazelle-files-in-lwip.patch | 489 -- 0216-cleancode-refactor-lwipsock.h.patch | 280 - ...e-refactor-posix-type-and-get_socket.patch | 1047 ---- 0218-fix-some-error-of-NULL-pointer.patch | 198 - 0219-cleancode-refactor-posix_api.patch | 775 --- 0220-cleancode-refactor-lwipgz_list.h.patch | 445 -- 0221-fix-EPOLLIN-event-dropd.patch | 32 - 0222-cleancode-refactor-lwipgz_hlist.h.patch | 160 - 0223-add-sem-post-when-update-event.patch | 24 - ...code-refactor-sys_now-and-lwip_ioctl.patch | 673 --- ...-timeout-disable-and-build-failed-in.patch | 41 - 0226-support-kernel-connect.patch | 48 - 0227-Check-the-return-of-lwip_init.patch | 29 - ...tio_user-modify-mbuf-index-for-bond4.patch | 60 - ...dump-when-hugetlbs-pagesize-is-1024M.patch | 48 - 0230-dfx-optimize-gazellectl-x-for-bond.patch | 41 - ...tio-fix-dfx-error-with-multiple-cpus.patch | 27 - ...-virtio_user-based-on-bond4-main-net.patch | 42 - ...tio_user-modify-mbuf-index-for-bond4.patch | 34 - ...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 - ...program-establishes-a-network-connec.patch | 31 - ...ode-did-not-bind-kernel-while-open-k.patch | 28 - 0240-WRAP-fix-bind-log-error.patch | 49 - ...o_user_name-when-multi-process-is-on.patch | 154 - ...dump-ctrl-c-during-the-pressure-test.patch | 33 - 0243-virtio_user-check-netif-status.patch | 73 - ...o-solve-compilation-error-in-2003sp3.patch | 24 - ...-CMAKE-fix-ltran-build-error-in-2403.patch | 33 - 0246-fix-mbuf_total-calculation-error.patch | 57 - ...-modify-maximum-tcp_conn_count-to-2w.patch | 25 - ...atch-script-date-wrong-and-update-th.patch | 47 - ...-fix-wild-pointer-detected-by-cooddy.patch | 24 - ...-fix-script-generate-patchname-wrong.patch | 34 - ...fix-when-errno-is-ENOTCONN-ignore-it.patch | 81 - ..._sock-no-need-to-create-ring-in-rtc-.patch | 52 - 0253-example-solve-double-free.patch | 99 - ...port-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch | 25 - 0255-DFX-adapt-log-optimization.patch | 71 - ...-log-when-udp-send_ring-is-exhausted.patch | 24 - ...factor-rtc_api-rtw_api-and-dummy_api.patch | 1035 ---- ...e-some-API-from-stack-to-rpc-and-rtw.patch | 2604 -------- ...c_async_call-remove-rpc_msg_arg.sock.patch | 693 --- ...e-declare-different-cfg_params-types.patch | 347 -- ...n-of-mbuf-to-send_ring-when-mbuf-is-.patch | 78 - 0262-add-pingpong-dfx-support.patch | 67 - 0263-add-interrupt-mode-support.patch | 977 --- ...set-rlimit-unlimit-when-gazelle-init.patch | 57 - ...x-stack-null-when-register-interrupt.patch | 32 - ...send-length-exceeding-send_ring_size.patch | 69 - ..._call-spinlock-block-when-msg-be-rec.patch | 84 - ...le-init-failed-while-setup-by-non-ro.patch | 39 - ...m-temporarily-due-to-kernel-cannot-t.patch | 97 - ...dk_nic_is_xdp-coredump-in-ltran-mode.patch | 27 - 0271-fix-the-coredump-when-gazellectl-l.patch | 36 - ...ll-epoll_ctl-delete-fd-when-fd-close.patch | 54 - ...oll-remove-unnecessary-judgment-code.patch | 34 - ...r-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch | 50 - ...l-when-executing-the-popen-command-f.patch | 25 - 0276-Fix-annotation-errors.patch | 73 - 0277-remove-the-unused-return-variable.patch | 40 - ...MA_ID-optname-for-adapting-opneGauss.patch | 28 - ...STATISTICS-by-posix_api-getsockopt_f.patch | 63 - ...fix-timeout-events-cannot-be-counted.patch | 25 - ...ve-code-about-nobolck-mode-for-mysql.patch | 76 - 0282-LOG-Optimize-some-log-displays.patch | 40 - 0283-xdp-support-bind-no-cpu-mode.patch | 967 --- 0284-support-auto-set-xdp-addr.patch | 391 -- 0285-suport-kernel-accept-for-openGauss.patch | 82 - 0286-openGauss-support-kernel-accept4.patch | 43 - ...ocket-init-wakeup-in-blocking-socket.patch | 125 - ...ntrol-thread-is-overwirtten-due-to-a.patch | 36 - ...tion-of-shutdown-in-callback-of-conn.patch | 29 - ...elling-description-in-the-notes-and-.patch | 154 - ...est-unitest-ltran-ltran_param_test.c.patch | 30 - ...inter-when-no-matching-device-is-fou.patch | 87 - ...how-dpdk-args-after-dpdk_adjust_args.patch | 66 - 0294-fix-build-error-in-2003SP4.patch | 27 - 0295-CFG-fix-xdp-iface-check-error.patch | 166 - 0296-xdp-support-stack-bind-numa.patch | 425 -- 0297-openGauss-support-kernel-connnect.patch | 125 - 0298-DUMP-gazelle-supports-dump-lstack.patch | 260 - ...enGauss-fix-gs_ctl-switchover-failed.patch | 59 - ...nGauss-fix-connection-attempt-failed.patch | 30 - ...pp_bind_numa-check-from-exclude_cpus.patch | 26 - ...-fix-rpc-pool-leak-when-thread-exits.patch | 99 - ...cv-threads-blocked-on-the-same-semap.patch | 148 - 0304-fix-errno-ETIMEFOUT.patch | 25 - ...at-it-s-unsupported-when-stack_num-1.patch | 32 - ...-issue-when-rpc-pools-are-added-to-r.patch | 65 - 0307-openGauss-unsupport_tcp_optname.patch | 24 - 0308-kernerl-bind-add-ipv6-add-check.patch | 48 - ...lwip-connect-if-dst_ip-and-host_ip-a.patch | 132 - ...rror-of-oe2003-because-of-micro-is-n.patch | 26 - ...gaction-function-to-keep-lstack-sign.patch | 310 - ...jack-sigal-table-to-hijack-SIGABRT-S.patch | 35 - ...abnomal-printing-in-the-dump-process.patch | 25 - ...ix-the-memory-leak-when-using-strdup.patch | 25 - ...k_stop-while-stacks-exit-by-rpc-mess.patch | 74 - ...AL-block-SIGSEGV-during-exit-process.patch | 58 - 0317-add-xdp-tx-checksum-tso-offload.patch | 191 - ...gazellectl-can-t-print-connenct-info.patch | 35 - ...ect-fix-benchmark_dws-connect-failed.patch | 25 - ...deathlock-between-protocol-threads-a.patch | 33 - 0321-update-gazelle-max-numa-nodes-8.patch | 38 - ...am-stuck-while-gazelle-exit-in-multi.patch | 134 - 0323-cleancode-add-GAZELLE_SAME_NODE.patch | 958 --- ...-cleancode-remove-gazelle_light_ring.patch | 104 - ...-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch | 292 - 0326-socket-refactor-sock_event.patch | 1613 ----- 0327-socket-adapt-to-sock_event.patch | 2955 --------- 0328-socket-refactor-tcp-and-udp.patch | 4524 -------------- 0329-socket-adapt-to-tcp-and-udp.patch | 5305 ----------------- ...e_max-and-change-default-rpc_msg_max.patch | 157 - 0331-cfg-add-mem_async_mode.patch | 98 - 0332-mempool-add-mem_thread_cache_flush.patch | 617 -- 0333-dfx-support-sk_wait-stat.patch | 526 -- 0334-mempool-fix-copy_mbuf_private.patch | 75 - 0335-socket-fix-connect-blocking.patch | 198 - ...ck_tcp_read-do-not-recv_finish_burst.patch | 32 - 0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch | 167 - 0338-socket-fix-tcp-closed.patch | 95 - ...ait-cannot-be-interrupted-by-signals.patch | 139 - ...pool-modify-mbuf-num-and-rpc_msg-num.patch | 98 - ..._ring-free-not-call-recv_finish_burs.patch | 125 - ...empool-mem_get_rpc-add-reserve-limit.patch | 363 -- ...ead_tryjoin_np-coredump-when-mysqld-.patch | 59 - ...op-using-cache-when-too-many-threads.patch | 158 - ...ait-fix-lwip_tcp_allow_send-coredump.patch | 45 - ...ng_common_free-coredump-when-rte_rin.patch | 52 - 0347-sk_wait-fix-sock_wait_common_free.patch | 62 - ...ket-fix-stack_udp_readmsg-return-len.patch | 60 - ..._wait_foreach_notify-coredump-at-sta.patch | 61 - ...epoll-fix-do_lwip_connected_callback.patch | 212 - ...tack_tcp_write-wrong-copied_total-af.patch | 36 - ...-epoll-wrong-event-notify-and-remove.patch | 349 -- ..._connected_callback-not-delete-poll-.patch | 158 - ...fix-rtw-broadcast-close-and-shutdown.patch | 53 - ...-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch | 26 - ...ack_tcp_send-output-too-many-at-once.patch | 76 - ...fix-sendmbox-full-return-EWOULDBLOCK.patch | 336 -- ..._wait-igonre-mem_thread-flush-signal.patch | 112 - 0359-fix-20.03-LTS-build-failed.patch | 25 - ...io-fix-tcp_write-not-remove-EPOLLOUT.patch | 108 - ...rpc_send-coredump-after-RPC_MSG_EXIT.patch | 335 -- gazelle-1.0.2.tar.gz | Bin 1060611 -> 0 bytes gazelle-1.0.3.tar.gz | Bin 0 -> 1814657 bytes gazelle.spec | 368 +- 362 files changed, 6 insertions(+), 72537 deletions(-) delete mode 100644 0001-remove-unused-dpdk-dynamic-libraries.patch delete mode 100644 0002-gazelle_stat_pkts-gazelle_stat_low_power_info.patch delete mode 100644 0003-set-localhost-ip-when-bind-ip-is-same-as-ip-in-lstac.patch delete mode 100644 0004-refactoring-preload-module.patch delete mode 100644 0005-fix-previous-commit-refactoring-preload-module.patch delete mode 100644 0006-add-lstack_preload.c-to-makefile.patch delete mode 100644 0007-cosmetic-changes.patch delete mode 100644 0008-add-loongarch64-and-sw64-arch-support.patch delete mode 100644 0009-CFG-fixed-the-dpdk-primary-default-parameter.patch delete mode 100644 0010-suport-clang-build.patch delete mode 100644 0011-ethdev-fix-pbuf-chain-tot_len-incorrect.patch delete mode 100644 0012-kernelevent-kernel-event-thread-report-kernel-events.patch delete mode 100644 0013-fix-bond-port-reta_size-init.patch delete mode 100644 0014-init-remove-sync-sem-between-lstack-thread-and-main-.patch delete mode 100644 0015-lstack_lwip-external-api-start-with-do_lwip_-prefix.patch delete mode 100644 0016-cfg-nic-rx-tx-queue-size-configure.patch delete mode 100644 0017-epoll-distinguish-add-del_sock_event-and-add-del_soc.patch delete mode 100644 0018-preload-support-thread-hijacking-mode.patch delete mode 100644 0019-cfg-add-run-to-completion-mode-configure.patch delete mode 100644 0020-statck-the-for-loop-in-lstack-thread-is-defined-as-s.patch delete mode 100644 0021-delete_rule-bug.patch delete mode 100644 0022-tools-gazelle_setup-adapt-non-ltran-mode.patch delete mode 100644 0023-wrap-add-run-to-completion-wakeup-mode-api.patch delete mode 100644 0024-fix-arping-gazelle-return-value-is-1.patch delete mode 100644 0025-init-stack-setup-in-app-thread-when-app-call-socket-.patch delete mode 100644 0026-epoll-adapt-epoll-interface-for-rtc-mode.patch delete mode 100644 0027-clean-useless-code.patch delete mode 100644 0028-ethdev-fix-arp-unicast-packets-cannot-be-transmitted.patch delete mode 100644 0029-stack-add-semaphore-to-ensure-all-stack-threads-setu.patch delete mode 100644 0030-ethdev-register-offload-to-netif.patch delete mode 100644 0031-epoll-fix-epollet-mode-error.patch delete mode 100644 0032-bond6.patch delete mode 100644 0033-cfg-fix-bond_mode-null.patch delete mode 100644 0034-dfx-add-four-snmp-udp-datas.patch delete mode 100644 0035-cfg-nic-queue-size-only-support-power-of-2.patch delete mode 100644 0036-stack-fix-possible-coredump-when-arp-packet-broadcas.patch delete mode 100644 0037-Fix-coredump-issue-and-skip-rte_pdump_init-for-secon.patch delete mode 100644 0038-solve-problem-that-rte_pktmbuf_poll_creat-in-same-nu.patch delete mode 100644 0040-when-timeout-occurs-process-exits.patch delete mode 100644 0041-wrap-support-select.patch delete mode 100644 0042-add-vlan-support.patch delete mode 100644 0043-slave-mac-addr.patch delete mode 100644 0044-PRE_LOG-modify-prelog-info-transfer-to-terminal-at-t.patch delete mode 100644 0045-ethdev-mbuf-data-start-pointer-pbuf-payload.patch delete mode 100644 0047-cfg-fix-lstack-mempool-lookup-failed-in-ltran-mode.patch delete mode 100644 0048-add-tx-package-timeout.patch delete mode 100644 0049-modif-mem.patch delete mode 100644 0050-enable-ipv6.patch delete mode 100644 0051-wrap-dont-hijack-select-temporarily.patch delete mode 100644 0052-ipv6.patch delete mode 100644 0053-add-gazelle-log.patch delete mode 100644 0054-PRE_LOG-modify-log-info-while-there-are-repeated-ite.patch delete mode 100644 0055-add-gazelle-log.patch delete mode 100644 0056-wrap-fix-connect-wrong-port-after-addr-bind-two-port.patch delete mode 100644 0057-cfg-rm-ipv6_enable.patch delete mode 100644 0058-ltran-support-vlan.patch delete mode 100644 0059-update-src-ltran-ltran_param.c.patch delete mode 100644 0060-dfx-support-bond-get-dpdk-xstats.patch delete mode 100644 0061-add-tcp-faste-timer-cnt.patch delete mode 100644 0062-stack-fix-coredump-caused-by-gazelleclt-in-rtc-mode.patch delete mode 100644 0063-dfx-add-tcp-exception-and-kernel-event-statistics.patch delete mode 100644 0064-add-vlan_id-in-netif.patch delete mode 100644 0065-support-vlan-offload.patch delete mode 100644 0066-gazellectl-fix-gazellectl-lstack-show-1-r-error.patch delete mode 100644 0067-fix-coredump-because-sock-closed-before-send-data-fu.patch delete mode 100644 0068-fix-compilation-error.patch delete mode 100644 0069-fix-coredump-because-of-addr-null-in-lwip_fill_sendr.patch delete mode 100644 0070-add-struct-gz_addr_t.patch delete mode 100644 0071-wrap-support-shutdown.patch delete mode 100644 0072-1.solve-the-problem-of-1w-connection-not-being-able-.patch delete mode 100644 0073-dfx-gazellectl-c-support-ipv6.patch delete mode 100644 0074-The-call-stack-is-not-printed-in-the-proactive-exit-.patch delete mode 100644 0075-dfx-fix-gazellectl-lstack-show-ip-failed.patch delete mode 100644 0076-gazellectl-add-connect-para.patch delete mode 100644 0077-log-optimize-lstack-log.patch delete mode 100644 0078-support-show-nic-offload-and-features.patch delete mode 100644 0079-Fixed-an-issue-where-no-packet-is-sent-or-received-w.patch delete mode 100644 0080-fix-example-print-error.patch delete mode 100644 0081-dfx-fix-kernel_events-stat.patch delete mode 100644 0082-add-keep-alive-info.patch delete mode 100644 0083-fix-close-can-t-exit.patch delete mode 100644 0084-mod-unix-time-stamp-to-local-time.patch delete mode 100644 0085-optimize-gazelle-exit-process.patch delete mode 100644 0086-fix-EPOLLIN-event-error.patch delete mode 100644 0087-mod-time-err.patch delete mode 100644 0088-fix-gazellectl-lstack-show-ip-r-with-ltran-error-log.patch delete mode 100644 0089-fix-udp-multicast-bind-error.patch delete mode 100644 0090-support-netperf.patch delete mode 100644 0091-fix-alloc-not-free.patch delete mode 100644 0092-sigaction-fix-deprecated-signal-flags.patch delete mode 100644 0093-fix-gazellectl-c-msg-error.patch delete mode 100644 0094-CFG-fix-check-func-strdup-return-value-is-NULL.patch delete mode 100644 0095-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0096-use-default-nonblock-mode.patch delete mode 100644 0097-fix-rte_ring_create-free-time-consuming.patch delete mode 100644 0098-optimize-shutdown-exit-process.patch delete mode 100644 0099-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0100-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0101-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0102-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0103-fix-func-stack_setup_thread-array-doesn-t-init.patch delete mode 100644 0104-fix-stack_setup_thread-array-range.patch delete mode 100644 0105-fix-func-separate_str_to_array-overflow-problem.patch delete mode 100644 0106-fix-dpdk_alloc_pktmbuf-time-consuming.patch delete mode 100644 0107-ltran-optimize-config-file-error-message.patch delete mode 100644 0108-replace-with-gz_addr_t.patch delete mode 100644 0109-match_host_addr-func-support-ipv6.patch delete mode 100644 0110-add-example-keep-alive-interval-para.patch delete mode 100644 0111-update-src-common-dpdk_common.c.patch delete mode 100644 0112-listen_shadow-support-ipv6.patch delete mode 100644 0113-lstack_dpdk-limit-mbuf-max-num.patch delete mode 100644 0114-gazellectl-add-tcp_input-empty-ack-cnt.patch delete mode 100644 0115-add-socket-accept-fail-cnt.patch delete mode 100644 0116-diff-lstack-and-ltran-dfx-sock.patch delete mode 100644 0117-fix-host_addr6-can-be-assigned-a-multicast-address.patch delete mode 100644 0118-udp-do-not-merge-data-into-last-pbuf.patch delete mode 100644 0119-adpat-dpdk-23.11.patch delete mode 100644 0120-modify-conf-vlan-default-vlaue.patch delete mode 100644 0121-remove-unused-variables-in-pbuf-and-reduce-mbuf-size.patch delete mode 100644 0122-optimize-recv-exit-process-for-FIN-and-unsupport-SO_.patch delete mode 100644 0123-remove-expand_send_ring.patch delete mode 100644 0124-set-ltran.patch delete mode 100644 0125-add-bond-doc.patch delete mode 100644 0126-cfg-host_addr-is-not-mandatory.patch delete mode 100644 0127-add-bond1-support.patch delete mode 100644 0128-fix-t_params-double-free.patch delete mode 100644 0129-fix-receive-fin-packet-process-error.patch delete mode 100644 0130-support-netperf-UDP_STREAM-and-UDP_RR.patch delete mode 100644 0131-adapt-lwip-2.2.0.patch delete mode 100644 0132-add-observable-method-of-data-aggregation.patch delete mode 100644 0133-try-to-ensure-arp-packet-can-be-sent.patch delete mode 100644 0134-gazellectl-support-send-latency-show.patch delete mode 100644 0135-rpc-function-does-not-depend-on-protocol-stack.patch delete mode 100644 0136-readv-return-1-errno-is-EAGAIN-when-recvring-no-data.patch delete mode 100644 0137-split-the-flow-fules-related-functions-into-separate.patch delete mode 100644 0138-fix-coreddump-when-stack-setup-failed-in-rtc-mode.patch delete mode 100644 0139-diff-udp-and-tcp-read-from-stack.patch delete mode 100644 0140-FAULT-INJECT-gazelle-add-packet-delay-and-packet-dro.patch delete mode 100644 0141-recv-support-MSG_DONTWAIT.patch delete mode 100644 0142-do_setsockopt-function-no-longer-checks-the-results-.patch delete mode 100644 0143-FAUT-INJECT-add-fault-inject-unset-method.patch delete mode 100644 0144-support-udp-pkglen-mtu.patch delete mode 100644 0145-add-limit-with-level-for-sockopt.patch delete mode 100644 0146-udp-add-restriction-message-too-long.patch delete mode 100644 0147-dfx-improve-log-readability-when-connect-ltran-lstac.patch delete mode 100644 0148-fix-rpc_pool-create-failed-coredump.patch delete mode 100644 0149-ensure-the-bond-interface-flow_type_rss_offloads-mat.patch delete mode 100644 0150-FAULT-INJECT-add-duplicate-and-reorder-methods.patch delete mode 100644 0151-select-timeout-arguments-check.patch delete mode 100644 0152-recvfrom-support-timeout.patch delete mode 100644 0153-fix-netperf-setsockopt-fail.patch delete mode 100644 0154-fix-LATENCY_WRITE-increase-in-recv-process.patch delete mode 100644 0155-dpdk-add-vlan-filter.patch delete mode 100644 0156-Correcting-spelling-errors.patch delete mode 100644 0157-perftool-add-lhist-statstic-tool.patch delete mode 100644 0158-add-udp-poll.patch delete mode 100644 0159-DFX-adapt-testcase-for-gazellectl-connect-failed.patch delete mode 100644 0160-warp-add-configuration-check-with-host_addr-and-serv.patch delete mode 100644 0161-add-latency-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch delete mode 100644 0162-fix-vlan-filter-can-be-added-when-vlan_mode-1.patch delete mode 100644 0163-Add-support-for-arch-ppc64le.patch delete mode 100644 0164-dfx-support-get-nic-bond-status.patch delete mode 100644 0165-remove-dpdk_skip_nic_init-for-dpdk-23.11.patch delete mode 100644 0166-gazellectl-add-lwip-stats_proto-print.patch delete mode 100644 0167-fix-port-not-support-vlan-filter.patch delete mode 100644 0168-fix-tcp-recv-does-not-return-pkg-when-ring-buffer-is.patch delete mode 100644 0169-add-tuple_fileter-error-info.patch delete mode 100644 0170-adapt-dpdk-23.11-remove-kni.patch delete mode 100644 0171-fix-ioctl-set-failed.patch delete mode 100644 0172-ltran-memset-quintuple.patch delete mode 100644 0173-gazellectl-add-lwip-stats_proto-print.patch delete mode 100644 0174-CFG-set-multicast-IP-assert.patch delete mode 100644 0175-cfg-devices-must-be-in-bond_slave_mac-for-BONDING_MO.patch delete mode 100644 0176-CFG-fix-multicast-IP-assert-error.patch delete mode 100644 0177-fix-mbuf-leak-in-dpdk-23.11-due-to-kni-removed.patch delete mode 100644 0178-add-riscv64-support.patch delete mode 100644 0179-dfx-fix-gazellectl-x-for-bond.patch delete mode 100644 0180-change-gazelle_stat_lstack_proto-from-u16-to-u64.patch delete mode 100644 0181-memary-error-fix-some-memary-error.patch delete mode 100644 0182-bond-remove-bond-initialization-code-in-dpdk_ethdev_.patch delete mode 100644 0183-make-rpc_msg_max-recv_ring_size-configurable.patch delete mode 100644 0184-EPOLL-fix-coredump-while-event-count-exceed-maxevent.patch delete mode 100644 0185-fix-fin-pack-free-coredump.patch delete mode 100644 0186-fix-MySQL-shutdown-cmd.patch delete mode 100644 0187-cfg-remove-map-perfect-flag-in-lstack.conf.patch delete mode 100644 0188-redis-perf-add-tx-driver-cache.patch delete mode 100644 0189-optimized-latency-distribution-dotting.patch delete mode 100644 0190-rtc-adapt-rtc_close.patch delete mode 100644 0191-virtio-flow_bifurcation-switch.patch delete mode 100644 0192-remove-legacy-mem.patch delete mode 100644 0193-cfg-bond_slave_mac-support-pci-addr.patch delete mode 100644 0194-refactor-tx-cache-module.patch delete mode 100644 0195-virtio-create-and-init-virtio_port.patch delete mode 100644 0196-refactor-udp-send.patch delete mode 100644 0197-solve-compile-err-in-20.03.patch delete mode 100644 0198-fix-function-call-error.patch delete mode 100644 0199-perftool-add-latency-tool.patch delete mode 100644 0200-cfg-del-unnecessary-logs.patch delete mode 100644 0201-fix-dpdk_bond_primary_set-bug.patch delete mode 100644 0202-fix-build-failed-in-2003sp4.patch delete mode 100644 0203-virtio-cfg-ipv4-and-ipv6-addr.patch delete mode 100644 0204-parse-packages-type-in-rx_poll.patch delete mode 100644 0205-virtio-distribute-pkg-by-dst_port.patch delete mode 100644 0206-fix-coredump-when-get-empty-from-udp-sendring.patch delete mode 100644 0207-fix-poll-init-not-clear-old-fd.patch delete mode 100644 0208-virtio-mode-actual_queue_num.patch delete mode 100644 0209-virtio-update-g_rule_port-by-reg_ring_type-enum.patch delete mode 100644 0210-virtio-dfx-data-of-virtio.patch delete mode 100644 0211-add-flow_bifurcation-switch-in-lstack_cfg-file.patch delete mode 100644 0212-example-sync-example-update.patch delete mode 100644 0213-cleancode-improving-makefile-readability.patch delete mode 100644 0214-add-.gitignore.patch delete mode 100644 0215-cleancode-rename-gazelle-files-in-lwip.patch delete mode 100644 0216-cleancode-refactor-lwipsock.h.patch delete mode 100644 0217-cleancode-refactor-posix-type-and-get_socket.patch delete mode 100644 0218-fix-some-error-of-NULL-pointer.patch delete mode 100644 0219-cleancode-refactor-posix_api.patch delete mode 100644 0220-cleancode-refactor-lwipgz_list.h.patch delete mode 100644 0221-fix-EPOLLIN-event-dropd.patch delete mode 100644 0222-cleancode-refactor-lwipgz_hlist.h.patch delete mode 100644 0223-add-sem-post-when-update-event.patch delete mode 100644 0224-cleancode-refactor-sys_now-and-lwip_ioctl.patch delete mode 100644 0225-POSIX-fix-select-timeout-disable-and-build-failed-in.patch delete mode 100644 0226-support-kernel-connect.patch delete mode 100644 0227-Check-the-return-of-lwip_init.patch delete mode 100644 0228-vitio_user-modify-mbuf-index-for-bond4.patch delete mode 100644 0229-fix-redis-coredump-when-hugetlbs-pagesize-is-1024M.patch delete mode 100644 0230-dfx-optimize-gazellectl-x-for-bond.patch delete mode 100644 0231-virtio-fix-dfx-error-with-multiple-cpus.patch delete mode 100644 0232-fix-issue-create-virtio_user-based-on-bond4-main-net.patch delete mode 100644 0233-virtio_user-modify-mbuf-index-for-bond4.patch delete mode 100644 0234-WRAP-fix-double-connect-lead-posix-api-disable.patch delete mode 100644 0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch delete mode 100644 0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch delete mode 100644 0237-refector-fill-udp-sendring.patch delete mode 100644 0238-virtio_user-The-program-establishes-a-network-connec.patch delete mode 100644 0239-WRAP-fix-ltran-mode-did-not-bind-kernel-while-open-k.patch delete mode 100644 0240-WRAP-fix-bind-log-error.patch delete mode 100644 0241-virtio-mod-virtio_user_name-when-multi-process-is-on.patch delete mode 100644 0242-fix-redis-coredump-ctrl-c-during-the-pressure-test.patch delete mode 100644 0243-virtio_user-check-netif-status.patch delete mode 100644 0244-virtio-solve-compilation-error-in-2003sp3.patch delete mode 100644 0245-CMAKE-fix-ltran-build-error-in-2403.patch delete mode 100644 0246-fix-mbuf_total-calculation-error.patch delete mode 100644 0247-cfg-modify-maximum-tcp_conn_count-to-2w.patch delete mode 100644 0248-tools-fix-sync-patch-script-date-wrong-and-update-th.patch delete mode 100644 0249-epoll-fix-wild-pointer-detected-by-cooddy.patch delete mode 100644 0250-tools-fix-script-generate-patchname-wrong.patch delete mode 100644 0251-fix-when-errno-is-ENOTCONN-ignore-it.patch delete mode 100644 0252-rtc-do_lwip_init_sock-no-need-to-create-ring-in-rtc-.patch delete mode 100644 0253-example-solve-double-free.patch delete mode 100644 0254-WRAP-support-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch delete mode 100644 0255-DFX-adapt-log-optimization.patch delete mode 100644 0256-LOG-add-log-when-udp-send_ring-is-exhausted.patch delete mode 100644 0257-cleancode-refactor-rtc_api-rtw_api-and-dummy_api.patch delete mode 100644 0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch delete mode 100644 0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch delete mode 100644 0260-cleancode-declare-different-cfg_params-types.patch delete mode 100644 0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch delete mode 100644 0262-add-pingpong-dfx-support.patch delete mode 100644 0263-add-interrupt-mode-support.patch delete mode 100644 0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch delete mode 100644 0265-fix-stack-null-when-register-interrupt.patch delete mode 100644 0266-rtw-fix-send-length-exceeding-send_ring_size.patch delete mode 100644 0267-rpc-fix-rpc_sync_call-spinlock-block-when-msg-be-rec.patch delete mode 100644 0268-bugfix-fix-gazelle-init-failed-while-setup-by-non-ro.patch delete mode 100644 0269-xdp-skip-checksum-temporarily-due-to-kernel-cannot-t.patch delete mode 100644 0270-fix-dpdk_nic_is_xdp-coredump-in-ltran-mode.patch delete mode 100644 0271-fix-the-coredump-when-gazellectl-l.patch delete mode 100644 0272-control-call-epoll_ctl-delete-fd-when-fd-close.patch delete mode 100644 0273-epoll-remove-unnecessary-judgment-code.patch delete mode 100644 0274-slove-compile-err-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch delete mode 100644 0275-bugfix-start-fail-when-executing-the-popen-command-f.patch delete mode 100644 0276-Fix-annotation-errors.patch delete mode 100644 0277-remove-the-unused-return-variable.patch delete mode 100644 0278-add-SO_NUMA_ID-optname-for-adapting-opneGauss.patch delete mode 100644 0279-xdp-support-XDP_STATISTICS-by-posix_api-getsockopt_f.patch delete mode 100644 0280-interrupt-fix-timeout-events-cannot-be-counted.patch delete mode 100644 0281-remove-code-about-nobolck-mode-for-mysql.patch delete mode 100644 0282-LOG-Optimize-some-log-displays.patch delete mode 100644 0283-xdp-support-bind-no-cpu-mode.patch delete mode 100644 0284-support-auto-set-xdp-addr.patch delete mode 100644 0285-suport-kernel-accept-for-openGauss.patch delete mode 100644 0286-openGauss-support-kernel-accept4.patch delete mode 100644 0287-socket-init-wakeup-in-blocking-socket.patch delete mode 100644 0288-fix-socket-of-control-thread-is-overwirtten-due-to-a.patch delete mode 100644 0289-LWIP-adjust-position-of-shutdown-in-callback-of-conn.patch delete mode 100644 0290-Fix-the-wrong-spelling-description-in-the-notes-and-.patch delete mode 100644 0291-update-test-unitest-ltran-ltran_param_test.c.patch delete mode 100644 0292-fix-free-null-pointer-when-no-matching-device-is-fou.patch delete mode 100644 0293-cfg-show-dpdk-args-after-dpdk_adjust_args.patch delete mode 100644 0294-fix-build-error-in-2003SP4.patch delete mode 100644 0295-CFG-fix-xdp-iface-check-error.patch delete mode 100644 0296-xdp-support-stack-bind-numa.patch delete mode 100644 0297-openGauss-support-kernel-connnect.patch delete mode 100644 0298-DUMP-gazelle-supports-dump-lstack.patch delete mode 100644 0299-openGauss-fix-gs_ctl-switchover-failed.patch delete mode 100644 0300-openGauss-fix-connection-attempt-failed.patch delete mode 100644 0301-remove-app_bind_numa-check-from-exclude_cpus.patch delete mode 100644 0302-fix-rpc-pool-leak-when-thread-exits.patch delete mode 100644 0303-fix-epoll-and-recv-threads-blocked-on-the-same-semap.patch delete mode 100644 0304-fix-errno-ETIMEFOUT.patch delete mode 100644 0305-cfg-notify-that-it-s-unsupported-when-stack_num-1.patch delete mode 100644 0306-fix-a-contention-issue-when-rpc-pools-are-added-to-r.patch delete mode 100644 0307-openGauss-unsupport_tcp_optname.patch delete mode 100644 0308-kernerl-bind-add-ipv6-add-check.patch delete mode 100644 0309-Connect-execute-lwip-connect-if-dst_ip-and-host_ip-a.patch delete mode 100644 0310-DUMP-fix-build-error-of-oe2003-because-of-micro-is-n.patch delete mode 100644 0311-SIGNAL-Adjust-sigaction-function-to-keep-lstack-sign.patch delete mode 100644 0312-SIGNAL-Adjust-hijack-sigal-table-to-hijack-SIGABRT-S.patch delete mode 100644 0313-DUMP-fix-abnomal-printing-in-the-dump-process.patch delete mode 100644 0314-fix-the-memory-leak-when-using-strdup.patch delete mode 100644 0315-Stack-unset-stack_stop-while-stacks-exit-by-rpc-mess.patch delete mode 100644 0316-SIGNAL-block-SIGSEGV-during-exit-process.patch delete mode 100644 0317-add-xdp-tx-checksum-tso-offload.patch delete mode 100644 0318-RTC-mode-fix-gazellectl-can-t-print-connenct-info.patch delete mode 100644 0319-Connect-fix-benchmark_dws-connect-failed.patch delete mode 100644 0320-Protocal-fixing-deathlock-between-protocol-threads-a.patch delete mode 100644 0321-update-gazelle-max-numa-nodes-8.patch delete mode 100644 0322-RTC-fixing-program-stuck-while-gazelle-exit-in-multi.patch delete mode 100644 0323-cleancode-add-GAZELLE_SAME_NODE.patch delete mode 100644 0324-cleancode-remove-gazelle_light_ring.patch delete mode 100644 0325-cleancode-remove-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch delete mode 100644 0326-socket-refactor-sock_event.patch delete mode 100644 0327-socket-adapt-to-sock_event.patch delete mode 100644 0328-socket-refactor-tcp-and-udp.patch delete mode 100644 0329-socket-adapt-to-tcp-and-udp.patch delete mode 100644 0330-cfg-add-mem_cache_max-and-change-default-rpc_msg_max.patch delete mode 100644 0331-cfg-add-mem_async_mode.patch delete mode 100644 0332-mempool-add-mem_thread_cache_flush.patch delete mode 100644 0333-dfx-support-sk_wait-stat.patch delete mode 100644 0334-mempool-fix-copy_mbuf_private.patch delete mode 100644 0335-socket-fix-connect-blocking.patch delete mode 100644 0336-socket-fix-stack_tcp_read-do-not-recv_finish_burst.patch delete mode 100644 0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch delete mode 100644 0338-socket-fix-tcp-closed.patch delete mode 100644 0339-socket-fix-sk_wait-cannot-be-interrupted-by-signals.patch delete mode 100644 0340-mempool-modify-mbuf-num-and-rpc_msg-num.patch delete mode 100644 0341-mempool-fix-mbox_ring-free-not-call-recv_finish_burs.patch delete mode 100644 0342-mempool-mem_get_rpc-add-reserve-limit.patch delete mode 100644 0343-mempool-fix-pthread_tryjoin_np-coredump-when-mysqld-.patch delete mode 100644 0344-mempool-stop-using-cache-when-too-many-threads.patch delete mode 100644 0345-sk_wait-fix-lwip_tcp_allow_send-coredump.patch delete mode 100644 0346-mbox-fix-mbox_ring_common_free-coredump-when-rte_rin.patch delete mode 100644 0347-sk_wait-fix-sock_wait_common_free.patch delete mode 100644 0348-socket-fix-stack_udp_readmsg-return-len.patch delete mode 100644 0349-sk_wait-fix-lwip_wait_foreach_notify-coredump-at-sta.patch delete mode 100644 0350-epoll-fix-do_lwip_connected_callback.patch delete mode 100644 0351-sockio-fix-rtw_stack_tcp_write-wrong-copied_total-af.patch delete mode 100644 0352-sk_event-fix-rtw-epoll-wrong-event-notify-and-remove.patch delete mode 100644 0353-poll-fix-do_lwip_connected_callback-not-delete-poll-.patch delete mode 100644 0354-sockctl-fix-rtw-broadcast-close-and-shutdown.patch delete mode 100644 0355-mempool-increase-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch delete mode 100644 0356-sockio-fix-callback_tcp_send-output-too-many-at-once.patch delete mode 100644 0357-sockio-fix-sendmbox-full-return-EWOULDBLOCK.patch delete mode 100644 0358-sk_wait-igonre-mem_thread-flush-signal.patch delete mode 100644 0359-fix-20.03-LTS-build-failed.patch delete mode 100644 0360-sockio-fix-tcp_write-not-remove-EPOLLOUT.patch delete mode 100644 0361-sockio-fix-rpc_send-coredump-after-RPC_MSG_EXIT.patch delete mode 100644 gazelle-1.0.2.tar.gz create mode 100644 gazelle-1.0.3.tar.gz diff --git a/0001-remove-unused-dpdk-dynamic-libraries.patch b/0001-remove-unused-dpdk-dynamic-libraries.patch deleted file mode 100644 index ec98466..0000000 --- a/0001-remove-unused-dpdk-dynamic-libraries.patch +++ /dev/null @@ -1,93 +0,0 @@ -From dac81b016b6eccfc9f4061c22c1e78d36ca17f88 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 28 Jun 2023 10:30:48 +0800 -Subject: [PATCH] remove unused dpdk dynamic libraries - ---- - src/lstack/Makefile | 6 +----- - src/ltran/CMakeLists.txt | 42 +++++++++------------------------------- - 2 files changed, 10 insertions(+), 38 deletions(-) - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index d9c8396..3550244 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -98,12 +98,8 @@ else - $(LIB_PATH)/librte_net_i40e.so \ - $(LIB_PATH)/librte_net_ixgbe.so \ - $(LIB_PATH)/librte_net_virtio.so \ -- $(LIB_PATH)/librte_pcapng.so \ -- $(LIB_PATH)/librte_rcu.so \ - $(LIB_PATH)/librte_telemetry.so \ -- $(LIB_PATH)/librte_bpf.so \ -- $(LIB_PATH)/librte_security.so \ -- $(LIB_PATH)/librte_cryptodev.so -+ $(LIB_PATH)/librte_pcapng.so - endif - - DEP_LIBS = $(LWIP_LIB) $(LIBRTE_LIB) -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index 1370dc8..b8d92b7 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -30,29 +30,12 @@ endif($ENV{GAZELLE_COVERAGE_ENABLE}) - if($ENV{DPDK_VERSION_1911}) - set(DPDK_DIR /usr/include/dpdk) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDPDK_VERSION_1911=1") -- set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_af_packet -Wl,-lrte_pmd_ark -Wl,-lrte_pmd_atlantic -Wl,-lrte_pmd_axgbe \ -- -Wl,-lrte_pmd_bnxt -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_cxgbe -Wl,-lrte_pmd_dpaa -Wl,-lrte_pmd_dpaa2 \ -- -Wl,-lrte_pmd_e1000 -Wl,-lrte_pmd_ena -Wl,-lrte_pmd_enetc -Wl,-lrte_pmd_enic -Wl,-lrte_pmd_failsafe \ -- -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe -Wl,-lrte_pmd_kni \ -- -Wl,-lrte_pmd_nfp -Wl,-lrte_pmd_null -Wl,-lpcap -Wl,-lrte_pmd_qede -Wl,-lrte_pmd_ring -Wl,-lrte_pmd_softnic \ -- -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_tap -Wl,-lrte_pmd_vdev_netvsc -Wl,-lrte_pmd_virtio -Wl,-lrte_pmd_vhost \ -- -Wl,-lrte_mempool_octeontx -Wl,-lrte_pmd_octeontx -Wl,-lrte_bus_vmbus -Wl,-lrte_pmd_netvsc \ -- -Wl,-lrte_pmd_vmxnet3_uio -Wl,-lrte_pmd_bbdev_null \ -- -Wl,-lrte_pmd_null_crypto -Wl,-lrte_pmd_octeontx_crypto -Wl,-lrte_pmd_crypto_scheduler \ -- -Wl,-lrte_pmd_dpaa2_sec -Wl,-lrte_pmd_dpaa_sec -Wl,-lrte_pmd_caam_jr -Wl,-lrte_pmd_virtio_crypto \ -- -Wl,-lrte_pmd_octeontx_zip -Wl,-lrte_pmd_qat -Wl,-lrte_pmd_skeleton_event -Wl,-lrte_pmd_sw_event \ -- -Wl,-lrte_pmd_dsw_event -Wl,-lrte_pmd_octeontx_ssovf -Wl,-lrte_pmd_dpaa_event -Wl,-lrte_pmd_dpaa2_event \ -- -Wl,-lrte_pmd_opdl_event -Wl,-lrte_pmd_lio -Wl,-lrte_pmd_thunderx_nicvf -Wl,-lrte_pmd_ifc") -+ set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_bond -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe \ -+ -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_virtio") - else() - set(DPDK_DIR /usr/local/include/) -- set(DPDK_LINK_FLAGS "-Wl,-lrte_net_af_packet -Wl,-lrte_net_ark -Wl,-lrte_net_atlantic -Wl,-lrte_net_axgbe \ -- -Wl,-lrte_net_bnxt -Wl,-lrte_net_bond -Wl,-lrte_net_cxgbe -Wl,-lrte_net_dpaa -Wl,-lrte_net_dpaa2 \ -- -Wl,-lrte_net_e1000 -Wl,-lrte_net_ena -Wl,-lrte_net_enetc -Wl,-lrte_net_enic -Wl,-lrte_net_failsafe \ -- -Wl,-lrte_net_i40e -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe -Wl,-lrte_net_kni \ -- -Wl,-lrte_net_nfp -Wl,-lrte_net_null -Wl,-lpcap -Wl,-lrte_net_qede -Wl,-lrte_net_ring -Wl,-lrte_net_softnic \ -- -Wl,-lrte_net_pcap -Wl,-lrte_net_tap -Wl,-lrte_net_vdev_netvsc -Wl,-lrte_net_virtio -Wl,-lrte_net_vhost \ -- -Wl,-lrte_mempool_octeontx -Wl,-lrte_net_octeontx -Wl,-lrte_bus_vmbus -Wl,-lrte_net_netvsc \ -- -Wl,-lrte_telemetry") -+ set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_i40e -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ -+ -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry") - endif($ENV{DPDK_VERSION_1911}) - - add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_stat.c ltran_errno.c -@@ -69,18 +52,11 @@ target_compile_options(ltran PRIVATE -march=native -fno-strict-aliasing -D__ARM_ - -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2) - - target_link_libraries(ltran PRIVATE config boundscheck rte_pdump -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines) --set_target_properties(ltran PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -Wl,--whole-archive -Wl,-lrte_pipeline \ -- -Wl,--no-whole-archive -Wl,-lrte_table -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--whole-archive -Wl,-lrte_port -Wl,--no-whole-archive \ -- -Wl,-lrte_distributor -Wl,-lrte_meter -Wl,-lrte_ip_frag -Wl,-lrte_lpm -Wl,--whole-archive -Wl,-lrte_acl -Wl,--no-whole-archive \ -- -Wl,-lrte_jobstats -Wl,-lrte_bitratestats -Wl,-lrte_metrics -Wl,-lrte_latencystats -Wl,-lrte_power -Wl,-lrte_efd -Wl,-lrte_bpf \ -- -Wl,--whole-archive -Wl,-lrte_gro -Wl,-lrte_cfgfile -Wl,-lrte_gso -Wl,-lrte_hash -Wl,-lrte_member -Wl,-lrte_vhost -Wl,-lrte_kvargs \ -- -Wl,-lrte_mbuf -Wl,-lrte_ethdev -Wl,-lrte_net -Wl,-lrte_bbdev -Wl,-lrte_cryptodev -Wl,-lrte_security -Wl,-lrte_compressdev -Wl,-lrte_eventdev \ -- -Wl,-lrte_rawdev -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci \ -- -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic -Wl,-lrte_cmdline \ -- -Wl,-lrte_sched -Wl,-lrte_reorder -Wl,-lrte_kni -Wl,-lrte_common_cpt -Wl,-lrte_common_octeontx -Wl,-lrte_common_dpaax -Wl,-lrte_bus_pci \ -- -Wl,-lrte_bus_dpaa -Wl,-lrte_bus_vdev -Wl,-lrte_bus_fslmc -Wl,-lrte_mempool_bucket -Wl,-lrte_mempool_stack -Wl,-lrte_mempool_dpaa \ -- -Wl,-lrte_mempool_dpaa2 -Wl,-lrte_bus_ifpga -Wl,-lrte_stack \ -- ${DPDK_LINK_FLAGS} \ -+set_target_properties(ltran PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -Wl,--no-whole-archive \ -+ -Wl,-lrte_meter -Wl,--whole-archive -Wl,-lrte_gro -Wl,-lrte_hash -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ethdev \ -+ -Wl,-lrte_net -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci \ -+ -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic -Wl,-lrte_cmdline -Wl,-lrte_kni -Wl,-lrte_bus_pci \ -+ -Wl,-lrte_bus_vdev ${DPDK_LINK_FLAGS} \ - -Wl,--no-whole-archive -Wl,-lm -Wl,-lrt -Wl,-lnuma -Wl,-ldl -Wl,-export-dynamic -Wl,-export-dynamic \ - -Wl,--as-needed -Wl,-export-dynamic -Wl,-Map=ltran.map -Wl,--cref") - --- -2.23.0 - diff --git a/0002-gazelle_stat_pkts-gazelle_stat_low_power_info.patch b/0002-gazelle_stat_pkts-gazelle_stat_low_power_info.patch deleted file mode 100644 index 113b9b1..0000000 --- a/0002-gazelle_stat_pkts-gazelle_stat_low_power_info.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 8f477abc2530a4defc37d2e443eca19271c1b6b8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E5=AD=99=E8=8B=8F=E7=9A=96?= -Date: Tue, 4 Apr 2023 09:19:48 +0000 -Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9gazelle=5Fstat=5Fpkts?= - =?UTF-8?q?=EF=BC=8Cgazelle=5Fstat=5Flow=5Fpower=5Finfo=E7=BB=93=E6=9E=84?= - =?UTF-8?q?=E4=BD=93=E6=88=90=E5=91=98=E9=A1=BA=E5=BA=8F=EF=BC=8C=E6=9D=A5?= - =?UTF-8?q?=E4=BD=BF=E7=BB=93=E6=9E=84=E4=BD=93=E5=A4=A7=E5=B0=8F=E5=8F=98?= - =?UTF-8?q?=E5=B0=8F?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: 孙苏皖 ---- - src/common/gazelle_dfx_msg.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index e4da687..7ce8874 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -79,11 +79,11 @@ struct gazelle_wakeup_stat { - }; - - struct gazelle_stat_pkts { -- uint64_t call_msg_cnt; - uint16_t conn_num; -+ uint32_t mempool_freecnt; -+ uint64_t call_msg_cnt; - uint64_t recv_list_cnt; - uint64_t call_alloc_fail; -- uint32_t mempool_freecnt; - struct gazelle_stack_stat stack_stat; - struct gazelle_wakeup_stat wakeup_stat; - }; -@@ -194,9 +194,9 @@ struct gazelle_stack_latency { - - struct gazelle_stat_low_power_info { - uint16_t low_power_mod; -+ uint16_t lpm_rx_pkts; - uint32_t lpm_pkts_in_detect; - uint32_t lpm_detect_ms; -- uint16_t lpm_rx_pkts; - }; - - #define RTE_ETH_XSTATS_NAME_SIZE 64 --- -2.23.0 - diff --git a/0003-set-localhost-ip-when-bind-ip-is-same-as-ip-in-lstac.patch b/0003-set-localhost-ip-when-bind-ip-is-same-as-ip-in-lstac.patch deleted file mode 100644 index f89791e..0000000 --- a/0003-set-localhost-ip-when-bind-ip-is-same-as-ip-in-lstac.patch +++ /dev/null @@ -1,27 +0,0 @@ -From c13dd0c6ae71dd7547b9c1c6240585ae0f5c7c6b Mon Sep 17 00:00:00 2001 -From: chengyechun -Date: Tue, 11 Jul 2023 10:57:35 +0800 -Subject: [PATCH] set localhost ip when bind ip is same as ip in lstack.conf - ---- - src/lstack/api/lstack_wrap.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 6a1a2c4..956d661 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -245,6 +245,10 @@ bool is_dst_ip_localhost(const struct sockaddr *addr) - char *p; - size_t linel = 0; - int linenum = 0; -+ if (get_global_cfg_params()->host_addr.addr == servaddr->sin_addr.s_addr) { -+ return true; -+ } -+ - FILE *ifh = fopen("/proc/net/dev", "r"); - if (ifh == NULL) { - LSTACK_LOG(ERR, LSTACK, "failed to open /proc/net/dev, errno is %d\n", errno); --- -2.23.0 - diff --git a/0004-refactoring-preload-module.patch b/0004-refactoring-preload-module.patch deleted file mode 100644 index 4f82116..0000000 --- a/0004-refactoring-preload-module.patch +++ /dev/null @@ -1,158 +0,0 @@ -From c2703d07662909f228e7e93ecec585bc4c826449 Mon Sep 17 00:00:00 2001 -From: yanan-rock -Date: Fri, 21 Jul 2023 08:34:53 +0000 -Subject: [PATCH] refactoring preload module - -Signed-off-by: yanan-rock ---- - src/lstack/core/lstack_init.c | 40 +-------------------- - src/lstack/core/lstack_preload.c | 55 +++++++++++++++++++++++++++++ - src/lstack/include/lstack_preload.h | 16 +++++++++ - 3 files changed, 72 insertions(+), 39 deletions(-) - create mode 100644 src/lstack/core/lstack_preload.c - create mode 100644 src/lstack/include/lstack_preload.h - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 4fbbc14..53bc541 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -46,11 +46,7 @@ - #include "posix/lstack_unistd.h" - #include "gazelle_base_func.h" - #include "lstack_protocol_stack.h" -- --#define LSTACK_PRELOAD_ENV_SYS "LD_PRELOAD" --#define LSTACK_SO_NAME "liblstack.so" --#define LSTACK_PRELOAD_NAME_LEN PATH_MAX --#define LSTACK_PRELOAD_ENV_PROC "GAZELLE_BIND_PROCNAME" -+#include "lstack_preload.h" - - static volatile bool g_init_fail = false; - -@@ -64,40 +60,6 @@ bool get_init_fail(void) - return g_init_fail; - } - --struct lstack_preload { -- int32_t preload_switch; -- char env_procname[LSTACK_PRELOAD_NAME_LEN]; --}; --static struct lstack_preload g_preload_info = {0}; -- --static int32_t preload_info_init(void) --{ -- char *enval = NULL; -- -- g_preload_info.preload_switch = 0; -- -- enval = getenv(LSTACK_PRELOAD_ENV_SYS); -- if (enval == NULL) { -- return 0; -- } -- -- if (strstr(enval, LSTACK_SO_NAME) == NULL) { -- return 0; -- } -- -- enval = getenv(LSTACK_PRELOAD_ENV_PROC); -- if (enval == NULL) { -- return -1; -- } -- if (strcpy_s(g_preload_info.env_procname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) { -- return -1; -- } -- -- g_preload_info.preload_switch = 1; -- LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); -- return 0; --} -- - static void check_process_start(void) - { - if (get_global_cfg_params()->is_primary) { -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -new file mode 100644 -index 0000000..9fc5819 ---- /dev/null -+++ b/src/lstack/core/lstack_preload.c -@@ -0,0 +1,55 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+#include -+#include -+#include -+ -+#include "lstack_preload.h" -+ -+#define LSTACK_PRELOAD_ENV_SYS "LD_PRELOAD" -+#define LSTACK_SO_NAME "liblstack.so" -+#define LSTACK_PRELOAD_NAME_LEN PATH_MAX -+#define LSTACK_PRELOAD_ENV_PROC "GAZELLE_BIND_PROCNAME" -+ -+struct lstack_preload { -+ int32_t preload_switch; -+ char env_procname[LSTACK_PRELOAD_NAME_LEN]; -+}; -+static struct lstack_preload g_preload_info = {0}; -+ -+static int32_t preload_info_init(void) -+{ -+ char *enval = NULL; -+ -+ g_preload_info.preload_switch = 0; -+ -+ enval = getenv(LSTACK_PRELOAD_ENV_SYS); -+ if (enval == NULL) { -+ return 0; -+ } -+ -+ if (strstr(enval, LSTACK_SO_NAME) == NULL) { -+ return 0; -+ } -+ -+ enval = getenv(LSTACK_PRELOAD_ENV_PROC); -+ if (enval == NULL) { -+ return -1; -+ } -+ if (strcpy_s(g_preload_info.env_procname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) { -+ return -1; -+ } -+ -+ g_preload_info.preload_switch = 1; -+ LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); -+ return 0; -+} -diff --git a/src/lstack/include/lstack_preload.h b/src/lstack/include/lstack_preload.h -new file mode 100644 -index 0000000..4ba6525 ---- /dev/null -+++ b/src/lstack/include/lstack_preload.h -@@ -0,0 +1,16 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+#ifndef __LSTACK_PRELOAD_H__ -+#define __LSTACK_PRELOAD_H__ -+ -+int preload_info_init(void); -+#endif --- -2.23.0 - diff --git a/0005-fix-previous-commit-refactoring-preload-module.patch b/0005-fix-previous-commit-refactoring-preload-module.patch deleted file mode 100644 index 5669435..0000000 --- a/0005-fix-previous-commit-refactoring-preload-module.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 6a5bb82feba31762f6c977e618bcee47a5f06d26 Mon Sep 17 00:00:00 2001 -From: yanan-rock -Date: Sun, 14 May 2023 15:02:58 -0400 -Subject: [PATCH] fix previous commit "refactoring preload module" - -Signed-off-by: yanan-rock ---- - src/lstack/core/lstack_init.c | 26 -------------------------- - src/lstack/core/lstack_preload.c | 25 ++++++++++++++++++++++++- - 2 files changed, 24 insertions(+), 27 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 53bc541..406a0b8 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -118,29 +118,6 @@ static int32_t check_process_conflict(void) - return 0; - } - --static int32_t check_preload_bind_proc(void) --{ -- char proc_path[PATH_MAX] = {0}; -- -- if (!g_preload_info.preload_switch) { -- return 0; -- } -- -- if (readlink("/proc/self/exe", proc_path, PATH_MAX - 1) <= 0) { -- return -1; -- } -- -- char *proc_name = strrchr(proc_path, '/'); -- if (!proc_name) { -- return -1; -- } -- -- if (strncmp(++proc_name, g_preload_info.env_procname, PATH_MAX) == 0) { -- return 0; -- } -- return -1; --} -- - __attribute__((destructor)) void gazelle_network_exit(void) - { - if (posix_api != NULL && !posix_api->ues_posix) { -@@ -262,9 +239,6 @@ __attribute__((constructor)) void gazelle_network_init(void) - if (preload_info_init() < 0) { - return; - } -- if (check_preload_bind_proc() < 0) { -- return; -- } - - /* Read configure from lstack.cfg */ - if (cfg_init() != 0) { -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 9fc5819..e04f49b 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -26,6 +26,29 @@ struct lstack_preload { - }; - static struct lstack_preload g_preload_info = {0}; - -+static int32_t preload_check_bind_proc(void) -+{ -+ char proc_path[PATH_MAX] = {0}; -+ -+ if (!g_preload_info.preload_switch) { -+ return 0; -+ } -+ -+ if (readlink("/proc/self/exe", proc_path, PATH_MAX - 1) <= 0) { -+ return -1; -+ } -+ -+ char *proc_name = strrchr(proc_path, '/'); -+ if (!proc_name) { -+ return -1; -+ } -+ -+ if (strncmp(++proc_name, g_preload_info.env_procname, PATH_MAX) == 0) { -+ return 0; -+ } -+ return -1; -+} -+ - static int32_t preload_info_init(void) - { - char *enval = NULL; -@@ -51,5 +74,5 @@ static int32_t preload_info_init(void) - - g_preload_info.preload_switch = 1; - LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); -- return 0; -+ return preload_check_bind_proc(); - } --- -2.23.0 - diff --git a/0006-add-lstack_preload.c-to-makefile.patch b/0006-add-lstack_preload.c-to-makefile.patch deleted file mode 100644 index 5788730..0000000 --- a/0006-add-lstack_preload.c-to-makefile.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 28cf0ab6a58444ee9e1fa36ce6d5b6aa6f37f5ad Mon Sep 17 00:00:00 2001 -From: yanan-rock -Date: Sun, 14 May 2023 21:47:21 -0400 -Subject: [PATCH] add lstack_preload.c to makefile fix compile failure - -Signed-off-by: yanan-rock ---- - src/lstack/core/dir.mk | 2 +- - src/lstack/core/lstack_preload.c | 5 ++++- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/dir.mk b/src/lstack/core/dir.mk -index 88c1e08..e2d10a5 100644 ---- a/src/lstack/core/dir.mk -+++ b/src/lstack/core/dir.mk -@@ -8,6 +8,6 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_init.c lstack_cfg.c lstack_dpdk.c lstack_control_plane.c lstack_stack_stat.c lstack_lwip.c lstack_protocol_stack.c lstack_thread_rpc.c -+SRC = lstack_preload.c lstack_init.c lstack_cfg.c lstack_dpdk.c lstack_control_plane.c lstack_stack_stat.c lstack_lwip.c lstack_protocol_stack.c lstack_thread_rpc.c - $(eval $(call register_dir, core, $(SRC))) - -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index e04f49b..e3a98fc 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -13,6 +13,9 @@ - #include - #include - -+#include "securec.h" -+ -+#include "lstack_log.h" - #include "lstack_preload.h" - - #define LSTACK_PRELOAD_ENV_SYS "LD_PRELOAD" -@@ -49,7 +52,7 @@ static int32_t preload_check_bind_proc(void) - return -1; - } - --static int32_t preload_info_init(void) -+int preload_info_init(void) - { - char *enval = NULL; - --- -2.23.0 - diff --git a/0007-cosmetic-changes.patch b/0007-cosmetic-changes.patch deleted file mode 100644 index 7f134fa..0000000 --- a/0007-cosmetic-changes.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 52e6a745e4b5bf27de66b55283c0e0f474213258 Mon Sep 17 00:00:00 2001 -From: Honggang LI -Date: Mon, 21 Aug 2023 08:48:00 +0800 -Subject: [PATCH] cosmetic changes - -Signed-off-by: Honggang LI ---- - src/lstack/core/lstack_init.c | 2 +- - src/lstack/core/lstack_lwip.c | 1 - - src/lstack/include/lstack_cfg.h | 2 +- - src/ltran/ltran_dfx.c | 2 +- - 4 files changed, 3 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 406a0b8..db203d2 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -256,7 +256,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - return; - } - -- /* check lstack num, and get process idx */ -+ /* check lstack num */ - if (check_params_from_primary() < 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "lstack num error, not same to primary process!\n"); - LSTACK_EXIT(1, "lstack num error, not same to primary process!\n"); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c1346f6..bcdbac0 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1239,7 +1239,6 @@ static inline void clone_lwip_socket_opt(struct lwip_sock *dst_sock, struct lwip - dst_sock->conn->pcb.tcp->netif_idx = src_sock->conn->pcb.tcp->netif_idx; - dst_sock->conn->pcb.tcp->flags = src_sock->conn->pcb.tcp->flags; - dst_sock->conn->pcb.tcp->keep_idle = src_sock->conn->pcb.tcp->keep_idle; -- dst_sock->conn->pcb.tcp->keep_idle = src_sock->conn->pcb.tcp->keep_idle; - dst_sock->conn->pcb.tcp->keep_intvl = src_sock->conn->pcb.tcp->keep_intvl; - dst_sock->conn->pcb.tcp->keep_cnt = src_sock->conn->pcb.tcp->keep_cnt; - } -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 9102fee..52a1abd 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -82,7 +82,7 @@ struct cfg_params { - uint32_t read_connect_number; - uint32_t rpc_number; - uint32_t nic_read_number; -- uint8_t use_ltran; // ture:lstack read from nic false:read form ltran -+ uint8_t use_ltran; // false:lstack read from nic. true:lstack read form ltran process. - - uint16_t num_process; - uint16_t num_listen_port; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index b8d9c99..e5fd0c8 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -836,7 +836,7 @@ static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_d - printf("ip_in_deliver: %u\n", snmp->ip_in_deliver); - printf("ip_out_req: %u\n", snmp->ip_out_req); - printf("ip_out_discard: %u\n", snmp->ip_out_discard); -- printf("ip_outnort: %u\n", snmp->ip_out_discard); -+ printf("ip_outnort: %u\n", snmp->ip_outnort); - printf("ip_reasm_ok: %u\n", snmp->ip_reasm_ok); - printf("ip_reasm_fail: %u\n", snmp->ip_reasm_fail); - printf("ip_frag_ok: %u\n", snmp->ip_frag_ok); --- -2.27.0 - diff --git a/0008-add-loongarch64-and-sw64-arch-support.patch b/0008-add-loongarch64-and-sw64-arch-support.patch deleted file mode 100644 index e5703bd..0000000 --- a/0008-add-loongarch64-and-sw64-arch-support.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 7b2803bfe36e6ca19d4389d28c5d9f15dcbe95e8 Mon Sep 17 00:00:00 2001 -From: herengui -Date: Wed, 30 Aug 2023 15:41:03 +0800 -Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=BE=99=E8=8A=AF=E5=92=8C?= - =?UTF-8?q?=E7=94=B3=E5=A8=81=E6=9E=B6=E6=9E=84=E6=94=AF=E6=8C=81?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: herengui ---- - src/lstack/Makefile | 9 +++++++-- - src/ltran/CMakeLists.txt | 17 +++++++++++++---- - test/unitest/ltran/CMakeLists.txt | 5 ++++- - 3 files changed, 24 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index 3550244..8f684ba 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -26,6 +26,7 @@ CC ?= gcc - OPTIMIZATION = -O2 -g - RM = rm -f - LDFLAGS = -shared -ldl -lm -lpthread -lrt -lnuma -lconfig -lboundscheck -+ARCH := $(shell uname -m) - - ifneq ($(CC),clang) - SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wl,-z,relro, -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIC -D_FORTIFY_SOURCE=2 -@@ -88,18 +89,22 @@ ifeq ($(DPDK_VERSION_1911), 1) - LIBRTE_LIB += $(LIB_PATH)/librte_pmd_pcap.so \ - $(LIB_PATH)/librte_pmd_bond.so \ - $(LIB_PATH)/librte_pmd_hinic.so \ -- $(LIB_PATH)/librte_pmd_i40e.so \ - $(LIB_PATH)/librte_pmd_ixgbe.so \ - $(LIB_PATH)/librte_pmd_virtio.so -+ ifneq ($(ARCH), loongarch64) -+ LIBRTE_LIB += $(LIB_PATH)/librte_pmd_i40e.so -+ endif - else - LIBRTE_LIB += $(LIB_PATH)/librte_net_pcap.so \ - $(LIB_PATH)/librte_net_bond.so \ - $(LIB_PATH)/librte_net_hinic.so \ -- $(LIB_PATH)/librte_net_i40e.so \ - $(LIB_PATH)/librte_net_ixgbe.so \ - $(LIB_PATH)/librte_net_virtio.so \ - $(LIB_PATH)/librte_telemetry.so \ - $(LIB_PATH)/librte_pcapng.so -+ ifneq ($(ARCH), loongarch64) -+ LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so -+ endif - endif - - DEP_LIBS = $(LWIP_LIB) $(LIBRTE_LIB) -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index b8d92b7..e098a77 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -30,12 +30,18 @@ endif($ENV{GAZELLE_COVERAGE_ENABLE}) - if($ENV{DPDK_VERSION_1911}) - set(DPDK_DIR /usr/include/dpdk) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDPDK_VERSION_1911=1") -- set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_bond -Wl,-lrte_pmd_i40e -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe \ -+ set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_bond -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe \ - -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_virtio") -+ if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") -+ set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_pmd_i40e") -+ endif() - else() - set(DPDK_DIR /usr/local/include/) -- set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_i40e -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ -+ set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ - -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry") -+ if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") -+ set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_net_i40e") -+ endif() - endif($ENV{DPDK_VERSION_1911}) - - add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_stat.c ltran_errno.c -@@ -44,12 +50,15 @@ add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_st - ${COMMON_DIR}/gazelle_parse_config.c) - - target_include_directories(ltran PRIVATE ${COMMON_DIR} ${PROJECT_SOURCE_DIR} ${LWIP_DIR} ${DPDK_DIR}) --target_compile_options(ltran PRIVATE -march=native -fno-strict-aliasing -D__ARM_FEATURE_CRC32=1 -DRTE_MACHINE_CPUFLAG_NEON -+target_compile_options(ltran PRIVATE -fno-strict-aliasing -D__ARM_FEATURE_CRC32=1 -DRTE_MACHINE_CPUFLAG_NEON - -DRTE_MACHINE_CPUFLAG_CRC32 -DRTE_MACHINE_CPUFLAG_PMULL -DRTE_MACHINE_CPUFLAG_AES - -DRTE_MACHINE_CPUFLAG_SHA1 -DRTE_MACHINE_CPUFLAG_SHA2 -include rte_config.h - -D_GNU_SOURCE -W -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wold-style-definition -- -Wpointer-arith -Wcast-align -Wcast-qual -Wnested-externs -Wformat-nonliteral -Wformat-security -Wundef -+ -Wpointer-arith -Wcast-qual -Wnested-externs -Wformat-nonliteral -Wformat-security -Wundef - -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2) -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64") -+ target_compile_options(ltran PRIVATE -march=native -Wcast-align) -+endif() - - target_link_libraries(ltran PRIVATE config boundscheck rte_pdump -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines) - set_target_properties(ltran PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -Wl,--no-whole-archive \ -diff --git a/test/unitest/ltran/CMakeLists.txt b/test/unitest/ltran/CMakeLists.txt -index 9496053..60bda83 100644 ---- a/test/unitest/ltran/CMakeLists.txt -+++ b/test/unitest/ltran/CMakeLists.txt -@@ -47,12 +47,15 @@ set_target_properties(ltran_test PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -W - -Wl,-lrte_bus_dpaa -Wl,-lrte_bus_vdev -Wl,-lrte_bus_fslmc -Wl,-lrte_mempool_bucket -Wl,-lrte_mempool_stack -Wl,-lrte_mempool_dpaa \ - -Wl,-lrte_mempool_dpaa2 -Wl,-lrte_net_af_packet -Wl,-lrte_net_ark -Wl,-lrte_net_atlantic -Wl,-lrte_net_axgbe \ - -Wl,-lrte_net_bnxt -Wl,-lrte_net_bond -Wl,-lrte_net_cxgbe -Wl,-lrte_net_dpaa -Wl,-lrte_net_dpaa2 -Wl,-lrte_net_e1000 -Wl,-lrte_net_ena \ -- -Wl,-lrte_net_enetc -Wl,-lrte_net_enic -Wl,-lrte_net_failsafe -Wl,-lrte_net_i40e -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe -Wl,-lrte_net_kni \ -+ -Wl,-lrte_net_enetc -Wl,-lrte_net_enic -Wl,-lrte_net_failsafe -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe -Wl,-lrte_net_kni \ - -Wl,-lrte_net_nfp -Wl,-lrte_net_null -Wl,-lpcap -Wl,-lrte_net_qede -Wl,-lrte_net_ring -Wl,-lrte_net_softnic \ - -Wl,-lrte_net_tap -Wl,-lrte_net_vdev_netvsc -Wl,-lrte_net_virtio -Wl,-lrte_net_vhost \ - -Wl,-lrte_bus_vmbus -Wl,-lrte_net_netvsc -Wl,-lrte_mempool_octeontx -Wl,-lrte_net_octeontx \ - -Wl,-lrte_bus_ifpga -Wl,-lrte_stack -Wl,-lrte_telemetry\ - -Wl,--no-whole-archive -Wl,-lm -Wl,-lrt -Wl,-lnuma -Wl,-ldl -Wl,-export-dynamic -Wl,-export-dynamic \ - -Wl,--as-needed -Wl,-export-dynamic -Wl,-Map=ltran.map -Wl,--cref") -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") -+ set_target_properties(ltran_test PROPERTIES LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-lrte_net_i40e") -+endif() - target_include_directories(ltran_test PRIVATE ${LIB_PATH}) - target_link_libraries(ltran_test PRIVATE config boundscheck cunit pthread) --- -2.27.0 - diff --git a/0009-CFG-fixed-the-dpdk-primary-default-parameter.patch b/0009-CFG-fixed-the-dpdk-primary-default-parameter.patch deleted file mode 100644 index 66b2a91..0000000 --- a/0009-CFG-fixed-the-dpdk-primary-default-parameter.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d8d70edfd8d5fc7ac617671c5ac8fe8364727e29 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Thu, 7 Sep 2023 19:55:58 +0800 -Subject: [PATCH] CFG:fixed the dpdk primary default parameter - ---- - src/lstack/core/lstack_cfg.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 32d63b9..9fc16dd 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -770,6 +770,8 @@ static int32_t parse_dpdk_args(void) - } - start_index = 1; - -+ struct cfg_params *global_params = get_global_cfg_params(); -+ global_params->is_primary = 1; - for (i = 0; i < g_config_params.dpdk_argc; i++) { - arg = config_setting_get_string_elem(args, i); - if (arg == NULL) -@@ -780,10 +782,9 @@ static int32_t parse_dpdk_args(void) - } - g_config_params.dpdk_argv[start_index + i] = p; - -- const char *primary = "primary"; -- if (strcmp(p, primary) == 0) { -- struct cfg_params *global_params = get_global_cfg_params(); -- global_params->is_primary = 1; -+ const char *secondary = "secondary"; -+ if (strcmp(p, secondary) == 0) { -+ global_params->is_primary = 0; - } - - (void)fprintf(stderr, "%s ", g_config_params.dpdk_argv[start_index + i]); --- -2.27.0 - diff --git a/0010-suport-clang-build.patch b/0010-suport-clang-build.patch deleted file mode 100644 index 57d3f17..0000000 --- a/0010-suport-clang-build.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 655bcc55ae2045b1a457f7b654569361ea32bfc2 Mon Sep 17 00:00:00 2001 -From: luofeng14 -Date: Tue, 12 Sep 2023 02:05:34 +0000 -Subject: [PATCH] suport clang build - -Signed-off-by: luofeng14 ---- - src/lstack/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index 8f684ba..30965f8 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -40,7 +40,7 @@ INC = -I$(LSTACK_DIR)/include \ - -I$(LWIP_INCLUDE_FILE) \ - -I$(DPDK_INCLUDE_FILE) - --CFLAGS = $(OPTIMIZATION) -fno-strict-aliasing $(INC) -+CFLAGS += $(OPTIMIZATION) -fno-strict-aliasing $(INC) -Wno-error=unused-function - - ifeq ($(GAZELLE_COVERAGE_ENABLE), 1) - LDFLAGS += -fprofile-arcs -ftest-coverage --- -2.27.0 - diff --git a/0011-ethdev-fix-pbuf-chain-tot_len-incorrect.patch b/0011-ethdev-fix-pbuf-chain-tot_len-incorrect.patch deleted file mode 100644 index a98e0a6..0000000 --- a/0011-ethdev-fix-pbuf-chain-tot_len-incorrect.patch +++ /dev/null @@ -1,25 +0,0 @@ -From d98cb71e63fed73197334b373cfb979b6a47e1ea Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 15 Sep 2023 10:16:19 +0800 -Subject: [PATCH] ethdev: fix pbuf chain tot_len incorrect p->tot_len = p->len - + (p->next ? p->next->tot_len : 0) - ---- - src/lstack/netif/lstack_ethdev.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 3ea8e52..e3e823b 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -96,6 +96,7 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - break; - } - next->tot_len = pkt_len; -+ pkt_len -= len; - #if CHECKSUM_CHECK_IP_HW || CHECKSUM_CHECK_TCP_HW - next->ol_flags = m->ol_flags; - #endif --- -2.27.0 - diff --git a/0012-kernelevent-kernel-event-thread-report-kernel-events.patch b/0012-kernelevent-kernel-event-thread-report-kernel-events.patch deleted file mode 100644 index ccfb33a..0000000 --- a/0012-kernelevent-kernel-event-thread-report-kernel-events.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 4267e381b25e42f19b2dd160fbf08efb5d8bd0fb Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 4 Sep 2023 11:16:12 +0800 -Subject: [PATCH] kernelevent: kernel event thread report kernel events to app - thread directly without passing through lstack thread - ---- - src/lstack/core/lstack_protocol_stack.c | 53 +++++++++++++------------ - 1 file changed, 27 insertions(+), 26 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 3a6e792..ca0b046 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -38,7 +38,7 @@ - #include "lstack_stack_stat.h" - #include "lstack_protocol_stack.h" - --#define KERNEL_EVENT_100us 100 -+#define KERNEL_EVENT_10us 10 - - static PER_THREAD struct protocol_stack *g_stack_p = NULL; - static struct protocol_stack_group g_stack_group = {0}; -@@ -258,6 +258,29 @@ static int32_t create_thread(void *arg, char *thread_name, stack_thread_func fun - return 0; - } - -+static void wakeup_kernel_event(struct protocol_stack *stack) -+{ -+ if (stack->kernel_event_num <= 0) { -+ return; -+ } -+ -+ for (int32_t i = 0; i < stack->kernel_event_num; i++) { -+ struct wakeup_poll *wakeup = stack->kernel_events[i].data.ptr; -+ if (wakeup->type == WAKEUP_CLOSE) { -+ continue; -+ } -+ -+ __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE); -+ if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -+ __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -+ rte_mb(); -+ pthread_mutex_unlock(&wakeup->wait); -+ } -+ } -+ -+ return; -+} -+ - static void* gazelle_kernelevent_thread(void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; -@@ -272,8 +295,9 @@ static void* gazelle_kernelevent_thread(void *arg) - - for (;;) { - stack->kernel_event_num = posix_api->epoll_wait_fn(stack->epollfd, stack->kernel_events, KERNEL_EPOLL_MAX, -1); -- while (stack->kernel_event_num > 0) { -- usleep(KERNEL_EVENT_100us); -+ if (stack->kernel_event_num > 0) { -+ wakeup_kernel_event(stack); -+ usleep(KERNEL_EVENT_10us); - } - } - -@@ -416,28 +440,6 @@ END1: - return NULL; - } - --static void wakeup_kernel_event(struct protocol_stack *stack) --{ -- if (stack->kernel_event_num == 0) { -- return; -- } -- -- for (int32_t i = 0; i < stack->kernel_event_num; i++) { -- struct wakeup_poll *wakeup = stack->kernel_events[i].data.ptr; -- if (wakeup->type == WAKEUP_CLOSE) { -- continue; -- } -- -- __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE); -- if (list_is_null(&wakeup->wakeup_list[stack->stack_idx])) { -- list_add_node(&stack->wakeup_list, &wakeup->wakeup_list[stack->stack_idx]); -- } -- } -- -- stack->kernel_event_num = 0; --} -- -- - static void* gazelle_stack_thread(void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; -@@ -485,7 +487,6 @@ static void* gazelle_stack_thread(void *arg) - read_recv_list(stack, read_connect_number); - - if ((wakeup_tick & 0xf) == 0) { -- wakeup_kernel_event(stack); - wakeup_stack_epoll(stack); - } - --- -2.27.0 - diff --git a/0013-fix-bond-port-reta_size-init.patch b/0013-fix-bond-port-reta_size-init.patch deleted file mode 100644 index 16df1f6..0000000 --- a/0013-fix-bond-port-reta_size-init.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2151d99ea4b19492543c5c05b3b1cc5ed6db316c Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Tue, 26 Sep 2023 01:29:21 +0000 -Subject: [PATCH] fix bond port reta_size init - ---- - src/lstack/core/lstack_dpdk.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index cd42047..6384439 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -552,6 +552,7 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; - dev_info.tx_offload_capa = slave_dev_info.tx_offload_capa; -+ dev_info.reta_size = slave_dev_info.reta_size; - } - - eth_params_checksum(ð_params->conf, &dev_info); --- -2.27.0 - diff --git a/0014-init-remove-sync-sem-between-lstack-thread-and-main-.patch b/0014-init-remove-sync-sem-between-lstack-thread-and-main-.patch deleted file mode 100644 index d06b3ce..0000000 --- a/0014-init-remove-sync-sem-between-lstack-thread-and-main-.patch +++ /dev/null @@ -1,383 +0,0 @@ -From a0371ba4a351362d7a804d10ed1ee80884da0d85 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 7 Oct 2023 21:35:52 +0800 -Subject: [PATCH] init: remove sync sem between lstack thread and main thread - ---- - src/lstack/core/lstack_dpdk.c | 14 --- - src/lstack/core/lstack_init.c | 26 +--- - src/lstack/core/lstack_protocol_stack.c | 133 +++++++-------------- - src/lstack/include/lstack_protocol_stack.h | 7 +- - 4 files changed, 51 insertions(+), 129 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index cd42047..d848275 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -568,18 +568,6 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - stack_group->nb_queues = nb_queues; - - if (get_global_cfg_params()->is_primary) { -- for (uint32_t i = 0; i < stack_group->stack_num; i++) { -- struct protocol_stack *stack = stack_group->stacks[i]; -- if (likely(stack)) { -- stack->port_id = stack_group->port_id; -- } else { -- LSTACK_LOG(ERR, LSTACK, "empty stack at stack_num %d\n", i); -- stack_group->eth_params = NULL; -- free(eth_params); -- return -EINVAL; -- } -- } -- - ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, ð_params->conf); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot config eth dev at port %d: %s\n", port_id, rte_strerror(-ret)); -@@ -760,8 +748,6 @@ int32_t init_dpdk_ethdev(void) - } - } - -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- sem_post(&stack_group->ethdev_init); - return 0; - } - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index db203d2..2183e3a 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -48,18 +48,6 @@ - #include "lstack_protocol_stack.h" - #include "lstack_preload.h" - --static volatile bool g_init_fail = false; -- --void set_init_fail(void) --{ -- g_init_fail = true; --} -- --bool get_init_fail(void) --{ -- return g_init_fail; --} -- - static void check_process_start(void) - { - if (get_global_cfg_params()->is_primary) { -@@ -286,8 +274,8 @@ __attribute__((constructor)) void gazelle_network_init(void) - lstack_log_level_init(); - lstack_prelog_uninit(); - -- if (init_protocol_stack() != 0) { -- LSTACK_EXIT(1, "init_protocol_stack failed\n"); -+ if (stack_group_init() != 0) { -+ LSTACK_EXIT(1, "stack_group_init failed\n"); - } - - if (!use_ltran()) { -@@ -296,15 +284,13 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - } - -+ if (stack_thread_setup() != 0) { -+ LSTACK_EXIT(1, "stack_init_in_setup failed\n"); -+ } -+ - /* lwip initialization */ - lwip_sock_init(); - -- /* wait stack thread and kernel_event thread init finish */ -- wait_sem_value(&get_protocol_stack_group()->all_init, get_protocol_stack_group()->stack_num); -- if (g_init_fail) { -- LSTACK_EXIT(1, "stack thread or kernel_event thread failed\n"); -- } -- - if (get_global_cfg_params()->kni_switch) { - set_kni_ip_mac(); - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ca0b046..8071bda 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -43,8 +43,6 @@ - static PER_THREAD struct protocol_stack *g_stack_p = NULL; - static struct protocol_stack_group g_stack_group = {0}; - --void set_init_fail(void); --bool get_init_fail(void); - typedef void *(*stack_thread_func)(void *arg); - - -@@ -286,12 +284,11 @@ static void* gazelle_kernelevent_thread(void *arg) - struct thread_params *t_params = (struct thread_params*) arg; - uint16_t idx = t_params->idx; - struct protocol_stack *stack = get_protocol_stack_group()->stacks[idx]; -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); - -- sem_post(&stack_group->thread_phase1); - bind_to_stack_numa(stack); - - LSTACK_LOG(INFO, LSTACK, "kernelevent_%02hu start\n", idx); -+ free(arg); - - for (;;) { - stack->kernel_event_num = posix_api->epoll_wait_fn(stack->epollfd, stack->kernel_events, KERNEL_EPOLL_MAX, -1); -@@ -311,6 +308,7 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - - stack->tid = rte_gettid(); - stack->queue_id = t_params->queue_id; -+ stack->port_id = stack_group->port_id; - stack->stack_idx = t_params->idx; - stack->lwip_stats = &lwip_stats; - -@@ -370,7 +368,12 @@ void wait_sem_value(sem_t *sem, int32_t wait_value) - - static int32_t create_affiliate_thread(void *arg) - { -- if (create_thread(arg, "gazellekernel", gazelle_kernelevent_thread) != 0) { -+ struct thread_params *params = malloc(sizeof(struct thread_params)); -+ if (params == NULL) { -+ return -1; -+ } -+ memcpy_s(params, sizeof(*params), arg, sizeof(struct thread_params)); -+ if (create_thread((void *)params, "gazellekernel", gazelle_kernelevent_thread) != 0) { - LSTACK_LOG(ERR, LSTACK, "gazellekernel errno=%d\n", errno); - return -1; - } -@@ -380,60 +383,49 @@ static int32_t create_affiliate_thread(void *arg) - - static struct protocol_stack *stack_thread_init(void *arg) - { -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); - struct protocol_stack *stack = calloc(1, sizeof(*stack)); - if (stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "malloc stack failed\n"); -- goto END2; -+ goto END; - } - - if (init_stack_value(stack, arg) != 0) { -- goto END2; -+ goto END; - } - - if (init_stack_numa_cpuset(stack) < 0) { -- goto END2; -+ goto END; - } - if (create_affiliate_thread(arg) < 0) { -- goto END2; -+ goto END; - } - - if (thread_affinity_init(stack->cpu_id) != 0) { -- goto END1; -+ goto END; - } - RTE_PER_LCORE(_lcore_id) = stack->cpu_id; - - if (hugepage_init() != 0) { - LSTACK_LOG(ERR, LSTACK, "hugepage init failed\n"); -- goto END1; -+ goto END; - } - - tcpip_init(NULL, NULL); - - if (use_ltran()) { - if (client_reg_thrd_ring() != 0) { -- goto END1; -+ goto END; - } - } - -- sem_post(&stack_group->thread_phase1); -- -- if (!use_ltran()) { -- wait_sem_value(&stack_group->ethdev_init, 1); -- } -- - usleep(SLEEP_US_BEFORE_LINK_UP); - - if (ethdev_init(stack) != 0) { -- goto END1; -+ goto END; - } - - return stack; --/* kernel event thread dont create, stack thread post sem twice */ --END2: -- sem_post(&stack_group->thread_phase1); --END1: -- sem_post(&stack_group->thread_phase1); -+END: - if (stack != NULL) { - free(stack); - } -@@ -453,23 +445,19 @@ static void* gazelle_stack_thread(void *arg) - uint32_t rpc_number = cfg->rpc_number; - uint32_t nic_read_number = cfg->nic_read_number; - uint32_t wakeup_tick = 0; -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); - - struct protocol_stack *stack = stack_thread_init(arg); - -+ free(arg); - if (stack == NULL) { -- /* exit in main thread, avoid create mempool and exit at the same time */ -- set_init_fail(); -- sem_post(&stack_group->all_init); - LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id); -- return NULL; -+ /* exit in signal thread */ -+ raise(SIGTERM); - } - if (!use_ltran() && queue_id == 0) { - init_listen_and_user_ports(); - } - -- sem_post(&stack_group->all_init); -- - LSTACK_LOG(INFO, LSTACK, "stack_%02hu init success\n", queue_id); - - for (;;) { -@@ -517,40 +505,9 @@ static void libnet_listen_thread(void *arg) - recv_pkts_from_other_process(cfg_param->process_idx, arg); - } - --static int32_t init_protocol_sem(void) -+int32_t stack_group_init(void) - { -- int32_t ret; - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- -- if (!use_ltran()) { -- ret = sem_init(&stack_group->ethdev_init, 0, 0); -- if (ret < 0) { -- LSTACK_LOG(ERR, PORT, "sem_init failed ret=%d errno=%d\n", ret, errno); -- return -1; -- } -- } -- -- ret = sem_init(&stack_group->thread_phase1, 0, 0); -- if (ret < 0) { -- LSTACK_LOG(ERR, PORT, "sem_init failed ret=%d errno=%d\n", ret, errno); -- return -1; -- } -- -- ret = sem_init(&stack_group->all_init, 0, 0); -- if (ret < 0) { -- LSTACK_LOG(ERR, PORT, "sem_init failed ret=%d errno=%d\n", ret, errno); -- return -1; -- } -- -- return 0; --} -- --int32_t init_protocol_stack(void) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- int32_t ret; -- char name[PATH_MAX]; -- - if (!get_global_cfg_params()->seperate_send_recv) { - stack_group->stack_num = get_global_cfg_params()->num_cpu; - } else { -@@ -560,13 +517,6 @@ int32_t init_protocol_stack(void) - init_list_node(&stack_group->poll_list); - pthread_spin_init(&stack_group->poll_list_lock, PTHREAD_PROCESS_PRIVATE); - pthread_spin_init(&stack_group->socket_lock, PTHREAD_PROCESS_PRIVATE); -- -- if (init_protocol_sem() != 0) { -- return -1; -- } -- int queue_num = get_global_cfg_params()->num_queue; -- struct thread_params *t_params[queue_num]; -- int process_index = get_global_cfg_params()->process_idx; - - if (get_global_cfg_params()->is_primary) { - uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; -@@ -580,6 +530,27 @@ int32_t init_protocol_stack(void) - } - } - -+ if (!use_ltran()) { -+ char name[PATH_MAX]; -+ sem_init(&stack_group->sem_listen_thread, 0, 0); -+ sprintf_s(name, sizeof(name), "%s", "listen_thread"); -+ struct sys_thread *thread = sys_thread_new(name, libnet_listen_thread, -+ (void*)(&stack_group->sem_listen_thread), 0, 0); -+ free(thread); -+ sem_wait(&stack_group->sem_listen_thread); -+ } -+ -+ return 0; -+} -+ -+int32_t stack_thread_setup(void) -+{ -+ int32_t ret; -+ char name[PATH_MAX]; -+ int queue_num = get_global_cfg_params()->num_queue; -+ struct thread_params *t_params[queue_num]; -+ int process_index = get_global_cfg_params()->process_idx; -+ - for (uint32_t i = 0; i < queue_num; i++) { - if (get_global_cfg_params()->seperate_send_recv) { - if (i % 2 == 0) { -@@ -610,26 +581,6 @@ int32_t init_protocol_stack(void) - } - } - -- /* stack_num * 2: stack thread and kernel event thread will post sem */ -- wait_sem_value(&stack_group->thread_phase1, stack_group->stack_num * 2); -- -- for (int idx = 0; idx < queue_num; idx++){ -- free(t_params[idx]); -- } -- -- if (!use_ltran()) { -- ret = sem_init(&stack_group->sem_listen_thread, 0, 0); -- ret = sprintf_s(name, sizeof(name), "%s", "listen_thread"); -- struct sys_thread *thread = sys_thread_new(name, libnet_listen_thread, -- (void*)(&stack_group->sem_listen_thread), 0, 0); -- free(thread); -- sem_wait(&stack_group->sem_listen_thread); -- } -- -- if (get_init_fail()) { -- return -1; -- } -- - return 0; - } - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index a23ddff..2d723d4 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -85,9 +85,6 @@ struct eth_params; - struct protocol_stack_group { - uint16_t stack_num; - uint16_t port_id; -- sem_t thread_phase1; -- sem_t ethdev_init; -- sem_t all_init; - uint64_t rx_offload; - uint64_t tx_offload; - uint32_t reta_mask; -@@ -112,7 +109,9 @@ struct protocol_stack *get_protocol_stack_by_fd(int32_t fd); - struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - --int32_t init_protocol_stack(void); -+int32_t stack_group_init(void); -+int32_t stack_thread_setup(void); -+ - void bind_to_stack_numa(struct protocol_stack *stack); - int32_t init_dpdk_ethdev(void); - --- -2.27.0 - diff --git a/0015-lstack_lwip-external-api-start-with-do_lwip_-prefix.patch b/0015-lstack_lwip-external-api-start-with-do_lwip_-prefix.patch deleted file mode 100644 index e0b0226..0000000 --- a/0015-lstack_lwip-external-api-start-with-do_lwip_-prefix.patch +++ /dev/null @@ -1,941 +0,0 @@ -From 9ba0b1d9df98b648eecdf5c5ed31611574d25272 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 20 Sep 2023 19:48:22 +0800 -Subject: [PATCH] lstack_lwip: external api start with do_lwip_ prefix - ---- - src/lstack/api/lstack_wrap.c | 22 +-- - src/lstack/core/lstack_dpdk.c | 12 +- - src/lstack/core/lstack_lwip.c | 198 ++++----------------- - src/lstack/core/lstack_protocol_stack.c | 138 +++++++++++++- - src/lstack/core/lstack_thread_rpc.c | 8 +- - src/lstack/include/lstack_dpdk.h | 1 + - src/lstack/include/lstack_lwip.h | 61 ++++--- - src/lstack/include/lstack_protocol_stack.h | 7 + - src/lstack/netif/lstack_ethdev.c | 8 +- - src/lstack/netif/lstack_vdev.c | 2 +- - 10 files changed, 241 insertions(+), 216 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 956d661..236c689 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -438,7 +438,7 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - - struct lwip_sock *sock = NULL; - if (select_path(sockfd, &sock) == PATH_LWIP) { -- return read_stack_data(sockfd, buf, len, flags, NULL, NULL); -+ return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); - } - - return posix_api->recv_fn(sockfd, buf, len, flags); -@@ -456,7 +456,7 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - - struct lwip_sock *sock = NULL; - if (select_path(s, &sock) == PATH_LWIP) { -- return read_stack_data(s, mem, len, 0, NULL, NULL); -+ return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); - } - return posix_api->read_fn(s, mem, len); - } -@@ -477,7 +477,7 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; -- ssize_t result = recvmsg_from_stack(s, &msg, 0); -+ ssize_t result = do_lwip_recvmsg_from_stack(s, &msg, 0); - if (result == -1 && errno == EAGAIN) { - errno = 0; - return 0; -@@ -492,7 +492,7 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - return posix_api->send_fn(sockfd, buf, len, flags); - } - -- return gazelle_send(sockfd, buf, len, flags, NULL, 0); -+ return do_lwip_send_to_stack(sockfd, buf, len, flags, NULL, 0); - } - - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) -@@ -502,7 +502,7 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - return posix_api->write_fn(s, mem, size); - } - -- return gazelle_send(s, mem, size, 0, NULL, 0); -+ return do_lwip_send_to_stack(s, mem, size, 0, NULL, 0); - } - - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) -@@ -521,7 +521,7 @@ static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; -- return sendmsg_to_stack(sock, s, &msg, 0); -+ return do_lwip_sendmsg_to_stack(sock, s, &msg, 0); - } - - static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flags) -@@ -532,7 +532,7 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - - struct lwip_sock *sock = NULL; - if (select_path(s, &sock) == PATH_LWIP) { -- return recvmsg_from_stack(s, message, flags); -+ return do_lwip_recvmsg_from_stack(s, message, flags); - } - - return posix_api->recv_msg(s, message, flags); -@@ -546,7 +546,7 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - - struct lwip_sock *sock = NULL; - if (select_path(s, &sock) == PATH_LWIP) { -- return sendmsg_to_stack(sock, s, message, flags); -+ return do_lwip_sendmsg_to_stack(sock, s, message, flags); - } - - return posix_api->send_msg(s, message, flags); -@@ -558,7 +558,7 @@ static inline ssize_t udp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void - int32_t ret; - - while (1) { -- ret = read_stack_data(sockfd, buf, len, flags, addr, addrlen); -+ ret = do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); - if (ret > 0) { - return ret; - } -@@ -581,7 +581,7 @@ static inline ssize_t udp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void - static inline ssize_t tcp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void *buf, size_t len, int32_t flags, - struct sockaddr *addr, socklen_t *addrlen) - { -- return read_stack_data(sockfd, buf, len, flags, addr, addrlen); -+ return do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); - } - - static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t flags, -@@ -615,7 +615,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen); - } - -- return gazelle_send(sockfd, buf, len, flags, addr, addrlen); -+ return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); - } - - static inline int32_t do_close(int32_t s) -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index cd42047..b4e29cb 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -281,6 +281,16 @@ int32_t create_shared_ring(struct protocol_stack *stack) - return 0; - } - -+int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num) -+{ -+ int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ return 0; -+} -+ - int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num) - { - int32_t ret; -@@ -291,7 +301,7 @@ int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, ui - while (remain > 0) { - batch = LWIP_MIN(remain, RING_SIZE(FREE_RX_QUEUE_SZ)); - -- ret = gazelle_alloc_pktmbuf(mempool, free_buf, batch); -+ ret = dpdk_alloc_pktmbuf(mempool, free_buf, batch); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "cannot alloc mbuf for ring, count: %u ret=%d\n", batch, ret); - return -1; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index bcdbac0..9ab8446 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -167,7 +167,7 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - return false; - } - --void gazelle_init_sock(int32_t fd) -+void do_lwip_init_sock(int32_t fd) - { - static _Atomic uint32_t name_tick = 0; - struct protocol_stack *stack = get_protocol_stack(); -@@ -200,7 +200,7 @@ void gazelle_init_sock(int32_t fd) - init_list_node_null(&sock->event_list); - } - --void gazelle_clean_sock(int32_t fd) -+void do_lwip_clean_sock(int32_t fd) - { - struct lwip_sock *sock = get_socket_by_fd(fd); - if (sock == NULL || sock->stack == NULL) { -@@ -220,7 +220,7 @@ void gazelle_clean_sock(int32_t fd) - list_del_node_null(&sock->recv_list); - } - --void gazelle_free_pbuf(struct pbuf *pbuf) -+void do_lwip_free_pbuf(struct pbuf *pbuf) - { - if (pbuf == NULL) { - return; -@@ -231,17 +231,7 @@ void gazelle_free_pbuf(struct pbuf *pbuf) - rte_pktmbuf_free_seg(mbuf); - } - --int32_t gazelle_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num) --{ -- int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); -- if (ret != 0) { -- return ret; -- } -- -- return 0; --} -- --struct pbuf *lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type) -+struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type) - { - struct rte_mbuf *mbuf; - struct protocol_stack *stack = get_protocol_stack(); -@@ -254,7 +244,7 @@ struct pbuf *lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type) - return init_mbuf_to_pbuf(mbuf, layer, length, type); - } - --struct pbuf *write_lwip_data(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags) -+struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags) - { - struct pbuf *pbuf = NULL; - -@@ -321,7 +311,7 @@ struct pbuf *write_lwip_data(struct lwip_sock *sock, uint16_t remain_size, uint8 - return pbuf; - } - --void write_lwip_over(struct lwip_sock *sock) -+void do_lwip_get_from_sendring_over(struct lwip_sock *sock) - { - sock->send_pre_del = NULL; - sock->stack->stats.write_lwip_cnt++; -@@ -549,8 +539,8 @@ int sem_timedwait_nsecs(sem_t *sem) - return sem_timedwait(sem, &ts); - } - --ssize_t write_stack_data(struct lwip_sock *sock, const void *buf, size_t len, -- const struct sockaddr *addr, socklen_t addrlen) -+static ssize_t do_lwip_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); -@@ -639,7 +629,7 @@ END: - return send_len; - } - --static inline bool replenish_send_ring(struct protocol_stack *stack, struct lwip_sock *sock) -+bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock) - { - bool replenish_again = false; - -@@ -652,16 +642,8 @@ static inline bool replenish_send_ring(struct protocol_stack *stack, struct lwip - return replenish_again; - } - --void rpc_replenish(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_0].p; -- struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_1].p; -- -- msg->result = replenish_send_ring(stack, sock); --} -- --static inline bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -- size_t len, int32_t flags) -+bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -+ size_t len, int32_t flags) - { - /* send all send_ring, so len set lwip send max. */ - if (NETCONN_IS_UDP(sock)) { -@@ -670,38 +652,7 @@ static inline bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct - (void)lwip_send(fd, sock, UINT16_MAX, flags); - } - -- return replenish_send_ring(stack, sock); --} -- --void stack_send(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- size_t len = msg->args[MSG_ARG_1].size; -- struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_3].p; -- bool replenish_again; -- -- struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -- msg->result = -1; -- LSTACK_LOG(ERR, LSTACK, "stack_send: sock error!\n"); -- rpc_msg_free(msg); -- return; -- } -- -- replenish_again = do_lwip_send(stack, sock->conn->socket, sock, len, 0); -- __sync_fetch_and_sub(&sock->call_num, 1); -- if (!NETCONN_IS_DATAOUT(sock) && !replenish_again) { -- rpc_msg_free(msg); -- return; -- } else { -- if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 0) { -- rpc_call(&stack->rpc_queue, msg); -- __sync_fetch_and_add(&sock->call_num, 1); -- } else { -- rpc_msg_free(msg); -- return; -- } -- } -+ return do_lwip_replenish_sendring(stack, sock); - } - - static inline void free_recv_ring_readover(struct rte_ring *ring) -@@ -721,7 +672,7 @@ static inline struct pbuf *pbuf_last(struct pbuf *pbuf) - return pbuf; - } - --ssize_t read_lwip_data(struct lwip_sock *sock, int32_t flags, u8_t apiflags) -+ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apiflags) - { - if (sock->conn->recvmbox == NULL) { - return 0; -@@ -808,7 +759,7 @@ static int32_t check_msg_vaild(const struct msghdr *message) - return 0; - } - --ssize_t recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags) -+ssize_t do_lwip_recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags) - { - ssize_t buflen = 0; - -@@ -821,8 +772,8 @@ ssize_t recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags) - continue; - } - -- ssize_t recvd_local = read_stack_data(s, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, -- flags, NULL, NULL); -+ ssize_t recvd_local = do_lwip_read_from_stack(s, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, -+ flags, NULL, NULL); - if (recvd_local > 0) { - buflen += recvd_local; - } -@@ -956,8 +907,8 @@ static inline void thread_bind_stack(struct lwip_sock *sock) - } - } - --ssize_t gazelle_send(int32_t fd, const void *buf, size_t len, int32_t flags, -- const struct sockaddr *addr, socklen_t addrlen) -+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) - { - if (buf == NULL) { - GAZELLE_RETURN(EINVAL); -@@ -974,7 +925,7 @@ ssize_t gazelle_send(int32_t fd, const void *buf, size_t len, int32_t flags, - if (sock->same_node_tx_ring != NULL) { - return gazelle_same_node_ring_send(sock, buf, len, flags); - } -- ssize_t send = write_stack_data(sock, buf, len, addr, addrlen); -+ ssize_t send = do_lwip_fill_sendring(sock, buf, len, addr, addrlen); - if (send <= 0) { - return send; - } -@@ -983,7 +934,7 @@ ssize_t gazelle_send(int32_t fd, const void *buf, size_t len, int32_t flags, - return send; - } - --ssize_t sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct msghdr *message, int32_t flags) -+ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct msghdr *message, int32_t flags) - { - int32_t ret; - int32_t i; -@@ -998,7 +949,7 @@ ssize_t sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct msghdr - continue; - } - -- ret = write_stack_data(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, NULL, 0); -+ ret = do_lwip_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; -@@ -1037,7 +988,8 @@ static struct pbuf *pbuf_free_partial(struct pbuf *pbuf, uint16_t free_len) - return pbuf; - } - --ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags, struct sockaddr *addr, socklen_t *addrlen) -+ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, -+ struct sockaddr *addr, socklen_t *addrlen) - { - size_t recv_left = len; - struct pbuf *pbuf = NULL; -@@ -1107,7 +1059,7 @@ ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags, struct - return recvd; - } - --void add_recv_list(int32_t fd) -+void do_lwip_add_recvlist(int32_t fd) - { - struct lwip_sock *sock = get_socket_by_fd(fd); - -@@ -1131,7 +1083,7 @@ void read_same_node_recv_list(struct protocol_stack *stack) - } - } - --void read_recv_list(struct protocol_stack *stack, uint32_t max_num) -+void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - { - struct list_node *list = &(stack->recv_list); - struct list_node *node, *temp; -@@ -1168,7 +1120,7 @@ void read_recv_list(struct protocol_stack *stack, uint32_t max_num) - } - } - --void gazelle_connected_callback(struct netconn *conn) -+void do_lwip_connected_callback(struct netconn *conn) - { - if (conn == NULL) { - return; -@@ -1225,7 +1177,7 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - } - } - --static inline void clone_lwip_socket_opt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock) -+void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock) - { - dst_sock->conn->pcb.ip->so_options = src_sock->conn->pcb.ip->so_options; - dst_sock->conn->pcb.ip->ttl = src_sock->conn->pcb.ip->ttl; -@@ -1244,19 +1196,19 @@ static inline void clone_lwip_socket_opt(struct lwip_sock *dst_sock, struct lwip - } - } - --int32_t gazelle_socket(int domain, int type, int protocol) -+int32_t do_lwip_socket(int domain, int type, int protocol) - { - int32_t fd = lwip_socket(AF_INET, type, 0); - if (fd < 0) { - return fd; - } - -- gazelle_init_sock(fd); -+ do_lwip_init_sock(fd); - - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL || sock->stack == NULL) { - lwip_close(fd); -- gazelle_clean_sock(fd); -+ do_lwip_clean_sock(fd); - posix_api->close_fn(fd); - return -1; - } -@@ -1264,66 +1216,14 @@ int32_t gazelle_socket(int domain, int type, int protocol) - return fd; - } - --void create_shadow_fd(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- struct sockaddr *addr = msg->args[MSG_ARG_1].p; -- socklen_t addr_len = msg->args[MSG_ARG_2].socklen; -- -- int32_t clone_fd = 0; -- struct lwip_sock *sock = get_socket_by_fd(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -- msg->result = -1; -- return; -- } -- -- if (NETCONN_IS_UDP(sock)) { -- clone_fd = gazelle_socket(AF_INET, SOCK_DGRAM, 0); -- } else { -- clone_fd = gazelle_socket(AF_INET, SOCK_STREAM, 0); -- } -- -- if (clone_fd < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = clone_fd; -- return; -- } -- -- struct lwip_sock *clone_sock = get_socket_by_fd(clone_fd); -- if (clone_sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -- msg->result = -1; -- return; -- } -- -- clone_lwip_socket_opt(clone_sock, sock); -- -- while (sock->listen_next) { -- sock = sock->listen_next; -- } -- sock->listen_next = clone_sock; -- -- int32_t ret = lwip_bind(clone_fd, addr, addr_len); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = ret; -- return; -- } -- -- msg->result = clone_fd; --} -- --void get_lwip_conntable(struct rpc_msg *msg) -+uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, -+ uint32_t max_num) - { - struct tcp_pcb *pcb = NULL; - uint32_t conn_num = 0; -- struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -- uint32_t max_num = msg->args[MSG_ARG_1].u; - - if (conn == NULL) { -- msg->result = -1; -- return; -+ return -1; - } - - for (pcb = tcp_active_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -@@ -1352,10 +1252,10 @@ void get_lwip_conntable(struct rpc_msg *msg) - conn_num++; - } - -- msg->result = conn_num; -+ return conn_num; - } - --void get_lwip_connnum(struct rpc_msg *msg) -+uint32_t do_lwip_get_connnum(void) - { - struct tcp_pcb *pcb = NULL; - struct tcp_pcb_listen *pcbl = NULL; -@@ -1373,33 +1273,7 @@ void get_lwip_connnum(struct rpc_msg *msg) - conn_num++; - } - -- msg->result = conn_num; --} -- --static uint32_t get_list_count(struct list_node *list) --{ -- struct list_node *node, *temp; -- uint32_t count = 0; -- -- list_for_each_safe(node, temp, list) { -- count++; -- } -- -- return count; --} -- --void stack_mempool_size(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_0].p; -- -- msg->result = rte_mempool_avail_count(stack->rxtx_pktmbuf_pool); --} -- --void stack_recvlist_count(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_0].p; -- -- msg->result = get_list_count(&stack->recv_list); -+ return conn_num; - } - - void netif_poll(struct netif *netif) -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ca0b046..5695438 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -484,7 +484,7 @@ static void* gazelle_stack_thread(void *arg) - read_same_node_recv_list(stack); - } - } -- read_recv_list(stack, read_connect_number); -+ do_lwip_read_recvlist(stack, read_connect_number); - - if ((wakeup_tick & 0xf) == 0) { - wakeup_stack_epoll(stack); -@@ -643,9 +643,9 @@ void stack_arp(struct rpc_msg *msg) - - void stack_socket(struct rpc_msg *msg) - { -- msg->result = gazelle_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -+ msg->result = do_lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); - if (msg->result < 0) { -- msg->result = gazelle_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -+ msg->result = do_lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); - if (msg->result < 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); - } -@@ -661,7 +661,7 @@ void stack_close(struct rpc_msg *msg) - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } - -- gazelle_clean_sock(fd); -+ do_lwip_clean_sock(fd); - - posix_api->close_fn(fd); - } -@@ -706,7 +706,7 @@ void stack_accept(struct rpc_msg *msg) - struct lwip_sock *sock = get_socket(accept_fd); - if (sock == NULL || sock->stack == NULL) { - lwip_close(accept_fd); -- gazelle_clean_sock(accept_fd); -+ do_lwip_clean_sock(accept_fd); - posix_api->close_fn(accept_fd); - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; -@@ -715,7 +715,7 @@ void stack_accept(struct rpc_msg *msg) - msg->result = accept_fd; - sock->stack->conn_num++; - if (rte_ring_count(sock->conn->recvmbox->ring)) { -- add_recv_list(accept_fd); -+ do_lwip_add_recvlist(accept_fd); - } - } - -@@ -783,6 +783,37 @@ void stack_recv(struct rpc_msg *msg) - msg->args[MSG_ARG_3].i); - } - -+void stack_send(struct rpc_msg *msg) -+{ -+ int32_t fd = msg->args[MSG_ARG_0].i; -+ size_t len = msg->args[MSG_ARG_1].size; -+ struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_3].p; -+ bool replenish_again; -+ -+ struct lwip_sock *sock = get_socket(fd); -+ if (sock == NULL) { -+ msg->result = -1; -+ LSTACK_LOG(ERR, LSTACK, "stack_send: sock error!\n"); -+ rpc_msg_free(msg); -+ return; -+ } -+ -+ replenish_again = do_lwip_send(stack, sock->conn->socket, sock, len, 0); -+ __sync_fetch_and_sub(&sock->call_num, 1); -+ if (!NETCONN_IS_DATAOUT(sock) && !replenish_again) { -+ rpc_msg_free(msg); -+ return; -+ } else { -+ if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 0) { -+ rpc_call(&stack->rpc_queue, msg); -+ __sync_fetch_and_add(&sock->call_num, 1); -+ } else { -+ rpc_msg_free(msg); -+ return; -+ } -+ } -+} -+ - /* any protocol stack thread receives arp packet and sync it to other threads so that it can have the arp table */ - void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack) - { -@@ -797,7 +828,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - continue; - } - -- ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - if (ret != 0) { - stack->stats.rx_allocmbuf_fail++; - return; -@@ -830,6 +861,99 @@ void stack_clean_epoll(struct rpc_msg *msg) - list_del_node_null(&wakeup->wakeup_list[stack->stack_idx]); - } - -+void stack_mempool_size(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_0].p; -+ -+ msg->result = rte_mempool_avail_count(stack->rxtx_pktmbuf_pool); -+} -+ -+void stack_create_shadow_fd(struct rpc_msg *msg) -+{ -+ int32_t fd = msg->args[MSG_ARG_0].i; -+ struct sockaddr *addr = msg->args[MSG_ARG_1].p; -+ socklen_t addr_len = msg->args[MSG_ARG_2].socklen; -+ -+ int32_t clone_fd = 0; -+ struct lwip_sock *sock = get_socket_by_fd(fd); -+ if (sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -+ msg->result = -1; -+ return; -+ } -+ -+ if (NETCONN_IS_UDP(sock)) { -+ clone_fd = do_lwip_socket(AF_INET, SOCK_DGRAM, 0); -+ } else { -+ clone_fd = do_lwip_socket(AF_INET, SOCK_STREAM, 0); -+ } -+ -+ if (clone_fd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = clone_fd; -+ return; -+ } -+ -+ struct lwip_sock *clone_sock = get_socket_by_fd(clone_fd); -+ if (clone_sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -+ msg->result = -1; -+ return; -+ } -+ -+ do_lwip_clone_sockopt(clone_sock, sock); -+ -+ while (sock->listen_next) { -+ sock = sock->listen_next; -+ } -+ sock->listen_next = clone_sock; -+ -+ int32_t ret = lwip_bind(clone_fd, addr, addr_len); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = ret; -+ return; -+ } -+ -+ msg->result = clone_fd; -+} -+ -+void stack_replenish_sendring(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_0].p; -+ struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_1].p; -+ -+ msg->result = do_lwip_replenish_sendring(stack, sock); -+} -+ -+void stack_get_conntable(struct rpc_msg *msg) -+{ -+ struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -+ uint32_t max_num = msg->args[MSG_ARG_1].u; -+ -+ msg->result = do_lwip_get_conntable(conn, max_num); -+} -+ -+void stack_get_connnum(struct rpc_msg *msg) -+{ -+ msg->result = do_lwip_get_connnum(); -+} -+ -+void stack_recvlist_count(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_0].p; -+ struct list_node *list = &stack->recv_list; -+ uint32_t count = 0; -+ struct list_node *node; -+ struct list_node *temp; -+ -+ list_for_each_safe(node, temp, list) { -+ count++; -+ } -+ -+ msg->result = count; -+} -+ - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ - int32_t stack_broadcast_close(int32_t fd) - { -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 1234bc6..92c58df 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -122,7 +122,7 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - - int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint32_t max_conn) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, get_lwip_conntable); -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_get_conntable); - if (msg == NULL) { - return -1; - } -@@ -135,7 +135,7 @@ int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint3 - - int32_t rpc_call_connnum(struct protocol_stack *stack) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, get_lwip_connnum); -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_get_connnum); - if (msg == NULL) { - return -1; - } -@@ -145,7 +145,7 @@ int32_t rpc_call_connnum(struct protocol_stack *stack) - - int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, create_shadow_fd); -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_create_shadow_fd); - if (msg == NULL) { - return -1; - } -@@ -434,7 +434,7 @@ int32_t rpc_call_ioctl(int fd, long cmd, void *argp) - - int32_t rpc_call_replenish(struct protocol_stack *stack, struct lwip_sock *sock) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, rpc_replenish); -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_replenish_sendring); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index c233120..6ca4f3b 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -59,4 +59,5 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id); - - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); -+int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num); - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 223ff93..55a483e 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -12,6 +12,9 @@ - - #ifndef __GAZELLE_LWIP_H__ - #define __GAZELLE_LWIP_H__ -+#include -+ -+#include "gazelle_dfx_msg.h" - - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) - #define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || (sock->same_node_rx_ring != NULL && same_node_ring_count(sock))) -@@ -24,32 +27,38 @@ struct rte_mempool; - struct rpc_msg; - struct rte_mbuf; - struct protocol_stack; --void create_shadow_fd(struct rpc_msg *msg); --void gazelle_init_sock(int32_t fd); --int32_t gazelle_socket(int domain, int type, int protocol); --void gazelle_clean_sock(int32_t fd); --struct pbuf *write_lwip_data(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags); --void write_lwip_over(struct lwip_sock *sock); --ssize_t write_stack_data(struct lwip_sock *sock, const void *buf, size_t len, -- const struct sockaddr *addr, socklen_t addrlen); --ssize_t read_stack_data(int32_t fd, void *buf, size_t len, int32_t flags, struct sockaddr *addr, socklen_t *addrlen); --ssize_t read_lwip_data(struct lwip_sock *sock, int32_t flags, uint8_t apiflags); --void read_recv_list(struct protocol_stack *stack, uint32_t max_num); -+ -+int32_t do_lwip_socket(int domain, int type, int protocol); -+void do_lwip_init_sock(int32_t fd); -+void do_lwip_clean_sock(int32_t fd); -+void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); -+ -+struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags); -+void do_lwip_get_from_sendring_over(struct lwip_sock *sock); -+bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock); -+ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, uint8_t apiflags); -+ -+/* app write/read ring */ -+ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, -+ const struct msghdr *message, int32_t flags); -+ssize_t do_lwip_recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags); -+ -+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 do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, -+ struct sockaddr *addr, socklen_t *addrlen); -+ -+void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num); -+void do_lwip_add_recvlist(int32_t fd); -+bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -+ size_t len, int32_t flags); -+ -+uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint32_t max_num); -+uint32_t do_lwip_get_connnum(void); -+ -+void do_lwip_free_pbuf(struct pbuf *pbuf); -+struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type); -+ - void read_same_node_recv_list(struct protocol_stack *stack); --void send_stack_list(struct protocol_stack *stack, uint32_t send_max); --void add_recv_list(int32_t fd); --void get_lwip_conntable(struct rpc_msg *msg); --void get_lwip_connnum(struct rpc_msg *msg); --void stack_recvlist_count(struct rpc_msg *msg); --void stack_send(struct rpc_msg *msg); --void app_rpc_write(struct rpc_msg *msg); --int32_t gazelle_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num); --void gazelle_free_pbuf(struct pbuf *pbuf); --ssize_t sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct msghdr *message, int32_t flags); --ssize_t recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags); --ssize_t gazelle_send(int32_t fd, const void *buf, size_t len, int32_t flags, -- const struct sockaddr *addr, socklen_t addrlen); --void rpc_replenish(struct rpc_msg *msg); --void stack_mempool_size(struct rpc_msg *msg); - - #endif -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index a23ddff..f8455bd 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -161,5 +161,12 @@ void stack_getsockopt(struct rpc_msg *msg); - void stack_setsockopt(struct rpc_msg *msg); - void stack_fcntl(struct rpc_msg *msg); - void stack_ioctl(struct rpc_msg *msg); -+void stack_send(struct rpc_msg *msg); -+void stack_mempool_size(struct rpc_msg *msg); -+void stack_create_shadow_fd(struct rpc_msg *msg); -+void stack_replenish_sendring(struct rpc_msg *msg); -+void stack_get_conntable(struct rpc_msg *msg); -+void stack_get_connnum(struct rpc_msg *msg); -+void stack_recvlist_count(struct rpc_msg *msg); - void kni_handle_tx(struct rte_mbuf *mbuf); - #endif -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index e3e823b..30c3c9a 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -540,9 +540,9 @@ void parse_arp_and_transefer(char* buf) - int32_t ret; - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - while (ret != 0) { -- ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - stack->stats.rx_allocmbuf_fail++; - } - copy_mbuf(mbuf_copy, mbuf); -@@ -569,9 +569,9 @@ void parse_tcp_and_transefer(char* buf) - struct rte_mbuf *mbuf_copy = NULL; - struct protocol_stack *stack = stack_group->stacks[stk_index]; - -- int32_t ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - while (ret != 0) { -- ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - stack->stats.rx_allocmbuf_fail++; - } - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 4307f24..81b48dc 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -56,7 +56,7 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - stack->rx_ring_used += rcvd_pkts; - if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) { - uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(DPDK_PKT_BURST_SIZE)); -- int32_t ret = gazelle_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)free_buf, free_cnt); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)free_buf, free_cnt); - if (likely(ret == 0)) { - nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt); - stack->rx_ring_used -= nr_pkts; --- -2.27.0 - diff --git a/0016-cfg-nic-rx-tx-queue-size-configure.patch b/0016-cfg-nic-rx-tx-queue-size-configure.patch deleted file mode 100644 index 1e62650..0000000 --- a/0016-cfg-nic-rx-tx-queue-size-configure.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 4adbb49fe002f097683c3c2155387d6fe7d59952 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 14:21:41 +0800 -Subject: [PATCH] cfg: nic rx/tx queue size configure - ---- - src/common/gazelle_opt.h | 4 ++-- - src/lstack/core/lstack_cfg.c | 20 ++++++++++++++++++++ - src/lstack/core/lstack_dpdk.c | 4 ++-- - src/lstack/include/lstack_cfg.h | 6 ++++++ - src/lstack/include/lstack_protocol_stack.h | 2 +- - src/lstack/lstack.conf | 3 +++ - 6 files changed, 34 insertions(+), 5 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 7b6aa19..7b855f9 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -42,8 +42,8 @@ - #define VDEV_TX_QUEUE_SZ DEFAULT_RING_SIZE - #define FREE_RX_QUEUE_SZ DPDK_PKT_BURST_SIZE - --#define RTE_TEST_TX_DESC_DEFAULT 2048 --#define RTE_TEST_RX_DESC_DEFAULT 4096 -+#define NIC_QUEUE_SIZE_MAX 8192 -+#define NIC_QUEUE_SIZE_MIN 512 - - #define TCP_CONN_COUNT 1500 - #define MBUF_COUNT_PER_CONN 170 -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 9fc16dd..0eca86e 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -74,6 +74,8 @@ static int32_t parse_use_bond4(void); - static int32_t parse_bond4_slave_mac(void); - static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); -+static int32_t parse_nic_rxqueue_size(void); -+static int32_t parse_nic_txqueue_size(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -131,6 +133,8 @@ static struct config_vector_t g_config_tbl[] = { - { "bond4_slave_mac", parse_bond4_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, -+ { "nic_rxqueue_size", parse_nic_rxqueue_size}, -+ { "nic_txqueue_size", parse_nic_txqueue_size}, - { NULL, NULL } - }; - -@@ -1163,3 +1167,19 @@ static int32_t parse_use_sockmap(void) - PARSE_ARG(g_config_params.use_sockmap, "use_sockmap", 0, 0, 1, ret); - return ret; - } -+ -+static int32_t parse_nic_rxqueue_size(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.nic.rxqueue_size, "nic_rxqueue_size", 4096, -+ NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -+ return ret; -+} -+ -+static int32_t parse_nic_txqueue_size(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.nic.txqueue_size, "nic_txqueue_size", 2048, -+ NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -+ return ret; -+} -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 902dadc..a53e85c 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -370,8 +370,8 @@ static struct eth_params *alloc_eth_params(uint16_t port_id, uint16_t nb_queues) - - eth_params->port_id = port_id; - eth_params->nb_queues = nb_queues; -- eth_params->nb_rx_desc = RTE_TEST_RX_DESC_DEFAULT; -- eth_params->nb_tx_desc = RTE_TEST_TX_DESC_DEFAULT; -+ eth_params->nb_rx_desc = get_global_cfg_params()->nic.rxqueue_size; -+ eth_params->nb_tx_desc = get_global_cfg_params()->nic.txqueue_size; - eth_params->conf.link_speeds = ETH_LINK_SPEED_AUTONEG; - eth_params->conf.txmode.mq_mode = ETH_MQ_TX_NONE; - eth_params->conf.rxmode.mq_mode = ETH_MQ_RX_NONE; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 52a1abd..e48a501 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -59,6 +59,11 @@ struct secondary_attach_arg { - char file_prefix[PATH_MAX]; - }; - -+struct cfg_nic_params { -+ uint32_t rxqueue_size; -+ uint32_t txqueue_size; -+}; -+ - struct cfg_params { - ip4_addr_t host_addr; - ip4_addr_t netmask; -@@ -110,6 +115,7 @@ struct cfg_params { - uint8_t bond4_slave2_mac_addr[ETHER_ADDR_LEN]; - bool use_sockmap; - bool udp_enable; -+ struct cfg_nic_params nic; - }; - - struct cfg_params *get_global_cfg_params(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index b7c18d3..a4f6ac2 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -69,7 +69,7 @@ struct protocol_stack { - uint32_t rx_ring_used; - uint32_t tx_ring_used; - -- struct rte_mbuf *pkts[RTE_TEST_RX_DESC_DEFAULT]; -+ struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX]; - struct list_node recv_list; - struct list_node same_node_recv_list; /* used for same node processes communication */ - struct list_node wakeup_list; -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index fa7e284..ad574e1 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -34,6 +34,9 @@ rpc_number = 4 - #read nic pkts number - nic_read_number = 128 - -+nic_rxqueue_size = 4096 -+nic_txqueue_size = 2048 -+ - #each cpu core start a protocol stack thread. - num_cpus="2" - --- -2.27.0 - diff --git a/0017-epoll-distinguish-add-del_sock_event-and-add-del_soc.patch b/0017-epoll-distinguish-add-del_sock_event-and-add-del_soc.patch deleted file mode 100644 index d1ec24f..0000000 --- a/0017-epoll-distinguish-add-del_sock_event-and-add-del_soc.patch +++ /dev/null @@ -1,203 +0,0 @@ -From 506a252ff94be857ab89b1c1d4aea0ef66ed9582 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 10:36:50 +0800 -Subject: [PATCH] epoll: distinguish add/del_sock_event and - add/del_sock_event_nolock - ---- - src/lstack/api/lstack_epoll.c | 59 +++++++++++++++++-------- - src/lstack/core/lstack_lwip.c | 47 ++++---------------- - src/lstack/include/posix/lstack_epoll.h | 6 +++ - 3 files changed, 56 insertions(+), 56 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 55ca4fe..7c40792 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -46,37 +46,60 @@ static void update_epoll_max_stack(struct wakeup_poll *wakeup); - static void change_epollfd_kernel_thread(struct wakeup_poll *wakeup, struct protocol_stack *old_stack, - struct protocol_stack *new_stack); - -+static inline void add_wakeup_to_stack_wakeuplist(struct wakeup_poll *wakeup, struct protocol_stack *stack) -+{ -+ if (list_is_null(&wakeup->wakeup_list[stack->stack_idx])) { -+ list_add_node(&stack->wakeup_list, &wakeup->wakeup_list[stack->stack_idx]); -+ } -+} -+ -+void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event) -+{ -+ struct wakeup_poll *wakeup = sock->wakeup; -+ -+ if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE || (event & sock->epoll_events) == 0) { -+ return; -+ } -+ sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events); -+ if (list_is_null(&sock->event_list)) { -+ list_add_node(&wakeup->event_list, &sock->event_list); -+ } -+ return; -+} -+ - void add_sock_event(struct lwip_sock *sock, uint32_t event) - { - struct wakeup_poll *wakeup = sock->wakeup; -+ struct protocol_stack *stack = sock->stack; - if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE || (event & sock->epoll_events) == 0) { - return; - } - - if (wakeup->type == WAKEUP_EPOLL) { - pthread_spin_lock(&wakeup->event_list_lock); -- -- /* app thread have read/write, event is outdated */ -- if (event == EPOLLIN && sock->conn->state != NETCONN_LISTEN && !NETCONN_IS_DATAIN(sock)) { -- pthread_spin_unlock(&wakeup->event_list_lock); -- return; -- } -- if (event == EPOLLOUT && !NETCONN_IS_OUTIDLE(sock)) { -- pthread_spin_unlock(&wakeup->event_list_lock); -- return; -- } -- -- sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events); -- if (list_is_null(&sock->event_list)) { -- list_add_node(&wakeup->event_list, &sock->event_list); -- } -+ add_sock_event_nolock(sock, event); - pthread_spin_unlock(&wakeup->event_list_lock); - } - -- struct protocol_stack *stack = sock->stack; -- if (list_is_null(&wakeup->wakeup_list[stack->stack_idx])) { -- list_add_node(&stack->wakeup_list, &wakeup->wakeup_list[stack->stack_idx]); -+ add_wakeup_to_stack_wakeuplist(wakeup, stack); -+ return; -+} -+ -+void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) -+{ -+ sock->events &= ~event; -+ -+ if (sock->events == 0) { -+ list_del_node_null(&sock->event_list); - } -+ return; -+} -+ -+void del_sock_event(struct lwip_sock *sock, uint32_t event) -+{ -+ pthread_spin_lock(&sock->wakeup->event_list_lock); -+ del_sock_event_nolock(sock, event); -+ pthread_spin_unlock(&sock->wakeup->event_list_lock); - } - - void wakeup_stack_epoll(struct protocol_stack *stack) -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 9ab8446..a98b1b8 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -317,22 +317,6 @@ void do_lwip_get_from_sendring_over(struct lwip_sock *sock) - sock->stack->stats.write_lwip_cnt++; - } - --static inline void del_data_out_event(struct lwip_sock *sock) --{ -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- -- /* check again avoid cover event add in stack thread */ -- if (!NETCONN_IS_OUTIDLE(sock)) { -- sock->events &= ~EPOLLOUT; -- -- if (sock->events == 0) { -- list_del_node_null(&sock->event_list); -- } -- } -- -- pthread_spin_unlock(&sock->wakeup->event_list_lock); --} -- - static ssize_t do_app_write(struct pbuf *pbufs[], void *buf, size_t len, uint32_t write_num) - { - ssize_t send_len = 0; -@@ -617,8 +601,9 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - wakeup->stat.app_write_cnt += write_num; - } - -- if (wakeup && wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLOUT)) { -- del_data_out_event(sock); -+ if (wakeup && wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLOUT) -+ && !NETCONN_IS_OUTIDLE(sock)) { -+ del_sock_event(sock, EPOLLOUT); - } - - END: -@@ -801,22 +786,6 @@ static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t - } - } - --static inline void del_data_in_event(struct lwip_sock *sock) --{ -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- -- /* check again avoid cover event add in stack thread */ -- if (!NETCONN_IS_DATAIN(sock)) { -- sock->events &= ~EPOLLIN; -- -- if (sock->events == 0) { -- list_del_node_null(&sock->event_list); -- } -- } -- -- pthread_spin_unlock(&sock->wakeup->event_list_lock); --} -- - /* process on same node use ring to recv data */ - ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) - { -@@ -847,8 +816,9 @@ ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, siz - - END: - /* rte_ring_count reduce lock */ -- if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN)) { -- del_data_in_event(sock); -+ if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN) -+ && (!NETCONN_IS_DATAIN(sock))) { -+ del_sock_event(sock, EPOLLIN); - } - return act_len; - } -@@ -1042,8 +1012,9 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - } - - /* rte_ring_count reduce lock */ -- if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN)) { -- del_data_in_event(sock); -+ if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLIN) -+ && (!NETCONN_IS_DATAIN(sock))) { -+ del_sock_event(sock, EPOLLIN); - } - - if (pbuf && addr && addrlen) { -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index d6c81a7..699a951 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -63,8 +63,14 @@ struct wakeup_poll { - - struct netconn; - struct lwip_sock; -+ - void add_sock_event(struct lwip_sock *sock, uint32_t event); -+void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event); -+void del_sock_event(struct lwip_sock *sock, uint32_t event); -+void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event); -+ - void wakeup_stack_epoll(struct protocol_stack *stack); -+ - int32_t lstack_epoll_create(int32_t size); - int32_t lstack_epoll_create1(int32_t flags); - int32_t lstack_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); --- -2.27.0 - diff --git a/0018-preload-support-thread-hijacking-mode.patch b/0018-preload-support-thread-hijacking-mode.patch deleted file mode 100644 index fe75ba7..0000000 --- a/0018-preload-support-thread-hijacking-mode.patch +++ /dev/null @@ -1,646 +0,0 @@ -From 7c6d623f4009ec40349504281b9af396d05418ec Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 11:36:34 +0800 -Subject: [PATCH] preload: support thread hijacking mode - ---- - src/lstack/api/lstack_wrap.c | 208 ++++++++++------------------ - src/lstack/core/lstack_cfg.c | 3 +- - src/lstack/core/lstack_init.c | 2 +- - src/lstack/core/lstack_preload.c | 114 ++++++++++++++- - src/lstack/include/lstack_preload.h | 9 ++ - 5 files changed, 202 insertions(+), 134 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 236c689..ab39a68 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -40,73 +40,15 @@ - #include "gazelle_base_func.h" - #include "lstack_thread_rpc.h" - -+#include "lstack_preload.h" -+ - #ifndef SOCK_TYPE_MASK - #define SOCK_TYPE_MASK 0xf - #endif - --enum KERNEL_LWIP_PATH { -- PATH_KERNEL = 0, -- PATH_LWIP, -- PATH_UNKNOW, --}; -- --static inline enum KERNEL_LWIP_PATH select_path(int fd, struct lwip_sock **socket) --{ -- if (unlikely(posix_api == NULL)) { -- /* -- * posix api maybe call before gazelle init -- * So, we must call posix_api_init at the head of select_path -- */ -- if (posix_api_init() != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); -- } -- return PATH_KERNEL; -- } -- -- if (unlikely(posix_api->ues_posix)) { -- return PATH_KERNEL; -- } -- -- struct lwip_sock *sock = get_socket_by_fd(fd); -- -- /* AF_UNIX case */ -- if (!sock || !sock->conn || CONN_TYPE_IS_HOST(sock->conn)) { -- return PATH_KERNEL; -- } -- -- if (socket) { -- *socket = sock; -- } -- -- if (likely(CONN_TYPE_IS_LIBOS(sock->conn))) { -- return PATH_LWIP; -- } -- -- if (NETCONN_IS_UDP(sock)) { -- return PATH_LWIP; -- } else { -- struct tcp_pcb *pcb = sock->conn->pcb.tcp; -- /* after lwip connect, call send immediately, pcb->state is SYN_SENT, need return PATH_LWIP */ -- /* pcb->state default value is CLOSED when call socket, need return PATH_UNKNOW */ -- if (pcb != NULL && pcb->state <= ESTABLISHED && pcb->state >= LISTEN) { -- return PATH_LWIP; -- } -- } -- -- return PATH_UNKNOW; --} -- - static inline int32_t do_epoll_create1(int32_t flags) - { -- if (posix_api == NULL) { -- /* posix api maybe call before gazelle init */ -- if (posix_api_init() != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); -- } -- return posix_api->epoll_create1_fn(flags); -- } -- -- if (unlikely(posix_api->ues_posix)) { -+ if (select_posix_path() == PATH_KERNEL) { - return posix_api->epoll_create1_fn(flags); - } - -@@ -115,15 +57,7 @@ static inline int32_t do_epoll_create1(int32_t flags) - - static inline int32_t do_epoll_create(int32_t size) - { -- if (posix_api == NULL) { -- /* posix api maybe call before gazelle init */ -- if (posix_api_init() != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); -- } -- return posix_api->epoll_create_fn(size); -- } -- -- if (unlikely(posix_api->ues_posix)) { -+ if (select_posix_path() == PATH_KERNEL) { - return posix_api->epoll_create_fn(size); - } - -@@ -132,7 +66,7 @@ static inline int32_t do_epoll_create(int32_t size) - - static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event) - { -- if (unlikely(posix_api->ues_posix)) { -+ if (select_posix_path() == PATH_KERNEL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -@@ -141,7 +75,7 @@ static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct - - static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { -- if (unlikely(posix_api->ues_posix)) { -+ if (select_posix_path() == PATH_KERNEL) { - return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); - } - -@@ -158,8 +92,7 @@ static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, in - - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { - return posix_api->accept_fn(s, addr, addrlen); - } - -@@ -177,8 +110,7 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - -@@ -219,22 +151,21 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - } - - struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, &sock) == PATH_KERNEL) { - return posix_api->bind_fn(s, name, namelen); - } - -- int32_t ret = posix_api->bind_fn(s, name, namelen); -- if (ret < 0) { -- /* ip is not lstack, just return */ -- if (!match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { -- return ret; -+ if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { -+ /* maybe kni addr */ -+ posix_api->bind_fn(s, name, namelen); -+ if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { -+ return stack_broadcast_bind(s, name, namelen); -+ } else { -+ return stack_single_bind(s, name, namelen); - } -- } -- -- if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { -- return stack_broadcast_bind(s, name, namelen); - } else { -- return stack_single_bind(s, name, namelen); -+ SET_CONN_TYPE_HOST(sock->conn); -+ return posix_api->bind_fn(s, name, namelen); - } - } - -@@ -299,7 +230,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - } - - struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, &sock) == PATH_KERNEL) { - return posix_api->connect_fn(s, name, namelen); - } - -@@ -309,6 +240,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - } - - if (!netconn_is_nonblocking(sock->conn)) { -+ LSTACK_LOG(ERR, LSTACK, "connect does not support blocking fd currently\n"); - GAZELLE_RETURN(EINVAL); - } - -@@ -330,8 +262,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - - static inline int32_t do_listen(int32_t s, int32_t backlog) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { - return posix_api->listen_fn(s, backlog); - } - -@@ -355,8 +286,7 @@ static inline int32_t do_getpeername(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP) { -+ if (select_fd_posix_path(s, NULL) == PATH_LWIP) { - return rpc_call_getpeername(s, name, namelen); - } - -@@ -369,8 +299,7 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP) { -+ if (select_fd_posix_path(s, NULL) == PATH_LWIP) { - return rpc_call_getsockname(s, name, namelen); - } - -@@ -391,8 +320,7 @@ static bool unsupport_optname(int32_t optname) - - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP && !unsupport_optname(optname)) { -+ if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(optname)) { - return rpc_call_getsockopt(s, level, optname, optval, optlen); - } - -@@ -401,8 +329,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v - - static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, const void *optval, socklen_t optlen) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL || unsupport_optname(optname)) { -+ if (select_fd_posix_path(s, NULL) == PATH_KERNEL || unsupport_optname(optname)) { - return posix_api->setsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -417,13 +344,27 @@ static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, c - - static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - { -- if ((domain != AF_INET && domain != AF_UNSPEC) -- || ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable) -- || posix_api->ues_posix) { -+ int32_t ret; -+ /* process not init completed or not hajacking thread */ -+ if (select_posix_path() == PATH_KERNEL) { -+ return posix_api->socket_fn(domain, type, protocol); -+ } -+ -+ if ((domain != AF_INET && domain != AF_UNSPEC) || -+ ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)) { - return posix_api->socket_fn(domain, type, protocol); - } - -- return rpc_call_socket(domain, type, protocol); -+ ret = rpc_call_socket(domain, type, protocol); -+ /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */ -+ if ((ret >= 0) && (type & SOCK_DGRAM)) { -+ struct lwip_sock *sock = get_socket(ret); -+ if (sock != NULL && sock->conn != NULL) { -+ SET_CONN_TYPE_LIBOS(sock->conn); -+ } -+ } -+ -+ return ret; - } - - static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t flags) -@@ -436,12 +377,12 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - return 0; - } - -- struct lwip_sock *sock = NULL; -- if (select_path(sockfd, &sock) == PATH_LWIP) { -- return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); -+ if (select_posix_path() == PATH_KERNEL || // maybe fd is created by open before posix_api_init called -+ select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) { -+ return posix_api->recv_fn(sockfd, buf, len, flags); - } - -- return posix_api->recv_fn(sockfd, buf, len, flags); -+ return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); - } - - static inline ssize_t do_read(int32_t s, void *mem, size_t len) -@@ -454,17 +395,18 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - return 0; - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP) { -- return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ return posix_api->read_fn(s, mem, len); - } -- return posix_api->read_fn(s, mem, len); -+ -+ return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); - } - - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) != PATH_LWIP) { -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, NULL) == PATH_KERNEL) { - return posix_api->readv_fn(s, iov, iovcnt); - } - -@@ -487,8 +429,8 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) - { -- struct lwip_sock *sock = NULL; -- if (select_path(sockfd, &sock) != PATH_LWIP) { -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) { - return posix_api->send_fn(sockfd, buf, len, flags); - } - -@@ -497,8 +439,8 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) != PATH_LWIP) { -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, NULL) == PATH_KERNEL) { - return posix_api->write_fn(s, mem, size); - } - -@@ -507,8 +449,9 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - { -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) != PATH_LWIP) { -+ struct lwip_sock *sock; -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, &sock) == PATH_KERNEL) { - return posix_api->writev_fn(s, iov, iovcnt); - } - -@@ -530,12 +473,12 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP) { -- return do_lwip_recvmsg_from_stack(s, message, flags); -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ return posix_api->recv_msg(s, message, flags); - } - -- return posix_api->recv_msg(s, message, flags); -+ return do_lwip_recvmsg_from_stack(s, message, flags); - } - - static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags) -@@ -544,12 +487,13 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_LWIP) { -- return do_lwip_sendmsg_to_stack(sock, s, message, flags); -+ struct lwip_sock *sock; -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ return posix_api->send_msg(s, message, flags); - } - -- return posix_api->send_msg(s, message, flags); -+ return do_lwip_sendmsg_to_stack(sock, s, message, flags); - } - - static inline ssize_t udp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void *buf, size_t len, int32_t flags, -@@ -596,7 +540,7 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t - } - - struct lwip_sock *sock = NULL; -- if (select_path(sockfd, &sock) == PATH_LWIP) { -+ if (select_fd_posix_path(sockfd, &sock) == PATH_LWIP) { - if (NETCONN_IS_UDP(sock)) { - return udp_recvfrom(sock, sockfd, buf, len, flags, addr, addrlen); - } else { -@@ -611,7 +555,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - const struct sockaddr *addr, socklen_t addrlen) - { - struct lwip_sock *sock = NULL; -- if (select_path(sockfd, &sock) != PATH_LWIP) { -+ if (select_fd_posix_path(sockfd, &sock) != PATH_LWIP) { - return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen); - } - -@@ -621,7 +565,8 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - static inline int32_t do_close(int32_t s) - { - struct lwip_sock *sock = NULL; -- if (select_path(s, &sock) == PATH_KERNEL) { -+ if (select_posix_path() == PATH_KERNEL || -+ select_fd_posix_path(s, &sock) == PATH_KERNEL) { - /* we called lwip_socket, even if kernel fd */ - if (posix_api != NULL && !posix_api->ues_posix && - /* contain posix_api->close_fn if success */ -@@ -639,7 +584,7 @@ static inline int32_t do_close(int32_t s) - - static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { -- if (unlikely(posix_api->ues_posix) || fds == NULL || nfds == 0) { -+ if ((select_posix_path() == PATH_KERNEL) || fds == NULL || nfds == 0) { - return posix_api->poll_fn(fds, nfds, timeout); - } - -@@ -684,7 +629,8 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - val = va_arg(ap, typeof(val)); \ - va_end(ap); \ - struct lwip_sock *sock = NULL; \ -- if (select_path(_fd, &sock) == PATH_KERNEL) \ -+ if (select_posix_path() == PATH_KERNEL || \ -+ select_fd_posix_path(_fd, &sock) == PATH_KERNEL) \ - return _fcntl_fn(_fd, _cmd, val); \ - int32_t ret = _fcntl_fn(_fd, _cmd, val); \ - if (ret == -1) \ -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0eca86e..189459a 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -223,7 +223,8 @@ static int32_t parse_host_addr(void) - int32_t match_host_addr(uint32_t addr) - { - /* network byte order */ -- if (addr == g_config_params.host_addr.addr) { -+ if (addr == g_config_params.host_addr.addr || -+ addr == INADDR_ANY) { - return 1; - } - return 0; -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 2183e3a..b6e9bf1 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -285,7 +285,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - - if (stack_thread_setup() != 0) { -- LSTACK_EXIT(1, "stack_init_in_setup failed\n"); -+ LSTACK_EXIT(1, "stack_thread_setup failed\n"); - } - - /* lwip initialization */ -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index e3a98fc..1d68501 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -12,8 +12,13 @@ - #include - #include - #include -+#define __USE_GNU -+#include -+#include - --#include "securec.h" -+#include -+#include -+#include - - #include "lstack_log.h" - #include "lstack_preload.h" -@@ -22,10 +27,17 @@ - #define LSTACK_SO_NAME "liblstack.so" - #define LSTACK_PRELOAD_NAME_LEN PATH_MAX - #define LSTACK_PRELOAD_ENV_PROC "GAZELLE_BIND_PROCNAME" -+#define LSTACK_PRELOAD_ENV_THRD "GAZELLE_THREAD_NAME" -+ -+#define EXCLUDE_THRD_CNT 1 -+const static char *g_exclude_thread[EXCLUDE_THRD_CNT] = {"eal-intr-thread"}; -+static PER_THREAD enum KERNEL_LWIP_PATH g_preload_thrdpath = PATH_UNKNOW; - - struct lstack_preload { - int32_t preload_switch; - char env_procname[LSTACK_PRELOAD_NAME_LEN]; -+ bool get_thrdname; -+ char env_thrdname[LSTACK_PRELOAD_NAME_LEN]; - }; - static struct lstack_preload g_preload_info = {0}; - -@@ -52,12 +64,104 @@ static int32_t preload_check_bind_proc(void) - return -1; - } - -+static void preload_get_thrdname(void) -+{ -+ g_preload_info.get_thrdname = true; -+ -+ char *enval = NULL; -+ enval = getenv(LSTACK_PRELOAD_ENV_THRD); -+ if (enval == NULL) { -+ return; -+ } -+ if (strcpy_s(g_preload_info.env_thrdname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) { -+ return; -+ } -+ -+ LSTACK_PRE_LOG(LSTACK_INFO, "thread name=%s ok\n", g_preload_info.env_thrdname); -+} -+ -+enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(fd); -+ -+ /* AF_UNIX case */ -+ if (!sock || !sock->conn || CONN_TYPE_IS_HOST(sock->conn)) { -+ return PATH_KERNEL; -+ } -+ -+ if (socket) { -+ *socket = sock; -+ } -+ -+ if (likely(CONN_TYPE_IS_LIBOS(sock->conn))) { -+ return PATH_LWIP; -+ } -+ -+ return PATH_UNKNOW; -+} -+ -+enum KERNEL_LWIP_PATH select_posix_path(void) -+{ -+ if (unlikely(posix_api == NULL)) { -+ /* -+ * posix api maybe call before gazelle init -+ * So, we must call posix_api_init at the head of select_path -+ */ -+ if (posix_api_init() != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); -+ } -+ return PATH_KERNEL; -+ } -+ -+ if (unlikely(posix_api->ues_posix)) { -+ return PATH_KERNEL; -+ } -+ -+ if (g_preload_thrdpath != PATH_UNKNOW) { -+ return g_preload_thrdpath; -+ } -+ -+ if (!g_preload_info.get_thrdname) { -+ preload_get_thrdname(); -+ } -+ -+ char thread_name[PATH_MAX] = {0}; -+ if (pthread_getname_np(pthread_self(), thread_name, PATH_MAX) != 0) { -+ g_preload_thrdpath = PATH_KERNEL; -+ return PATH_KERNEL; -+ } -+ -+ /* exclude dpdk thread */ -+ for (int i = 0; i < EXCLUDE_THRD_CNT; i++) { -+ if (strstr(thread_name, g_exclude_thread[i]) != NULL) { -+ g_preload_thrdpath = PATH_KERNEL; -+ return PATH_KERNEL; -+ } -+ } -+ -+ /* not set GAZELLE_THREAD_NAME, select all thread */ -+ if (g_preload_info.env_thrdname[0] == '\0') { -+ g_preload_thrdpath = PATH_LWIP; -+ return PATH_LWIP; -+ } -+ -+ if (strstr(thread_name, g_preload_info.env_thrdname) == NULL) { -+ g_preload_thrdpath = PATH_KERNEL; -+ return PATH_KERNEL; -+ } -+ -+ g_preload_thrdpath = PATH_LWIP; -+ return PATH_LWIP; -+} -+ - int preload_info_init(void) - { - char *enval = NULL; - - g_preload_info.preload_switch = 0; - -+ preload_get_thrdname(); -+ - enval = getenv(LSTACK_PRELOAD_ENV_SYS); - if (enval == NULL) { - return 0; -@@ -75,6 +179,14 @@ int preload_info_init(void) - return -1; - } - -+ enval = getenv(LSTACK_PRELOAD_ENV_THRD); -+ if (enval != NULL) { -+ if (strcpy_s(g_preload_info.env_thrdname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) { -+ return -1; -+ } -+ g_preload_info.get_thrdname = true; -+ } -+ - g_preload_info.preload_switch = 1; - LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); - return preload_check_bind_proc(); -diff --git a/src/lstack/include/lstack_preload.h b/src/lstack/include/lstack_preload.h -index 4ba6525..0ad7877 100644 ---- a/src/lstack/include/lstack_preload.h -+++ b/src/lstack/include/lstack_preload.h -@@ -11,6 +11,15 @@ - */ - #ifndef __LSTACK_PRELOAD_H__ - #define __LSTACK_PRELOAD_H__ -+#include - -+enum KERNEL_LWIP_PATH { -+ PATH_KERNEL = 0, -+ PATH_LWIP, -+ PATH_UNKNOW, -+}; -+ -+enum KERNEL_LWIP_PATH select_posix_path(void); -+enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket); - int preload_info_init(void); - #endif --- -2.23.0 - diff --git a/0019-cfg-add-run-to-completion-mode-configure.patch b/0019-cfg-add-run-to-completion-mode-configure.patch deleted file mode 100644 index b11a79d..0000000 --- a/0019-cfg-add-run-to-completion-mode-configure.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 3208a2f1ada7c8c388bdea356d38c9edef1e05dd Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 8 Oct 2023 19:48:45 +0800 -Subject: [PATCH] cfg: add run-to-completion mode configure - ---- - src/lstack/core/lstack_cfg.c | 30 ++++++++++++++++++++++++++++++ - src/lstack/include/lstack_cfg.h | 1 + - src/lstack/lstack.conf | 2 ++ - 3 files changed, 33 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0eca86e..951e6e8 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -76,6 +76,7 @@ static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); - static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); -+static int32_t parse_stack_thread_mode(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -135,6 +136,7 @@ static struct config_vector_t g_config_tbl[] = { - { "udp_enable", parse_udp_enable }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, -+ { "stack_thread_mode", parse_stack_thread_mode }, - { NULL, NULL } - }; - -@@ -1183,3 +1185,31 @@ static int32_t parse_nic_txqueue_size(void) - NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); - return ret; - } -+ -+static int32_t parse_stack_thread_mode(void) -+{ -+ const config_setting_t *thread_mode = NULL; -+ const char *args = NULL; -+ -+ thread_mode = config_lookup(&g_config, "stack_thread_mode"); -+ if (thread_mode == NULL) { -+ g_config_params.stack_mode_rtc = false; -+ return 0; -+ } -+ -+ args = config_setting_get_string(thread_mode); -+ if (args == NULL) { -+ return -EINVAL; -+ } -+ -+ if (strncmp(args, "run-to-completion", strlen("run-to-completion") + 1) == 0) { -+ g_config_params.stack_mode_rtc = true; -+ } else if (strncmp(args, "run-to-wakeup", strlen("run-to-wakeup") + 1) == 0) { -+ g_config_params.stack_mode_rtc = false; -+ } else { -+ LSTACK_LOG(ERR, LSTACK, "stack_mode_rtc only support run-to-completion or run-to-wakeup\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index e48a501..1d895ec 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -116,6 +116,7 @@ struct cfg_params { - bool use_sockmap; - bool udp_enable; - struct cfg_nic_params nic; -+ bool stack_mode_rtc; - }; - - struct cfg_params *get_global_cfg_params(void); -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index ad574e1..48973fe 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -10,6 +10,8 @@ - - dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] - -+stack_thread_mode="run-to-wakeup" -+ - use_ltran=1 - kni_switch=0 - --- -2.23.0 - diff --git a/0020-statck-the-for-loop-in-lstack-thread-is-defined-as-s.patch b/0020-statck-the-for-loop-in-lstack-thread-is-defined-as-s.patch deleted file mode 100644 index 0e11592..0000000 --- a/0020-statck-the-for-loop-in-lstack-thread-is-defined-as-s.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 71defaec9e10ee23bf9b3e01989dac4feab94d82 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 10:28:30 +0800 -Subject: [PATCH] statck: the for loop in lstack thread is defined as - stack_polling - ---- - src/lstack/core/lstack_protocol_stack.c | 85 ++++++++++++---------- - src/lstack/include/lstack_protocol_stack.h | 1 + - 2 files changed, 49 insertions(+), 37 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 09cba14..ea85bc1 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -432,18 +432,60 @@ END: - return NULL; - } - --static void* gazelle_stack_thread(void *arg) -+void stack_polling(uint32_t wakeup_tick) - { -- struct thread_params *t_params = (struct thread_params*) arg; -- -- uint16_t queue_id = t_params->queue_id; - struct cfg_params *cfg = get_global_cfg_params(); - uint8_t use_ltran_flag = cfg->use_ltran; - bool kni_switch = cfg->kni_switch; - bool use_sockmap = cfg->use_sockmap; -- uint32_t read_connect_number = cfg->read_connect_number; -+ bool stack_mode_rtc = cfg->stack_mode_rtc; - uint32_t rpc_number = cfg->rpc_number; - uint32_t nic_read_number = cfg->nic_read_number; -+ uint32_t read_connect_number = cfg->read_connect_number; -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ poll_rpc_msg(stack, rpc_number); -+ gazelle_eth_dev_poll(stack, use_ltran_flag, nic_read_number); -+ sys_timer_run(); -+ if (cfg->low_power_mod != 0) { -+ low_power_idling(stack); -+ } -+ -+ if (stack_mode_rtc) { -+ return; -+ } -+ -+ do_lwip_read_recvlist(stack, read_connect_number); -+ if ((wakeup_tick & 0xf) == 0) { -+ wakeup_stack_epoll(stack); -+ } -+ -+ /* run to completion mode currently does not support sockmap */ -+ if (use_sockmap) { -+ netif_poll(&stack->netif); -+ /* reduce traversal times */ -+ if ((wakeup_tick & 0xff) == 0) { -+ read_same_node_recv_list(stack); -+ } -+ } -+ -+ /* run to completion mode currently does not support kni */ -+ /* KNI requests are generally low-rate I/Os, -+ * so processing KNI requests only in the thread with queue_id No.0 is sufficient. */ -+ if (kni_switch && !stack->queue_id && !(wakeup_tick & 0xfff)) { -+ rte_kni_handle_request(get_gazelle_kni()); -+ if (get_kni_started()) { -+ kni_handle_rx(get_port_id()); -+ } -+ } -+ return; -+} -+ -+static void* gazelle_stack_thread(void *arg) -+{ -+ struct thread_params *t_params = (struct thread_params*) arg; -+ -+ uint16_t queue_id = t_params->queue_id; - uint32_t wakeup_tick = 0; - - struct protocol_stack *stack = stack_thread_init(arg); -@@ -461,39 +503,8 @@ static void* gazelle_stack_thread(void *arg) - LSTACK_LOG(INFO, LSTACK, "stack_%02hu init success\n", queue_id); - - for (;;) { -- poll_rpc_msg(stack, rpc_number); -- -- gazelle_eth_dev_poll(stack, use_ltran_flag, nic_read_number); -- -- if (use_sockmap) { -- netif_poll(&stack->netif); -- /* reduce traversal times */ -- if ((wakeup_tick & 0xff) == 0) { -- read_same_node_recv_list(stack); -- } -- } -- do_lwip_read_recvlist(stack, read_connect_number); -- -- if ((wakeup_tick & 0xf) == 0) { -- wakeup_stack_epoll(stack); -- } -- -- /* KNI requests are generally low-rate I/Os, -- * so processing KNI requests only in the thread with queue_id No.0 is sufficient. */ -- if (kni_switch && !queue_id && !(wakeup_tick & 0xfff)) { -- rte_kni_handle_request(get_gazelle_kni()); -- if (get_kni_started()) { -- kni_handle_rx(get_port_id()); -- } -- } -- -+ stack_polling(wakeup_tick); - wakeup_tick++; -- -- sys_timer_run(); -- -- if (cfg->low_power_mod != 0) { -- low_power_idling(stack); -- } - } - - return NULL; -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index a4f6ac2..7cb37bf 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -167,5 +167,6 @@ void stack_replenish_sendring(struct rpc_msg *msg); - void stack_get_conntable(struct rpc_msg *msg); - void stack_get_connnum(struct rpc_msg *msg); - void stack_recvlist_count(struct rpc_msg *msg); -+void stack_polling(uint32_t wakeup_tick); - void kni_handle_tx(struct rte_mbuf *mbuf); - #endif --- -2.27.0 - diff --git a/0021-delete_rule-bug.patch b/0021-delete_rule-bug.patch deleted file mode 100644 index a78f1f0..0000000 --- a/0021-delete_rule-bug.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 09c2b39b22397272668e49060e5f3e3b50fd40b4 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Fri, 20 Oct 2023 09:52:11 +0800 -Subject: [PATCH] delete_rule bug - ---- - src/lstack/netif/lstack_ethdev.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 30c3c9a..6e4c9de 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -189,7 +189,7 @@ void delete_rule(char* rule_key) - { - struct flow_rule *rule = NULL; - HASH_FIND_STR(g_flow_rules, rule_key, rule); -- if (rule == NULL) { -+ if (rule != NULL) { - HASH_DEL(g_flow_rules, rule); - free(rule); - } --- -2.27.0 - diff --git a/0022-tools-gazelle_setup-adapt-non-ltran-mode.patch b/0022-tools-gazelle_setup-adapt-non-ltran-mode.patch deleted file mode 100644 index 539d25d..0000000 --- a/0022-tools-gazelle_setup-adapt-non-ltran-mode.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 1ebdb7124823835cd29d62c8a81a0b8010c1d754 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Fri, 20 Oct 2023 19:44:52 +0800 -Subject: [PATCH] tools: gazelle_setup adapt non ltran mode - ---- - tools/gazelle_common.sh | 40 ++++++++++++++++++++-------------------- - tools/gazelle_setup.sh | 38 ++++++++++++++++++-------------------- - 2 files changed, 38 insertions(+), 40 deletions(-) - -diff --git a/tools/gazelle_common.sh b/tools/gazelle_common.sh -index b4c011a..fac0d68 100644 ---- a/tools/gazelle_common.sh -+++ b/tools/gazelle_common.sh -@@ -231,18 +231,18 @@ install_nic_mod() { - } - - create_mnt_huge() { -- msg_show "Creating /mnt/hugepages and mounting as hugetlbfs" -- sudo mkdir -p /mnt/hugepages -- sudo mkdir -p /mnt/hugepages-2M -+ msg_show "Creating /mnt/hugepages-ltran and mounting as hugetlbfs" -+ sudo mkdir -p /mnt/hugepages-ltran -+ sudo mkdir -p /mnt/hugepages-lstack - -- grep -s "/mnt/hugepages " /proc/mounts > /dev/null -+ grep -s "/mnt/hugepages-ltran " /proc/mounts > /dev/null - if [ $? -ne 0 ]; then -- sudo mount -t hugetlbfs nodev /mnt/hugepages -+ sudo mount -t hugetlbfs nodev /mnt/hugepages-ltran - fi - -- grep -s "/mnt/hugepages-2M " /proc/mounts > /dev/null -+ grep -s "/mnt/hugepages-lstack " /proc/mounts > /dev/null - if [ $? -ne 0 ]; then -- sudo mount -t hugetlbfs nodev /mnt/hugepages-2M -+ sudo mount -t hugetlbfs nodev /mnt/hugepages-lstack - fi - } - -@@ -285,21 +285,21 @@ set_numa_pages() { - - # Removes all reserved hugepages. - clear_huge_pages() { -- msg_show "Unmounting /mnt/hugepages and removing directory" -- grep -s "/mnt/hugepages " /proc/mounts > /dev/null -+ msg_show "Unmounting /mnt/hugepages-ltran and removing directory" -+ grep -s "/mnt/hugepages-ltran " /proc/mounts > /dev/null - if [ $? -eq 0 ]; then -- sudo umount /mnt/hugepages -+ sudo umount /mnt/hugepages-ltran - if [ $? -ne 0 ]; then -- msg_err "sudo umount /mnt/hugepages failed!" -+ msg_err "sudo umount /mnt/hugepages-ltran failed!" - return 1 - fi - fi - -- grep -s "/mnt/hugepages-2M " /proc/mounts > /dev/null -+ grep -s "/mnt/hugepages-lstack " /proc/mounts > /dev/null - if [ $? -eq 0 ]; then -- sudo umount /mnt/hugepages-2M -+ sudo umount /mnt/hugepages-lstack - if [ $? -ne 0 ]; then -- msg_err "sudo umount /mnt/hugepages-2M failed!" -+ msg_err "sudo umount /mnt/hugepages-lstack failed!" - return 1 - fi - fi -@@ -312,17 +312,17 @@ clear_huge_pages() { - sudo sh .echo_tmp - rm -f .echo_tmp - -- if [ -d /mnt/hugepages ]; then -- sudo rm -R /mnt/hugepages -+ if [ -d /mnt/hugepages-ltran ]; then -+ sudo rm -R /mnt/hugepages-ltran - if [ $? -ne 0 ]; then -- msg_err "sudo rm -R /mnt/hugepages failed!" -+ msg_err "sudo rm -R /mnt/hugepages-ltran failed!" - return 1 - fi - fi -- if [ -d /mnt/hugepages-2M ]; then -- sudo rm -R /mnt/hugepages-2M -+ if [ -d /mnt/hugepages-lstack ]; then -+ sudo rm -R /mnt/hugepages-lstack - if [ $? -ne 0 ]; then -- msg_err "sudo rm -R /mnt/hugepages failed!" -+ msg_err "sudo rm -R /mnt/hugepages-lstack failed!" - return 1 - fi - fi -diff --git a/tools/gazelle_setup.sh b/tools/gazelle_setup.sh -index 014d333..c3ad830 100644 ---- a/tools/gazelle_setup.sh -+++ b/tools/gazelle_setup.sh -@@ -66,8 +66,10 @@ show_usage() { - echo " [-l|--lowpower=]" - echo " [--ltrancore=]" - echo " [--lstackcore=]" -+ echo " [--useltran=]" -+ echo " [--listenshadow=]" - echo "examples:" -- echo " $0 -i eth0 -n 1024,1024 -d 1/0 -k 1/0 -l 1/0 --ltrancore 0,1 --lstackcore 2-3" -+ echo " $0 -i eth0 -n 1024,1024 -d 1/0 -k 1/0 -l 1/0 --ltrancore 0,1 --lstackcore 2-3 --useltran 0/1 --listenshadow 0/1" - } - - check_init() { -@@ -155,14 +157,13 @@ check_args() { - g_low_power=${g_low_power:-0} - check_switch_param $g_low_power - ret=$(($? + ret)) -- g_useltran=${g_useltran:-1} -+ g_useltran=${g_useltran:-0} - check_switch_param $g_useltran -- g_listen_shadow=${g_listen_shadow:-0} -+ g_listen_shadow=${g_listen_shadow:-1} - check_switch_param $g_listen_shadow - ret=$(($? + ret)) - g_ltrancore=${g_ltrancore:-0,1} - g_lstackcore=${g_lstackcore:-2} -- g_wakeupcpus=${g_lstackcore} - if [ $ret -eq 0 ]; then - msg_show "the args is reasonable..." - else -@@ -278,6 +279,12 @@ gen_lstack_conf() { - sed -i "/^gateway_addr/c gateway_addr=\"$g_gateway\"" $CONF_DIR/lstack.conf - sed -i "/^devices/c devices=\"$g_kni_mac\"" $CONF_DIR/lstack.conf - -+ if [ ${g_useltran} -eq 0 ]; then -+ sed -i "/^kni_switch/c kni_switch = $g_kni_switch" $CONF_DIR/lstack.conf -+ else -+ sed -i "/^kni_switch/c kni_switch = 0" $CONF_DIR/lstack.conf -+ fi -+ - shadow_exist=$(grep listen_shadow $CONF_DIR/lstack.conf) - if [ -n "${shadow_exist}" ];then - sed -i "/^listen_shadow/c listen_shadow = $g_listen_shadow" $CONF_DIR/lstack.conf -@@ -289,20 +296,15 @@ gen_lstack_conf() { - local old_lstackcore=$(grep num_cpus $CONF_DIR/lstack.conf | awk -F= '{print $2}' | awk -F "\"" '{print $2}') - sed -i "/^num_cpus/s/${old_lstackcore}/${g_lstackcore}/" $CONF_DIR/lstack.conf - -- # wakeup_cpus -- local old_wakeupcpus=$(grep wakeup_cpus $CONF_DIR/lstack.conf | awk -F= '{print $2}' | awk -F "\"" '{print $2}') -- if [ -n "${g_wakeupcpus}" ]; then -- sed -i "/^wakeup_cpus/s/${old_wakeupcpus}/${g_wakeupcpus}/" $CONF_DIR/lstack.conf -- fi -- - local old_numa=$(grep dpdk_args $CONF_DIR/lstack.conf | awk -F "-socket-mem" '{print $2}' | awk '{print $2}' | awk -F "\"" '{print $2}') - old_numa="\"${old_numa}\"," - sed -i "/^dpdk_args/s/${old_numa}/\"${g_hugepages}\",/" $CONF_DIR/lstack.conf - local cpu_count=$(parse_cpu_count ${g_lstackcore}) -- local mbuf_pool_size=$(expr 200000 \* ${cpu_count} + 8192) -- sed -i "/^mbuf_pool_size/c mbuf_pool_size=${mbuf_pool_size}" $CONF_DIR/lstack.conf -+ tcp_conn_count=1500 -+ mbuf_count_per_conn=$(expr 170 \* ${cpu_count}) - -- # export LSTACK_CONF_PATH=$CONF_DIR/lstack.conf -+ sed -i "/^tcp_conn_count/c tcp_conn_count=${tcp_conn_count}" $CONF_DIR/lstack.conf -+ sed -i "/^mbuf_count_per_conn/c mbuf_count_per_conn=${mbuf_count_per_conn}" $CONF_DIR/lstack.conf - } - - gen_run_param() { -@@ -399,10 +401,6 @@ while true; do - g_lstackcore=$2 - shift 2 - ;; -- --wakeupcpus) -- g_wakeupcpus=$2 -- shift 2 -- ;; - -h | --help) - show_usage - shift 1 -@@ -458,8 +456,8 @@ gen_run_param - msg_show "-----------------" - msg_show "start dpdk" - setup_dpdk --__chown /mnt/hugepages --__chown /mnt/hugepages-2M -+__chown /mnt/hugepages-ltran -+__chown /mnt/hugepages-lstack - - ############################################## - # generate the conf file -@@ -504,7 +502,7 @@ fi - ############################################## - # start ltran - if [ $g_useltran -eq 0 ];then -- msg_show "only gen lstack conf" -+ msg_show "gen lstack conf success" - exit 0 - fi - msg_show "start ltran on $g_conn_if" --- -2.27.0 - diff --git a/0023-wrap-add-run-to-completion-wakeup-mode-api.patch b/0023-wrap-add-run-to-completion-wakeup-mode-api.patch deleted file mode 100644 index cbdb864..0000000 --- a/0023-wrap-add-run-to-completion-wakeup-mode-api.patch +++ /dev/null @@ -1,993 +0,0 @@ -From 476b225bc50737678223fa29757b0ac08f1a500d Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 8 Oct 2023 20:59:57 +0800 -Subject: [PATCH] wrap: add run-to-completion/wakeup mode api - ---- - src/lstack/api/dir.mk | 2 +- - src/lstack/api/lstack_rtc_api.c | 72 ++++++ - src/lstack/api/lstack_rtw_api.c | 239 ++++++++++++++++++ - src/lstack/api/lstack_wrap.c | 206 +++++++-------- - src/lstack/core/lstack_init.c | 3 + - src/lstack/core/lstack_lwip.c | 2 +- - src/lstack/include/lstack_lwip.h | 2 +- - .../lstack_socket.h => lstack_rtc_api.h} | 59 +++-- - src/lstack/include/lstack_rtw_api.h | 47 ++++ - src/lstack/include/lstack_wrap.h | 19 ++ - 10 files changed, 514 insertions(+), 137 deletions(-) - create mode 100644 src/lstack/api/lstack_rtc_api.c - create mode 100644 src/lstack/api/lstack_rtw_api.c - rename src/lstack/include/{posix/lstack_socket.h => lstack_rtc_api.h} (53%) - create mode 100644 src/lstack/include/lstack_rtw_api.h - create mode 100644 src/lstack/include/lstack_wrap.h - -diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk -index f5370a2..ffbb137 100644 ---- a/src/lstack/api/dir.mk -+++ b/src/lstack/api/dir.mk -@@ -8,7 +8,7 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c -+SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c - - $(eval $(call register_dir, api, $(SRC))) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -new file mode 100644 -index 0000000..b7c6380 ---- /dev/null -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -0,0 +1,72 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "posix/lstack_epoll.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_rtc_api.h" -+ -+int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) -+{ -+ return -1; -+} -+ -+int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+{ -+ return -1; -+} -+ -+int rtc_socket(int domain, int type, int protocol) -+{ -+ int ret; -+ -+ /* need call stack thread init function */ -+ ret = lwip_socket(domain, type, protocol); -+ struct lwip_sock *sock = get_socket(ret); -+ if (sock != NULL) { -+ sock->stack = get_protocol_stack(); -+ sock->epoll_events = 0; -+ sock->events = 0; -+ sock->wakeup = NULL; -+ init_list_node_null(&sock->event_list); -+ } -+ return ret; -+} -+ -+int rtc_close(int s) -+{ -+ return lwip_close(s); -+} -+ -+int rtc_epoll_create(int flags) -+{ -+ /* need call stack thread init function */ -+ return lstack_epoll_create(flags); -+} -+ -+int rtc_epoll_create1(int flags) -+{ -+ /* need call stack thread init function */ -+ return lstack_epoll_create1(flags); -+} -+ -+int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -+{ -+ return lstack_epoll_ctl(epfd, op, fd, event); -+} -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -new file mode 100644 -index 0000000..9b8678a ---- /dev/null -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -0,0 +1,239 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "lstack_thread_rpc.h" -+#include "posix/lstack_epoll.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_cfg.h" -+#include "lstack_lwip.h" -+#include "lstack_rtw_api.h" -+ -+int rtw_socket(int domain, int type, int protocol) -+{ -+ return rpc_call_socket(domain, type, protocol); -+} -+ -+int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ return stack_broadcast_accept(s, addr, addrlen); -+} -+ -+int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ return stack_broadcast_accept4(s, addr, addrlen, flags); -+} -+ -+int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(s); -+ -+ if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { -+ return stack_broadcast_bind(s, name, namelen); -+ } else { -+ return stack_single_bind(s, name, namelen); -+ } -+} -+ -+int rtw_listen(int s, int backlog) -+{ -+ if (!get_global_cfg_params()->tuple_filter && -+ !get_global_cfg_params()->listen_shadow) { -+ return stack_single_listen(s, backlog); -+ } else { -+ return stack_broadcast_listen(s, backlog); -+ } -+} -+ -+int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) -+{ -+ return rpc_call_connect(s, name, namelen); -+} -+ -+int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -+{ -+ return rpc_call_setsockopt(s, level, optname, optval, optlen); -+} -+ -+int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -+{ -+ return rpc_call_getsockopt(s, level, optname, optval, optlen); -+} -+ -+int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -+{ -+ return rpc_call_getpeername(s, name, namelen); -+} -+ -+int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -+{ -+ return rpc_call_getsockname(s, name, namelen); -+} -+ -+ssize_t rtw_read(int s, void *mem, size_t len) -+{ -+ return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); -+} -+ -+ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) -+{ -+ struct msghdr msg; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -+ msg.msg_iovlen = iovcnt; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ ssize_t result = do_lwip_recvmsg_from_stack(s, &msg, 0); -+ if (result == -1 && errno == EAGAIN) { -+ errno = 0; -+ return 0; -+ } -+ return result; -+} -+ -+ssize_t rtw_write(int s, const void *mem, size_t size) -+{ -+ return do_lwip_send_to_stack(s, mem, size, 0, NULL, 0); -+} -+ -+ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(s); -+ struct msghdr msg; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -+ msg.msg_iovlen = iovcnt; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ return do_lwip_sendmsg_to_stack(sock, s, &msg, 0); -+} -+ -+ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags) -+{ -+ return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); -+} -+ -+ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags) -+{ -+ return do_lwip_send_to_stack(sockfd, buf, len, flags, NULL, 0); -+} -+ -+ssize_t rtw_recvmsg(int s, const struct msghdr *message, int flags) -+{ -+ return do_lwip_recvmsg_from_stack(s, message, flags); -+} -+ -+ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(s); -+ return do_lwip_sendmsg_to_stack(sock, s, message, flags); -+} -+ -+static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, -+ struct sockaddr *addr, socklen_t *addrlen) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(sockfd); -+ int ret; -+ -+ while (1) { -+ ret = do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -+ if (ret > 0) { -+ return ret; -+ } -+ if (ret <= 0 && errno != EAGAIN) { -+ return -1; -+ } -+ sock = sock->listen_next; -+ if (sock != NULL && sock->conn != NULL) { -+ sockfd = sock->conn->socket; -+ } else { -+ if (sock == NULL) { -+ errno = EAGAIN; -+ return -1; -+ } else { -+ errno = ENOTCONN; -+ return -1; -+ } -+ } -+ } -+} -+ -+static inline ssize_t rtw_tcp_recvfrom(int sockfd, void *buf, size_t len, int flags, -+ struct sockaddr *addr, socklen_t *addrlen) -+{ -+ return do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -+} -+ -+ -+ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -+ struct sockaddr *addr, socklen_t *addrlen) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(sockfd); -+ if (NETCONN_IS_UDP(sock)) { -+ return rtw_udp_recvfrom(sockfd, buf, len, flags, addr, addrlen); -+ } else { -+ return rtw_tcp_recvfrom(sockfd, buf, len, flags, addr, addrlen); -+ } -+} -+ -+ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen) -+{ -+ return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); -+} -+ -+ -+int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+{ -+ return lstack_epoll_wait(epfd, events, maxevents, timeout); -+} -+ -+int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) -+{ -+ return lstack_poll(fds, nfds, timeout); -+} -+ -+int rtw_close(int s) -+{ -+ struct lwip_sock *sock = get_socket(s); -+ if (sock && sock->wakeup && sock->wakeup->epollfd == s) { -+ return lstack_epoll_close(s); -+ } -+ return stack_broadcast_close(s); -+} -+ -+int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -+{ -+ return lstack_epoll_ctl(epfd, op, fd, event); -+} -+ -+int rtw_epoll_create1(int flags) -+{ -+ return lstack_epoll_create1(flags); -+} -+ -+int rtw_epoll_create(int flags) -+{ -+ return lstack_epoll_create(flags); -+} -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index ab39a68..a808ee8 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -12,17 +12,12 @@ - - #define _GNU_SOURCE - #include --#include - - #include --#include - #include --#include --#include - #include - #include - #include --#include - #include - #include - -@@ -30,29 +25,94 @@ - #include - #include - --#include "posix/lstack_epoll.h" - #include "posix/lstack_unistd.h" --#include "posix/lstack_socket.h" - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" --#include "lstack_protocol_stack.h" - #include "gazelle_base_func.h" --#include "lstack_thread_rpc.h" -- - #include "lstack_preload.h" - -+#include "lstack_rtc_api.h" -+#include "lstack_rtw_api.h" -+ - #ifndef SOCK_TYPE_MASK - #define SOCK_TYPE_MASK 0xf - #endif - -+posix_api_t g_wrap_api_value; -+posix_api_t *g_wrap_api; -+ -+void wrap_api_init(void) -+{ -+ if (g_wrap_api != NULL) { -+ return; -+ } -+ -+ g_wrap_api = &g_wrap_api_value; -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ g_wrap_api->socket_fn = rtc_socket; -+ g_wrap_api->accept_fn = lwip_accept; -+ g_wrap_api->accept4_fn = lwip_accept4; -+ g_wrap_api->bind_fn = lwip_bind; -+ g_wrap_api->listen_fn = lwip_listen; -+ g_wrap_api->connect_fn = lwip_connect; -+ g_wrap_api->setsockopt_fn = lwip_setsockopt; -+ g_wrap_api->getsockopt_fn = lwip_getsockopt; -+ g_wrap_api->getpeername_fn = lwip_getpeername; -+ g_wrap_api->getsockname_fn = lwip_getsockname; -+ g_wrap_api->read_fn = lwip_read; -+ g_wrap_api->readv_fn = lwip_readv; -+ g_wrap_api->write_fn = lwip_write; -+ g_wrap_api->writev_fn = lwip_writev; -+ g_wrap_api->recv_fn = lwip_recv; -+ g_wrap_api->send_fn = lwip_send; -+ g_wrap_api->recv_msg = lwip_recvmsg; -+ g_wrap_api->send_msg = lwip_sendmsg; -+ g_wrap_api->recv_from = lwip_recvfrom; -+ g_wrap_api->send_to = lwip_sendto; -+ g_wrap_api->epoll_wait_fn = rtc_epoll_wait; -+ g_wrap_api->poll_fn = rtc_poll; -+ g_wrap_api->close_fn = rtc_close; -+ g_wrap_api->epoll_ctl_fn = rtc_epoll_ctl; -+ g_wrap_api->epoll_create1_fn = rtc_epoll_create1; -+ g_wrap_api->epoll_create_fn = rtc_epoll_create; -+ } else { -+ g_wrap_api->socket_fn = rtw_socket; -+ g_wrap_api->accept_fn = rtw_accept; -+ g_wrap_api->accept4_fn = rtw_accept4; -+ g_wrap_api->bind_fn = rtw_bind; -+ g_wrap_api->listen_fn = rtw_listen; -+ g_wrap_api->connect_fn = rtw_connect; -+ g_wrap_api->setsockopt_fn = rtw_setsockopt; -+ g_wrap_api->getsockopt_fn = rtw_getsockopt; -+ g_wrap_api->getpeername_fn = rtw_getpeername; -+ g_wrap_api->getsockname_fn = rtw_getsockname; -+ g_wrap_api->read_fn = rtw_read; -+ g_wrap_api->readv_fn = rtw_readv; -+ g_wrap_api->write_fn = rtw_write; -+ g_wrap_api->writev_fn = rtw_writev; -+ g_wrap_api->recv_fn = rtw_recv; -+ g_wrap_api->send_fn = rtw_send; -+ g_wrap_api->recv_msg = rtw_recvmsg; -+ g_wrap_api->send_msg = rtw_sendmsg; -+ g_wrap_api->recv_from = rtw_recvfrom; -+ g_wrap_api->send_to = rtw_sendto; -+ g_wrap_api->epoll_wait_fn = rtw_epoll_wait; -+ g_wrap_api->poll_fn = rtw_poll; -+ g_wrap_api->close_fn = rtw_close; -+ g_wrap_api->epoll_ctl_fn = rtw_epoll_ctl; -+ g_wrap_api->epoll_create1_fn = rtw_epoll_create1; -+ g_wrap_api->epoll_create_fn = rtw_epoll_create; -+ } -+} -+ - static inline int32_t do_epoll_create1(int32_t flags) - { - if (select_posix_path() == PATH_KERNEL) { - return posix_api->epoll_create1_fn(flags); - } - -- return lstack_epoll_create1(flags); -+ return g_wrap_api->epoll_create1_fn(flags); - } - - static inline int32_t do_epoll_create(int32_t size) -@@ -61,7 +121,7 @@ static inline int32_t do_epoll_create(int32_t size) - return posix_api->epoll_create_fn(size); - } - -- return lstack_epoll_create(size); -+ return g_wrap_api->epoll_create_fn(size); - } - - static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event) -@@ -70,7 +130,7 @@ static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -- return lstack_epoll_ctl(epfd, op, fd, event); -+ return g_wrap_api->epoll_ctl_fn(epfd, op, fd, event); - } - - static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) -@@ -87,7 +147,7 @@ static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, in - GAZELLE_RETURN(EINVAL); - } - -- return lstack_epoll_wait(epfd, events, maxevents, timeout); -+ return g_wrap_api->epoll_wait_fn(epfd, events, maxevents, timeout); - } - - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) -@@ -96,7 +156,7 @@ static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *add - return posix_api->accept_fn(s, addr, addrlen); - } - -- int32_t fd = stack_broadcast_accept(s, addr, addrlen); -+ int32_t fd = g_wrap_api->accept_fn(s, addr, addrlen); - if (fd >= 0) { - return fd; - } -@@ -114,7 +174,7 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - -- int32_t fd = stack_broadcast_accept4(s, addr, addrlen, flags); -+ int32_t fd = g_wrap_api->accept4_fn(s, addr, addrlen, flags); - if (fd >= 0) { - return fd; - } -@@ -158,11 +218,7 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { - /* maybe kni addr */ - posix_api->bind_fn(s, name, namelen); -- if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { -- return stack_broadcast_bind(s, name, namelen); -- } else { -- return stack_single_bind(s, name, namelen); -- } -+ return g_wrap_api->bind_fn(s, name, namelen); - } else { - SET_CONN_TYPE_HOST(sock->conn); - return posix_api->bind_fn(s, name, namelen); -@@ -253,7 +309,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - ret = posix_api->connect_fn(s, name, namelen); - SET_CONN_TYPE_HOST(sock->conn); - } else { -- ret = rpc_call_connect(s, name, namelen); -+ ret = g_wrap_api->connect_fn(s, name, namelen); - SET_CONN_TYPE_LIBOS(sock->conn); - } - -@@ -266,13 +322,7 @@ static inline int32_t do_listen(int32_t s, int32_t backlog) - return posix_api->listen_fn(s, backlog); - } - -- int32_t ret; -- if (!get_global_cfg_params()->tuple_filter && -- !get_global_cfg_params()->listen_shadow) { -- ret = stack_single_listen(s, backlog); -- } else { -- ret = stack_broadcast_listen(s, backlog); -- } -+ int32_t ret = g_wrap_api->listen_fn(s, backlog); - if (ret != 0) { - return ret; - } -@@ -287,7 +337,7 @@ static inline int32_t do_getpeername(int32_t s, struct sockaddr *name, socklen_t - } - - if (select_fd_posix_path(s, NULL) == PATH_LWIP) { -- return rpc_call_getpeername(s, name, namelen); -+ return g_wrap_api->getpeername_fn(s, name, namelen); - } - - return posix_api->getpeername_fn(s, name, namelen); -@@ -300,7 +350,7 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - } - - if (select_fd_posix_path(s, NULL) == PATH_LWIP) { -- return rpc_call_getsockname(s, name, namelen); -+ return g_wrap_api->getsockname_fn(s, name, namelen); - } - - return posix_api->getsockname_fn(s, name, namelen); -@@ -321,7 +371,7 @@ static bool unsupport_optname(int32_t optname) - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { - if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(optname)) { -- return rpc_call_getsockopt(s, level, optname, optval, optlen); -+ return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } - - return posix_api->getsockopt_fn(s, level, optname, optval, optlen); -@@ -339,7 +389,7 @@ static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, c - return ret; - } - -- return rpc_call_setsockopt(s, level, optname, optval, optlen); -+ return g_wrap_api->setsockopt_fn(s, level, optname, optval, optlen); - } - - static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) -@@ -355,7 +405,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - return posix_api->socket_fn(domain, type, protocol); - } - -- ret = rpc_call_socket(domain, type, protocol); -+ ret = g_wrap_api->socket_fn(domain, type, protocol); - /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */ - if ((ret >= 0) && (type & SOCK_DGRAM)) { - struct lwip_sock *sock = get_socket(ret); -@@ -382,7 +432,7 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - return posix_api->recv_fn(sockfd, buf, len, flags); - } - -- return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); -+ return g_wrap_api->recv_fn(sockfd, buf, len, flags); - } - - static inline ssize_t do_read(int32_t s, void *mem, size_t len) -@@ -400,7 +450,7 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - return posix_api->read_fn(s, mem, len); - } - -- return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); -+ return g_wrap_api->read_fn(s, mem, len); - } - - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) -@@ -410,21 +460,7 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - return posix_api->readv_fn(s, iov, iovcnt); - } - -- struct msghdr msg; -- -- msg.msg_name = NULL; -- msg.msg_namelen = 0; -- msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -- msg.msg_iovlen = iovcnt; -- msg.msg_control = NULL; -- msg.msg_controllen = 0; -- msg.msg_flags = 0; -- ssize_t result = do_lwip_recvmsg_from_stack(s, &msg, 0); -- if (result == -1 && errno == EAGAIN) { -- errno = 0; -- return 0; -- } -- return result; -+ return g_wrap_api->readv_fn(s, iov, iovcnt); - } - - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) -@@ -434,7 +470,7 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - return posix_api->send_fn(sockfd, buf, len, flags); - } - -- return do_lwip_send_to_stack(sockfd, buf, len, flags, NULL, 0); -+ return g_wrap_api->send_fn(sockfd, buf, len, flags); - } - - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) -@@ -444,7 +480,7 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - return posix_api->write_fn(s, mem, size); - } - -- return do_lwip_send_to_stack(s, mem, size, 0, NULL, 0); -+ return g_wrap_api->write_fn(s, mem, size); - } - - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) -@@ -455,16 +491,7 @@ static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - return posix_api->writev_fn(s, iov, iovcnt); - } - -- struct msghdr msg; -- -- msg.msg_name = NULL; -- msg.msg_namelen = 0; -- msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -- msg.msg_iovlen = iovcnt; -- msg.msg_control = NULL; -- msg.msg_controllen = 0; -- msg.msg_flags = 0; -- return do_lwip_sendmsg_to_stack(sock, s, &msg, 0); -+ return g_wrap_api->writev_fn(s, iov, iovcnt); - } - - static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flags) -@@ -478,7 +505,7 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - return posix_api->recv_msg(s, message, flags); - } - -- return do_lwip_recvmsg_from_stack(s, message, flags); -+ return g_wrap_api->recv_msg(s, message, flags); - } - - static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags) -@@ -493,39 +520,7 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - return posix_api->send_msg(s, message, flags); - } - -- return do_lwip_sendmsg_to_stack(sock, s, message, flags); --} -- --static inline ssize_t udp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void *buf, size_t len, int32_t flags, -- struct sockaddr *addr, socklen_t *addrlen) --{ -- int32_t ret; -- -- while (1) { -- ret = do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -- if (ret > 0) { -- return ret; -- } -- if (ret <= 0 && errno != EAGAIN) { -- return -1; -- } -- sock = sock->listen_next; -- if (sock != NULL && sock->conn != NULL) { -- sockfd = sock->conn->socket; -- } else { -- if (sock == NULL) { -- GAZELLE_RETURN(EAGAIN); -- } else { -- GAZELLE_RETURN(ENOTCONN); -- } -- } -- } --} -- --static inline ssize_t tcp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void *buf, size_t len, int32_t flags, -- struct sockaddr *addr, socklen_t *addrlen) --{ -- return do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -+ return g_wrap_api->send_msg(s, message, flags); - } - - static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t flags, -@@ -541,11 +536,7 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t - - struct lwip_sock *sock = NULL; - if (select_fd_posix_path(sockfd, &sock) == PATH_LWIP) { -- if (NETCONN_IS_UDP(sock)) { -- return udp_recvfrom(sock, sockfd, buf, len, flags, addr, addrlen); -- } else { -- return tcp_recvfrom(sock, sockfd, buf, len, flags, addr, addrlen); -- } -+ return g_wrap_api->recv_from(sockfd, buf, len, flags, addr, addrlen); - } - - return posix_api->recv_from(sockfd, buf, len, flags, addr, addrlen); -@@ -559,7 +550,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen); - } - -- return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); -+ return g_wrap_api->send_to(sockfd, buf, len, flags, addr, addrlen); - } - - static inline int32_t do_close(int32_t s) -@@ -570,16 +561,13 @@ static inline int32_t do_close(int32_t s) - /* we called lwip_socket, even if kernel fd */ - if (posix_api != NULL && !posix_api->ues_posix && - /* contain posix_api->close_fn if success */ -- stack_broadcast_close(s) == 0) { -+ g_wrap_api->close_fn(s) == 0) { - return 0; - } else { - return posix_api->close_fn(s); - } - } -- if (sock && sock->wakeup && sock->wakeup->epollfd == s) { -- return lstack_epoll_close(s); -- } -- return stack_broadcast_close(s); -+ return g_wrap_api->close_fn(s); - } - - static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) -@@ -588,7 +576,7 @@ static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - return posix_api->poll_fn(fds, nfds, timeout); - } - -- return lstack_poll(fds, nfds, timeout); -+ return g_wrap_api->poll_fn(fds, nfds, timeout); - } - - static int32_t do_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index b6e9bf1..950fa8d 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -47,6 +47,7 @@ - #include "gazelle_base_func.h" - #include "lstack_protocol_stack.h" - #include "lstack_preload.h" -+#include "lstack_wrap.h" - - static void check_process_start(void) - { -@@ -235,6 +236,8 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - LSTACK_PRE_LOG(LSTACK_INFO, "cfg_init success\n"); - -+ wrap_api_init(); -+ - /* check primary process start */ - check_process_start(); - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a98b1b8..cdb0089 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -744,7 +744,7 @@ static int32_t check_msg_vaild(const struct msghdr *message) - return 0; - } - --ssize_t do_lwip_recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags) -+ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int32_t flags) - { - ssize_t buflen = 0; - -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 55a483e..4a13204 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -41,7 +41,7 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, uint8_t ap - /* app write/read ring */ - ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, - const struct msghdr *message, int32_t flags); --ssize_t do_lwip_recvmsg_from_stack(int32_t s, struct msghdr *message, int32_t flags); -+ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int32_t flags); - - 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); -diff --git a/src/lstack/include/posix/lstack_socket.h b/src/lstack/include/lstack_rtc_api.h -similarity index 53% -rename from src/lstack/include/posix/lstack_socket.h -rename to src/lstack/include/lstack_rtc_api.h -index a3ce1eb..563cbd8 100644 ---- a/src/lstack/include/posix/lstack_socket.h -+++ b/src/lstack/include/lstack_rtc_api.h -@@ -10,37 +10,46 @@ - * See the Mulan PSL v2 for more details. - */ - --#ifndef _GAZELLE_SOCKET_H_ --#define _GAZELLE_SOCKET_H_ -+#ifndef _LSTACK_RTC_API_H_ -+#define _LSTACK_RTC_API_H_ -+#include -+#include - --#ifdef __cplusplus --extern "C" { --#endif -- --int lwip_socket(int domain, int type, int protocol); --int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); --int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); --int lwip_listen(int s, int backlog); -+/* don't include lwip/sockets.h, conflict with sys/socket.h */ -+/* extern lwip_api here */ -+int lwip_fcntl(int s, int cmd, int val); -+int lwip_ioctl(int s, long cmd, ...); - int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); --int lwip_close(int s); -+int lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); -+int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); -+int lwip_shutdown(int s, int how); - int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen); - int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen); - int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); - int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); -- --ssize_t lwip_write(int s, const void *dataptr, size_t size); --ssize_t lwip_send(int s, const void *data, size_t size, int flags); --ssize_t lwip_recvmsg(int s, struct msghdr *message, int flags); --ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); --ssize_t lwip_read(int s, void *mem, size_t len); --ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, void *from, void *fromlen); -+int lwip_close(int s); -+int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); -+int lwip_listen(int s, int backlog); - ssize_t lwip_recv(int s, void *mem, size_t len, int flags); -+ssize_t lwip_read(int s, void *mem, size_t len); -+ssize_t lwip_readv(int s, const struct iovec *iov, int iovcnt); -+ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, -+ struct sockaddr *from, socklen_t *fromlen); -+ssize_t lwip_recvmsg(int s, const struct msghdr *message, int flags); -+ssize_t lwip_send(int s, const void *dataptr, size_t size, int flags); -+ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); -+ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, -+ const struct sockaddr *to, socklen_t tolen); -+int lwip_socket(int domain, int type, int protocol); -+ssize_t lwip_write(int s, const void *dataptr, size_t size); -+ssize_t lwip_writev(int s, const struct iovec *iov, int iovcnt); - --int lwip_fcntl(int s, int cmd, int val); --int lwip_ioctl(int s, int cmd, ...); -- --#ifdef __cplusplus --} --#endif -+int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout); -+int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); -+int rtc_socket(int domain, int type, int protocol); -+int rtc_close(int s); -+int rtc_epoll_create(int flags); -+int rtc_epoll_create1(int flags); -+int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); - --#endif /* _GAZELLE_SOCKET_H_ */ -+#endif /* __LSTACK_RTC_API_H_ */ -diff --git a/src/lstack/include/lstack_rtw_api.h b/src/lstack/include/lstack_rtw_api.h -new file mode 100644 -index 0000000..facf4c0 ---- /dev/null -+++ b/src/lstack/include/lstack_rtw_api.h -@@ -0,0 +1,47 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_RTW_API_H_ -+#define _LSTACK_RTW_API_H_ -+ -+#include -+#include -+ -+int rtw_socket(int domain, int type, int protocol); -+int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -+int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); -+int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen); -+int rtw_listen(int s, int backlog); -+int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen); -+int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); -+int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); -+int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen); -+int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen); -+ssize_t rtw_read(int s, void *mem, size_t len); -+ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt); -+ssize_t rtw_write(int s, const void *mem, size_t size); -+ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt); -+ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags); -+ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags); -+ssize_t rtw_recvmsg(int s, const struct msghdr *message, int flags); -+ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags); -+ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -+ struct sockaddr *addr, socklen_t *addrlen); -+ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen); -+int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); -+int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout); -+int rtw_close(int s); -+int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -+int rtw_epoll_create1(int flags); -+int rtw_epoll_create(int flags); -+#endif /* _LSTACK_RTW_API_H_ */ -diff --git a/src/lstack/include/lstack_wrap.h b/src/lstack/include/lstack_wrap.h -new file mode 100644 -index 0000000..80e5f3c ---- /dev/null -+++ b/src/lstack/include/lstack_wrap.h -@@ -0,0 +1,19 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_WRAP_H_ -+#define _LSTACK_WRAP_H_ -+ -+void wrap_api_init(void); -+ -+#endif -+ --- -2.27.0 - diff --git a/0024-fix-arping-gazelle-return-value-is-1.patch b/0024-fix-arping-gazelle-return-value-is-1.patch deleted file mode 100644 index 8f2d144..0000000 --- a/0024-fix-arping-gazelle-return-value-is-1.patch +++ /dev/null @@ -1,25 +0,0 @@ -From e7fc6fab09b5687e84467520bf04f84f79de2c03 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 24 Oct 2023 14:33:00 +0800 -Subject: [PATCH] fix arping gazelle return value is 1 - ---- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ea85bc1..1ef0850 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -786,7 +786,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- if (cur_stack == stack && use_ltran()) { -+ if (cur_stack == stack) { - continue; - } - --- -2.27.0 - diff --git a/0025-init-stack-setup-in-app-thread-when-app-call-socket-.patch b/0025-init-stack-setup-in-app-thread-when-app-call-socket-.patch deleted file mode 100644 index 0948253..0000000 --- a/0025-init-stack-setup-in-app-thread-when-app-call-socket-.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 76dc40bf3d8730e4155c142002bc4a27325672a8 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 10:18:20 +0800 -Subject: [PATCH] init: stack setup in app thread when app call - socket/epoll_create first in rtc mode - ---- - src/lstack/api/lstack_rtc_api.c | 14 ++++++- - src/lstack/core/lstack_init.c | 6 ++- - src/lstack/core/lstack_protocol_stack.c | 43 ++++++++++++++++++++-- - src/lstack/include/lstack_protocol_stack.h | 3 +- - 4 files changed, 57 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index b7c6380..276bec0 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -35,6 +35,10 @@ int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int time - int rtc_socket(int domain, int type, int protocol) - { - int ret; -+ -+ if (stack_setup_app_thread() < 0) { -+ LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ } - - /* need call stack thread init function */ - ret = lwip_socket(domain, type, protocol); -@@ -56,13 +60,19 @@ int rtc_close(int s) - - int rtc_epoll_create(int flags) - { -- /* need call stack thread init function */ -+ if (stack_setup_app_thread() < 0) { -+ LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ } -+ - return lstack_epoll_create(flags); - } - - int rtc_epoll_create1(int flags) - { -- /* need call stack thread init function */ -+ if (stack_setup_app_thread() < 0) { -+ LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ } -+ - return lstack_epoll_create1(flags); - } - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 950fa8d..a3ca4ff 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -287,8 +287,10 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - } - -- if (stack_thread_setup() != 0) { -- LSTACK_EXIT(1, "stack_thread_setup failed\n"); -+ if (!get_global_cfg_params()->stack_mode_rtc) { -+ if (stack_setup_thread() != 0) { -+ LSTACK_EXIT(1, "stack_setup_thread failed\n"); -+ } - } - - /* lwip initialization */ -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ea85bc1..69897c7 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -501,6 +501,9 @@ static void* gazelle_stack_thread(void *arg) - } - - LSTACK_LOG(INFO, LSTACK, "stack_%02hu init success\n", queue_id); -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ return NULL; -+ } - - for (;;) { - stack_polling(wakeup_tick); -@@ -510,7 +513,7 @@ static void* gazelle_stack_thread(void *arg) - return NULL; - } - --static void libnet_listen_thread(void *arg) -+static void gazelle_listen_thread(void *arg) - { - struct cfg_params *cfg_param = get_global_cfg_params(); - recv_pkts_from_other_process(cfg_param->process_idx, arg); -@@ -541,11 +544,12 @@ int32_t stack_group_init(void) - } - } - -- if (!use_ltran()) { -+ /* run to completion mode does not currently support multiple process */ -+ if (!use_ltran() && !get_global_cfg_params()->stack_mode_rtc) { - char name[PATH_MAX]; - sem_init(&stack_group->sem_listen_thread, 0, 0); - sprintf_s(name, sizeof(name), "%s", "listen_thread"); -- struct sys_thread *thread = sys_thread_new(name, libnet_listen_thread, -+ struct sys_thread *thread = sys_thread_new(name, gazelle_listen_thread, - (void*)(&stack_group->sem_listen_thread), 0, 0); - free(thread); - sem_wait(&stack_group->sem_listen_thread); -@@ -554,7 +558,33 @@ int32_t stack_group_init(void) - return 0; - } - --int32_t stack_thread_setup(void) -+int32_t stack_setup_app_thread(void) -+{ -+ static PER_THREAD int first_flags = 1; -+ static _Atomic uint32_t queue_id = 0; -+ -+ if (likely(first_flags == 0)) { -+ return 0; -+ } -+ first_flags=0; -+ -+ uint32_t cur_queue_id = atomic_fetch_add(&queue_id, 1); -+ struct thread_params *t_params = malloc(sizeof(struct thread_params)); -+ if (t_params == NULL) { -+ return -1; -+ } -+ t_params->idx = cur_queue_id; -+ t_params->queue_id = cur_queue_id; -+ -+ if (stack_thread_init(t_params) == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "stack setup failed in app thread\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int32_t stack_setup_thread(void) - { - int32_t ret; - char name[PATH_MAX]; -@@ -790,6 +820,11 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - continue; - } - -+ /* stack maybe not init in app thread yet */ -+ if (stack == NULL || !(netif_is_up(&stack->netif))) { -+ continue; -+ } -+ - ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - if (ret != 0) { - stack->stats.rx_allocmbuf_fail++; -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 7cb37bf..4f1b127 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -110,7 +110,8 @@ struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - - int32_t stack_group_init(void); --int32_t stack_thread_setup(void); -+int32_t stack_setup_thread(void); -+int32_t stack_setup_app_thread(void); - - void bind_to_stack_numa(struct protocol_stack *stack); - int32_t init_dpdk_ethdev(void); --- -2.27.0 - diff --git a/0026-epoll-adapt-epoll-interface-for-rtc-mode.patch b/0026-epoll-adapt-epoll-interface-for-rtc-mode.patch deleted file mode 100644 index 9d7dbc4..0000000 --- a/0026-epoll-adapt-epoll-interface-for-rtc-mode.patch +++ /dev/null @@ -1,365 +0,0 @@ -From 8afdae8f8f41bb62d3e57db638735c29abe132d1 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 9 Oct 2023 11:33:01 +0800 -Subject: [PATCH] epoll: adapt epoll interface for rtc mode - ---- - src/lstack/api/lstack_epoll.c | 158 +++++++++++++++++++++--- - src/lstack/api/lstack_rtc_api.c | 4 +- - src/lstack/api/lstack_rtw_api.c | 4 +- - src/lstack/include/lstack_rtc_api.h | 52 ++++---- - src/lstack/include/posix/lstack_epoll.h | 6 +- - 5 files changed, 178 insertions(+), 46 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7c40792..d1fb209 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -155,6 +155,34 @@ static uint32_t update_events(struct lwip_sock *sock) - return event; - } - -+static void rtc_raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *sock) -+{ -+ uint32_t event = 0; -+ -+ if (sock->rcvevent) { -+ event |= EPOLLIN; -+ } -+ -+ if (sock->errevent > 0) { -+ event |= EPOLLERR | EPOLLIN; -+ } -+ -+ if (sock->sendevent) { -+ /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -+ if (sock->conn && CONN_TYPE_IS_LIBOS(sock->conn)) { -+ event |= EPOLLOUT; -+ } -+ } -+ -+ if (event) { -+ sock->events = event; -+ if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && -+ list_is_null(&sock->event_list)) { -+ list_add_node(&wakeup->event_list, &sock->event_list); -+ } -+ } -+} -+ - static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *sock) - { - uint32_t event = 0; -@@ -230,11 +258,16 @@ int32_t lstack_do_epoll_create(int32_t fd) - wakeup->epollfd = fd; - sock->wakeup = wakeup; - -- update_epoll_max_stack(wakeup); -- change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, wakeup->max_stack); -- wakeup->bind_stack = wakeup->max_stack; -- if (get_global_cfg_params()->app_bind_numa) { -- bind_to_stack_numa(wakeup->bind_stack); -+ if (!get_global_cfg_params()->stack_mode_rtc) { -+ update_epoll_max_stack(wakeup); -+ change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, wakeup->max_stack); -+ wakeup->bind_stack = wakeup->max_stack; -+ if (get_global_cfg_params()->app_bind_numa) { -+ bind_to_stack_numa(wakeup->bind_stack); -+ } -+ } else { -+ wakeup->bind_stack = wakeup->max_stack = get_protocol_stack(); -+ change_epollfd_kernel_thread(wakeup, NULL, wakeup->max_stack); - } - - return fd; -@@ -329,7 +362,45 @@ static void update_epoll_max_stack(struct wakeup_poll *wakeup) - wakeup->max_stack = stack_group->stacks[bind_id]; - } - --int32_t lstack_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event) -+int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event) -+{ -+ if (epfd < 0 || fd < 0 || epfd == fd || (event == NULL && op != EPOLL_CTL_DEL)) { -+ LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d\n", fd, epfd, op); -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ struct lwip_sock *epoll_sock = get_socket_by_fd(epfd); -+ if (epoll_sock == NULL || epoll_sock->wakeup == NULL) { -+ return posix_api->epoll_ctl_fn(epfd, op, fd, event); -+ } -+ -+ struct wakeup_poll *wakeup = epoll_sock->wakeup; -+ struct lwip_sock *sock = get_socket(fd); -+ if (sock == NULL) { -+ return posix_api->epoll_ctl_fn(epfd, op, fd, event); -+ } -+ -+ switch (op) { -+ case EPOLL_CTL_ADD: -+ sock->wakeup = wakeup; -+ /* fall through */ -+ case EPOLL_CTL_MOD: -+ sock->epoll_events = event->events | EPOLLERR | EPOLLHUP; -+ sock->ep_data = event->data; -+ rtc_raise_pending_events(wakeup, sock); -+ break; -+ case EPOLL_CTL_DEL: -+ sock->epoll_events = 0; -+ list_del_node_null(&sock->event_list); -+ break; -+ default: -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ return 0; -+} -+ -+int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event) - { - LSTACK_LOG(DEBUG, LSTACK, "op=%d events: fd: %d\n", op, fd); - -@@ -384,29 +455,28 @@ int32_t lstack_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_even - return 0; - } - --static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents) -+int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents) - { - int32_t event_num = 0; - struct list_node *node, *temp; - -- pthread_spin_lock(&wakeup->event_list_lock); -- - list_for_each_safe(node, temp, &wakeup->event_list) { - struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list); - - if ((sock->epoll_events & sock->events) == 0) { -- list_del_node_null(&sock->event_list); -+ list_del_node_null(node); - continue; - } - - if (sock->epoll_events & EPOLLET) { -- list_del_node_null(&sock->event_list); -+ list_del_node_null(node); -+ sock->events = 0; - } - - /* EPOLLONESHOT: generate event after epoll_ctl add/mod event again - epoll_event set 0 avoid generating event util epoll_ctl set epoll_event a valu */ - if (sock->epoll_events & EPOLLONESHOT) { -- list_del_node_null(&sock->event_list); -+ list_del_node_null(node); - sock->epoll_events = 0; - } - -@@ -415,13 +485,25 @@ static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event * - event_num++; - - if (event_num >= maxevents) { -+ /* move list head after the current node, and start traversing from this node next time */ -+ list_del_node_null(&wakeup->event_list); -+ list_add_node(node, &wakeup->event_list); - break; - } - } - -+ wakeup->stat.app_events += event_num; -+ return event_num; -+} -+ -+static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents) -+{ -+ int32_t event_num; -+ -+ pthread_spin_lock(&wakeup->event_list_lock); -+ event_num = epoll_lwip_event_nolock(wakeup, events, maxevents); - pthread_spin_unlock(&wakeup->event_list_lock); - -- wakeup->stat.app_events += event_num; - return event_num; - } - -@@ -484,7 +566,55 @@ static void ms_to_timespec(struct timespec *timespec, int32_t timeout) - timespec->tv_nsec = timespec->tv_nsec % SEC_TO_NSEC; - } - --int32_t lstack_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) -+int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(epfd); -+ -+ if (sock == NULL || sock->wakeup == NULL) { -+ return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -+ } -+ -+ struct wakeup_poll *wakeup = sock->wakeup; -+ int32_t lwip_num = 0; -+ /* 16: avoid app process events for a long time */ -+ int32_t tmpmaxevents = 16; -+ /* avoid the starvation of epoll events from both netstack */ -+ int host_maxevents = tmpmaxevents / 2; -+ uint32_t poll_ts = sys_now(); -+ bool loop_flag; -+ int32_t kernel_num = 0; -+ int32_t tmptimeout = timeout; -+ -+ do { -+ stack_polling(0); -+ if (__atomic_load_n(&wakeup->have_kernel_event, __ATOMIC_ACQUIRE)) { -+ kernel_num = posix_api->epoll_wait_fn(epfd, events, host_maxevents, 0); -+ if (!kernel_num) { -+ __atomic_store_n(&wakeup->have_kernel_event, false, __ATOMIC_RELEASE); -+ } -+ } -+ if (tmptimeout > 0) { -+ tmptimeout = update_timeout(tmptimeout, poll_ts); -+ } -+ -+ loop_flag = false; -+ if (!kernel_num && list_is_empty(&wakeup->event_list) && tmptimeout != 0) { -+ loop_flag = true; -+ } -+ } while (loop_flag); -+ -+ if (kernel_num < 0) { -+ LSTACK_LOG(ERR, LSTACK, "lstack_rtc_epoll_wait: kernel event failed\n"); -+ return kernel_num; -+ } -+ -+ lwip_num = epoll_lwip_event_nolock(wakeup, &events[kernel_num], tmpmaxevents - kernel_num); -+ wakeup->stat.app_events += lwip_num; -+ -+ return lwip_num + kernel_num; -+} -+ -+int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { - struct lwip_sock *sock = get_socket_by_fd(epfd); - if (sock == NULL || sock->wakeup == NULL) { -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index b7c6380..b9abf0f 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -29,7 +29,7 @@ int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) - - int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) - { -- return -1; -+ return lstack_rtc_epoll_wait(epfd, events, maxevents, timeout); - } - - int rtc_socket(int domain, int type, int protocol) -@@ -68,5 +68,5 @@ int rtc_epoll_create1(int flags) - - int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { -- return lstack_epoll_ctl(epfd, op, fd, event); -+ return lstack_rtc_epoll_ctl(epfd, op, fd, event); - } -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 9b8678a..7d14ffa 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -206,7 +206,7 @@ ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, - - int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) - { -- return lstack_epoll_wait(epfd, events, maxevents, timeout); -+ return lstack_rtw_epoll_wait(epfd, events, maxevents, timeout); - } - - int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) -@@ -225,7 +225,7 @@ int rtw_close(int s) - - int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { -- return lstack_epoll_ctl(epfd, op, fd, event); -+ return lstack_rtw_epoll_ctl(epfd, op, fd, event); - } - - int rtw_epoll_create1(int flags) -diff --git a/src/lstack/include/lstack_rtc_api.h b/src/lstack/include/lstack_rtc_api.h -index 563cbd8..0aff928 100644 ---- a/src/lstack/include/lstack_rtc_api.h -+++ b/src/lstack/include/lstack_rtc_api.h -@@ -17,32 +17,32 @@ - - /* don't include lwip/sockets.h, conflict with sys/socket.h */ - /* extern lwip_api here */ --int lwip_fcntl(int s, int cmd, int val); --int lwip_ioctl(int s, long cmd, ...); --int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); --int lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); --int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); --int lwip_shutdown(int s, int how); --int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen); --int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen); --int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); --int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); --int lwip_close(int s); --int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); --int lwip_listen(int s, int backlog); --ssize_t lwip_recv(int s, void *mem, size_t len, int flags); --ssize_t lwip_read(int s, void *mem, size_t len); --ssize_t lwip_readv(int s, const struct iovec *iov, int iovcnt); --ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, -- struct sockaddr *from, socklen_t *fromlen); --ssize_t lwip_recvmsg(int s, const struct msghdr *message, int flags); --ssize_t lwip_send(int s, const void *dataptr, size_t size, int flags); --ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); --ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, -- const struct sockaddr *to, socklen_t tolen); --int lwip_socket(int domain, int type, int protocol); --ssize_t lwip_write(int s, const void *dataptr, size_t size); --ssize_t lwip_writev(int s, const struct iovec *iov, int iovcnt); -+extern int lwip_fcntl(int s, int cmd, int val); -+extern int lwip_ioctl(int s, long cmd, ...); -+extern int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); -+extern int lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); -+extern int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); -+extern int lwip_shutdown(int s, int how); -+extern int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen); -+extern int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen); -+extern int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); -+extern int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); -+extern int lwip_close(int s); -+extern int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); -+extern int lwip_listen(int s, int backlog); -+extern ssize_t lwip_recv(int s, void *mem, size_t len, int flags); -+extern ssize_t lwip_read(int s, void *mem, size_t len); -+extern ssize_t lwip_readv(int s, const struct iovec *iov, int iovcnt); -+extern ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, -+ struct sockaddr *from, socklen_t *fromlen); -+extern ssize_t lwip_recvmsg(int s, const struct msghdr *message, int flags); -+extern ssize_t lwip_send(int s, const void *dataptr, size_t size, int flags); -+extern ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); -+extern ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, -+ const struct sockaddr *to, socklen_t tolen); -+extern int lwip_socket(int domain, int type, int protocol); -+extern ssize_t lwip_write(int s, const void *dataptr, size_t size); -+extern ssize_t lwip_writev(int s, const struct iovec *iov, int iovcnt); - - int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout); - int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index 699a951..c42f3a5 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -73,8 +73,10 @@ void wakeup_stack_epoll(struct protocol_stack *stack); - - int32_t lstack_epoll_create(int32_t size); - int32_t lstack_epoll_create1(int32_t flags); --int32_t lstack_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); --int32_t lstack_epoll_wait(int32_t epfd, struct epoll_event *events, int32_t maxevents, int32_t timeout); -+int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); -+int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); -+int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event *events, int32_t maxevents, int32_t timeout); -+int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout); - int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout); - - #ifdef __cplusplus --- -2.27.0 - diff --git a/0027-clean-useless-code.patch b/0027-clean-useless-code.patch deleted file mode 100644 index 3be5e8a..0000000 --- a/0027-clean-useless-code.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 0398acfead1f6c118234559b3473ace2c5676015 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Thu, 26 Oct 2023 13:20:03 +0000 -Subject: [PATCH] clean useless code - ---- - src/lstack/core/lstack_dpdk.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a53e85c..48fa67d 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -740,10 +740,6 @@ int32_t init_dpdk_ethdev(void) - return -1; - } - -- /* 20: sleep for lacp ,this is a temp plan, it will be changed in future */ -- int wait_lacp = 20; -- sleep(wait_lacp); -- - } else { - ret = dpdk_ethdev_init(0, 0); - if (ret != 0) { --- -2.27.0 - diff --git a/0028-ethdev-fix-arp-unicast-packets-cannot-be-transmitted.patch b/0028-ethdev-fix-arp-unicast-packets-cannot-be-transmitted.patch deleted file mode 100644 index 0ed2539..0000000 --- a/0028-ethdev-fix-arp-unicast-packets-cannot-be-transmitted.patch +++ /dev/null @@ -1,55 +0,0 @@ -From aa2e11540cf897d2b1051ab33245e8c988618aaa Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 26 Oct 2023 17:45:56 +0800 -Subject: [PATCH] ethdev: fix arp unicast packets cannot be transmitted to - current procotol stack - ---- - src/lstack/core/lstack_protocol_stack.c | 8 ++++++++ - src/lstack/netif/lstack_ethdev.c | 11 ++--------- - 2 files changed, 10 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 0726054..511d2b9 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -837,6 +837,14 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - } -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ if (ret != 0) { -+ stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ kni_handle_tx(mbuf_copy); -+ return; - } - - void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup) -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 30c3c9a..f2353f8 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -780,15 +780,8 @@ int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_fla - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); - if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == ethh->ether_type)) { - stack_broadcast_arp(stack->pkts[i], stack); --#if DPDK_VERSION_1911 -- if (!rte_is_broadcast_ether_addr(ðh->d_addr)) { --#else /* DPDK_VERSION_1911 */ -- if (!rte_is_broadcast_ether_addr(ðh->dst_addr)) { --#endif /* DPDK_VERSION_1911 */ -- // copy arp into other process -- transfer_arp_to_other_process(stack->pkts[i]); -- transfer_type = TRANSFER_KERNEL; -- } -+ /* copy arp into other process */ -+ transfer_arp_to_other_process(stack->pkts[i]); - } else { - if (get_global_cfg_params()->tuple_filter && stack->queue_id == 0) { - transfer_type = distribute_pakages(stack->pkts[i]); --- -2.27.0 - diff --git a/0029-stack-add-semaphore-to-ensure-all-stack-threads-setu.patch b/0029-stack-add-semaphore-to-ensure-all-stack-threads-setu.patch deleted file mode 100644 index 394ce6a..0000000 --- a/0029-stack-add-semaphore-to-ensure-all-stack-threads-setu.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 24deab28953f33ab4dc1596291289b91b805b4de Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 26 Oct 2023 19:36:02 +0800 -Subject: [PATCH] stack: add semaphore to ensure all stack threads setup - success in rtw mode before call main() - ---- - src/lstack/core/lstack_protocol_stack.c | 19 +++++++++++++++++-- - src/lstack/include/lstack_protocol_stack.h | 2 ++ - src/lstack/netif/lstack_ethdev.c | 4 ++-- - 3 files changed, 21 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 0726054..27e5005 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -289,6 +289,7 @@ static void* gazelle_kernelevent_thread(void *arg) - - LSTACK_LOG(INFO, LSTACK, "kernelevent_%02hu start\n", idx); - free(arg); -+ sem_post(&g_stack_group.sem_stack_setup); - - for (;;) { - stack->kernel_event_num = posix_api->epoll_wait_fn(stack->epollfd, stack->kernel_events, KERNEL_EPOLL_MAX, -1); -@@ -493,9 +494,12 @@ static void* gazelle_stack_thread(void *arg) - free(arg); - if (stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id); -- /* exit in signal thread */ -- raise(SIGTERM); -+ g_stack_group.stack_setup_fail = 1; -+ sem_post(&g_stack_group.sem_stack_setup); -+ return NULL; - } -+ sem_post(&g_stack_group.sem_stack_setup); -+ - if (!use_ltran() && queue_id == 0) { - init_listen_and_user_ports(); - } -@@ -531,6 +535,11 @@ int32_t stack_group_init(void) - init_list_node(&stack_group->poll_list); - pthread_spin_init(&stack_group->poll_list_lock, PTHREAD_PROCESS_PRIVATE); - pthread_spin_init(&stack_group->socket_lock, PTHREAD_PROCESS_PRIVATE); -+ if (sem_init(&stack_group->sem_stack_setup, 0, 0) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "sem_init failed errno=%d\n", errno); -+ return -1; -+ } -+ stack_group->stack_setup_fail = 0; - - if (get_global_cfg_params()->is_primary) { - uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; -@@ -622,6 +631,12 @@ int32_t stack_setup_thread(void) - } - } - -+ /* 2: wait stack thread and kernel_event thread init finish */ -+ wait_sem_value(&g_stack_group.sem_stack_setup, g_stack_group.stack_num * 2); -+ if (g_stack_group.stack_setup_fail) { -+ return -1; -+ } -+ - return 0; - } - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 4f1b127..2c581b3 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -96,6 +96,8 @@ struct protocol_stack_group { - pthread_spinlock_t poll_list_lock; - sem_t sem_listen_thread; - struct rte_mempool *total_rxtx_pktmbuf_pool[PROTOCOL_STACK_MAX]; -+ sem_t sem_stack_setup; -+ bool stack_setup_fail; - - /* dfx stats */ - bool latency_start; -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 30c3c9a..b0dbba4 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -319,7 +319,7 @@ struct rte_flow *create_flow_director(uint16_t port_id, uint16_t queue_id, - if (!res) { - flow = rte_flow_create(port_id, &attr, pattern, action, error); - } else { -- LSTACK_LOG(ERR, PORT, "rte_flow_create.rte_flow_validate error, res %d \n", res); -+ LSTACK_LOG(ERR, LSTACK, "rte_flow_create.rte_flow_validate error, res %d \n", res); - } - - return flow; -@@ -364,7 +364,7 @@ void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) - struct rte_flow_error error; - int ret = rte_flow_destroy(port_id, fl->flow, &error); - if(ret != 0){ -- LSTACK_LOG(ERR, PORT, "Flow can't be delete %d message: %s\n", -+ LSTACK_LOG(ERR, LSTACK, "Flow can't be delete %d message: %s\n", - error.type, error.message ? error.message : "(no stated reason)"); - } - delete_rule(rule_key); --- -2.27.0 - diff --git a/0030-ethdev-register-offload-to-netif.patch b/0030-ethdev-register-offload-to-netif.patch deleted file mode 100644 index a3e8656..0000000 --- a/0030-ethdev-register-offload-to-netif.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f15f4d7c178b35b41bab7c42162517e4142ae77a Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Fri, 27 Oct 2023 20:11:29 +0800 -Subject: [PATCH] ethdev: register offload to netif - ---- - src/lstack/netif/lstack_ethdev.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 6e4c9de..80932c8 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -895,6 +895,12 @@ static err_t eth_dev_init(struct netif *netif) - - netif->hwaddr_len = ETHER_ADDR_LEN; - -+ netif_set_rxol_flags(netif, get_protocol_stack_group()->rx_offload); -+ netif_set_txol_flags(netif, get_protocol_stack_group()->tx_offload); -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ netif_set_rtc_mode(netif); -+ } -+ - return ERR_OK; - } - --- -2.27.0 - diff --git a/0031-epoll-fix-epollet-mode-error.patch b/0031-epoll-fix-epollet-mode-error.patch deleted file mode 100644 index a7a674a..0000000 --- a/0031-epoll-fix-epollet-mode-error.patch +++ /dev/null @@ -1,44 +0,0 @@ -From c6cca5f100c09769a5d260e729f4c149be964ea4 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 28 Oct 2023 20:17:26 +0800 -Subject: [PATCH] epoll: fix epollet mode error - ---- - src/lstack/api/lstack_epoll.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index d1fb209..a711ae3 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -468,22 +468,22 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - continue; - } - -+ events[event_num].events = sock->events & sock->epoll_events; -+ events[event_num].data = sock->ep_data; -+ event_num++; -+ - if (sock->epoll_events & EPOLLET) { - list_del_node_null(node); - sock->events = 0; - } - - /* EPOLLONESHOT: generate event after epoll_ctl add/mod event again -- epoll_event set 0 avoid generating event util epoll_ctl set epoll_event a valu */ -+ epoll_event set 0 avoid generating event util epoll_ctl reset epoll_event */ - if (sock->epoll_events & EPOLLONESHOT) { - list_del_node_null(node); - sock->epoll_events = 0; - } - -- events[event_num].events = sock->events & sock->epoll_events; -- events[event_num].data = sock->ep_data; -- event_num++; -- - if (event_num >= maxevents) { - /* move list head after the current node, and start traversing from this node next time */ - list_del_node_null(&wakeup->event_list); --- -2.27.0 - diff --git a/0032-bond6.patch b/0032-bond6.patch deleted file mode 100644 index 3933e16..0000000 --- a/0032-bond6.patch +++ /dev/null @@ -1,210 +0,0 @@ -From c3cc06b64d2da294001289d7610f186a6af7a8c4 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 30 Oct 2023 21:52:29 +0800 -Subject: [PATCH] bond6 - ---- - src/lstack/core/lstack_cfg.c | 34 +++++++++++++++++++++------------ - src/lstack/core/lstack_dpdk.c | 33 +++++++++++++++++++------------- - src/lstack/include/lstack_cfg.h | 6 +++--- - 3 files changed, 45 insertions(+), 28 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index ad89bca..c4278b5 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -24,6 +24,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -70,8 +71,8 @@ static int32_t parse_process_numa(void); - static int32_t parse_process_index(void); - static int32_t parse_seperate_sendrecv_args(void); - static int32_t parse_tuple_filter(void); --static int32_t parse_use_bond4(void); --static int32_t parse_bond4_slave_mac(void); -+static int32_t parse_bond_mode(void); -+static int32_t parse_bond_slave_mac(void); - static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); - static int32_t parse_nic_rxqueue_size(void); -@@ -130,8 +131,8 @@ static struct config_vector_t g_config_tbl[] = { - { "process_numa", parse_process_numa }, - { "process_idx", parse_process_index }, - { "tuple_filter", parse_tuple_filter }, -- { "use_bond4", parse_use_bond4 }, -- { "bond4_slave_mac", parse_bond4_slave_mac }, -+ { "bond_mode", parse_bond_mode }, -+ { "bond_slave_mac", parse_bond_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, -@@ -1114,16 +1115,25 @@ static int32_t parse_udp_enable(void) - return ret; - } - --static int32_t parse_use_bond4(void) -+static int32_t parse_bond_mode(void) - { -- int32_t ret; -- PARSE_ARG(g_config_params.use_bond4, "use_bond4", 0, 0, 1, ret); -- return ret; -+ const config_setting_t *bond_mode = NULL; -+ bond_mode = config_lookup(&g_config, "bond_mode"); -+ g_config_params.bond_mode = config_setting_get_int(bond_mode); -+ if (g_config_params.bond_mode == -1) { -+ return 0; -+ } -+ if (g_config_params.bond_mode != BONDING_MODE_8023AD && g_config_params.bond_mode != BONDING_MODE_ALB) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid bond mode = %d. only supports bond mode = 4,6.\n", -+ g_config_params.bond_mode); -+ return -EINVAL; -+ } -+ return 0; - } - --static int32_t parse_bond4_slave_mac(void) -+static int32_t parse_bond_slave_mac(void) - { -- if (g_config_params.use_bond4 == 0) { -+ if (g_config_params.bond_mode == -1) { - return 0; - } - -@@ -1151,13 +1161,13 @@ static int32_t parse_bond4_slave_mac(void) - } - - /* add dev */ -- ret = str_to_eth_addr(slave_mac1, g_config_params.bond4_slave1_mac_addr); -+ ret = str_to_eth_addr(slave_mac1, g_config_params.bond_slave1_mac_addr); - if (ret != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", slave_mac1, ret); - return ret; - } - -- ret = str_to_eth_addr(slave_mac2, g_config_params.bond4_slave2_mac_addr); -+ ret = str_to_eth_addr(slave_mac2, g_config_params.bond_slave2_mac_addr); - if (ret != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", slave_mac2, ret); - } -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 48fa67d..1a5b568 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -463,7 +463,6 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - int32_t dpdk_ethdev_init(int port_id, bool bond_port) - { - uint16_t nb_queues = get_global_cfg_params()->num_cpu; -- int32_t use_bond4 = get_global_cfg_params()->use_bond4; - if (get_global_cfg_params()->seperate_send_recv) { - nb_queues = get_global_cfg_params()->num_cpu * 2; - } -@@ -474,7 +473,7 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - -- if (!use_bond4) { -+ if (get_global_cfg_params()->bond_mode < 0) { - port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); - if (port_id < 0) { - return port_id; -@@ -499,13 +498,13 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - if (bond_port) { - int slave_num = 2; - int32_t slave_port_id[2]; -- slave_port_id[0] = ethdev_port_id(get_global_cfg_params()->bond4_slave1_mac_addr); -+ slave_port_id[0] = ethdev_port_id(get_global_cfg_params()->bond_slave1_mac_addr); - if (slave_port_id[0] < 0) { - LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[0]); - return slave_port_id[0]; - } - -- slave_port_id[1] = ethdev_port_id(get_global_cfg_params()->bond4_slave2_mac_addr); -+ slave_port_id[1] = ethdev_port_id(get_global_cfg_params()->bond_slave2_mac_addr); - if (slave_port_id[1] < 0) { - LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[1]); - return slave_port_id[1]; -@@ -648,7 +647,7 @@ int32_t dpdk_ethdev_start(void) - } - } - -- if (get_global_cfg_params()->use_bond4) { -+ if (get_global_cfg_params()->bond_mode >= 0) { - return 0; - } - -@@ -697,15 +696,16 @@ int32_t init_dpdk_ethdev(void) - { - int32_t ret; - -- if (get_global_cfg_params()->use_bond4) { -- int bond_port_id = rte_eth_bond_create("net_bonding0", 4, (uint8_t)rte_socket_id()); -+ if (get_global_cfg_params()->bond_mode >= 0) { -+ uint8_t socket_id = rte_socket_id(); -+ int bond_port_id = rte_eth_bond_create("net_bonding0", get_global_cfg_params()->bond_mode, socket_id); - if (bond_port_id < 0) { - LSTACK_LOG(ERR, LSTACK, "get bond port id failed ret=%d\n", bond_port_id); - return bond_port_id; - } - - ret = dpdk_ethdev_init(bond_port_id, 1); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); - return -1; - } -@@ -716,10 +716,17 @@ int32_t init_dpdk_ethdev(void) - return -1; - } - -- ret = rte_eth_bond_8023ad_dedicated_queues_enable(bond_port_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); -- return -1; -+ if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { -+ ret = rte_eth_bond_8023ad_dedicated_queues_enable(bond_port_id); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); -+ return -1; -+ } -+ } else { -+ ret = rte_eth_bond_mode_set(bond_port_id, get_global_cfg_params()->bond_mode); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk enable mode set failed ret = %d\n", ret); -+ } - } - - ret = rte_eth_promiscuous_enable(bond_port_id); -@@ -735,7 +742,7 @@ int32_t init_dpdk_ethdev(void) - } - - ret = rte_eth_dev_start(bond_port_id); -- if (ret < 0) { -+ if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk start bond port failed ret = %d\n", ret); - return -1; - } -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 1d895ec..fc627e3 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -110,9 +110,9 @@ struct cfg_params { - uint16_t send_ring_size; - bool expand_send_ring; - bool tuple_filter; -- bool use_bond4; -- uint8_t bond4_slave1_mac_addr[ETHER_ADDR_LEN]; -- uint8_t bond4_slave2_mac_addr[ETHER_ADDR_LEN]; -+ int8_t bond_mode; -+ uint8_t bond_slave1_mac_addr[ETHER_ADDR_LEN]; -+ uint8_t bond_slave2_mac_addr[ETHER_ADDR_LEN]; - bool use_sockmap; - bool udp_enable; - struct cfg_nic_params nic; --- -2.27.0 - diff --git a/0033-cfg-fix-bond_mode-null.patch b/0033-cfg-fix-bond_mode-null.patch deleted file mode 100644 index 6e842b5..0000000 --- a/0033-cfg-fix-bond_mode-null.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 845b5afa76205cf1eaffc966257eb62ea64af837 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 4 Nov 2023 19:18:12 +0800 -Subject: [PATCH] cfg: fix bond_mode null - ---- - src/lstack/core/lstack_cfg.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index c4278b5..8e83c0d 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1119,6 +1119,11 @@ static int32_t parse_bond_mode(void) - { - const config_setting_t *bond_mode = NULL; - bond_mode = config_lookup(&g_config, "bond_mode"); -+ if (bond_mode == NULL) { -+ g_config_params.bond_mode = -1; -+ return 0; -+ } -+ - g_config_params.bond_mode = config_setting_get_int(bond_mode); - if (g_config_params.bond_mode == -1) { - return 0; --- -2.27.0 - diff --git a/0034-dfx-add-four-snmp-udp-datas.patch b/0034-dfx-add-four-snmp-udp-datas.patch deleted file mode 100644 index 844cbd7..0000000 --- a/0034-dfx-add-four-snmp-udp-datas.patch +++ /dev/null @@ -1,28 +0,0 @@ -From fcab00c220dfd8eaced2e07d4bc3cb9be71b82ff Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 6 Nov 2023 16:38:32 +0800 -Subject: [PATCH] dfx: add four snmp udp datas - ---- - src/ltran/ltran_dfx.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index e5fd0c8..582a4b7 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -846,6 +846,11 @@ static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_d - printf("ip_fw_dgm: %u\n", snmp->ip_fw_dgm); - printf("ip_in_recv: %u\n", snmp->ip_in_recv); - -+ printf("udp_in_datagrams: %u\n", snmp->udp_in_datagrams); -+ printf("udp_no_ports: %u\n", snmp->udp_no_ports); -+ printf("udp_in_errors: %u\n", snmp->udp_in_errors); -+ printf("udp_out_datagrams: %u\n", snmp->udp_out_datagrams); -+ - printf("tcp_act_open: %u\n", snmp->tcp_act_open); - printf("tcp_passive_open: %u\n", snmp->tcp_passive_open); - printf("tcp_attempt_fail: %u\n", snmp->tcp_attempt_fail); --- -2.23.0 - diff --git a/0035-cfg-nic-queue-size-only-support-power-of-2.patch b/0035-cfg-nic-queue-size-only-support-power-of-2.patch deleted file mode 100644 index 11d5a64..0000000 --- a/0035-cfg-nic-queue-size-only-support-power-of-2.patch +++ /dev/null @@ -1,38 +0,0 @@ -From cb8d274804ccc9d9c5bb434d1c2e60aaf14e8fd5 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 8 Nov 2023 20:53:22 +0800 -Subject: [PATCH] cfg: nic queue size only support power of 2 - ---- - src/lstack/core/lstack_cfg.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 8e83c0d..d2d0fc1 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1191,6 +1191,10 @@ static int32_t parse_nic_rxqueue_size(void) - int32_t ret; - PARSE_ARG(g_config_params.nic.rxqueue_size, "nic_rxqueue_size", 4096, - NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -+ if (!rte_is_power_of_2(g_config_params.nic.rxqueue_size)) { -+ LSTACK_LOG(ERR, LSTACK, "nic queue size only support power of two\n"); -+ return -1; -+ } - return ret; - } - -@@ -1199,6 +1203,10 @@ static int32_t parse_nic_txqueue_size(void) - int32_t ret; - PARSE_ARG(g_config_params.nic.txqueue_size, "nic_txqueue_size", 2048, - NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -+ if (!rte_is_power_of_2(g_config_params.nic.txqueue_size)) { -+ LSTACK_LOG(ERR, LSTACK, "nic queue size only support power of two\n"); -+ return -1; -+ } - return ret; - } - --- -2.23.0 - diff --git a/0036-stack-fix-possible-coredump-when-arp-packet-broadcas.patch b/0036-stack-fix-possible-coredump-when-arp-packet-broadcas.patch deleted file mode 100644 index adb15f3..0000000 --- a/0036-stack-fix-possible-coredump-when-arp-packet-broadcas.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 8e5dd5204c57e4443cb79cb01cdc8c16665e6734 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 10 Nov 2023 18:07:14 +0800 -Subject: [PATCH] stack: fix possible coredump when arp packet broadcast in rtc - mode - ---- - src/lstack/core/lstack_protocol_stack.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 3662948..bafb569 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -852,9 +852,9 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - } -- ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); - if (ret != 0) { -- stack->stats.rx_allocmbuf_fail++; -+ cur_stack->stats.rx_allocmbuf_fail++; - return; - } - copy_mbuf(mbuf_copy, mbuf); --- -2.23.0 - diff --git a/0037-Fix-coredump-issue-and-skip-rte_pdump_init-for-secon.patch b/0037-Fix-coredump-issue-and-skip-rte_pdump_init-for-secon.patch deleted file mode 100644 index d90372e..0000000 --- a/0037-Fix-coredump-issue-and-skip-rte_pdump_init-for-secon.patch +++ /dev/null @@ -1,53 +0,0 @@ -From c4e5033d44b4e6ff5a2b35e0087a26539bd9d785 Mon Sep 17 00:00:00 2001 -From: Honggang LI -Date: Mon, 13 Nov 2023 09:35:57 +0800 -Subject: [PATCH] Fix coredump issue and skip rte_pdump_init for secondary - process - -Signed-off-by: Honggang LI ---- - src/lstack/core/lstack_dpdk.c | 14 ++++++++------ - src/lstack/core/lstack_lwip.c | 2 +- - 2 files changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 1a5b568..5fc641e 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -125,12 +125,14 @@ int32_t dpdk_eal_init(void) - LSTACK_PRE_LOG(LSTACK_INFO, "dpdk_eal_init success\n"); - } - -- ret = rte_pdump_init(); -- if (ret < 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "rte_pdump_init failed init, rte_errno %d\n", rte_errno); -- /* We do not care whether the pdump is successfully loaded. So, just print an alarm. */ -- } else { -- LSTACK_PRE_LOG(LSTACK_INFO, "rte_pdump_init success\n"); -+ if (get_global_cfg_params()->is_primary) { -+ ret = rte_pdump_init(); -+ if (ret < 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "rte_pdump_init failed init, rte_errno %d\n", rte_errno); -+ /* We do not care whether the pdump is successfully loaded. So, just print an alarm. */ -+ } else { -+ LSTACK_PRE_LOG(LSTACK_INFO, "rte_pdump_init success\n"); -+ } - } - - return ret; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index cdb0089..a2b02df 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1216,7 +1216,7 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - conn[conn_num].l_port = pcbl->local_port; - conn[conn_num].tcp_sub_state = pcbl->state; - struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -- conn[conn_num].fd = netconn->socket; -+ conn[conn_num].fd = netconn != NULL ? netconn->socket : -1; - if (netconn != NULL && netconn->acceptmbox != NULL) { - conn[conn_num].recv_cnt = rte_ring_count(netconn->acceptmbox->ring); - } --- -2.23.0 - diff --git a/0038-solve-problem-that-rte_pktmbuf_poll_creat-in-same-nu.patch b/0038-solve-problem-that-rte_pktmbuf_poll_creat-in-same-nu.patch deleted file mode 100644 index ffa7581..0000000 --- a/0038-solve-problem-that-rte_pktmbuf_poll_creat-in-same-nu.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 2a5891557162fb5743f13cb550dc7ff109476176 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Wed, 1 Nov 2023 18:34:07 +0800 -Subject: [PATCH] solve problem that rte_pktmbuf_poll_creat in same numa . - ---- - src/lstack/core/lstack_dpdk.c | 11 +++--- - src/lstack/core/lstack_protocol_stack.c | 52 ++++++++++++++++++++----- - src/lstack/include/lstack_dpdk.h | 2 +- - 3 files changed, 50 insertions(+), 15 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 48fa67d..88a6c45 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -110,7 +110,7 @@ int32_t dpdk_eal_init(void) - { - int32_t ret; - struct cfg_params *global_params = get_global_cfg_params(); -- -+ - ret = rte_eal_init(global_params->dpdk_argc, global_params->dpdk_argv); - if (ret < 0) { - if (rte_errno == EALREADY) { -@@ -137,7 +137,7 @@ int32_t dpdk_eal_init(void) - } - - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -- uint32_t mbuf_cache_size, uint16_t queue_id) -+ uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id) - { - int32_t ret; - char pool_name[PATH_MAX]; -@@ -145,12 +145,13 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - - ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d \n", ret); - return NULL; - } - - /* time stamp before pbuf_custom as priv_data */ - uint16_t private_size = RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); -- pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf, mbuf_cache_size, private_size, MBUF_SZ, rte_socket_id()); -+ pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf, mbuf_cache_size, private_size, MBUF_SZ, numa_id); - if (pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "cannot create %s pool rte_err=%d\n", pool_name, rte_errno); - } -@@ -611,7 +612,7 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i - int32_t ret; - - struct rte_mempool *rxtx_pktmbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx]; -- -+ - uint16_t socket_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); - if (!cfg->use_ltran && cfg->num_process == 1) { -@@ -664,7 +665,7 @@ int32_t dpdk_ethdev_start(void) - int32_t dpdk_init_lstack_kni(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- stack_group->kni_pktmbuf_pool = create_pktmbuf_mempool("kni_mbuf", KNI_NB_MBUF, 0, 0); -+ stack_group->kni_pktmbuf_pool = create_pktmbuf_mempool("kni_mbuf", KNI_NB_MBUF, 0, 0, rte_socket_id()); - if (stack_group->kni_pktmbuf_pool == NULL) { - return -1; - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 3662948..2fd8d0a 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -523,6 +523,46 @@ static void gazelle_listen_thread(void *arg) - recv_pkts_from_other_process(cfg_param->process_idx, arg); - } - -+int32_t stack_group_init_mempool(void) -+{ -+ struct cfg_params *global_cfg_parmas = get_global_cfg_params(); -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct rte_mempool *rxtx_mbuf = NULL; -+ uint32_t cpu_id = 0; -+ unsigned numa_id = 0; -+ int queue_id = 0; -+ -+ LSTACK_LOG(INFO, LSTACK, -+ "config::num_cpu=%d num_process=%d \n", global_cfg_parmas->num_cpu, global_cfg_parmas->num_process); -+ -+ uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; -+ -+ for (int cpu_idx = 0; cpu_idx < global_cfg_parmas->num_cpu; cpu_idx++) { -+ cpu_id = global_cfg_parmas->cpus[cpu_idx]; -+ numa_id = numa_node_of_cpu(cpu_id); -+ -+ for (int process_idx = 0; process_idx < global_cfg_parmas->num_process; process_idx++) { -+ queue_id = cpu_idx * global_cfg_parmas->num_process + process_idx; -+ if (queue_id >= PROTOCOL_STACK_MAX) { -+ LSTACK_LOG(ERR, LSTACK, "index is over\n"); -+ return -1; -+ } -+ -+ rxtx_mbuf = create_pktmbuf_mempool( -+ "rxtx_mbuf", total_mbufs / stack_group->stack_num, RXTX_CACHE_SZ, queue_id, numa_id); -+ if (rxtx_mbuf == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "cpuid=%u, numid=%d , rxtx_mbuf idx= %d create_pktmbuf_mempool fail\n", -+ cpu_id, numa_id, queue_id); -+ return -1; -+ } -+ -+ get_protocol_stack_group()->total_rxtx_pktmbuf_pool[queue_id] = rxtx_mbuf; -+ } -+ } -+ -+ return 0; -+} -+ - int32_t stack_group_init(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -@@ -542,14 +582,8 @@ int32_t stack_group_init(void) - stack_group->stack_setup_fail = 0; - - if (get_global_cfg_params()->is_primary) { -- uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; -- for (uint16_t idx = 0; idx < get_global_cfg_params()->tot_queue_num; idx++) { -- struct rte_mempool* rxtx_mbuf = create_pktmbuf_mempool("rxtx_mbuf", -- total_mbufs / stack_group->stack_num, RXTX_CACHE_SZ, idx); -- if (rxtx_mbuf == NULL) { -- return -1; -- } -- get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx] = rxtx_mbuf; -+ if (stack_group_init_mempool() != 0) { -+ return -1; - } - } - -@@ -970,7 +1004,7 @@ void stack_recvlist_count(struct rpc_msg *msg) - list_for_each_safe(node, temp, list) { - count++; - } -- -+ - msg->result = count; - } - -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 6ca4f3b..1a054d6 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -56,7 +56,7 @@ void dpdk_restore_pci(void); - bool port_in_stack_queue(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); - uint16_t get_port_id(void); - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -- uint32_t mbuf_cache_size, uint16_t queue_id); -+ uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); - - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num); --- -2.23.0 - diff --git a/0040-when-timeout-occurs-process-exits.patch b/0040-when-timeout-occurs-process-exits.patch deleted file mode 100644 index 088226a..0000000 --- a/0040-when-timeout-occurs-process-exits.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 3a0bb8c06789288c7152e439b4eed0007a234134 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Wed, 1 Nov 2023 20:18:07 +0800 -Subject: [PATCH] when timeout occurs,process exits. - ---- - src/common/gazelle_dfx_msg.c | 37 +++++++++++++++++++++++------------- - src/common/gazelle_dfx_msg.h | 2 +- - 2 files changed, 25 insertions(+), 14 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.c b/src/common/gazelle_dfx_msg.c -index 2070d5f..b8472be 100644 ---- a/src/common/gazelle_dfx_msg.c -+++ b/src/common/gazelle_dfx_msg.c -@@ -14,28 +14,39 @@ - #include - #include - #include -+#include -+#include - - #include "gazelle_dfx_msg.h" - - int read_specied_len(int fd, char *buf, size_t target_size) - { -- ssize_t tmp_size; -- char *tmp_pbuf = buf; -- while (target_size > 0) { -- tmp_size = read(fd, tmp_pbuf, target_size); -- if ((tmp_size == -1) && (errno != EINTR)) { -- printf("read msg from fd %d failed, errno %d\n", fd, errno); -+ size_t total_read = 0; -+ struct pollfd fds[1]; -+ fds[0].fd = fd; -+ fds[0].events = POLLIN; -+ -+ while (total_read < target_size) { -+ int ret = poll(fds, 1, GAZELLECTL_TIMEOUT); -+ if (ret < 0) { -+ printf("read_specied_len:: poll ret=%d \n", ret); - return -1; -- } else if (tmp_size == 0) { -- printf("read zero bytes from fd %d, maybe peer is down\n", fd); -+ } else if (ret == 0) { -+ printf("read_specied_len:: time out"); - return -1; - } -- -- tmp_size = (tmp_size < 0) ? 0 : tmp_size; -- target_size -= (size_t)tmp_size; -- tmp_pbuf += tmp_size; -+ if (fds[0].revents & POLLIN) { -+ int n = read(fd, buf + total_read, target_size - total_read); -+ if (n < 0) { -+ printf("read_specied_len:: read ret=%d", ret); -+ return -1; -+ } else if (n == 0) { -+ printf("read_specied_len:: Connection closed"); -+ return -1; -+ } -+ total_read += n; -+ } - } -- - return 0; - } - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 19dddd8..93fe3df 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -18,7 +18,7 @@ - - #define GAZELLE_CLIENT_NUM_MIN 1 - #define GAZELLE_LOG_LEVEL_MAX 10 -- -+#define GAZELLECTL_TIMEOUT 5000 // millisecond - /* maybe it should be consistent with MEMP_NUM_TCP_PCB */ - #define GAZELLE_LSTACK_MAX_CONN (20000 + 2000) // same as MAX_CLIENTS + RESERVED_CLIENTS in lwipopts.h - --- -2.27.0 - diff --git a/0041-wrap-support-select.patch b/0041-wrap-support-select.patch deleted file mode 100644 index 72949d0..0000000 --- a/0041-wrap-support-select.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 21425705a687706faa642e8b99a9c549d7bcaab6 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 2 Nov 2023 16:10:04 +0800 -Subject: [PATCH] wrap: support select - ---- - src/lstack/api/lstack_epoll.c | 88 +++++++++++++++++++++++++ - src/lstack/api/lstack_rtc_api.c | 7 ++ - src/lstack/api/lstack_rtw_api.c | 5 ++ - src/lstack/api/lstack_wrap.c | 19 ++++++ - src/lstack/include/lstack_rtc_api.h | 2 + - src/lstack/include/lstack_rtw_api.h | 3 + - src/lstack/include/posix/lstack_epoll.h | 1 + - 7 files changed, 125 insertions(+) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index a711ae3..f2c4a8b 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -870,3 +871,90 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - return lwip_num + kernel_num; - } -+ -+static void select_set_revent_fdset(struct pollfd *fds, nfds_t nfds, fd_set *eventfds, uint32_t event) -+{ -+ FD_ZERO(eventfds); -+ -+ /* Set the fd_set parameter based on the actual revents. */ -+ for (int i = 0; i < nfds; i++) { -+ if (fds[i].revents & event) { -+ FD_SET(fds[i].fd, eventfds); -+ } -+ } -+} -+ -+static void fds_poll2select(struct pollfd *fds, nfds_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -+{ -+ if (fds == NULL || nfds == 0) { -+ return; -+ } -+ -+ if (readfds) { -+ select_set_revent_fdset(fds, nfds, readfds, EPOLLIN); -+ } -+ if (writefds) { -+ select_set_revent_fdset(fds, nfds, writefds, EPOLLOUT); -+ } -+ if (exceptfds) { -+ select_set_revent_fdset(fds, nfds, exceptfds, EPOLLERR); -+ } -+} -+ -+static inline int timeval_to_ms(struct timeval *timeval) -+{ -+ if (timeval == NULL) { -+ return -1; -+ } -+ -+ return (timeval->tv_sec * 1000 + timeval->tv_usec / 1000); -+} -+ -+static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct pollfd **fds) -+{ -+ struct pollfd pollfds[FD_SETSIZE] = { 0 }; -+ nfds_t nfds = 0; -+ -+ for (int i = 0; i < maxfd; i++) { -+ if (readfds && FD_ISSET(i, readfds)) { -+ pollfds[nfds].events = POLLIN; -+ } -+ if (writefds && FD_ISSET(i, writefds)) { -+ pollfds[nfds].events |= POLLOUT; -+ } -+ if (exceptfds && FD_ISSET(i, exceptfds)) { -+ pollfds[nfds].events |= POLLERR; -+ } -+ if (pollfds[nfds].events > 0) { -+ pollfds[nfds].fd = i; -+ nfds++; -+ } -+ } -+ -+ *fds = pollfds; -+ return nfds; -+} -+ -+int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval) -+{ -+ if (maxfd == 0) { -+ return 0; -+ } -+ -+ if (maxfd < 0 || maxfd > FD_SETSIZE || (readfds == NULL && writefds == NULL && exceptfds == NULL)) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ /* Convert the select parameter to the poll parameter. */ -+ struct pollfd *fds = NULL; -+ nfds_t nfds = fds_select2poll(maxfd, readfds, writefds, exceptfds, &fds); -+ int timeout = timeval_to_ms(timeval); -+ -+ int event_num = lstack_poll(fds, nfds, timeout); -+ -+ /* After poll, set select fd_set by fds.revents. */ -+ fds_poll2select(fds, nfds, readfds, writefds, exceptfds); -+ -+ return event_num; -+} -+ -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 059b518..5fad3e8 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -24,6 +24,13 @@ - - int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) - { -+ LSTACK_LOG(ERR, LSTACK, "rtc_poll: rtc currently does not support poll\n"); -+ return -1; -+} -+ -+int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ LSTACK_LOG(ERR, LSTACK, "rtc_select: rtc currently does not support select\n"); - return -1; - } - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 7d14ffa..c524bf9 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -214,6 +214,11 @@ int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) - return lstack_poll(fds, nfds, timeout); - } - -+int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ return lstack_select(nfds, readfds, writefds, exceptfds, timeout); -+} -+ - int rtw_close(int s) - { - struct lwip_sock *sock = get_socket(s); -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index a808ee8..5bad513 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -76,6 +76,7 @@ void wrap_api_init(void) - g_wrap_api->epoll_ctl_fn = rtc_epoll_ctl; - g_wrap_api->epoll_create1_fn = rtc_epoll_create1; - g_wrap_api->epoll_create_fn = rtc_epoll_create; -+ g_wrap_api->select_fn = rtc_select; - } else { - g_wrap_api->socket_fn = rtw_socket; - g_wrap_api->accept_fn = rtw_accept; -@@ -103,6 +104,7 @@ void wrap_api_init(void) - g_wrap_api->epoll_ctl_fn = rtw_epoll_ctl; - g_wrap_api->epoll_create1_fn = rtw_epoll_create1; - g_wrap_api->epoll_create_fn = rtw_epoll_create; -+ g_wrap_api->select_fn = rtw_select; - } - } - -@@ -609,6 +611,15 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - return lstack_sigaction(signum, act, oldact); - } - -+static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ if (select_posix_path() == PATH_KERNEL) { -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ } -+ -+ return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+} -+ - #define WRAP_VA_PARAM(_fd, _cmd, _lwip_fcntl, _fcntl_fn) \ - do { \ - unsigned long val; \ -@@ -769,6 +780,10 @@ pid_t fork(void) - { - return lstack_fork(); - } -+int32_t select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ return do_select(nfds, readfds, writefds, exceptfds, timeout); -+} - - /* -------------------------------------------------------- - * ------- Compile mode replacement interface ----------- -@@ -898,3 +913,7 @@ pid_t __wrap_fork(void) - { - return lstack_fork(); - } -+int32_t __wrap_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ return do_select(nfds, readfds, writefds, exceptfds, timeout); -+} -diff --git a/src/lstack/include/lstack_rtc_api.h b/src/lstack/include/lstack_rtc_api.h -index 0aff928..dd90e59 100644 ---- a/src/lstack/include/lstack_rtc_api.h -+++ b/src/lstack/include/lstack_rtc_api.h -@@ -13,6 +13,7 @@ - #ifndef _LSTACK_RTC_API_H_ - #define _LSTACK_RTC_API_H_ - #include -+#include - #include - - /* don't include lwip/sockets.h, conflict with sys/socket.h */ -@@ -51,5 +52,6 @@ int rtc_close(int s); - int rtc_epoll_create(int flags); - int rtc_epoll_create1(int flags); - int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -+int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); - - #endif /* __LSTACK_RTC_API_H_ */ -diff --git a/src/lstack/include/lstack_rtw_api.h b/src/lstack/include/lstack_rtw_api.h -index facf4c0..d0f77b7 100644 ---- a/src/lstack/include/lstack_rtw_api.h -+++ b/src/lstack/include/lstack_rtw_api.h -@@ -14,6 +14,7 @@ - #define _LSTACK_RTW_API_H_ - - #include -+#include - #include - - int rtw_socket(int domain, int type, int protocol); -@@ -44,4 +45,6 @@ int rtw_close(int s); - int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); - int rtw_epoll_create1(int flags); - int rtw_epoll_create(int flags); -+int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -+ - #endif /* _LSTACK_RTW_API_H_ */ -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index c42f3a5..9c34eb3 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -78,6 +78,7 @@ int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event *events, int32_t maxevents, int32_t timeout); - int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout); - int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout); -+int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval); - - #ifdef __cplusplus - } --- -2.27.0 - diff --git a/0042-add-vlan-support.patch b/0042-add-vlan-support.patch deleted file mode 100644 index 02c5138..0000000 --- a/0042-add-vlan-support.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 1febf2f274f5bf13004ddde6d20e8744e36fd650 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Fri, 3 Nov 2023 14:33:20 +0000 -Subject: [PATCH] add vlan support - ---- - src/common/gazelle_opt.h | 4 +++- - src/lstack/core/lstack_cfg.c | 13 +++++++++++++ - src/lstack/core/lstack_lwip.c | 4 ++++ - src/lstack/include/lstack_cfg.h | 1 + - src/lstack/lstack.conf | 3 +++ - src/lstack/netif/lstack_ethdev.c | 8 +++++++- - src/lstack/netif/lstack_vdev.c | 4 +++- - 7 files changed, 34 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 7b855f9..0479051 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -52,7 +52,9 @@ - #define STACK_THREAD_DEFAULT 4 - #define STACK_NIC_READ_DEFAULT 128 - --#define MBUF_MAX_DATA_LEN 1460 -+#define MTU_DEFAULT_DATA_LEN 1460 -+#define VLAN_HEAD_LEN 4 -+#define MBUF_MAX_DATA_LEN (MTU_DEFAULT_DATA_LEN - VLAN_HEAD_LEN) - - #define DPDK_PKT_BURST_SIZE 512 - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index c4278b5..ac96b1b 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -78,6 +78,7 @@ static int32_t parse_udp_enable(void); - static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); -+static int32_t parse_nic_vlan_mode(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -138,6 +139,7 @@ static struct config_vector_t g_config_tbl[] = { - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, -+ { "nic_vlan_mode", parse_nic_vlan_mode }, - { NULL, NULL } - }; - -@@ -1224,3 +1226,14 @@ static int32_t parse_stack_thread_mode(void) - - return 0; - } -+ -+static int32_t parse_nic_vlan_mode(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.nic.vlan_mode, "nic_vlan_mode", 0, 0, 4094, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid vlan mode value %d ret=%d. only support 0~4094\n", \ -+ g_config_params.nic.vlan_mode, ret); -+ } -+ return ret; -+} -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index cdb0089..d5c4896 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -196,6 +196,10 @@ void do_lwip_init_sock(int32_t fd) - (void)replenish_send_idlembuf(stack, sock); - - sock->stack = stack; -+ if (get_global_cfg_params()->nic.vlan_mode > 0 && get_global_cfg_params()->nic.vlan_mode < 4095) { -+ sock->conn->pcb.udp->netif_hints.tci = get_global_cfg_params()->nic.vlan_mode; -+ } -+ - init_list_node_null(&sock->recv_list); - init_list_node_null(&sock->event_list); - } -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index fc627e3..9dea4c1 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -62,6 +62,7 @@ struct secondary_attach_arg { - struct cfg_nic_params { - uint32_t rxqueue_size; - uint32_t txqueue_size; -+ uint16_t vlan_mode; - }; - - struct cfg_params { -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 48973fe..3eb4685 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -63,3 +63,6 @@ process_idx=0 - - #tuple_filer=0, below cfg valid - listen_shadow=0 -+ -+#vlan mode; only support 0~4094, 0 is disabled -+nic_vlan_mode=0 -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index da16e85..383a56b 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -778,7 +778,13 @@ int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_fla - /* copy arp into other stack */ - if (!use_ltran_flag) { - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); -- if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == ethh->ether_type)) { -+ u16_t type; -+ type = ethh->ether_type; -+ if (type == PP_HTONS(ETHTYPE_VLAN)) { -+ struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethh) + SIZEOF_ETH_HDR); -+ type = vlan->tpid; -+ } -+ if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == type)) { - stack_broadcast_arp(stack->pkts[i], stack); - /* copy arp into other process */ - transfer_arp_to_other_process(stack->pkts[i]); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 81b48dc..fb295e0 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - #include "lstack_cfg.h" - #include "lstack_dpdk.h" -@@ -83,12 +84,13 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - } - - /* skip gro when tcp/ip cksum offloads disable */ -- if (get_protocol_stack_group()->rx_offload == 0) { -+ if (get_protocol_stack_group()->rx_offload == 0 || get_global_cfg_params()->nic.vlan_mode > 0) { - return pkt_num; - } - - for (uint32_t i = 0; i < pkt_num; i++) { - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); -+ - if (unlikely(RTE_BE16(RTE_ETHER_TYPE_IPV4) != ethh->ether_type)) { - continue; - } --- -2.27.0 - diff --git a/0043-slave-mac-addr.patch b/0043-slave-mac-addr.patch deleted file mode 100644 index f212faa..0000000 --- a/0043-slave-mac-addr.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 5e10c47492fef0eef886fa42651d3acef03f4196 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Wed, 1 Nov 2023 07:50:16 +0800 -Subject: [PATCH] slave mac addr - ---- - src/lstack/core/lstack_cfg.c | 50 ++++++++++++++++----------------- - src/lstack/core/lstack_dpdk.c | 47 ++++++++++++++----------------- - src/lstack/include/lstack_cfg.h | 4 +-- - 3 files changed, 48 insertions(+), 53 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index c4278b5..5ac6aa7 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1137,40 +1137,40 @@ static int32_t parse_bond_slave_mac(void) - return 0; - } - -- int32_t ret; -- const char *slave_mac1 = NULL; -- const char *slave_mac2 = NULL; -+ int32_t ret = 0; -+ const char *bond_slave_mac = NULL; - const config_setting_t *devs = NULL; - -- devs = config_lookup(&g_config, "slave_mac1"); -- if (devs == NULL) { -- return -EINVAL; -- } -- slave_mac1 = config_setting_get_string(devs); -- if (slave_mac1 == NULL) { -- return 0; -- } -- -- devs = config_lookup(&g_config, "slave_mac2"); -+ devs = config_lookup(&g_config, "bond_slave_mac"); - if (devs == NULL) { - return -EINVAL; - } -- slave_mac2 = config_setting_get_string(devs); -- if (slave_mac2 == NULL) { -+ bond_slave_mac = config_setting_get_string(devs); -+ if (bond_slave_mac == NULL) { - return 0; - } - -- /* add dev */ -- ret = str_to_eth_addr(slave_mac1, g_config_params.bond_slave1_mac_addr); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", slave_mac1, ret); -- return ret; -- } -- -- ret = str_to_eth_addr(slave_mac2, g_config_params.bond_slave2_mac_addr); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", slave_mac2, ret); -+ int32_t k = 0; -+ char *bond_slave_mac_tmp = strdup(bond_slave_mac); -+ char *tmp = NULL; -+ const char *delim = ";"; -+ -+ char *mac_addr = strtok_s(bond_slave_mac_tmp, delim, &tmp); -+ while (mac_addr != NULL) { -+ if (k >= GAZELLE_MAX_BOND_NUM) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: too many slave mac address. The maximum number of mac address is %d.\n", -+ GAZELLE_MAX_BOND_NUM); -+ return -EINVAL; -+ } -+ ret = str_to_eth_addr(mac_addr, g_config_params.bond_slave_mac_addr[k].addr_bytes); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", mac_addr, ret); -+ return ret; -+ } -+ mac_addr = strtok_s(NULL, delim, &tmp); -+ k = k + 1; - } -+ free(bond_slave_mac_tmp); - return ret; - } - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 1a5b568..4318096 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -496,46 +496,41 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - - if (bond_port) { -- int slave_num = 2; -- int32_t slave_port_id[2]; -- slave_port_id[0] = ethdev_port_id(get_global_cfg_params()->bond_slave1_mac_addr); -- if (slave_port_id[0] < 0) { -- LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[0]); -- return slave_port_id[0]; -- } -- -- slave_port_id[1] = ethdev_port_id(get_global_cfg_params()->bond_slave2_mac_addr); -- if (slave_port_id[1] < 0) { -- LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[1]); -- return slave_port_id[1]; -- } -- -- for (int i = 0; i < slave_num; i++) { -+ int32_t slave_port_id[GAZELLE_MAX_BOND_NUM]; -+ for (int i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -+ if (rte_is_zero_ether_addr(&get_global_cfg_params()->bond_slave_mac_addr[i])) { -+ break; -+ } -+ slave_port_id[i] = ethdev_port_id(get_global_cfg_params()->bond_slave_mac_addr[i].addr_bytes); -+ if (slave_port_id[i] < 0) { -+ LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[1]); -+ return slave_port_id[i]; -+ } - ret = dpdk_ethdev_init(slave_port_id[i], 0); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); - return -1; - } - ret = rte_eth_promiscuous_enable(slave_port_id[i]); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk slave enable promiscuous failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_allmulticast_enable(slave_port_id[i]); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk slave enable allmulticast failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_bond_slave_add(port_id, slave_port_id[i]); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk add slave port failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_dev_start(slave_port_id[i]); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk start slave port failed ret = %d\n", ret); - return -1; - } -@@ -550,15 +545,15 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - if (bond_port) { - struct rte_eth_dev_info slave_dev_info; - int slave_id = rte_eth_bond_primary_get(port_id); -- if (slave_id < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk get bond primary port failed port = %d\n", slave_id); -- return slave_id; -- } -+ if (slave_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk get bond primary port failed port = %d\n", slave_id); -+ return slave_id; -+ } - ret = rte_eth_dev_info_get(slave_id, &slave_dev_info); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk get bond dev info failed ret = %d\n", ret); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk get bond dev info failed ret = %d\n", ret); - return ret; -- } -+ } - dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; - dev_info.tx_offload_capa = slave_dev_info.tx_offload_capa; - dev_info.reta_size = slave_dev_info.reta_size; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index fc627e3..c1a6464 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -15,6 +15,7 @@ - #include - - #include -+#include - - #include "lstack_protocol_stack.h" - #include "gazelle_opt.h" -@@ -111,8 +112,7 @@ struct cfg_params { - bool expand_send_ring; - bool tuple_filter; - int8_t bond_mode; -- uint8_t bond_slave1_mac_addr[ETHER_ADDR_LEN]; -- uint8_t bond_slave2_mac_addr[ETHER_ADDR_LEN]; -+ struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; - bool use_sockmap; - bool udp_enable; - struct cfg_nic_params nic; --- -2.27.0 - diff --git a/0044-PRE_LOG-modify-prelog-info-transfer-to-terminal-at-t.patch b/0044-PRE_LOG-modify-prelog-info-transfer-to-terminal-at-t.patch deleted file mode 100644 index 74be8d0..0000000 --- a/0044-PRE_LOG-modify-prelog-info-transfer-to-terminal-at-t.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 69451fc6a5a7ca0f903c82cf8b44bcdbfa2707b6 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Thu, 16 Nov 2023 17:29:21 +0800 -Subject: [PATCH] PRE_LOG: modify prelog info transfer to terminal at the same - time - ---- - src/lstack/include/lstack_log.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/include/lstack_log.h b/src/lstack/include/lstack_log.h -index 8b4209a..e4bed37 100644 ---- a/src/lstack/include/lstack_log.h -+++ b/src/lstack/include/lstack_log.h -@@ -32,7 +32,7 @@ do { \ - - static inline void lstack_prelog_init(const char *name) - { -- openlog(name, LOG_CONS | LOG_PID, LOG_USER); -+ openlog(name, LOG_PERROR | LOG_PID, LOG_USER); - } - static inline void lstack_prelog_uninit(void) - { --- -2.27.0 - diff --git a/0045-ethdev-mbuf-data-start-pointer-pbuf-payload.patch b/0045-ethdev-mbuf-data-start-pointer-pbuf-payload.patch deleted file mode 100644 index 1efe4b2..0000000 --- a/0045-ethdev-mbuf-data-start-pointer-pbuf-payload.patch +++ /dev/null @@ -1,64 +0,0 @@ -From b902a2a2f392ab945bedf7d2d9eb22f6a0aa032c Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 15 Nov 2023 19:15:13 +0800 -Subject: [PATCH] ethdev: mbuf data start pointer pbuf->payload - ---- - src/lstack/netif/lstack_ethdev.c | 26 ++++++++++---------------- - 1 file changed, 10 insertions(+), 16 deletions(-) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index da16e85..1d04684 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -809,10 +809,7 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - struct rte_mbuf *pre_mbuf = NULL; - struct rte_mbuf *first_mbuf = NULL; - struct pbuf *first_pbuf = pbuf; -- uint16_t header_len = 0; -- if (likely(first_pbuf != NULL)) { -- header_len = first_pbuf->l2_len + first_pbuf->l3_len + first_pbuf->l4_len; -- } -+ void *buf_addr; - - while (likely(pbuf != NULL)) { - struct rte_mbuf *mbuf = pbuf_to_mbuf(pbuf); -@@ -821,26 +818,23 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - mbuf->pkt_len = pbuf->tot_len; - mbuf->ol_flags = pbuf->ol_flags; - mbuf->next = NULL; -+ buf_addr = rte_pktmbuf_mtod(mbuf, void *); -+ -+ /* -+ * |rte_mbuf | mbuf_private | data_off | data | -+ * ^ ^ -+ * buf_addr payload -+ * m->buf_addr pointer pbuf->payload -+ */ -+ mbuf->data_off += (uint8_t *)pbuf->payload - (uint8_t *)buf_addr; - - if (first_mbuf == NULL) { - first_mbuf = mbuf; - first_pbuf = pbuf; - first_mbuf->nb_segs = 1; -- if (pbuf->header_off > 0) { -- mbuf->data_off -= header_len; -- pbuf->header_off = 0; -- } - } else { - first_mbuf->nb_segs++; - pre_mbuf->next = mbuf; -- if (pbuf->header_off == 0) { -- mbuf->data_off += header_len; -- pbuf->header_off = header_len; -- } -- } -- -- if (first_pbuf->l4_len == 8) { -- mbuf->data_off += 12; - } - - if (likely(first_mbuf->pkt_len > MBUF_MAX_LEN)) { --- -2.27.0 - diff --git a/0047-cfg-fix-lstack-mempool-lookup-failed-in-ltran-mode.patch b/0047-cfg-fix-lstack-mempool-lookup-failed-in-ltran-mode.patch deleted file mode 100644 index 4fc20ce..0000000 --- a/0047-cfg-fix-lstack-mempool-lookup-failed-in-ltran-mode.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 31a7c86437dcc5c3ea03694f094fef2236021174 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 17 Nov 2023 19:52:38 +0800 -Subject: [PATCH] cfg: fix lstack mempool lookup failed in ltran mode - ---- - src/lstack/core/lstack_cfg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index d2d0fc1..441a2dc 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1026,6 +1026,7 @@ static int32_t parse_seperate_sendrecv_args(void) - static int32_t parse_num_process(void) - { - if (g_config_params.use_ltran) { -+ g_config_params.num_process = 1; - return 0; - } - --- -2.27.0 - diff --git a/0048-add-tx-package-timeout.patch b/0048-add-tx-package-timeout.patch deleted file mode 100644 index 51acbf0..0000000 --- a/0048-add-tx-package-timeout.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 80eccdd1bb639a1ea8c186c8c2b7f451b0b38a7e Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Tue, 31 Oct 2023 11:44:29 +0000 -Subject: [PATCH] add tx package timeout - ---- - src/lstack/netif/lstack_vdev.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 81b48dc..62abe80 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -142,10 +142,11 @@ static uint32_t vdev_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkt - stack->stats.tx_prepare_fail++; - LSTACK_LOG(INFO, LSTACK, "rte_eth_tx_prepare failed\n"); - } -+ const uint32_t tbegin = sys_now(); - - do { - sent_pkts += rte_eth_tx_burst(stack->port_id, stack->queue_id, &pkts[sent_pkts], nr_pkts - sent_pkts); -- } while (sent_pkts < nr_pkts); -+ } while (sent_pkts < nr_pkts && (ENQUEUE_RING_RETRY_TIMEOUT > sys_now() - tbegin)); - - return sent_pkts; - } --- -2.27.0 - diff --git a/0049-modif-mem.patch b/0049-modif-mem.patch deleted file mode 100644 index 7ace811..0000000 --- a/0049-modif-mem.patch +++ /dev/null @@ -1,48 +0,0 @@ -From e69c39c7c73abd1245c1f7aecde3333fdb45ca2b Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sat, 18 Nov 2023 17:07:32 +0800 -Subject: [PATCH] modif mem - ---- - src/lstack/api/lstack_epoll.c | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index f2c4a8b..7572918 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -910,9 +910,9 @@ static inline int timeval_to_ms(struct timeval *timeval) - return (timeval->tv_sec * 1000 + timeval->tv_usec / 1000); - } - --static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct pollfd **fds) -+static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct pollfd *fds) - { -- struct pollfd pollfds[FD_SETSIZE] = { 0 }; -+ struct pollfd *pollfds = fds; - nfds_t nfds = 0; - - for (int i = 0; i < maxfd; i++) { -@@ -930,8 +930,6 @@ static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_s - nfds++; - } - } -- -- *fds = pollfds; - return nfds; - } - -@@ -946,8 +944,8 @@ int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfd - } - - /* Convert the select parameter to the poll parameter. */ -- struct pollfd *fds = NULL; -- nfds_t nfds = fds_select2poll(maxfd, readfds, writefds, exceptfds, &fds); -+ struct pollfd fds[FD_SETSIZE] = { 0 }; -+ nfds_t nfds = fds_select2poll(maxfd, readfds, writefds, exceptfds, fds); - int timeout = timeval_to_ms(timeval); - - int event_num = lstack_poll(fds, nfds, timeout); --- -2.27.0 - diff --git a/0050-enable-ipv6.patch b/0050-enable-ipv6.patch deleted file mode 100644 index 2337d2f..0000000 --- a/0050-enable-ipv6.patch +++ /dev/null @@ -1,734 +0,0 @@ -From 480ef35615b5b0cb21818b117d4bedec42de93e4 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Tue, 31 Oct 2023 04:24:34 +0800 -Subject: [PATCH] enable ipv6 - ---- - src/common/gazelle_opt.h | 3 +- - src/lstack/api/lstack_wrap.c | 93 ++++++---------- - src/lstack/core/lstack_cfg.c | 29 ++++- - src/lstack/core/lstack_control_plane.c | 4 +- - src/lstack/core/lstack_dpdk.c | 29 +++-- - src/lstack/core/lstack_lwip.c | 38 +++++-- - src/lstack/core/lstack_protocol_stack.c | 5 +- - src/lstack/include/lstack_cfg.h | 2 + - src/lstack/include/lstack_dpdk.h | 3 +- - src/lstack/netif/lstack_ethdev.c | 141 ++++++++++++++++-------- - src/lstack/netif/lstack_vdev.c | 36 +++--- - src/ltran/ltran_timer.c | 8 ++ - 12 files changed, 241 insertions(+), 150 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 0479051..7316fc6 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -54,7 +54,8 @@ - - #define MTU_DEFAULT_DATA_LEN 1460 - #define VLAN_HEAD_LEN 4 --#define MBUF_MAX_DATA_LEN (MTU_DEFAULT_DATA_LEN - VLAN_HEAD_LEN) -+#define IPV6_EXTRA_HEAD_LEN 20 -+#define MBUF_MAX_DATA_LEN (MTU_DEFAULT_DATA_LEN - VLAN_HEAD_LEN - IPV6_EXTRA_HEAD_LEN) - - #define DPDK_PKT_BURST_SIZE 512 - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 5bad513..9468003 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -12,6 +12,8 @@ - - #define _GNU_SOURCE - #include -+#include -+#include - - #include - #include -@@ -184,28 +186,6 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - --#define SIOCGIFADDR 0x8915 --static int get_addr(struct sockaddr_in *sin, char *interface) --{ -- int sockfd = 0; -- struct ifreq ifr; -- -- if ((sockfd = posix_api->socket_fn(AF_INET, SOCK_STREAM, 0)) < 0) return -1; -- -- memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); -- snprintf_s(ifr.ifr_name, sizeof(ifr.ifr_name), (sizeof(ifr.ifr_name) - 1), "%s", interface); -- -- if (posix_api->ioctl_fn(sockfd, SIOCGIFADDR, &ifr) < 0) { -- posix_api->close_fn(sockfd); -- return -1; -- } -- posix_api->close_fn(sockfd); -- -- memcpy_s(sin, sizeof(struct sockaddr_in), &ifr.ifr_addr, sizeof(struct sockaddr_in)); -- -- return 0; --} -- - static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen) - { - if (name == NULL) { -@@ -229,55 +209,39 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - - bool is_dst_ip_localhost(const struct sockaddr *addr) - { -- struct sockaddr_in *servaddr = (struct sockaddr_in *) addr; -- char *line = NULL; -- char *p; -- size_t linel = 0; -- int linenum = 0; -- if (get_global_cfg_params()->host_addr.addr == servaddr->sin_addr.s_addr) { -- return true; -- } -+ struct ifaddrs *ifap; -+ struct ifaddrs *ifa; - -- FILE *ifh = fopen("/proc/net/dev", "r"); -- if (ifh == NULL) { -- LSTACK_LOG(ERR, LSTACK, "failed to open /proc/net/dev, errno is %d\n", errno); -- return false; -+ if (addr->sa_family == AF_INET) { -+ if (get_global_cfg_params()->host_addr.addr == ((struct sockaddr_in *)addr)->sin_addr.s_addr) { -+ return true; -+ } - } -- struct sockaddr_in* sin = malloc(sizeof(struct sockaddr_in)); -- if (sin == NULL) { -- LSTACK_LOG(ERR, LSTACK, "sockaddr_in malloc failed\n"); -- fclose(ifh); -+ -+ if (getifaddrs(&ifap) == -1) { -+ LSTACK_LOG(ERR, LSTACK, "get interface IP address failed\n"); - return false; - } - -- while (getdelim(&line, &linel, '\n', ifh) > 0) { -- /* 2: skip the first two lines, which are not nic name */ -- if (linenum++ < 2) { -+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { -+ if (ifa->ifa_addr == NULL) { - continue; - } -- -- p = line; -- while (isspace(*p)) { -- ++p; -- } -- int n = strcspn(p, ": \t"); -- -- char interface[20] = {0}; /* 20: nic name len */ -- strncpy_s(interface, sizeof(interface), p, n); -- -- memset_s(sin, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)); -- int ret = get_addr(sin, interface); -- if (ret == 0) { -- if (sin->sin_addr.s_addr == servaddr->sin_addr.s_addr) { -- free(sin); -- fclose(ifh); -+ if (ifa->ifa_addr->sa_family == AF_INET && addr->sa_family == AF_INET) { -+ struct sockaddr_in *if_addr = (struct sockaddr_in *)ifa->ifa_addr; -+ if (memcmp(&if_addr->sin_addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr)) == 0) { -+ freeifaddrs(ifap); -+ return true; -+ } -+ } else if (ifa->ifa_addr->sa_family == AF_INET6 && addr->sa_family == AF_INET6) { -+ struct sockaddr_in6 *if_addr = (struct sockaddr_in6 *)ifa->ifa_addr; -+ if (memcmp(&if_addr->sin6_addr, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof(struct in6_addr)) == 0) { -+ freeifaddrs(ifap); - return true; - } - } - } -- free(sin); -- fclose(ifh); -- -+ freeifaddrs(ifap); - return false; - } - -@@ -303,11 +267,15 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - } - - int32_t ret = 0; -+ int32_t remote_port; -+ bool is_local = is_dst_ip_localhost(name); -+ -+ remote_port = htons(((struct sockaddr_in *)name)->sin_port); -+ - char listen_ring_name[RING_NAME_LEN]; -- int remote_port = htons(((struct sockaddr_in *)name)->sin_port); - snprintf_s(listen_ring_name, sizeof(listen_ring_name), sizeof(listen_ring_name) - 1, - "listen_rx_ring_%d", remote_port); -- if (is_dst_ip_localhost(name) && rte_ring_lookup(listen_ring_name) == NULL) { -+ if (is_local && rte_ring_lookup(listen_ring_name) == NULL) { - ret = posix_api->connect_fn(s, name, namelen); - SET_CONN_TYPE_HOST(sock->conn); - } else { -@@ -403,6 +371,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - } - - if ((domain != AF_INET && domain != AF_UNSPEC) || -+ ((domain == AF_INET6) && !get_global_cfg_params()->ipv6_enable) || - ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)) { - return posix_api->socket_fn(domain, type, protocol); - } -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 729dccb..9f3143f 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -46,6 +46,7 @@ static struct cfg_params g_config_params; - static config_t g_config; - - static int32_t parse_host_addr(void); -+static int32_t parse_host_addr6(void); - static int32_t parse_low_power_mode(void); - static int32_t parse_stack_cpu_number(void); - static int32_t parse_app_bind_numa(void); -@@ -75,6 +76,7 @@ static int32_t parse_bond_mode(void); - static int32_t parse_bond_slave_mac(void); - static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); -+static int32_t parse_ipv6_enable(void); - static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); -@@ -107,6 +109,7 @@ struct config_vector_t { - - static struct config_vector_t g_config_tbl[] = { - { "host_addr", parse_host_addr }, -+ { "host_addr6", parse_host_addr6 }, - { "gateway_addr", parse_gateway_addr }, - { "mask_addr", parse_mask_addr }, - { "use_ltran", parse_use_ltran }, -@@ -136,6 +139,7 @@ static struct config_vector_t g_config_tbl[] = { - { "bond_slave_mac", parse_bond_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, -+ { "ipv6_enable", parse_ipv6_enable }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, -@@ -221,15 +225,29 @@ static int32_t parse_host_addr(void) - if (g_config_params.host_addr.addr == INADDR_NONE) { - return -EINVAL; - } -+ return 0; -+} - -+static int32_t parse_host_addr6(void) -+{ -+ char *value = NULL; -+ bool ok; -+ -+ ok = config_lookup_string(&g_config, "host_addr6", (const char **)&value); -+ if (!ok) { -+ return 0; -+ } -+ -+ if (ip6addr_aton(value, &g_config_params.host_addr6) == 0) { -+ return -EINVAL; -+ } - return 0; - } - - int32_t match_host_addr(uint32_t addr) - { - /* network byte order */ -- if (addr == g_config_params.host_addr.addr || -- addr == INADDR_ANY) { -+ if (addr == g_config_params.host_addr.addr || addr == INADDR_ANY) { - return 1; - } - return 0; -@@ -1251,3 +1269,10 @@ static int32_t parse_nic_vlan_mode(void) - } - return ret; - } -+ -+static int32_t parse_ipv6_enable(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.ipv6_enable, "ipv6_enable", 0, 0, 1, ret); -+ return ret; -+} -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index be156dc..f5049e9 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -355,15 +355,13 @@ static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_ - if (conn->conn_list[i].state != table_state) { - continue; - } -- - qtuple.protocol = 0; - qtuple.src_ip = conn->conn_list[i].lip; - qtuple.src_port = lwip_htons(conn->conn_list[i].l_port); - qtuple.dst_ip = conn->conn_list[i].rip; - qtuple.dst_port = lwip_htons(conn->conn_list[i].r_port); - -- if ((table_state == LISTEN_LIST) && -- (!match_host_addr(qtuple.src_ip))) { -+ if ((table_state == LISTEN_LIST) && (!match_host_addr(qtuple.src_ip))) { - continue; - } - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 0776e50..6700357 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -763,20 +763,33 @@ int32_t init_dpdk_ethdev(void) - return 0; - } - --bool port_in_stack_queue(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) -+bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - if (stack_group->reta_mask == 0 || stack_group->nb_queues <= 1) { - return true; - } - -- struct rte_ipv4_tuple tuple = {0}; -- tuple.src_addr = rte_be_to_cpu_32(src_ip); -- tuple.dst_addr = rte_be_to_cpu_32(dst_ip); -- tuple.sport = src_port; -- tuple.dport = dst_port; -- -- uint32_t hash = rte_softrss((uint32_t *)&tuple, RTE_THASH_V4_L4_LEN, g_default_rss_key); -+ union rte_thash_tuple tuple; -+ uint32_t hash = 0; -+ if (IP_IS_V4_VAL(src_ip)) { -+ tuple.v4.src_addr = rte_be_to_cpu_32(ip_2_ip4(&src_ip)->addr); -+ tuple.v4.dst_addr = rte_be_to_cpu_32(ip_2_ip4(&dst_ip)->addr); -+ tuple.v4.sport = src_port; -+ tuple.v4.dport = dst_port; -+ hash = rte_softrss((uint32_t *)&tuple, RTE_THASH_V4_L4_LEN, g_default_rss_key); -+ } else { -+ int i; -+ for (i = 0; i < 4; i++) { -+ *((uint32_t *)tuple.v6.src_addr + i) = -+ rte_be_to_cpu_32(*((const uint32_t *)src_ip.u_addr.ip6.addr + i)); -+ *((uint32_t *)tuple.v6.dst_addr + i) = -+ rte_be_to_cpu_32(*((const uint32_t *)dst_ip.u_addr.ip6.addr + i)); -+ } -+ tuple.v6.sport = src_port; -+ tuple.v6.dport = dst_port; -+ hash = rte_softrss((uint32_t *)&tuple, RTE_THASH_V6_L4_LEN, g_default_rss_key); -+ } - - uint32_t reta_index = hash & stack_group->reta_mask; - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 3baddec..c8b4e8f 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -123,7 +123,7 @@ static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, u - pbuf->allow_in = 1; - pbuf->head = 0; - pbuf->last = pbuf; -- pbuf->addr.addr = 0; -+ pbuf->addr = *IP_ANY_TYPE; - pbuf->port = 0; - pthread_spin_init(&pbuf->pbuf_lock, PTHREAD_PROCESS_SHARED); - } -@@ -441,10 +441,21 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - ssize_t send_len = do_app_write(pbufs, buf, len, write_num); - - if (addr) { -- struct sockaddr_in *saddr = (struct sockaddr_in *)addr; -- for (int i = 0; i < write_num; i++) { -- pbufs[i]->addr.addr = saddr->sin_addr.s_addr; -- pbufs[i]->port = lwip_ntohs((saddr)->sin_port); -+ if (addr->sa_family == AF_INET) { -+ struct sockaddr_in *saddr = (struct sockaddr_in *)addr; -+ for (int i = 0; i < write_num; i++) { -+ pbufs[i]->addr.u_addr.ip4.addr = saddr->sin_addr.s_addr; -+ pbufs[i]->port = lwip_ntohs((saddr)->sin_port); -+ } -+ } else if (addr->sa_family == AF_INET6) { -+ struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; -+ for (int i = 0; i < write_num; i++) { -+ memcpy_s(pbufs[i]->addr.u_addr.ip6.addr, sizeof(pbufs[i]->addr.u_addr.ip6.addr), -+ saddr->sin6_addr.s6_addr, sizeof(saddr->sin6_addr.s6_addr)); -+ pbufs[i]->port = lwip_ntohs((saddr)->sin6_port); -+ } -+ } else { -+ return 0; - } - } - -@@ -573,10 +584,15 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - if (wakeup) { - wakeup->stat.app_write_cnt += write_num; - } -- if (addr) { -+ if (addr->sa_family == AF_INET) { - struct sockaddr_in *saddr = (struct sockaddr_in *)addr; -- last_pbuf->addr.addr = saddr->sin_addr.s_addr; -+ last_pbuf->addr.u_addr.ip4.addr = saddr->sin_addr.s_addr; - last_pbuf->port = lwip_ntohs((saddr)->sin_port); -+ } else if (addr->sa_family == AF_INET6) { -+ struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; -+ memcpy_s(last_pbuf->addr.u_addr.ip6.addr, sizeof(last_pbuf->addr.u_addr.ip6.addr), -+ saddr->sin6_addr.s6_addr, sizeof(saddr->sin6_addr.s6_addr)); -+ last_pbuf->port = lwip_ntohs((saddr)->sin6_port); - } - } else { - (void)rpc_call_replenish(stack, sock); -@@ -1122,8 +1138,8 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; - -- conn->lip = pcb->local_ip.addr; -- conn->rip = pcb->remote_ip.addr; -+ conn->lip = ip_2_ip4(&pcb->local_ip)->addr; -+ conn->rip = ip_2_ip4(&pcb->remote_ip)->addr; - conn->l_port = pcb->local_port; - conn->r_port = pcb->remote_port; - conn->in_send = pcb->snd_queuelen; -@@ -1173,7 +1189,7 @@ void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_soc - - int32_t do_lwip_socket(int domain, int type, int protocol) - { -- int32_t fd = lwip_socket(AF_INET, type, 0); -+ int32_t fd = lwip_socket(domain, type, 0); - if (fd < 0) { - return fd; - } -@@ -1216,7 +1232,7 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - for (struct tcp_pcb_listen *pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL && conn_num < max_num; - pcbl = pcbl->next) { - conn[conn_num].state = LISTEN_LIST; -- conn[conn_num].lip = pcbl->local_ip.addr; -+ conn[conn_num].lip = ip_2_ip4(&pcbl->local_ip)->addr; - conn[conn_num].l_port = pcbl->local_port; - conn[conn_num].tcp_sub_state = pcbl->state; - struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 74a17d4..54cf9e8 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -936,10 +936,11 @@ void stack_create_shadow_fd(struct rpc_msg *msg) - return; - } - -+ int domain = addr->sa_family; - if (NETCONN_IS_UDP(sock)) { -- clone_fd = do_lwip_socket(AF_INET, SOCK_DGRAM, 0); -+ clone_fd = do_lwip_socket(domain, SOCK_DGRAM, 0); - } else { -- clone_fd = do_lwip_socket(AF_INET, SOCK_STREAM, 0); -+ clone_fd = do_lwip_socket(domain, SOCK_STREAM, 0); - } - - if (clone_fd < 0) { -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index a7b99af..e3edc57 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -68,6 +68,7 @@ struct cfg_nic_params { - - struct cfg_params { - ip4_addr_t host_addr; -+ ip6_addr_t host_addr6; - ip4_addr_t netmask; - ip4_addr_t gateway_addr; - uint8_t mac_addr[ETHER_ADDR_LEN]; -@@ -116,6 +117,7 @@ struct cfg_params { - struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; - bool use_sockmap; - bool udp_enable; -+ bool ipv6_enable; - struct cfg_nic_params nic; - bool stack_mode_rtc; - }; -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 1a054d6..3a621d0 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -13,6 +13,7 @@ - #ifndef _GAZELLE_DPDK_H_ - #define _GAZELLE_DPDK_H_ - -+#include - #include "gazelle_opt.h" - #include "gazelle_dfx_msg.h" - -@@ -53,7 +54,7 @@ int dpdk_ethdev_start(void); - void dpdk_skip_nic_init(void); - int32_t dpdk_init_lstack_kni(void); - void dpdk_restore_pci(void); --bool port_in_stack_queue(uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); -+bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port); - uint16_t get_port_id(void); - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 6914cff..02aa611 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -16,9 +16,11 @@ - #include - #include - #include -+#include - - #include - #include -+#include - #include - #include - #include -@@ -664,57 +666,92 @@ void concat_mbuf_and_queue_id(struct rte_mbuf *mbuf, uint16_t queue_id, - sprintf_s(mbuf_and_queue_id, write_len, "%lu%s%u", mbuf, SPLIT_DELIM, queue_id); - } - --int distribute_pakages(struct rte_mbuf *mbuf) --{ -- struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -- uint8_t ip_version = (iph->version_ihl & 0xf0) >> IPV4_VERSION_OFFSET; -- if (likely(ip_version == IPV4_VERSION)) { -- if (likely(iph->next_proto_id == IPPROTO_TCP)) { -- int each_process_queue_num = get_global_cfg_params()->num_queue; -- -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -- uint16_t dst_port = tcp_hdr->dst_port; -- uint32_t user_process_idx; -- -- if (g_listen_ports[dst_port] != INVAILD_PROCESS_IDX) { -- user_process_idx = g_listen_ports[dst_port]; -- } else { -- user_process_idx = g_user_ports[dst_port]; -+static int mbuf_to_idx(struct rte_mbuf *mbuf, uint16_t *dst_port) -+{ -+ struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); -+ u16_t type = rte_be_to_cpu_16(ethh->ether_type); -+ uint32_t index = 0; -+ if (type == RTE_ETHER_TYPE_IPV4) { -+ struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -+ uint8_t ip_version = (iph->version_ihl & 0xf0) >> IPV4_VERSION_OFFSET; -+ if (likely(ip_version == IPV4_VERSION)) { -+ if (likely(iph->next_proto_id == IPPROTO_TCP)) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -+ *dst_port = tcp_hdr->dst_port; -+ -+ if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -+ uint32_t src_ip = iph->src_addr; -+ uint16_t src_port = tcp_hdr->src_port; -+ index = rte_jhash_3words(src_ip, src_port | ((*dst_port) << 16), 0, 0); -+ } else { -+ return -1; -+ } - } -+ } -+ } else if (type == RTE_ETHER_TYPE_IPV6) { -+ struct rte_ipv6_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr)); -+ if (likely(iph->proto == IPPROTO_TCP)) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr)); -+ *dst_port = tcp_hdr->dst_port; - -- if (user_process_idx == INVAILD_PROCESS_IDX) { -- return TRANSFER_KERNEL; -- } - if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -- uint32_t src_ip = iph->src_addr; -+ uint32_t *src_ip = (uint32_t *) &iph->src_addr; - uint16_t src_port = tcp_hdr->src_port; -- uint32_t index = rte_jhash_3words(src_ip, src_port | ((dst_port) << 16), 0, 0); -- index = index % each_process_queue_num; -- uint16_t queue_id = 0; -- if (get_global_cfg_params()->seperate_send_recv) { -- queue_id = user_process_idx * each_process_queue_num + (index / 2) * 2; -- } else { -- queue_id = user_process_idx * each_process_queue_num + index; -- } -- if (queue_id != 0) { -- if (user_process_idx == 0) { -- transfer_tcp_to_thread(mbuf, queue_id); -- } else { -- char mbuf_and_queue_id[TRANSFER_TCP_MUBF_LEN]; -- concat_mbuf_and_queue_id(mbuf, queue_id, mbuf_and_queue_id, TRANSFER_TCP_MUBF_LEN); -- transfer_pkt_to_other_process(mbuf_and_queue_id, user_process_idx, -- TRANSFER_TCP_MUBF_LEN, false); -- } -- return TRANSFER_OTHER_THREAD; -- } else { -- return TRANSFER_CURRENT_THREAD; -- } -+ uint32_t v = rte_jhash_3words(src_ip[0], src_ip[1], src_ip[2], 0); -+ index = rte_jhash_3words(src_ip[3], src_port | ((*dst_port) << 16), v, 0); - } else { -- return TRANSFER_CURRENT_THREAD; -+ return -1; - } - } -+ } else { -+ return -1; -+ } -+ return index; -+} -+ -+int distribute_pakages(struct rte_mbuf *mbuf) -+{ -+ uint16_t dst_port = 0; -+ uint32_t index = mbuf_to_idx(mbuf, &dst_port); -+ if (index == -1) { -+ return TRANSFER_CURRENT_THREAD; -+ } -+ -+ uint16_t queue_id = 0; -+ uint32_t user_process_idx = 0; -+ int each_process_queue_num = get_global_cfg_params()->num_queue; -+ index = index % each_process_queue_num; -+ if (g_listen_ports[dst_port] != INVAILD_PROCESS_IDX) { -+ user_process_idx = g_listen_ports[dst_port]; -+ } else { -+ user_process_idx = g_user_ports[dst_port]; -+ } -+ -+ if (user_process_idx == INVAILD_PROCESS_IDX) { -+ return TRANSFER_KERNEL; -+ } -+ -+ if (get_global_cfg_params()->seperate_send_recv) { -+ queue_id = user_process_idx * each_process_queue_num + (index / 2) * 2; -+ } else { -+ queue_id = user_process_idx * each_process_queue_num + index; -+ } -+ if (queue_id != 0) { -+ if (user_process_idx == 0) { -+ transfer_tcp_to_thread(mbuf, queue_id); -+ } else { -+ char mbuf_and_queue_id[TRANSFER_TCP_MUBF_LEN]; -+ concat_mbuf_and_queue_id(mbuf, queue_id, mbuf_and_queue_id, TRANSFER_TCP_MUBF_LEN); -+ transfer_pkt_to_other_process(mbuf_and_queue_id, user_process_idx, -+ TRANSFER_TCP_MUBF_LEN, false); -+ } -+ return TRANSFER_OTHER_THREAD; -+ } else { -+ return TRANSFER_CURRENT_THREAD; - } -+ - return TRANSFER_KERNEL; - } - -@@ -874,10 +911,11 @@ static err_t eth_dev_init(struct netif *netif) - - netif->name[0] = 'e'; - netif->name[1] = 't'; -- netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; -+ netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; - netif->mtu = FRAME_MTU; - netif->output = etharp_output; - netif->linkoutput = eth_dev_output; -+ netif->output_ip6 = ethip6_output; - - int32_t ret; - ret = memcpy_s(netif->hwaddr, sizeof(netif->hwaddr), cfg->mac_addr, ETHER_ADDR_LEN); -@@ -914,11 +952,20 @@ int32_t ethdev_init(struct protocol_stack *stack) - - netif_set_default(&stack->netif); - -- struct netif *netif = netif_add(&stack->netif, &cfg->host_addr, &cfg->netmask, &cfg->gateway_addr, NULL, -- eth_dev_init, ethernet_input); -+ struct netif *netif; -+ if (!ip4_addr_isany(&cfg->host_addr)) { -+ netif = netif_add(&stack->netif, &cfg->host_addr, &cfg->netmask, -+ &cfg->gateway_addr, NULL, eth_dev_init, ethernet_input); -+ } else { -+ netif = netif_add(&stack->netif, NULL, NULL, NULL, NULL, eth_dev_init, ethernet_input); -+ } - if (netif == NULL) { - LSTACK_LOG(ERR, LSTACK, "netif_add failed\n"); -- return ERR_IF; -+ return ERR_IF; -+ } -+ if (!ip6_addr_isany(&cfg->host_addr6)) { -+ netif_ip6_addr_set(&stack->netif, 0, &cfg->host_addr6); -+ netif_ip6_addr_set_state(&stack->netif, 0, IP6_ADDR_VALID); - } - - netif_set_link_up(&stack->netif); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 4a93f87..d57ce59 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -90,24 +90,34 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - - for (uint32_t i = 0; i < pkt_num; i++) { - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); -+ u16_t type = ethh->ether_type; - -- if (unlikely(RTE_BE16(RTE_ETHER_TYPE_IPV4) != ethh->ether_type)) { -- continue; -- } - pkts[i]->l2_len = sizeof(struct rte_ether_hdr); - -- struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(pkts[i], struct rte_ipv4_hdr *, -- sizeof(struct rte_ether_hdr)); -- if (unlikely((iph->version_ihl & IPV4_MASK) != IPV4_VERION)) { -- continue; -- } -- pkts[i]->l3_len = sizeof(struct rte_ipv4_hdr); -+ if (type == RTE_BE16(RTE_ETHER_TYPE_IPV4)) { -+ struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(pkts[i], struct rte_ipv4_hdr *, -+ sizeof(struct rte_ether_hdr)); -+ if (unlikely((iph->version_ihl & IPV4_MASK) != IPV4_VERION)) { -+ continue; -+ } -+ pkts[i]->l3_len = sizeof(struct rte_ipv4_hdr); - -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -- pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -+ pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); - -- pkts[i]->packet_type = RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; -+ } else if (type == RTE_BE16(RTE_ETHER_TYPE_IPV6)) { -+ pkts[i]->l3_len = sizeof(struct rte_ipv6_hdr); -+ -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr)); -+ pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -+ -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; -+ } else { -+ continue; -+ } - } - pkt_num = rte_gro_reassemble_burst(pkts, pkt_num, &gro_param); - -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 85ea324..749b8e0 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -24,6 +24,14 @@ - #include "ltran_tcp_conn.h" - #include "ltran_instance.h" - #include "ltran_timer.h" -+/* undefine lwip_ntohs in lwip/def.h */ -+#ifdef ntohs -+#undef ntohs -+#endif -+#ifdef htons -+#undef htons -+#endif -+ - - static uint64_t g_cycles_per_us = 0; - --- -2.27.0 - diff --git a/0051-wrap-dont-hijack-select-temporarily.patch b/0051-wrap-dont-hijack-select-temporarily.patch deleted file mode 100644 index ff72315..0000000 --- a/0051-wrap-dont-hijack-select-temporarily.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 801aafea1889a5c54ca884f62b0a24c5d6b6d8ce Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 18 Nov 2023 19:09:34 +0800 -Subject: [PATCH] wrap: dont hijack select temporarily - ---- - src/lstack/api/lstack_wrap.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 9468003..1e67b76 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -582,11 +582,7 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - - static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { -- if (select_posix_path() == PATH_KERNEL) { -- return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -- } -- -- return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - - #define WRAP_VA_PARAM(_fd, _cmd, _lwip_fcntl, _fcntl_fn) \ --- -2.27.0 - diff --git a/0052-ipv6.patch b/0052-ipv6.patch deleted file mode 100644 index c587389..0000000 --- a/0052-ipv6.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 894c59a8e2351f0c0b34e3582054a696a913f114 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Sat, 18 Nov 2023 00:44:43 +0800 -Subject: [PATCH] ipv6 - ---- - 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 1e67b76..b6ac1bd 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -370,7 +370,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - return posix_api->socket_fn(domain, type, protocol); - } - -- if ((domain != AF_INET && domain != AF_UNSPEC) || -+ if ((domain != AF_INET && domain != AF_UNSPEC && domain != AF_INET6) || - ((domain == AF_INET6) && !get_global_cfg_params()->ipv6_enable) || - ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)) { - return posix_api->socket_fn(domain, type, protocol); --- -2.27.0 - diff --git a/0053-add-gazelle-log.patch b/0053-add-gazelle-log.patch deleted file mode 100644 index ec5036a..0000000 --- a/0053-add-gazelle-log.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 9980175dfd8e33ed17bbe928c5adaeee10907e4b Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sat, 18 Nov 2023 10:28:59 +0800 -Subject: [PATCH] add gazelle log - ---- - src/common/gazelle_dfx_msg.c | 6 ++--- - src/lstack/core/lstack_control_plane.c | 9 ++++++++ - src/lstack/core/lstack_dpdk.c | 31 ++++++++++++++++++++------ - 3 files changed, 36 insertions(+), 10 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.c b/src/common/gazelle_dfx_msg.c -index b8472be..5fe4e06 100644 ---- a/src/common/gazelle_dfx_msg.c -+++ b/src/common/gazelle_dfx_msg.c -@@ -32,16 +32,16 @@ int read_specied_len(int fd, char *buf, size_t target_size) - printf("read_specied_len:: poll ret=%d \n", ret); - return -1; - } else if (ret == 0) { -- printf("read_specied_len:: time out"); -+ printf("read_specied_len:: time out \n"); - return -1; - } - if (fds[0].revents & POLLIN) { - int n = read(fd, buf + total_read, target_size - total_read); - if (n < 0) { -- printf("read_specied_len:: read ret=%d", ret); -+ printf("read_specied_len:: read ret=%d \n", ret); - return -1; - } else if (n == 0) { -- printf("read_specied_len:: Connection closed"); -+ printf("read_specied_len:: Connection closed \n"); - return -1; - } - total_read += n; -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index be156dc..746c209 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -134,11 +134,13 @@ static int32_t msg_proc_init(enum request_type rqt_type, struct reg_request_msg - - ret = strncpy_s(conf->file_prefix, PATH_MAX, global_params->sec_attach_arg.file_prefix, PATH_MAX - 1); - if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "strncpy_s fail ret=%d \n", ret); - return ret; - } - - ret = memcpy_s(conf->mac_addr, ETHER_ADDR_LEN, global_params->mac_addr, ETHER_ADDR_LEN); - if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "memcpy_s fail ret=%d \n", ret); - return ret; - } - switch (rqt_type) { -@@ -153,14 +155,17 @@ static int32_t msg_proc_init(enum request_type rqt_type, struct reg_request_msg - conf->argc = 0; - ret = gazelle_copy_param(OPT_SOCKET_MEM, true, (int32_t *)&conf->argc, conf->argv); - if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "gazelle_copy_param OPT_SOCKET_MEM fail ret=%d \n", ret); - return ret; - } - ret = gazelle_copy_param(OPT_FILE_PREFIX, true, (int32_t *)&conf->argc, conf->argv); - if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "gazelle_copy_param OPT_FILE_PREFIX fail ret=%d \n", ret); - return ret; - } - ret = gazelle_copy_param(OPT_LEGACY_MEM, false, (int32_t *)&conf->argc, conf->argv); - if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "gazelle_copy_param OPT_LEGACY_MEM fail ret=%d \n", ret); - return ret; - } - -@@ -494,6 +499,7 @@ int32_t control_init_client(bool is_reconnect) - - ret = client_reg_proc_memory(is_reconnect); - if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "client_reg_proc_memory ret=%d \n", ret); - posix_api->close_fn(g_data_fd); - g_data_fd = -1; - return -1; -@@ -501,6 +507,7 @@ int32_t control_init_client(bool is_reconnect) - - ret = client_reg_proc_attach(is_reconnect); - if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "client_reg_proc_memory ret=%d \n", ret); - posix_api->close_fn(g_data_fd); - g_data_fd = -1; - return -1; -@@ -636,12 +643,14 @@ static int32_t client_reg_proc_reconnect(int32_t epfd) - /* longterm connect g_data_fd; init process info */ - ret = control_init_client(true); - if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "control_init_client fail ret=%d\n", ret); - return -1; - } - sockfd = g_data_fd; - - ret = thread_register(); - if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "thread_register fail ret=%d\n", ret); - posix_api->close_fn(sockfd); - g_data_fd = -1; - return -1; -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index da6eda0..966507f 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -75,15 +75,20 @@ int32_t thread_affinity_default(void) - { - static cpu_set_t cpuset; - static bool first_flags = true; -+ int ret = 0; - if (first_flags) { - CPU_ZERO(&cpuset); -- if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) != 0) { -+ ret = pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "pthread_getaffinity_np fail ret=%d\n", ret); - return -1; - } - first_flags = false; - } else { - /* cancel the core binding from DPDK initialization */ -- if (pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) != 0) { -+ ret = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "pthread_setaffinity_np fail ret=%d\n", ret); - return -1; - } - } -@@ -167,6 +172,7 @@ static struct rte_mempool* get_pktmbuf_mempool(const char *name, uint16_t queue_ - - ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); - return NULL; - } - pool = rte_mempool_lookup(pool_name); -@@ -185,6 +191,7 @@ static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_ - - ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); - return NULL; - } - -@@ -205,12 +212,14 @@ int32_t pktmbuf_pool_init(struct protocol_stack *stack, uint16_t stack_num) - - stack->rxtx_pktmbuf_pool = get_pktmbuf_mempool("rxtx_mbuf", stack->queue_id); - if (stack->rxtx_pktmbuf_pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "rxtx_pktmbuf_pool is NULL\n"); - return -1; - } - - if (use_ltran()) { - stack->reg_buf = create_reg_mempool("reg_ring_msg", stack->queue_id); - if (stack->reg_buf == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "rxtx_pktmbuf_pool is NULL\n"); - return -1; - } - } -@@ -226,6 +235,7 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si - int32_t ret = snprintf_s(pool_name, sizeof(pool_name), RTE_MEMPOOL_NAMESIZE - 1, - "%s_%d", name, idx); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); - return NULL; - } - -@@ -246,6 +256,7 @@ struct rte_ring *create_ring(const char *name, uint32_t count, uint32_t flags, i - int32_t ret = snprintf_s(ring_name, sizeof(ring_name), RTE_RING_NAMESIZE - 1, - "%s_%d_%d", name, get_global_cfg_params()->process_idx, queue_id); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); - return NULL; - } - -@@ -286,6 +297,8 @@ int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, ui - { - int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); - if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:=%s \n", -+ num, ret, rte_strerror(-ret)); - return ret; - } - -@@ -477,6 +490,7 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - if (get_global_cfg_params()->bond_mode < 0) { - port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); - if (port_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "ethdev_port_id FAIL port_id=%d\n", port_id); - return port_id; - } - } -@@ -589,7 +603,7 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - - ret = dpdk_ethdev_start(); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_start failed\n"); -+ LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_start failed ret=%d\n", ret); - stack_group->eth_params = NULL; - free(eth_params); - return ret; -@@ -644,6 +658,7 @@ int32_t dpdk_ethdev_start(void) - for (int32_t i = 0; i < get_global_cfg_params()->tot_queue_num; i++) { - ret = dpdk_ethdev_setup(stack_group->eth_params, i); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_setup fail queueid=%d, ret=%d\n", i, ret); - return ret; - } - } -@@ -666,11 +681,13 @@ int32_t dpdk_init_lstack_kni(void) - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - stack_group->kni_pktmbuf_pool = create_pktmbuf_mempool("kni_mbuf", KNI_NB_MBUF, 0, 0, rte_socket_id()); - if (stack_group->kni_pktmbuf_pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "kni_mbuf is NULL\n"); - return -1; - } - - int32_t ret = dpdk_kni_init(stack_group->port_id, stack_group->kni_pktmbuf_pool); - if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk_kni_init fail ret=%d\n", ret); - return -1; - } - -@@ -706,18 +723,18 @@ int32_t init_dpdk_ethdev(void) - } - - ret = dpdk_ethdev_init(bond_port_id, 1); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_bond_xmit_policy_set(bond_port_id, BALANCE_XMIT_POLICY_LAYER34); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk set bond xmit policy failed ret = %d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond xmit policy failed ret = %d\n", ret); - return -1; - } - -- if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { -+ if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { - ret = rte_eth_bond_8023ad_dedicated_queues_enable(bond_port_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); -@@ -743,7 +760,7 @@ int32_t init_dpdk_ethdev(void) - } - - ret = rte_eth_dev_start(bond_port_id); -- if (ret < 0) { -+ if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk start bond port failed ret = %d\n", ret); - return -1; - } --- -2.27.0 - diff --git a/0054-PRE_LOG-modify-log-info-while-there-are-repeated-ite.patch b/0054-PRE_LOG-modify-log-info-while-there-are-repeated-ite.patch deleted file mode 100644 index 5345a88..0000000 --- a/0054-PRE_LOG-modify-log-info-while-there-are-repeated-ite.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 38ce070bc6922470a92b925e030ba61586a6e92a Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 20 Nov 2023 11:08:10 +0800 -Subject: [PATCH] PRE_LOG: modify log info while there are repeated items in - conf file - ---- - src/lstack/core/lstack_cfg.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 9f3143f..7a4504f 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -946,6 +946,7 @@ static int32_t parse_conf_file(const char *path) - int32_t ret; - - if (realpath(path, real_path) == NULL) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "Config path error. Errno: %d. Please check conf file path: %s\n", errno, path); - return -1; - } - -@@ -953,7 +954,7 @@ static int32_t parse_conf_file(const char *path) - - ret = config_read_file(&g_config, real_path); - if (ret == 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "Config file path error, Please check conf file path.\n"); -+ LSTACK_PRE_LOG(LSTACK_ERR, "Read config file \"%s\" error: %s\n", real_path, config_error_text(&g_config)); - config_destroy(&g_config); - return -EINVAL; - } -@@ -961,7 +962,7 @@ static int32_t parse_conf_file(const char *path) - for (int32_t i = 0; g_config_tbl[i].name && g_config_tbl[i].f; ++i) { - ret = g_config_tbl[i].f(); - if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "error parsing parameter '%s' ret=%d\n.", g_config_tbl[i].name, ret); -+ LSTACK_PRE_LOG(LSTACK_ERR, "error parsing parameter '%s' ret=%d.\n", g_config_tbl[i].name, ret); - config_destroy(&g_config); - return ret; - } --- -2.27.0 - diff --git a/0055-add-gazelle-log.patch b/0055-add-gazelle-log.patch deleted file mode 100644 index bd4827c..0000000 --- a/0055-add-gazelle-log.patch +++ /dev/null @@ -1,100 +0,0 @@ -From c136185db539fe2a7de58a4677b293f0c24f0e2a Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 20 Nov 2023 09:56:50 +0800 -Subject: [PATCH] add gazelle log - ---- - src/lstack/api/lstack_epoll.c | 3 +++ - src/lstack/core/lstack_protocol_stack.c | 12 +++++++++--- - 2 files changed, 12 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index f2c4a8b..eacbe33 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -821,6 +821,7 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - if (wakeup == NULL) { - wakeup = calloc(1, sizeof(struct wakeup_poll)); - if (wakeup == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); - GAZELLE_RETURN(EINVAL); - } - -@@ -938,10 +939,12 @@ static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_s - int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval) - { - if (maxfd == 0) { -+ LSTACK_LOG(ERR, LSTACK, "select maxfd is zero\n"); - return 0; - } - - if (maxfd < 0 || maxfd > FD_SETSIZE || (readfds == NULL && writefds == NULL && exceptfds == NULL)) { -+ LSTACK_LOG(ERR, LSTACK, "select input param error, fd num=%d\n", maxfd); - GAZELLE_RETURN(EINVAL); - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 74a17d4..aedf9c5 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -325,6 +325,7 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - - stack->epollfd = posix_api->epoll_create_fn(GAZELLE_LSTACK_MAX_CONN); - if (stack->epollfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "kernel epoll_create failed\n"); - return -1; - } - -@@ -349,10 +350,12 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - } - - if (pktmbuf_pool_init(stack, stack_group->stack_num) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "pktmbuf_pool_init failed\n"); - return -1; - } - - if (create_shared_ring(stack) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "create_shared_ring failed\n"); - return -1; - } - -@@ -583,6 +586,7 @@ int32_t stack_group_init(void) - - if (get_global_cfg_params()->is_primary) { - if (stack_group_init_mempool() != 0) { -+ LSTACK_LOG(ERR, LSTACK, "stack group init mempool failed\n"); - return -1; - } - } -@@ -789,7 +793,8 @@ void stack_getsockopt(struct rpc_msg *msg) - msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, - msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); - } - } - -@@ -798,7 +803,8 @@ void stack_setsockopt(struct rpc_msg *msg) - msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, - msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].socklen); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); - } - } - -@@ -834,7 +840,7 @@ void stack_send(struct rpc_msg *msg) - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - msg->result = -1; -- LSTACK_LOG(ERR, LSTACK, "stack_send: sock error!\n"); -+ LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); - rpc_msg_free(msg); - return; - } --- -2.27.0 - diff --git a/0056-wrap-fix-connect-wrong-port-after-addr-bind-two-port.patch b/0056-wrap-fix-connect-wrong-port-after-addr-bind-two-port.patch deleted file mode 100644 index 5e42a15..0000000 --- a/0056-wrap-fix-connect-wrong-port-after-addr-bind-two-port.patch +++ /dev/null @@ -1,38 +0,0 @@ -From c7a9c71456844b164477f329f79f5e10de7898a4 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 15 Nov 2023 11:23:04 +0800 -Subject: [PATCH] wrap: fix connect wrong port after addr bind two ports - ---- - src/lstack/api/lstack_wrap.c | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 5bad513..f427d33 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -219,7 +219,20 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - - if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { - /* maybe kni addr */ -- posix_api->bind_fn(s, name, namelen); -+ if (posix_api->bind_fn(s, name, namelen) != 0) { -+ SET_CONN_TYPE_LIBOS(sock->conn); -+ } else { -+ /* 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; -+ } -+ } - return g_wrap_api->bind_fn(s, name, namelen); - } else { - SET_CONN_TYPE_HOST(sock->conn); --- -2.27.0 - diff --git a/0057-cfg-rm-ipv6_enable.patch b/0057-cfg-rm-ipv6_enable.patch deleted file mode 100644 index 799a8c4..0000000 --- a/0057-cfg-rm-ipv6_enable.patch +++ /dev/null @@ -1,88 +0,0 @@ -From d0c8c259add3b170e413d4c3a9e248ba3e550680 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Thu, 23 Nov 2023 11:19:01 +0800 -Subject: [PATCH] cfg: rm ipv6_enable - ---- - src/lstack/api/lstack_wrap.c | 2 +- - src/lstack/core/lstack_cfg.c | 8 -------- - src/lstack/include/lstack_cfg.h | 1 - - src/lstack/netif/lstack_ethdev.c | 4 ++-- - 4 files changed, 3 insertions(+), 12 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 43b9dad..abbf8a1 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -384,7 +384,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - } - - if ((domain != AF_INET && domain != AF_UNSPEC && domain != AF_INET6) || -- ((domain == AF_INET6) && !get_global_cfg_params()->ipv6_enable) || -+ ((domain == AF_INET6) && ip6_addr_isany(&get_global_cfg_params()->host_addr6)) || - ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)) { - return posix_api->socket_fn(domain, type, protocol); - } -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 7a4504f..d1cbd1d 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -76,7 +76,6 @@ static int32_t parse_bond_mode(void); - static int32_t parse_bond_slave_mac(void); - static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); --static int32_t parse_ipv6_enable(void); - static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); -@@ -139,7 +138,6 @@ static struct config_vector_t g_config_tbl[] = { - { "bond_slave_mac", parse_bond_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, -- { "ipv6_enable", parse_ipv6_enable }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, -@@ -1271,9 +1269,3 @@ static int32_t parse_nic_vlan_mode(void) - return ret; - } - --static int32_t parse_ipv6_enable(void) --{ -- int32_t ret; -- PARSE_ARG(g_config_params.ipv6_enable, "ipv6_enable", 0, 0, 1, ret); -- return ret; --} -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index e3edc57..26da357 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -117,7 +117,6 @@ struct cfg_params { - struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; - bool use_sockmap; - bool udp_enable; -- bool ipv6_enable; - struct cfg_nic_params nic; - bool stack_mode_rtc; - }; -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 02aa611..9912858 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -961,11 +961,11 @@ int32_t ethdev_init(struct protocol_stack *stack) - } - if (netif == NULL) { - LSTACK_LOG(ERR, LSTACK, "netif_add failed\n"); -- return ERR_IF; -+ return ERR_IF; - } - if (!ip6_addr_isany(&cfg->host_addr6)) { - netif_ip6_addr_set(&stack->netif, 0, &cfg->host_addr6); -- netif_ip6_addr_set_state(&stack->netif, 0, IP6_ADDR_VALID); -+ netif_ip6_addr_set_state(&stack->netif, 0, IP6_ADDR_VALID); - } - - netif_set_link_up(&stack->netif); --- -2.27.0 - diff --git a/0058-ltran-support-vlan.patch b/0058-ltran-support-vlan.patch deleted file mode 100644 index f3d9370..0000000 --- a/0058-ltran-support-vlan.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 0b7daa128d4b6dc231814537594158f8d928ef6c Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Thu, 23 Nov 2023 16:20:50 +0800 -Subject: [PATCH] ltran support vlan - ---- - src/ltran/ltran_forward.c | 35 ++++++++++++++++++++++++++++------- - 1 file changed, 28 insertions(+), 7 deletions(-) - -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index b41e1e2..a6f2d71 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -281,14 +281,26 @@ static __rte_always_inline int32_t tcp_handle(struct rte_mbuf *m, const struct r - return GAZELLE_OK; - } - -+static uint32_t get_vlan_offset(const struct rte_mbuf *m) -+{ -+ uint32_t offset = 0; -+ struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); -+ u16_t type = ethh->ether_type; -+ if (type == PP_HTONS(RTE_ETHER_TYPE_VLAN)) { -+ offset += sizeof(struct rte_vlan_hdr); -+ } -+ return offset; -+} -+ - static struct gazelle_stack* get_icmp_handle_stack(const struct rte_mbuf *m) - { - int32_t i; - struct gazelle_stack** stack_array = NULL; - struct rte_ipv4_hdr *ipv4_hdr = NULL; - struct gazelle_instance *instance = NULL; -+ uint32_t offset = get_vlan_offset(m); - -- ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -+ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr) + offset); - instance = gazelle_instance_get_by_ip(get_instance_mgr(), ipv4_hdr->dst_addr); - if (instance == NULL) { - return NULL; -@@ -321,10 +333,11 @@ static __rte_always_inline int32_t ipv4_handle(struct rte_mbuf *m, struct rte_ip - { - struct rte_tcp_hdr *tcp_hdr = NULL; - int32_t ret = -1; -+ uint32_t offset = get_vlan_offset(m); - - if (likely(ipv4_hdr->next_proto_id == IPPROTO_TCP)) { - tcp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_tcp_hdr *, sizeof(struct rte_ether_hdr) + -- sizeof(struct rte_ipv4_hdr)); -+ sizeof(struct rte_ipv4_hdr) + offset); - get_statistics()->port_stats[g_port_index].tcp_pkt++; - ret = tcp_handle(m, ipv4_hdr, tcp_hdr); - } else if (ipv4_hdr->next_proto_id == IPPROTO_ICMP) { -@@ -336,7 +349,8 @@ static __rte_always_inline int32_t ipv4_handle(struct rte_mbuf *m, struct rte_ip - - static __rte_always_inline void arp_handle(struct rte_mbuf *m) - { -- struct rte_arp_hdr *arph = rte_pktmbuf_mtod_offset(m, struct rte_arp_hdr *, sizeof(struct rte_ether_hdr)); -+ uint32_t offset = get_vlan_offset(m); -+ struct rte_arp_hdr *arph = rte_pktmbuf_mtod_offset(m, struct rte_arp_hdr *, sizeof(struct rte_ether_hdr) + offset); - - get_statistics()->port_stats[g_port_index].arp_pkt++; - -@@ -367,14 +381,14 @@ static __rte_always_inline void arp_handle(struct rte_mbuf *m) - static __rte_always_inline void upstream_forward_one(struct rte_mbuf *m) - { - struct rte_ipv4_hdr *iph = NULL; -- struct rte_ether_hdr *ethh = NULL; - uint8_t ip_version; - const int32_t ipv4_version_offset = 4; - const int32_t ipv4_version = 4; -+ uint32_t offset = get_vlan_offset(m); - - get_statistics()->port_stats[g_port_index].rx_bytes += m->data_len; - -- iph = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -+ iph = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr) + offset); - ip_version = (iph->version_ihl & 0xf0) >> ipv4_version_offset; - if (likely(ip_version == ipv4_version)) { - int32_t ret = ipv4_handle(m, iph); -@@ -385,8 +399,15 @@ static __rte_always_inline void upstream_forward_one(struct rte_mbuf *m) - goto forward_to_kni; - } - -- ethh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); -- if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == ethh->ether_type)) { -+ uint16_t type = 0; -+ if (offset > 0) { -+ struct rte_vlan_hdr *vlan_hdr = rte_pktmbuf_mtod_offset(m, struct rte_vlan_hdr *, sizeof(struct rte_ether_hdr)); -+ type = vlan_hdr->eth_proto; -+ } else { -+ struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); -+ type = ethh->ether_type; -+ } -+ if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == type)) { - arp_handle(m); - // arp packets are sent to kni by default - goto forward_to_kni; --- -2.27.0 - diff --git a/0059-update-src-ltran-ltran_param.c.patch b/0059-update-src-ltran-ltran_param.c.patch deleted file mode 100644 index 1498d4f..0000000 --- a/0059-update-src-ltran-ltran_param.c.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a82c372c3dc55167b2a83a2f3b5632bd0771d306 Mon Sep 17 00:00:00 2001 -From: gaojiazhen -Date: Thu, 23 Nov 2023 17:43:11 +0000 -Subject: [PATCH] =?UTF-8?q?update=20src/ltran/ltran=5Fparam.c.=20=E8=A7=84?= - =?UTF-8?q?=E8=8C=83679=E8=A1=8C=E7=9A=84=E6=8A=A5=E9=94=99=E6=97=A5?= - =?UTF-8?q?=E5=BF=97=E4=BF=A1=E6=81=AF=EF=BC=8C=E5=B0=86=E2=80=9C,?= - =?UTF-8?q?=E2=80=9D=E4=B9=8B=E5=90=8E=E7=9A=84=E2=80=9CPlease=E2=80=9D?= - =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=BA=E2=80=9Cplease=E2=80=9D?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: gaojiazhen ---- - src/ltran/ltran_param.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ltran/ltran_param.c b/src/ltran/ltran_param.c -index e16e648..11a4bc8 100644 ---- a/src/ltran/ltran_param.c -+++ b/src/ltran/ltran_param.c -@@ -676,7 +676,7 @@ int32_t parse_config_file_args(const char *conf_file_path, struct ltran_config * - ret = config_read_file(&config, conf_file_path); - if (ret == 0) { - config_destroy(&config); -- syslog(LOG_ERR, "Err: Config file path %s error, Please check conf file path.\n", conf_file_path); -+ syslog(LOG_ERR, "Err: Config file path %s error, please check conf file path.\n", conf_file_path); - return -GAZELLE_EPATH; - } - --- -2.27.0 - diff --git a/0060-dfx-support-bond-get-dpdk-xstats.patch b/0060-dfx-support-bond-get-dpdk-xstats.patch deleted file mode 100644 index 2f5b1e4..0000000 --- a/0060-dfx-support-bond-get-dpdk-xstats.patch +++ /dev/null @@ -1,262 +0,0 @@ -From 75e11463d7bd67732d3c7f0e7ed3a9dece8c4982 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 25 Nov 2023 09:26:23 +0800 -Subject: [PATCH] dfx: support bond get dpdk xstats - ---- - src/lstack/core/lstack_control_plane.c | 2 + - src/lstack/core/lstack_dpdk.c | 93 +++++++++++++++++++------ - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/core/lstack_stack_stat.c | 14 ++-- - src/lstack/include/lstack_cfg.h | 1 - - src/lstack/include/lstack_dpdk.h | 1 - - src/lstack/include/lstack_stack_stat.h | 3 +- - src/lstack/netif/lstack_ethdev.c | 4 +- - 8 files changed, 89 insertions(+), 31 deletions(-) - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index b97ee7f..4633834 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -586,6 +586,8 @@ static int32_t handle_stat_request(int32_t sockfd) - if (msg.stat_mode == GAZELLE_STAT_LSTACK_LOG_LEVEL_SET || - msg.stat_mode == GAZELLE_STAT_LSTACK_LOW_POWER_MDF) { - return handle_proc_cmd(sockfd, &msg); -+ } else if (msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) { -+ return handle_dpdk_cmd(sockfd, msg.stat_mode); - } else { - ret = handle_stack_cmd(sockfd, msg.stat_mode); - if (ret != 0) { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 703fd0d..19a7bf4 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -346,13 +346,6 @@ void lstack_log_level_init(void) - } - } - --// get port id --inline uint16_t get_port_id(void) --{ -- uint16_t port_id = get_global_cfg_params()->port_id; -- return port_id; --} -- - static int32_t ethdev_port_id(uint8_t *mac) - { - int32_t port_id; -@@ -497,8 +490,6 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - } - -- get_global_cfg_params()->port_id = port_id; -- - struct rte_eth_dev_info dev_info; - int32_t ret = rte_eth_dev_info_get(port_id, &dev_info); - if (ret != 0) { -@@ -814,23 +805,83 @@ bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, - return (reta_index % stack_group->nb_queues) == stack->queue_id; - } - --void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) -+static int dpdk_nic_xstats_value_get(uint64_t *values, unsigned int len, uint16_t *ports, unsigned int count) - { -- int32_t ret; -- int32_t len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL); -- dfx->data.nic_xstats.len = len; -- dfx->data.nic_xstats.port_id = port_id; -+ uint64_t tmp_values[RTE_ETH_XSTATS_MAX_LEN]; -+ int p_idx; -+ int v_idx; -+ int ret; -+ -+ for (p_idx = 0; p_idx < count; p_idx++) { -+ ret = rte_eth_xstats_get_by_id(ports[p_idx], NULL, tmp_values, len); -+ if (ret < 0 || ret > len) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_by_id failed.\n"); -+ return -1; -+ } -+ -+ for (v_idx = 0; v_idx < len; v_idx++) { -+ values[v_idx] += tmp_values[v_idx]; -+ } -+ } -+ return 0; -+} -+ -+static int dpdk_nic_xstats_name_get(struct nic_eth_xstats_name *names, uint16_t port_id) -+{ -+ int len; -+ -+ len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL); - if (len < 0) { -- return; -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_names_by_id failed.\n"); -+ return -1; -+ } -+ -+ if (len != rte_eth_xstats_get_names_by_id(port_id, (struct rte_eth_xstat_name *)names, len, NULL)) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_xstats_get_names_by_id failed.\n"); -+ return -1; - } -- if (len != rte_eth_xstats_get_names_by_id(port_id, -- (struct rte_eth_xstat_name *)dfx->data.nic_xstats.xstats_name, len, NULL)) { -- dfx->data.nic_xstats.len = -1; -+ -+ return len; -+} -+ -+void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) -+{ -+ struct rte_eth_dev_info dev_info; -+ int len; -+ int ret; -+ -+ dfx->data.nic_xstats.len = -1; -+ dfx->data.nic_xstats.port_id = port_id; -+ ret = rte_eth_dev_info_get(port_id, &dev_info); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_info_get failed.\n"); - return; - } - -- ret = rte_eth_xstats_get_by_id(port_id, NULL, dfx->data.nic_xstats.values, len); -- if (ret < 0 || ret > len) { -- dfx->data.nic_xstats.len = -1; -+ /* bond not support get xstats, we get xstats from slave device of bond */ -+ if (strcmp(dev_info.driver_name, "net_bonding") == 0) { -+ uint16_t slaves[RTE_MAX_ETHPORTS]; -+ int slave_count; -+ slave_count = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS); -+ if (slave_count <= 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_slaves_get failed.\n"); -+ return; -+ } -+ len = dpdk_nic_xstats_name_get(dfx->data.nic_xstats.xstats_name, slaves[0]); -+ if (len <= 0) { -+ return; -+ } -+ if (dpdk_nic_xstats_value_get(dfx->data.nic_xstats.values, len, slaves, slave_count) != 0) { -+ return; -+ } -+ } else { -+ len = dpdk_nic_xstats_name_get(dfx->data.nic_xstats.xstats_name, port_id); -+ if (len <= 0) { -+ return; -+ } -+ if (dpdk_nic_xstats_value_get(dfx->data.nic_xstats.values, len, &port_id, 1) != 0) { -+ return; -+ } - } -+ dfx->data.nic_xstats.len = len; - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index cbc8b8f..dfebfcc 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -479,7 +479,7 @@ void stack_polling(uint32_t wakeup_tick) - if (kni_switch && !stack->queue_id && !(wakeup_tick & 0xfff)) { - rte_kni_handle_request(get_gazelle_kni()); - if (get_kni_started()) { -- kni_handle_rx(get_port_id()); -+ kni_handle_rx(stack->port_id); - } - } - return; -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 60832b4..18548ab 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -256,19 +256,25 @@ static int32_t send_control_cmd_data(int32_t fd, struct gazelle_stack_dfx_data * - return 0; - } - --int32_t handle_stack_cmd(int32_t fd, enum GAZELLE_STAT_MODE stat_mode) -+int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) - { - struct gazelle_stack_dfx_data dfx; -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); - - if (stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) { -- dpdk_nic_xstats_get(&dfx, get_port_id()); -+ dpdk_nic_xstats_get(&dfx, get_protocol_stack_group()->port_id); - dfx.tid = 0; - dfx.eof = 1; - send_control_cmd_data(fd, &dfx); -- return 0; - } - -+ return 0; -+} -+ -+int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) -+{ -+ struct gazelle_stack_dfx_data dfx; -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ - for (uint32_t i = 0; i < stack_group->stack_num; i++) { - struct protocol_stack *stack = stack_group->stacks[i]; - -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 26da357..e33f4fe 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -94,7 +94,6 @@ struct cfg_params { - - uint16_t num_process; - uint16_t num_listen_port; -- uint16_t port_id; - uint16_t is_primary; - uint16_t num_queue; - uint16_t tot_queue_num; -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 3a621d0..e3daefa 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -55,7 +55,6 @@ void dpdk_skip_nic_init(void); - int32_t dpdk_init_lstack_kni(void); - void dpdk_restore_pci(void); - bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port); --uint16_t get_port_id(void); - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); - -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index 5737bae..d5a4ec7 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -24,7 +24,8 @@ enum GAZELLE_STAT_MODE; - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, - enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); --int32_t handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); -+int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); -+int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); - uint64_t get_current_time(void); - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info); - void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 9912858..29bef21 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -330,7 +330,7 @@ struct rte_flow *create_flow_director(uint16_t port_id, uint16_t queue_id, - void config_flow_director(uint16_t queue_id, uint32_t src_ip, - uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) - { -- uint16_t port_id = get_port_id(); -+ uint16_t port_id = get_protocol_stack_group()->port_id; - char rule_key[RULE_KEY_LEN] = {0}; - sprintf_s(rule_key, sizeof(rule_key), "%u_%u_%u", src_ip, src_port, dst_port); - struct flow_rule *fl_exist = find_rule(rule_key); -@@ -357,7 +357,7 @@ void config_flow_director(uint16_t queue_id, uint32_t src_ip, - - void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) - { -- uint16_t port_id = get_port_id(); -+ uint16_t port_id = get_protocol_stack_group()->port_id; - char rule_key[RULE_KEY_LEN] = {0}; - sprintf_s(rule_key, RULE_KEY_LEN, "%u_%u_%u",dst_ip, dst_port, src_port); - struct flow_rule *fl = find_rule(rule_key); --- -2.27.0 - diff --git a/0061-add-tcp-faste-timer-cnt.patch b/0061-add-tcp-faste-timer-cnt.patch deleted file mode 100644 index 7052525..0000000 --- a/0061-add-tcp-faste-timer-cnt.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4098ba1fbc9f382d0f9d6b6b071d7ed9a2682cfc Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Fri, 24 Nov 2023 14:19:16 +0800 -Subject: [PATCH] add tcp faste timer cnt - ---- - src/common/gazelle_dfx_msg.h | 3 +++ - src/ltran/ltran_dfx.c | 28 ++++++++++++++++++---------- - 2 files changed, 21 insertions(+), 10 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 93fe3df..8071108 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -117,6 +117,9 @@ struct gazelle_stat_lstack_snmp { - uint32_t tcp_in_seg; - uint32_t tcp_in_err; - uint32_t tcp_out_rst; -+ uint32_t tcp_fin_ack_cnt; -+ uint32_t tcp_delay_ack_cnt; -+ uint32_t tcp_refused_cnt; - - /* UDP */ - uint32_t udp_in_datagrams; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 582a4b7..98e23dc 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -825,6 +825,22 @@ static void gazelle_print_lstack_stat_rate(void *buf, const struct gazelle_stat_ - } while (true); - } - -+static void gazelle_print_lstack_tcp_stat(const struct gazelle_stat_lstack_snmp *snmp) -+{ -+ printf("tcp_act_open: %u\n", snmp->tcp_act_open); -+ printf("tcp_passive_open: %u\n", snmp->tcp_passive_open); -+ printf("tcp_attempt_fail: %u\n", snmp->tcp_attempt_fail); -+ printf("tcp_estab_rst: %u\n", snmp->tcp_estab_rst); -+ printf("tcp_out_seg: %u\n", snmp->tcp_out_seg); -+ printf("tcp_retran_seg: %u\n", snmp->tcp_retran_seg); -+ printf("tcp_in_seg: %u\n", snmp->tcp_in_seg); -+ printf("tcp_in_err: %u\n", snmp->tcp_in_err); -+ printf("tcp_out_rst: %u\n", snmp->tcp_out_rst); -+ printf("tcp_fin_ack_cnt: %u\n", snmp->tcp_fin_ack_cnt); -+ printf("tcp_delay_ack_cnt: %u\n", snmp->tcp_delay_ack_cnt); -+ printf("tcp_refused_cnt: %u\n", snmp->tcp_refused_cnt); -+} -+ - static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_data *stat, - const struct gazelle_stat_lstack_snmp *snmp) - { -@@ -850,16 +866,8 @@ static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_d - printf("udp_no_ports: %u\n", snmp->udp_no_ports); - printf("udp_in_errors: %u\n", snmp->udp_in_errors); - printf("udp_out_datagrams: %u\n", snmp->udp_out_datagrams); -- -- printf("tcp_act_open: %u\n", snmp->tcp_act_open); -- printf("tcp_passive_open: %u\n", snmp->tcp_passive_open); -- printf("tcp_attempt_fail: %u\n", snmp->tcp_attempt_fail); -- printf("tcp_estab_rst: %u\n", snmp->tcp_estab_rst); -- printf("tcp_out_seg: %u\n", snmp->tcp_out_seg); -- printf("tcp_retran_seg: %u\n", snmp->tcp_retran_seg); -- printf("tcp_in_seg: %u\n", snmp->tcp_in_seg); -- printf("tcp_in_err: %u\n", snmp->tcp_in_err); -- printf("tcp_out_rst: %u\n", snmp->tcp_out_rst); -+ -+ gazelle_print_lstack_tcp_stat(snmp); - - printf("icmp_in_msgs: %u\n", snmp->icmp_in_msgs); - printf("icmp_in_errors: %u\n", snmp->icmp_in_errors); --- -2.27.0 - diff --git a/0062-stack-fix-coredump-caused-by-gazelleclt-in-rtc-mode.patch b/0062-stack-fix-coredump-caused-by-gazelleclt-in-rtc-mode.patch deleted file mode 100644 index 4f5a698..0000000 --- a/0062-stack-fix-coredump-caused-by-gazelleclt-in-rtc-mode.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 94e60e452e11fcc785fe44a66358608b5e2d90a7 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 27 Nov 2023 21:41:13 +0800 -Subject: [PATCH] stack: fix coredump caused by gazelleclt in rtc mode when - stack num defined is greater than the hijacked thread num - ---- - src/lstack/core/lstack_dpdk.c | 7 +------ - src/lstack/core/lstack_protocol_stack.c | 20 ++++++++------------ - src/lstack/include/lstack_dpdk.h | 2 +- - 3 files changed, 10 insertions(+), 19 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 19a7bf4..839516e 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -205,13 +205,8 @@ static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_ - return reg_buf; - } - --int32_t pktmbuf_pool_init(struct protocol_stack *stack, uint16_t stack_num) -+int32_t pktmbuf_pool_init(struct protocol_stack *stack) - { -- if (stack_num == 0) { -- LSTACK_LOG(ERR, LSTACK, "stack_num=0.\n"); -- return -1; -- } -- - stack->rxtx_pktmbuf_pool = get_pktmbuf_mempool("rxtx_mbuf", stack->queue_id); - if (stack->rxtx_pktmbuf_pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "rxtx_pktmbuf_pool is NULL\n"); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index dfebfcc..baacaa9 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -349,7 +349,7 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - return -1; - } - -- if (pktmbuf_pool_init(stack, stack_group->stack_num) != 0) { -+ if (pktmbuf_pool_init(stack) != 0) { - LSTACK_LOG(ERR, LSTACK, "pktmbuf_pool_init failed\n"); - return -1; - } -@@ -529,7 +529,7 @@ static void gazelle_listen_thread(void *arg) - int32_t stack_group_init_mempool(void) - { - struct cfg_params *global_cfg_parmas = get_global_cfg_params(); -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; - struct rte_mempool *rxtx_mbuf = NULL; - uint32_t cpu_id = 0; - unsigned numa_id = 0; -@@ -537,10 +537,8 @@ int32_t stack_group_init_mempool(void) - - LSTACK_LOG(INFO, LSTACK, - "config::num_cpu=%d num_process=%d \n", global_cfg_parmas->num_cpu, global_cfg_parmas->num_process); -- -- uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; - -- for (int cpu_idx = 0; cpu_idx < global_cfg_parmas->num_cpu; cpu_idx++) { -+ for (int cpu_idx = 0; cpu_idx < get_global_cfg_params()->num_queue; cpu_idx++) { - cpu_id = global_cfg_parmas->cpus[cpu_idx]; - numa_id = numa_node_of_cpu(cpu_id); - -@@ -552,7 +550,7 @@ int32_t stack_group_init_mempool(void) - } - - rxtx_mbuf = create_pktmbuf_mempool( -- "rxtx_mbuf", total_mbufs / stack_group->stack_num, RXTX_CACHE_SZ, queue_id, numa_id); -+ "rxtx_mbuf", total_mbufs / get_global_cfg_params()->num_queue, RXTX_CACHE_SZ, queue_id, numa_id); - if (rxtx_mbuf == NULL) { - LSTACK_LOG(ERR, LSTACK, "cpuid=%u, numid=%d , rxtx_mbuf idx= %d create_pktmbuf_mempool fail\n", - cpu_id, numa_id, queue_id); -@@ -569,11 +567,7 @@ int32_t stack_group_init_mempool(void) - int32_t stack_group_init(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- if (!get_global_cfg_params()->seperate_send_recv) { -- stack_group->stack_num = get_global_cfg_params()->num_cpu; -- } else { -- stack_group->stack_num = get_global_cfg_params()->num_cpu * 2; -- } -+ stack_group->stack_num = 0; - - init_list_node(&stack_group->poll_list); - pthread_spin_init(&stack_group->poll_list_lock, PTHREAD_PROCESS_PRIVATE); -@@ -627,6 +621,7 @@ int32_t stack_setup_app_thread(void) - LSTACK_LOG(INFO, LSTACK, "stack setup failed in app thread\n"); - return -1; - } -+ atomic_fetch_add(&g_stack_group.stack_num, 1); - - return 0; - } -@@ -670,10 +665,11 @@ int32_t stack_setup_thread(void) - } - - /* 2: wait stack thread and kernel_event thread init finish */ -- wait_sem_value(&g_stack_group.sem_stack_setup, g_stack_group.stack_num * 2); -+ wait_sem_value(&g_stack_group.sem_stack_setup, queue_num * 2); - if (g_stack_group.stack_setup_fail) { - return -1; - } -+ g_stack_group.stack_num = queue_num; - - return 0; - } -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index e3daefa..6554a7e 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -43,7 +43,7 @@ struct rte_ring; - struct rte_mbuf; - int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num); - int32_t dpdk_eal_init(void); --int32_t pktmbuf_pool_init(struct protocol_stack *stack, uint16_t stack_num); -+int32_t pktmbuf_pool_init(struct protocol_stack *stack); - struct rte_ring *create_ring(const char *name, uint32_t count, uint32_t flags, int32_t queue_id); - struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t size, - uint32_t flags, int32_t idx); --- -2.27.0 - diff --git a/0063-dfx-add-tcp-exception-and-kernel-event-statistics.patch b/0063-dfx-add-tcp-exception-and-kernel-event-statistics.patch deleted file mode 100644 index c1a9119..0000000 --- a/0063-dfx-add-tcp-exception-and-kernel-event-statistics.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 66f2015f6710d86966b8abcf028f69a3165c10aa Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 28 Nov 2023 18:43:42 +0800 -Subject: [PATCH] dfx: add tcp exception and kernel event statistics - ---- - src/common/gazelle_dfx_msg.h | 4 ++++ - src/lstack/api/lstack_epoll.c | 9 +++++++-- - src/ltran/ltran_dfx.c | 7 ++++++- - 3 files changed, 17 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 8071108..bfc4992 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -75,6 +75,7 @@ struct gazelle_wakeup_stat { - uint64_t app_write_cnt; - uint64_t app_read_cnt; - uint64_t read_null; -+ uint64_t kernel_events; - }; - - struct gazelle_stat_pkts { -@@ -120,6 +121,9 @@ struct gazelle_stat_lstack_snmp { - uint32_t tcp_fin_ack_cnt; - uint32_t tcp_delay_ack_cnt; - uint32_t tcp_refused_cnt; -+ uint32_t tcp_out_of_seq; -+ uint32_t tcp_acceptmbox_full; -+ uint32_t tcp_listen_drops; - - /* UDP */ - uint32_t udp_in_datagrams; -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 2cb459e..a2d2a9b 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -493,7 +493,6 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - } - } - -- wakeup->stat.app_events += event_num; - return event_num; - } - -@@ -611,6 +610,7 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - - lwip_num = epoll_lwip_event_nolock(wakeup, &events[kernel_num], tmpmaxevents - kernel_num); - wakeup->stat.app_events += lwip_num; -+ wakeup->stat.kernel_events += kernel_num; - - return lwip_num + kernel_num; - } -@@ -634,7 +634,6 @@ int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - do { - __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); - lwip_num = epoll_lwip_event(wakeup, events, maxevents); -- wakeup->stat.app_events += lwip_num; - - if (__atomic_load_n(&wakeup->have_kernel_event, __ATOMIC_ACQUIRE)) { - kernel_num = posix_api->epoll_wait_fn(epfd, &events[lwip_num], maxevents - lwip_num, 0); -@@ -661,6 +660,9 @@ int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - } while (ret == 0); - - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -+ wakeup->stat.app_events += lwip_num; -+ wakeup->stat.kernel_events += kernel_num; -+ - return lwip_num + kernel_num; - } - -@@ -870,6 +872,9 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - } while (ret == 0); - - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -+ wakeup->stat.app_events += lwip_num; -+ wakeup->stat.kernel_events += kernel_num; -+ - return lwip_num + kernel_num; - } - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 98e23dc..3bd120c 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -604,7 +604,9 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("write_lwip: %-17"PRIu64" ", lstack_stat->data.pkts.stack_stat.write_lwip_cnt); - printf("app_write_rpc: %-14"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.app_write_rpc); - printf("recv_list: %-18"PRIu64" ", lstack_stat->data.pkts.recv_list_cnt); -- printf("conn_num: %-19hu \n", lstack_stat->data.pkts.conn_num); -+ printf("conn_num: %-19hu ", lstack_stat->data.pkts.conn_num); -+ -+ printf("kernel_events: %-14"PRIu64"\n", lstack_stat->data.pkts.wakeup_stat.kernel_events); - printf("wakeup_events: %-14"PRIu64" ", lstack_stat->data.pkts.stack_stat.wakeup_events); - printf("app_events: %-17"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_events); - printf("read_null: %-18"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.read_null); -@@ -839,6 +841,9 @@ static void gazelle_print_lstack_tcp_stat(const struct gazelle_stat_lstack_snmp - printf("tcp_fin_ack_cnt: %u\n", snmp->tcp_fin_ack_cnt); - printf("tcp_delay_ack_cnt: %u\n", snmp->tcp_delay_ack_cnt); - printf("tcp_refused_cnt: %u\n", snmp->tcp_refused_cnt); -+ printf("tcp_out_of_seq: %u\n", snmp->tcp_out_of_seq); -+ printf("tcp_acceptmbox_full: %u\n", snmp->tcp_acceptmbox_full); -+ printf("tcp_listen_drops: %u\n", snmp->tcp_listen_drops); - } - - static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_data *stat, --- -2.27.0 - diff --git a/0064-add-vlan_id-in-netif.patch b/0064-add-vlan_id-in-netif.patch deleted file mode 100644 index c35d11e..0000000 --- a/0064-add-vlan_id-in-netif.patch +++ /dev/null @@ -1,88 +0,0 @@ -From fcdf8a09859cc0ba148a5c0a410997931fb4fa20 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Wed, 22 Nov 2023 16:08:22 +0800 -Subject: [PATCH] add vlan_id in netif - ---- - src/lstack/core/lstack_cfg.c | 4 ++-- - src/lstack/core/lstack_lwip.c | 3 --- - src/lstack/include/lstack_cfg.h | 2 +- - src/lstack/netif/lstack_ethdev.c | 5 +++++ - src/lstack/netif/lstack_vdev.c | 2 +- - 5 files changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index d1cbd1d..6324c97 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1261,9 +1261,9 @@ static int32_t parse_stack_thread_mode(void) - static int32_t parse_nic_vlan_mode(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.nic.vlan_mode, "nic_vlan_mode", 0, 0, 4094, ret); -+ PARSE_ARG(g_config_params.nic.vlan_mode, "nic_vlan_mode", -1, -1, 4094, ret); - if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid vlan mode value %d ret=%d. only support 0~4094\n", \ -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid vlan mode value %d ret=%d. only support -1~4094\n", \ - g_config_params.nic.vlan_mode, ret); - } - return ret; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c8b4e8f..af9bf73 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -196,9 +196,6 @@ void do_lwip_init_sock(int32_t fd) - (void)replenish_send_idlembuf(stack, sock); - - sock->stack = stack; -- if (get_global_cfg_params()->nic.vlan_mode > 0 && get_global_cfg_params()->nic.vlan_mode < 4095) { -- sock->conn->pcb.udp->netif_hints.tci = get_global_cfg_params()->nic.vlan_mode; -- } - - init_list_node_null(&sock->recv_list); - init_list_node_null(&sock->event_list); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index e33f4fe..a6bdfd5 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -63,7 +63,7 @@ struct secondary_attach_arg { - struct cfg_nic_params { - uint32_t rxqueue_size; - uint32_t txqueue_size; -- uint16_t vlan_mode; -+ int32_t vlan_mode; - }; - - struct cfg_params { -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 29bef21..cce2fcf 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -967,6 +967,11 @@ int32_t ethdev_init(struct protocol_stack *stack) - netif_ip6_addr_set(&stack->netif, 0, &cfg->host_addr6); - netif_ip6_addr_set_state(&stack->netif, 0, IP6_ADDR_VALID); - } -+ -+ /* 0-4094: The vlaue range for VLAN IDs is 0 to 4094. */ -+ if (get_global_cfg_params()->nic.vlan_mode >= 0 && get_global_cfg_params()->nic.vlan_mode <= 4094) { -+ netif_set_vlan_tci(&stack->netif, (u16_t)get_global_cfg_params()->nic.vlan_mode); -+ } - - netif_set_link_up(&stack->netif); - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index d57ce59..18322a6 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -84,7 +84,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - } - - /* skip gro when tcp/ip cksum offloads disable */ -- if (get_protocol_stack_group()->rx_offload == 0 || get_global_cfg_params()->nic.vlan_mode > 0) { -+ if (get_protocol_stack_group()->rx_offload == 0 || get_global_cfg_params()->nic.vlan_mode >= 0) { - return pkt_num; - } - --- -2.27.0 - diff --git a/0065-support-vlan-offload.patch b/0065-support-vlan-offload.patch deleted file mode 100644 index 2d5beb1..0000000 --- a/0065-support-vlan-offload.patch +++ /dev/null @@ -1,89 +0,0 @@ -From a449111fed8c0c4cd7b8021ff20b3ea12f334479 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Tue, 28 Nov 2023 14:14:15 +0800 -Subject: [PATCH] support vlan offload - ---- - src/common/dpdk_common.c | 12 ++++++++++++ - src/lstack/netif/lstack_ethdev.c | 13 +++++++------ - src/lstack/netif/lstack_vdev.c | 3 ++- - 3 files changed, 21 insertions(+), 7 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index 52a163f..50f0bf0 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -104,6 +104,12 @@ void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev - COMMON_INFO("DEV_RX_OFFLOAD_UDP_CKSUM\n"); - } - -+ // rx vlan -+ if (rx_ol_capa & DEV_RX_OFFLOAD_VLAN_STRIP) { -+ rx_ol |= DEV_RX_OFFLOAD_VLAN_STRIP; -+ COMMON_INFO("DEV_RX_OFFLOAD_VLAN_STRIP\n"); -+ } -+ - // tx ip - if (tx_ol_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) { - tx_ol |= DEV_TX_OFFLOAD_IPV4_CKSUM; -@@ -128,6 +134,12 @@ void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev - COMMON_INFO("DEV_TX_OFFLOAD_TCP_TSO\n"); - } - -+ // tx vlan -+ if (tx_ol_capa & DEV_TX_OFFLOAD_VLAN_INSERT) { -+ tx_ol |= DEV_TX_OFFLOAD_VLAN_INSERT; -+ COMMON_INFO("DEV_TX_OFFLOAD_VLAN_INSERT\n"); -+ } -+ - if (!(rx_ol & DEV_RX_OFFLOAD_UDP_CKSUM) || - !(rx_ol & DEV_RX_OFFLOAD_TCP_CKSUM) || - !(rx_ol & DEV_RX_OFFLOAD_IPV4_CKSUM)) { -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index cce2fcf..31856f2 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -815,12 +815,12 @@ int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_fla - /* copy arp into other stack */ - if (!use_ltran_flag) { - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); -- u16_t type; -- type = ethh->ether_type; -- if (type == PP_HTONS(ETHTYPE_VLAN)) { -- struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethh) + SIZEOF_ETH_HDR); -- type = vlan->tpid; -- } -+ u16_t type; -+ type = ethh->ether_type; -+ if (type == PP_HTONS(ETHTYPE_VLAN)) { -+ struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethh) + SIZEOF_ETH_HDR); -+ type = vlan->tpid; -+ } - if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == type)) { - stack_broadcast_arp(stack->pkts[i], stack); - /* copy arp into other process */ -@@ -860,6 +860,7 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - mbuf->data_len = pbuf->len; - mbuf->pkt_len = pbuf->tot_len; - mbuf->ol_flags = pbuf->ol_flags; -+ mbuf->vlan_tci = pbuf->vlan_tci; - mbuf->next = NULL; - buf_addr = rte_pktmbuf_mtod(mbuf, void *); - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 18322a6..e1438da 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -84,7 +84,8 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - } - - /* skip gro when tcp/ip cksum offloads disable */ -- if (get_protocol_stack_group()->rx_offload == 0 || get_global_cfg_params()->nic.vlan_mode >= 0) { -+ if (get_protocol_stack_group()->rx_offload == 0 || (get_global_cfg_params()->nic.vlan_mode >= 0 -+ && !(get_protocol_stack_group()->rx_offload & DEV_RX_OFFLOAD_VLAN_STRIP))) { - return pkt_num; - } - --- -2.27.0 - diff --git a/0066-gazellectl-fix-gazellectl-lstack-show-1-r-error.patch b/0066-gazellectl-fix-gazellectl-lstack-show-1-r-error.patch deleted file mode 100644 index 9d7711d..0000000 --- a/0066-gazellectl-fix-gazellectl-lstack-show-1-r-error.patch +++ /dev/null @@ -1,487 +0,0 @@ -From 1a43d75144d7fc4f052758aceadf47535ef3262e Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 20 Nov 2023 21:15:51 +0800 -Subject: [PATCH] gazellectl: fix gazellectl lstack show 1 -r error - ---- - src/common/gazelle_dfx_msg.h | 28 +++-- - src/lstack/core/lstack_stack_stat.c | 15 +-- - src/ltran/ltran_dfx.c | 188 ++++++++++++++++------------ - src/ltran/ltran_monitor.c | 5 +- - 4 files changed, 131 insertions(+), 105 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index bfc4992..ac6ea5e 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -25,6 +25,7 @@ - enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LTRAN_SHOW = 0, - GAZELLE_STAT_LTRAN_SHOW_RATE, -+ GAZELLE_STAT_LTRAN_SHOW_LB_RATE, - GAZELLE_STAT_LTRAN_SHOW_INSTANCE, - GAZELLE_STAT_LTRAN_SHOW_BURST, - GAZELLE_STAT_LTRAN_SHOW_LATENCY, -@@ -78,6 +79,18 @@ struct gazelle_wakeup_stat { - uint64_t kernel_events; - }; - -+struct gazelle_stack_aggregate_stats { -+ /* 0: RX, 1: TX, 2: APP_TX */ -+ uint32_t size_1_64[3]; -+ uint32_t size_65_512[3]; -+ uint32_t size_513_1460[3]; -+ uint32_t size_1461_8192[3]; -+ uint32_t size_8193_max[3]; -+ -+ uint64_t rx_bytes; -+ uint64_t tx_bytes; -+}; -+ - struct gazelle_stat_pkts { - uint16_t conn_num; - uint32_t mempool_freecnt; -@@ -86,6 +99,7 @@ struct gazelle_stat_pkts { - uint64_t call_alloc_fail; - struct gazelle_stack_stat stack_stat; - struct gazelle_wakeup_stat wakeup_stat; -+ struct gazelle_stack_aggregate_stats aggregate_stats; - }; - - /* same as define in lwip/stats.h - struct stats_mib2 */ -@@ -218,23 +232,12 @@ struct nic_eth_xstats { - uint16_t port_id; - }; - --struct gazelle_stack_aggregate_stats { -- /* 0: RX, 1: TX, 2: APP_TX */ -- uint32_t size_1_64[3]; -- uint32_t size_65_512[3]; -- uint32_t size_513_1460[3]; -- uint32_t size_1461_8192[3]; -- uint32_t size_8193_max[3]; -- -- uint64_t rx_bytes; -- uint64_t tx_bytes; --}; -- - struct gazelle_stack_dfx_data { - /* indicates whether the current message is the last */ - uint32_t eof; - uint32_t tid; - int32_t loglevel; -+ uint32_t stack_id; - struct gazelle_stat_low_power_info low_power_info; - - union lstack_msg { -@@ -243,7 +246,6 @@ struct gazelle_stack_dfx_data { - struct gazelle_stat_lstack_conn conn; - struct gazelle_stat_lstack_snmp snmp; - struct nic_eth_xstats nic_xstats; -- struct gazelle_stack_aggregate_stats aggregate_stats; - } data; - }; - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 18548ab..3fd5903 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -198,6 +198,13 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - case GAZELLE_STAT_LSTACK_SHOW: - case GAZELLE_STAT_LSTACK_SHOW_RATE: - get_stack_stats(dfx, stack); -+ /* fall through */ -+ case GAZELLE_STAT_LSTACK_SHOW_AGGREGATE: -+ ret = memcpy_s(&dfx->data.pkts.aggregate_stats, sizeof(dfx->data.pkts.aggregate_stats), -+ &stack->aggregate_stats, sizeof(stack->aggregate_stats)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); -+ } - break; - case GAZELLE_STAT_LSTACK_SHOW_SNMP: - ret = memcpy_s(&dfx->data.snmp, sizeof(dfx->data.snmp), &stack->lwip_stats->mib2, -@@ -218,13 +225,6 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); - } - break; -- case GAZELLE_STAT_LSTACK_SHOW_AGGREGATE: -- ret = memcpy_s(&dfx->data.aggregate_stats, sizeof(dfx->data.aggregate_stats), -- &stack->aggregate_stats, sizeof(stack->aggregate_stats)); -- if (ret != EOK) { -- LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); -- } -- break; - case GAZELLE_STAT_LTRAN_START_LATENCY: - set_latency_start_flag(true); - break; -@@ -287,6 +287,7 @@ int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) - } - - dfx.tid = stack->tid; -+ dfx.stack_id = i; - if (i == stack_group->stack_num - 1) { - dfx.eof = 1; - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 3bd120c..d3ff527 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -45,6 +45,7 @@ - #define GAZELLE_LSTACK_SET_MINNUM 6 - - #define GAZELLE_CMD_MAX 5 -+#define CMD_WAIT_TIME 1 // sec - - #define GAZELLE_RESULT_LEN 8291 - #define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins -@@ -55,6 +56,7 @@ static int32_t g_unix_fd = -1; - static int32_t g_ltran_rate_show_flag = GAZELLE_OFF; // not show when first get total statistics - static struct gazelle_stat_ltran_total g_last_ltran_total; - static struct gazelle_stat_lstack_total g_last_lstack_total[GAZELLE_MAX_STACK_ARRAY_SIZE]; -+static struct gazelle_stack_dfx_data g_last_lstack_data[GAZELLE_MAX_STACK_ARRAY_SIZE]; - - static bool g_use_ltran = false; - -@@ -73,6 +75,7 @@ struct gazelle_dfx_list { - - static void gazelle_print_ltran_stat_total(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_ltran_stat_rate(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_ltran_stat_client(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_ltran_stat_burst(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_ltran_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg); -@@ -92,6 +95,7 @@ static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_ - static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_SHOW, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_total}, - {GAZELLE_STAT_LTRAN_SHOW_RATE, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_rate}, -+ {GAZELLE_STAT_LTRAN_SHOW_LB_RATE, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_lb_rate}, - {GAZELLE_STAT_LTRAN_SHOW_INSTANCE, sizeof(struct gazelle_stat_ltran_client), gazelle_print_ltran_stat_client}, - {GAZELLE_STAT_LTRAN_SHOW_BURST, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_burst}, - {GAZELLE_STAT_LTRAN_SHOW_LATENCY, sizeof(struct in_addr), gazelle_print_ltran_stat_latency}, -@@ -103,7 +107,7 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_SHOW_CONNTABLE, sizeof(struct gazelle_stat_forward_table), gazelle_print_ltran_conn}, - {GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, 0, gazelle_print_ltran_wait}, - {GAZELLE_STAT_LSTACK_SHOW, sizeof(struct gazelle_stat_lstack_total), gazelle_print_lstack_stat_total}, -- {GAZELLE_STAT_LSTACK_SHOW_RATE, sizeof(struct gazelle_stat_lstack_total), gazelle_print_lstack_stat_rate}, -+ {GAZELLE_STAT_LSTACK_SHOW_RATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_rate}, - {GAZELLE_STAT_LSTACK_SHOW_SNMP, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_snmp}, - {GAZELLE_STAT_LSTACK_SHOW_CONN, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_conn}, - {GAZELLE_STAT_LSTACK_SHOW_LATENCY, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_latency}, -@@ -422,7 +426,7 @@ static void gazelle_print_ltran_wait(void *buf, const struct gazelle_stat_msg_re - { - (void)buf; - (void)req_msg; -- sleep(1); // give ltran time to read cmd -+ sleep(CMD_WAIT_TIME); // give ltran time to read cmd - } - - static void gazelle_print_ltran_start_latency(void *buf, const struct gazelle_stat_msg_request *req_msg) -@@ -774,44 +778,39 @@ static void gazelle_print_lstack_stat_rate(void *buf, const struct gazelle_stat_ - { - int32_t ret; - double rate; -- uint32_t stack_index; -+ uint32_t index; - char *rate_type = NULL; -- struct gazelle_stat_lstack_total *stats = (struct gazelle_stat_lstack_total *)buf; -+ uint32_t total_wait_time = g_wait_reply + CMD_WAIT_TIME; /* STOP_LATENCY would sleep */ -+ struct gazelle_stack_dfx_data *stats = (struct gazelle_stack_dfx_data *)buf; - /* not show when first get total statistics */ - static int32_t g_lstack_rate_show_flag[GAZELLE_MAX_STACK_ARRAY_SIZE] = {0}; - - do { -- stack_index = stats->index; -- if (stack_index >= GAZELLE_MAX_STACK_ARRAY_SIZE) { -+ index = stats->stack_id; -+ if (index >= GAZELLE_MAX_STACK_ARRAY_SIZE) { - break; - } - -- if (g_lstack_rate_show_flag[stack_index] == GAZELLE_ON) { -+ if (g_lstack_rate_show_flag[index] == GAZELLE_ON) { - printf("------ Statistics of lstack rate stack tid: %6u ------\n", stats->tid); -- printf("rx_pkts: %-15"PRIu64" ", (stats->rx - g_last_lstack_total[stack_index].rx) / -- GAZELLE_DFX_REQ_INTERVAL_S); -- rate = rate_convert_type((stats->rx_bytes - g_last_lstack_total[stack_index].rx_bytes) / -- GAZELLE_DFX_REQ_INTERVAL_S, &rate_type); -+ printf("rx_pkts: %-15"PRIu64" ", (stats->data.pkts.stack_stat.rx - -+ g_last_lstack_data[index].data.pkts.stack_stat.rx) / total_wait_time); -+ rate = rate_convert_type((stats->data.pkts.aggregate_stats.rx_bytes / g_wait_reply), &rate_type); - printf("rx_bytes: %7.2lf%s ", rate, rate_type); -- printf("rx_err: %-15"PRIu64" ", (stats->rx_err - g_last_lstack_total[stack_index].rx_err) / -- GAZELLE_DFX_REQ_INTERVAL_S); -- printf("rx_drop: %-15"PRIu64"\n", (stats->rx_drop - g_last_lstack_total[stack_index].rx_drop) / -- GAZELLE_DFX_REQ_INTERVAL_S); -- printf("tx_pkts: %-15"PRIu64" ", (stats->tx - g_last_lstack_total[stack_index].tx) / -- GAZELLE_DFX_REQ_INTERVAL_S); -- rate = rate_convert_type((stats->tx_bytes - g_last_lstack_total[stack_index].tx_bytes) / -- GAZELLE_DFX_REQ_INTERVAL_S, &rate_type); -+ printf("rx_drop: %-15"PRIu64"\n", (stats->data.pkts.stack_stat.rx_drop - -+ g_last_lstack_data[index].data.pkts.stack_stat.rx_drop) /total_wait_time); -+ printf("tx_pkts: %-15"PRIu64" ", (stats->data.pkts.stack_stat.tx - -+ g_last_lstack_data[index].data.pkts.stack_stat.tx) / total_wait_time); -+ rate = rate_convert_type((stats->data.pkts.aggregate_stats.tx_bytes / g_wait_reply), &rate_type); - printf("tx_bytes: %7.2lf%s ", rate, rate_type); -- printf("tx_err: %-15"PRIu64" ", (stats->tx_err - g_last_lstack_total[stack_index].tx_err) / -- GAZELLE_DFX_REQ_INTERVAL_S); -- printf("tx_drop: %-15"PRIu64"\n\n", (stats->tx_drop - g_last_lstack_total[stack_index].tx_drop) / -- GAZELLE_DFX_REQ_INTERVAL_S); -+ printf("tx_drop: %-15"PRIu64"\n\n", (stats->data.pkts.stack_stat.tx_drop - -+ g_last_lstack_data[index].data.pkts.stack_stat.tx_drop) / total_wait_time); - } else { -- g_lstack_rate_show_flag[stack_index] = GAZELLE_ON; -+ g_lstack_rate_show_flag[index] = GAZELLE_ON; - } - -- ret = memcpy_s(&g_last_lstack_total[stack_index], sizeof(*stats), stats, -- sizeof(struct gazelle_stat_lstack_total)); -+ ret = memcpy_s(&g_last_lstack_data[index], sizeof(*stats), stats, -+ sizeof(struct gazelle_stack_dfx_data)); - if (ret != EOK) { - printf("%s:%d memcpy_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - } -@@ -820,7 +819,7 @@ static void gazelle_print_lstack_stat_rate(void *buf, const struct gazelle_stat_ - break; - } - -- ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stat_lstack_total), req_msg->stat_mode); -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); - if (ret != GAZELLE_OK) { - return; - } -@@ -846,6 +845,63 @@ static void gazelle_print_lstack_tcp_stat(const struct gazelle_stat_lstack_snmp - printf("tcp_listen_drops: %u\n", snmp->tcp_listen_drops); - } - -+static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t ret; -+ double rate; -+ uint32_t stack_index; -+ char *rate_type = NULL; -+ struct gazelle_stat_lstack_total *stats = (struct gazelle_stat_lstack_total *)buf; -+ /* not show when first get total statistics */ -+ static int32_t g_ltran_lb_rate_show_flag[GAZELLE_MAX_STACK_ARRAY_SIZE] = {0}; -+ -+ do { -+ stack_index = stats->index; -+ if (stack_index >= GAZELLE_MAX_STACK_ARRAY_SIZE) { -+ break; -+ } -+ -+ if (g_ltran_lb_rate_show_flag[stack_index] == GAZELLE_ON) { -+ printf("------ Statistics of lstack rate stack tid: %6u ------\n", stats->tid); -+ printf("rx_pkts: %-15"PRIu64" ", (stats->rx - g_last_lstack_total[stack_index].rx) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ rate = rate_convert_type((stats->rx_bytes - g_last_lstack_total[stack_index].rx_bytes) / -+ GAZELLE_DFX_REQ_INTERVAL_S, &rate_type); -+ printf("rx_bytes: %7.2lf%s ", rate, rate_type); -+ printf("rx_err: %-15"PRIu64" ", (stats->rx_err - g_last_lstack_total[stack_index].rx_err) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ printf("rx_drop: %-15"PRIu64"\n", (stats->rx_drop - g_last_lstack_total[stack_index].rx_drop) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ printf("tx_pkts: %-15"PRIu64" ", (stats->tx - g_last_lstack_total[stack_index].tx) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ rate = rate_convert_type((stats->tx_bytes - g_last_lstack_total[stack_index].tx_bytes) / -+ GAZELLE_DFX_REQ_INTERVAL_S, &rate_type); -+ printf("tx_bytes: %7.2lf%s ", rate, rate_type); -+ printf("tx_err: %-15"PRIu64" ", (stats->tx_err - g_last_lstack_total[stack_index].tx_err) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ printf("tx_drop: %-15"PRIu64"\n\n", (stats->tx_drop - g_last_lstack_total[stack_index].tx_drop) / -+ GAZELLE_DFX_REQ_INTERVAL_S); -+ } else { -+ g_ltran_lb_rate_show_flag[stack_index] = GAZELLE_ON; -+ } -+ -+ ret = memcpy_s(&g_last_lstack_total[stack_index], sizeof(*stats), stats, -+ sizeof(struct gazelle_stat_lstack_total)); -+ if (ret != EOK) { -+ printf("%s:%d memcpy_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); -+ } -+ -+ if (stats->eof != 0) { -+ break; -+ } -+ -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stat_lstack_total), req_msg->stat_mode); -+ if (ret != GAZELLE_OK) { -+ return; -+ } -+ } while (true); -+} -+ - static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_data *stat, - const struct gazelle_stat_lstack_snmp *snmp) - { -@@ -1048,15 +1104,12 @@ static int32_t parse_dfx_ltran_show_args(int32_t argc, char *argv[], struct gaze - if (strcmp(param, "rate") == 0 || strcmp(param, "-r") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_RATE; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; -- } -- if (strcmp(param, "instance") == 0 || strcmp(param, "-i") == 0) { -+ } else if (strcmp(param, "instance") == 0 || strcmp(param, "-i") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_INSTANCE; -- } -- if (strcmp(param, "burst") == 0 || strcmp(param, "-b") == 0) { -+ } else if (strcmp(param, "burst") == 0 || strcmp(param, "-b") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_BURST; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; -- } -- if (strcmp(param, "table") == 0 || strcmp(param, "-t") == 0) { -+ } else if (strcmp(param, "table") == 0 || strcmp(param, "-t") == 0) { - if (argc < GAZELLE_OPT_LPM_ARG_IDX1) { - return cmd_index; - } -@@ -1067,8 +1120,7 @@ static int32_t parse_dfx_ltran_show_args(int32_t argc, char *argv[], struct gaze - if (strcmp(param, "conntable") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_CONNTABLE; - } -- } -- if (strcmp(param, "latency") == 0 || strcmp(param, "-l") == 0) { -+ } else if (strcmp(param, "latency") == 0 || strcmp(param, "-l") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_LATENCY; -@@ -1092,7 +1144,7 @@ static int32_t parse_dfx_ltran_show_args(int32_t argc, char *argv[], struct gaze - static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - struct gazelle_stack_dfx_data *dfx = (struct gazelle_stack_dfx_data *)buf; -- struct gazelle_stack_aggregate_stats *stats = &dfx->data.aggregate_stats; -+ struct gazelle_stack_aggregate_stats *stats = &dfx->data.pkts.aggregate_stats; - char *rate_type = NULL; - double rate; - int32_t ret = 0; -@@ -1219,19 +1271,21 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - - char *param = argv[GAZELLE_OPTIONS1_ARG_IDX]; - if (strcmp(param, "rate") == 0 || strcmp(param, "-r") == 0) { -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_RATE; -+ if (g_use_ltran) { -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_LB_RATE; -+ } else { -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_RATE; -+ } - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; -- } -- if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) { -+ } else if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_SNMP; -- } -- if (strcmp(param, "connect") == 0 || strcmp(param, "-c") == 0) { -+ } else if (strcmp(param, "connect") == 0 || strcmp(param, "-c") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_CONN; -- } -- if (strcmp(param, "xstats") == 0 || strcmp(param, "-x") == 0) { -+ } else if (strcmp(param, "xstats") == 0 || strcmp(param, "-x") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_XSTATS; -- } -- if (strcmp(param, "latency") == 0 || strcmp(param, "-l") == 0) { -+ } else if (strcmp(param, "latency") == 0 || strcmp(param, "-l") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_LATENCY; -@@ -1242,8 +1296,7 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - if (parse_delay_arg(argc, argv, delay) != 0) { - return 0; - } -- } -- if (strcmp(param, "aggragate") == 0 || strcmp(param, "-a") == 0) { -+ } else if (strcmp(param, "aggragate") == 0 || strcmp(param, "-a") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_AGGREGATE; -@@ -1314,31 +1367,6 @@ static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_sta - return num_cmd; - } - --static int32_t check_cmd_support(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) --{ -- switch (req_msg[0].stat_mode) { -- case GAZELLE_STAT_LSTACK_LOG_LEVEL_SET: -- case GAZELLE_STAT_LSTACK_SHOW: -- case GAZELLE_STAT_LSTACK_SHOW_SNMP: -- case GAZELLE_STAT_LSTACK_SHOW_CONN: -- case GAZELLE_STAT_LSTACK_SHOW_LATENCY: -- case GAZELLE_STAT_LSTACK_LOW_POWER_MDF: -- case GAZELLE_STAT_LSTACK_SHOW_XSTATS: -- case GAZELLE_STAT_LSTACK_SHOW_AGGREGATE: -- return 0; -- default: -- if (req_msg[0].stat_mode == GAZELLE_STAT_LTRAN_START_LATENCY && -- (req_msg[req_msg_num - 1].stat_mode == GAZELLE_STAT_LSTACK_SHOW_LATENCY || -- req_msg[req_msg_num - 1].stat_mode == GAZELLE_STAT_LSTACK_SHOW_AGGREGATE)) { -- return 0; -- } -- /* keep output consistency */ -- printf("connect ltran failed. errno: 111 ret=-1\n"); -- printf("You may need to use the -u parameter to specify the UNIX_PREFIX that matches the configuration.\n"); -- return -1; -- } --} -- - int32_t dfx_loop(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) - { - int32_t ret; -@@ -1377,8 +1405,10 @@ int32_t dfx_loop(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) - - // stat_mode = GAZELLE_STAT_MODE_MAX need repeat command - if (req_msg[msg_index].stat_mode == GAZELLE_STAT_MODE_MAX) { -- msg_index--; -- sleep(GAZELLE_DFX_REQ_INTERVAL_S); -+ if (req_msg[msg_index - 1].stat_mode != GAZELLE_STAT_LSTACK_SHOW_RATE) { -+ sleep(GAZELLE_DFX_REQ_INTERVAL_S); -+ } -+ msg_index = 0; - } - } - -@@ -1388,7 +1418,7 @@ int32_t dfx_loop(struct gazelle_stat_msg_request *req_msg, int32_t req_msg_num) - int32_t main(int32_t argc, char *argv[]) - { - struct gazelle_stat_msg_request req_msg[GAZELLE_CMD_MAX] = {0}; -- int32_t req_msg_num, ret; -+ int32_t req_msg_num; - - int unix_arg = 0; - for (int32_t i = 1; i < argc; i++) { -@@ -1418,13 +1448,5 @@ int32_t main(int32_t argc, char *argv[]) - return 0; - } - -- if (!g_use_ltran) { -- g_gazelle_dfx_tbl[GAZELLE_STAT_LSTACK_SHOW].recv_size = sizeof(struct gazelle_stack_dfx_data); -- ret = check_cmd_support(req_msg, req_msg_num); -- if (ret < 0) { -- return -1; -- } -- } -- - return dfx_loop(req_msg, req_msg_num); - } -diff --git a/src/ltran/ltran_monitor.c b/src/ltran/ltran_monitor.c -index d163a47..792db89 100644 ---- a/src/ltran/ltran_monitor.c -+++ b/src/ltran/ltran_monitor.c -@@ -335,14 +335,15 @@ static int32_t lstack_req_mode_process(int32_t fd, const struct gazelle_stat_msg - case GAZELLE_STAT_LSTACK_LOG_LEVEL_SET: - handle_resp_lstack_transfer(req_msg, -1); - break; -- case GAZELLE_STAT_LSTACK_SHOW_RATE: -+ case GAZELLE_STAT_LTRAN_SHOW_LB_RATE: - handle_resp_lstack_total(req_msg, fd); - break; - case GAZELLE_STAT_LSTACK_SHOW: - handle_resp_lstack_total(req_msg, fd); - handle_resp_lstack_transfer(req_msg, fd); - break; -- case GAZELLE_STAT_LSTACK_SHOW_SNMP: // fall through -+ case GAZELLE_STAT_LSTACK_SHOW_RATE: // fall through -+ case GAZELLE_STAT_LSTACK_SHOW_SNMP: - case GAZELLE_STAT_LSTACK_SHOW_CONN: - case GAZELLE_STAT_LSTACK_SHOW_LATENCY: - case GAZELLE_STAT_LSTACK_LOW_POWER_MDF: --- -2.27.0 - diff --git a/0067-fix-coredump-because-sock-closed-before-send-data-fu.patch b/0067-fix-coredump-because-sock-closed-before-send-data-fu.patch deleted file mode 100644 index 0bd8a48..0000000 --- a/0067-fix-coredump-because-sock-closed-before-send-data-fu.patch +++ /dev/null @@ -1,129 +0,0 @@ -From 1a6c2c86c51997d541c6243a80580c9f54f99bb2 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 28 Nov 2023 11:30:49 +0800 -Subject: [PATCH] fix coredump because sock closed before send data fully - ---- - src/lstack/core/lstack_protocol_stack.c | 15 ++++++++++----- - src/lstack/core/lstack_thread_rpc.c | 20 +++++++++++--------- - src/lstack/include/lstack_thread_rpc.h | 3 ++- - 3 files changed, 23 insertions(+), 15 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 54cf9e8..71e7bcc 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -696,7 +696,15 @@ void stack_socket(struct rpc_msg *msg) - void stack_close(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; -- -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ struct lwip_sock *sock = get_socket(fd); -+ -+ if (NETCONN_IS_DATAOUT(sock)) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -+ return; -+ } -+ - msg->result = lwip_close(fd); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -@@ -842,15 +850,12 @@ void stack_send(struct rpc_msg *msg) - replenish_again = do_lwip_send(stack, sock->conn->socket, sock, len, 0); - __sync_fetch_and_sub(&sock->call_num, 1); - if (!NETCONN_IS_DATAOUT(sock) && !replenish_again) { -- rpc_msg_free(msg); - return; - } else { - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 0) { -+ msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); - __sync_fetch_and_add(&sock->call_num, 1); -- } else { -- rpc_msg_free(msg); -- return; - } - } - } -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 92c58df..03e014d 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -71,8 +71,8 @@ static struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func - - pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); - msg->func = func; -- msg->self_release = 1; -- -+ msg->sync_flag = 1; -+ msg->recall_flag = 0; - return msg; - } - -@@ -94,6 +94,7 @@ static inline __attribute__((always_inline)) int32_t rpc_sync_call(lockless_queu - void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - { - struct rpc_msg *msg = NULL; -+ struct lwip_sock *sock = NULL; - - while (max_num--) { - lockless_queue_node *node = lockless_queue_mpsc_pop(&stack->rpc_queue); -@@ -109,14 +110,15 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - stack->stats.call_null++; - } - -- /* stack_send free msg in stack_send */ -- if (msg->func != stack_send) { -- if (msg->self_release) { -+ if (!msg->recall_flag) { -+ if (msg->sync_flag) { - pthread_spin_unlock(&msg->lock); - } else { - rpc_msg_free(msg); - } -- } -+ } else { -+ msg->recall_flag = 0; -+ } - } - } - -@@ -224,7 +226,7 @@ int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf) - return -1; - } - -- msg->self_release = 0; -+ msg->sync_flag = 0; - msg->args[MSG_ARG_0].p = mbuf; - msg->args[MSG_ARG_1].p = stack; - -@@ -458,8 +460,8 @@ int32_t rpc_call_send(int fd, const void *buf, size_t len, int flags) - msg->args[MSG_ARG_1].size = len; - msg->args[MSG_ARG_2].i = flags; - msg->args[MSG_ARG_3].p = stack; -- msg->self_release = 0; -- -+ msg->sync_flag = 0; -+ - rpc_call(&stack->rpc_queue, msg); - - return 0; -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index bcb40dd..80e254f 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -44,7 +44,8 @@ union rpc_msg_arg { - struct rpc_msg_pool; - struct rpc_msg { - pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */ -- int32_t self_release; /* 0:msg handler release msg 1:msg sender release msg */ -+ int8_t sync_flag : 1; -+ int8_t recall_flag : 1; - int64_t result; /* func return val */ - lockless_queue_node queue_node; - struct rpc_msg_pool *pool; --- -2.27.0 - diff --git a/0068-fix-compilation-error.patch b/0068-fix-compilation-error.patch deleted file mode 100644 index 398c566..0000000 --- a/0068-fix-compilation-error.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 876393a2263c2d5de441d357a22db0db0e80a81f Mon Sep 17 00:00:00 2001 -From: wuchangye -Date: Sat, 2 Dec 2023 13:46:03 +0800 -Subject: [PATCH] fix compilation error - ---- - src/lstack/core/lstack_thread_rpc.c | 1 - - src/lstack/include/lstack_thread_rpc.h | 3 --- - 2 files changed, 4 deletions(-) - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 03e014d..f23d935 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -94,7 +94,6 @@ static inline __attribute__((always_inline)) int32_t rpc_sync_call(lockless_queu - void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - { - struct rpc_msg *msg = NULL; -- struct lwip_sock *sock = NULL; - - while (max_num--) { - lockless_queue_node *node = lockless_queue_mpsc_pop(&stack->rpc_queue); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 80e254f..aa8c451 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -96,9 +96,6 @@ static inline __attribute__((always_inline)) void rpc_call(lockless_queue *queue - static inline __attribute__((always_inline)) void rpc_msg_free(struct rpc_msg *msg) - { - pthread_spin_destroy(&msg->lock); -- -- msg->self_release = 0; -- - rte_mempool_put(msg->pool->rpc_pool, (void *)msg); - } - --- -2.27.0 - diff --git a/0069-fix-coredump-because-of-addr-null-in-lwip_fill_sendr.patch b/0069-fix-coredump-because-of-addr-null-in-lwip_fill_sendr.patch deleted file mode 100644 index f719c93..0000000 --- a/0069-fix-coredump-because-of-addr-null-in-lwip_fill_sendr.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 7ad97d182db49ae91e9044f4d50e52f8633b2b1c Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 1 Dec 2023 15:58:09 +0800 -Subject: [PATCH] fix coredump because of addr null in lwip_fill_sendring - ---- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index c087098..27eeafb 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -699,7 +699,7 @@ void stack_close(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = get_socket(fd); - -- if (NETCONN_IS_DATAOUT(sock)) { -+ if (sock && NETCONN_IS_DATAOUT(sock)) { - msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ - return; --- -2.27.0 - diff --git a/0070-add-struct-gz_addr_t.patch b/0070-add-struct-gz_addr_t.patch deleted file mode 100644 index 9d74e67..0000000 --- a/0070-add-struct-gz_addr_t.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 7d721f7c7e5b1ac5265a8a7a30158e81f0e45b9b Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 4 Dec 2023 20:28:41 +0800 -Subject: [PATCH] add struct gz_addr_t -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -日期: Tue Dec 5 9:30:41 2023 +0800 ---- - src/lstack/core/lstack_dpdk.c | 14 ++++++-------- - src/lstack/include/lstack_dpdk.h | 4 ++-- - src/ltran/ltran_timer.c | 8 -------- - 3 files changed, 8 insertions(+), 18 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 839516e..a742335 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -766,7 +766,7 @@ int32_t init_dpdk_ethdev(void) - return 0; - } - --bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port) -+bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port, uint16_t dst_port) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - if (stack_group->reta_mask == 0 || stack_group->nb_queues <= 1) { -@@ -775,19 +775,17 @@ bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, - - union rte_thash_tuple tuple; - uint32_t hash = 0; -- if (IP_IS_V4_VAL(src_ip)) { -- tuple.v4.src_addr = rte_be_to_cpu_32(ip_2_ip4(&src_ip)->addr); -- tuple.v4.dst_addr = rte_be_to_cpu_32(ip_2_ip4(&dst_ip)->addr); -+ if (IP_IS_V4_VAL(*src_ip)) { -+ tuple.v4.src_addr = rte_be_to_cpu_32(src_ip->u_addr.ip4.addr); -+ tuple.v4.dst_addr = rte_be_to_cpu_32(dst_ip->u_addr.ip4.addr); - tuple.v4.sport = src_port; - tuple.v4.dport = dst_port; - hash = rte_softrss((uint32_t *)&tuple, RTE_THASH_V4_L4_LEN, g_default_rss_key); - } else { - int i; - for (i = 0; i < 4; i++) { -- *((uint32_t *)tuple.v6.src_addr + i) = -- rte_be_to_cpu_32(*((const uint32_t *)src_ip.u_addr.ip6.addr + i)); -- *((uint32_t *)tuple.v6.dst_addr + i) = -- rte_be_to_cpu_32(*((const uint32_t *)dst_ip.u_addr.ip6.addr + i)); -+ *((uint32_t *)tuple.v6.src_addr + i) = rte_be_to_cpu_32(*(src_ip->u_addr.ip6.addr + i)); -+ *((uint32_t *)tuple.v6.dst_addr + i) = rte_be_to_cpu_32(*(dst_ip->u_addr.ip6.addr + i)); - } - tuple.v6.sport = src_port; - tuple.v6.dport = dst_port; -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 6554a7e..724ab24 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -13,7 +13,7 @@ - #ifndef _GAZELLE_DPDK_H_ - #define _GAZELLE_DPDK_H_ - --#include -+#include - #include "gazelle_opt.h" - #include "gazelle_dfx_msg.h" - -@@ -54,7 +54,7 @@ int dpdk_ethdev_start(void); - void dpdk_skip_nic_init(void); - int32_t dpdk_init_lstack_kni(void); - void dpdk_restore_pci(void); --bool port_in_stack_queue(ip_addr_t src_ip, ip_addr_t dst_ip, uint16_t src_port, uint16_t dst_port); -+bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port, uint16_t dst_port); - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); - -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 749b8e0..85ea324 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -24,14 +24,6 @@ - #include "ltran_tcp_conn.h" - #include "ltran_instance.h" - #include "ltran_timer.h" --/* undefine lwip_ntohs in lwip/def.h */ --#ifdef ntohs --#undef ntohs --#endif --#ifdef htons --#undef htons --#endif -- - - static uint64_t g_cycles_per_us = 0; - --- -2.27.0 - diff --git a/0071-wrap-support-shutdown.patch b/0071-wrap-support-shutdown.patch deleted file mode 100644 index b2bafed..0000000 --- a/0071-wrap-support-shutdown.patch +++ /dev/null @@ -1,305 +0,0 @@ -From e1bdd31e6f4ec0aa426cdc2e24b2c78fb7903cfe Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 6 Dec 2023 09:26:45 +0800 -Subject: [PATCH] wrap: support shutdown - ---- - src/lstack/api/lstack_rtc_api.c | 5 +++ - src/lstack/api/lstack_rtw_api.c | 13 +++++++ - src/lstack/api/lstack_wrap.c | 24 ++++++++++++ - src/lstack/core/lstack_dpdk.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 45 ++++++++++++++++++++++ - src/lstack/core/lstack_thread_rpc.c | 16 ++++++++ - src/lstack/include/lstack_protocol_stack.h | 3 ++ - src/lstack/include/lstack_rtc_api.h | 1 + - src/lstack/include/lstack_rtw_api.h | 1 + - src/lstack/include/lstack_thread_rpc.h | 1 + - 10 files changed, 110 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 5fad3e8..50d72bc 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -65,6 +65,11 @@ int rtc_close(int s) - return lwip_close(s); - } - -+int rtc_shutdown(int fd, int how) -+{ -+ return lwip_shutdown(fd, how); -+} -+ - int rtc_epoll_create(int flags) - { - if (stack_setup_app_thread() < 0) { -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index c524bf9..04944d5 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -22,8 +22,10 @@ - #include "lstack_protocol_stack.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" -+#include "gazelle_base_func.h" - #include "lstack_rtw_api.h" - -+ - int rtw_socket(int domain, int type, int protocol) - { - return rpc_call_socket(domain, type, protocol); -@@ -228,6 +230,16 @@ int rtw_close(int s) - return stack_broadcast_close(s); - } - -+int rtw_shutdown(int fd, int how) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(fd); -+ if (sock && sock->wakeup && sock->wakeup->epollfd == fd) { -+ GAZELLE_RETURN(ENOTSOCK); -+ } -+ -+ return stack_broadcast_shutdown(fd, how); -+} -+ - int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { - return lstack_rtw_epoll_ctl(epfd, op, fd, event); -@@ -242,3 +254,4 @@ int rtw_epoll_create(int flags) - { - return lstack_epoll_create(flags); - } -+ -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index abbf8a1..07d5f27 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -75,6 +75,7 @@ void wrap_api_init(void) - g_wrap_api->epoll_wait_fn = rtc_epoll_wait; - g_wrap_api->poll_fn = rtc_poll; - g_wrap_api->close_fn = rtc_close; -+ g_wrap_api->shutdown_fn = rtc_shutdown; - g_wrap_api->epoll_ctl_fn = rtc_epoll_ctl; - g_wrap_api->epoll_create1_fn = rtc_epoll_create1; - g_wrap_api->epoll_create_fn = rtc_epoll_create; -@@ -103,6 +104,7 @@ void wrap_api_init(void) - g_wrap_api->epoll_wait_fn = rtw_epoll_wait; - g_wrap_api->poll_fn = rtw_poll; - g_wrap_api->close_fn = rtw_close; -+ g_wrap_api->shutdown_fn = rtw_shutdown; - g_wrap_api->epoll_ctl_fn = rtw_epoll_ctl; - g_wrap_api->epoll_create1_fn = rtw_epoll_create1; - g_wrap_api->epoll_create_fn = rtw_epoll_create; -@@ -554,6 +556,20 @@ static inline int32_t do_close(int32_t s) - return g_wrap_api->close_fn(s); - } - -+static int32_t do_shutdown(int fd, int how) -+{ -+ struct lwip_sock *sock = NULL; -+ if (select_posix_path() == PATH_KERNEL || select_fd_posix_path(fd, &sock) == PATH_KERNEL) { -+ if (posix_api != NULL && !posix_api->ues_posix && g_wrap_api->shutdown_fn(fd, how) == 0) { -+ return 0; -+ } else { -+ return posix_api->shutdown_fn(fd, how); -+ } -+ } -+ -+ return g_wrap_api->shutdown_fn(fd, how); -+} -+ - static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { - if ((select_posix_path() == PATH_KERNEL) || fds == NULL || nfds == 0) { -@@ -742,6 +758,10 @@ int32_t close(int32_t s) - { - return do_close(s); - } -+int32_t shutdown(int fd, int how) -+{ -+ return do_shutdown(fd, how); -+} - int32_t poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { - return do_poll(fds, nfds, timeout); -@@ -875,6 +895,10 @@ int32_t __wrap_close(int32_t s) - { - return do_close(s); - } -+int32_t __wrap_shutdown(int fd, int how) -+{ -+ return do_shutdown(fd, how); -+} - int32_t __wrap_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { - return do_poll(fds, nfds, timeout); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a742335..1811a9d 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -294,7 +294,7 @@ int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, ui - { - int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:=%s \n", -+ LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:%s \n", - num, ret, rte_strerror(-ret)); - return ret; - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 27eeafb..dc8f143 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -715,6 +715,27 @@ void stack_close(struct rpc_msg *msg) - posix_api->close_fn(fd); - } - -+void stack_shutdown(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ int how = msg->args[MSG_ARG_1].i; -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ struct lwip_sock *sock = get_socket(fd); -+ -+ if (sock && NETCONN_IS_DATAOUT(sock)) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); -+ return; -+ } -+ -+ msg->result = lwip_shutdown(fd, how); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), fd, msg->result); -+ } -+ -+ posix_api->shutdown_fn(fd, how); -+} -+ - void stack_bind(struct rpc_msg *msg) - { - msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].socklen); -@@ -1041,6 +1062,29 @@ int32_t stack_broadcast_close(int32_t fd) - return ret; - } - -+int stack_broadcast_shutdown(int fd, int how) -+{ -+ int32_t ret = 0; -+ struct lwip_sock *sock = get_socket(fd); -+ if (sock == NULL) { -+ return -1; -+ } -+ -+ do { -+ sock = sock->listen_next; -+ if (rpc_call_shutdown(fd, how)) { -+ ret = -1; -+ } -+ -+ if (sock == NULL || sock->conn == NULL) { -+ break; -+ } -+ fd = sock->conn->socket; -+ } while (sock); -+ -+ return ret; -+} -+ - /* choice one stack listen */ - int32_t stack_single_listen(int32_t fd, int32_t backlog) - { -@@ -1204,3 +1248,4 @@ int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *add - { - return stack_broadcast_accept4(fd, addr, addrlen, 0); - } -+ -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index f23d935..4dc3da3 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -262,6 +262,21 @@ int32_t rpc_call_close(int fd) - return rpc_sync_call(&stack->rpc_queue, msg); - } - -+int32_t rpc_call_shutdown(int fd, int how) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_shutdown); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].i = how; -+ -+ return rpc_sync_call(&stack->rpc_queue, msg); -+} -+ - void rpc_call_clean_epoll(struct protocol_stack *stack, struct wakeup_poll *wakeup) - { - struct rpc_msg *msg = rpc_msg_alloc(stack, stack_clean_epoll); -@@ -465,3 +480,4 @@ int32_t rpc_call_send(int fd, const void *buf, size_t len, int flags) - - return 0; - } -+ -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 2c581b3..e339b8d 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -126,6 +126,8 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ - int32_t stack_broadcast_close(int32_t fd); - -+int stack_broadcast_shutdown(int fd, int how); -+ - /* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ - int32_t stack_broadcast_listen(int32_t fd, int backlog); - int32_t stack_single_listen(int32_t fd, int32_t backlog); -@@ -152,6 +154,7 @@ void stack_clean_epoll(struct rpc_msg *msg); - void stack_arp(struct rpc_msg *msg); - void stack_socket(struct rpc_msg *msg); - void stack_close(struct rpc_msg *msg); -+void stack_shutdown(struct rpc_msg *msg); - void stack_bind(struct rpc_msg *msg); - void stack_listen(struct rpc_msg *msg); - void stack_accept(struct rpc_msg *msg); -diff --git a/src/lstack/include/lstack_rtc_api.h b/src/lstack/include/lstack_rtc_api.h -index dd90e59..3a41e6f 100644 ---- a/src/lstack/include/lstack_rtc_api.h -+++ b/src/lstack/include/lstack_rtc_api.h -@@ -49,6 +49,7 @@ int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout); - int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); - int rtc_socket(int domain, int type, int protocol); - int rtc_close(int s); -+int rtc_shutdown(int fd, int how); - int rtc_epoll_create(int flags); - int rtc_epoll_create1(int flags); - int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -diff --git a/src/lstack/include/lstack_rtw_api.h b/src/lstack/include/lstack_rtw_api.h -index d0f77b7..a38b656 100644 ---- a/src/lstack/include/lstack_rtw_api.h -+++ b/src/lstack/include/lstack_rtw_api.h -@@ -42,6 +42,7 @@ ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, - int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); - int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout); - int rtw_close(int s); -+int rtw_shutdown(int fd, int how); - int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); - int rtw_epoll_create1(int flags); - int rtw_epoll_create(int flags); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index aa8c451..13f5ec2 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -74,6 +74,7 @@ int32_t rpc_call_connnum(struct protocol_stack *stack); - int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf); - int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol); - int32_t rpc_call_close(int32_t fd); -+int32_t rpc_call_shutdown(int fd, int how); - int32_t rpc_call_bind(int32_t fd, const struct sockaddr *addr, socklen_t addrlen); - int32_t rpc_call_listen(int s, int backlog); - int32_t rpc_call_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); --- -2.27.0 - diff --git a/0072-1.solve-the-problem-of-1w-connection-not-being-able-.patch b/0072-1.solve-the-problem-of-1w-connection-not-being-able-.patch deleted file mode 100644 index 9512287..0000000 --- a/0072-1.solve-the-problem-of-1w-connection-not-being-able-.patch +++ /dev/null @@ -1,395 +0,0 @@ -From 17d320fa7a978de0d76ae13d0afb1744cf456250 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 4 Dec 2023 15:45:09 +0800 -Subject: [PATCH] 1.solve the problem of 1w connection not being able to ping - 2.add debug info : rpc_mempool availd size - -3.mod struct member name -3.1 rxtx_pktmbuf_pool -> rxtx_mbufpool -3.2 pool -> rpcpool; rpc_pool -> mempool ---- - src/common/gazelle_dfx_msg.h | 3 ++- - src/lstack/core/lstack_dpdk.c | 15 +++++++++------ - src/lstack/core/lstack_lwip.c | 8 ++++---- - src/lstack/core/lstack_protocol_stack.c | 12 +++++++++--- - src/lstack/core/lstack_stack_stat.c | 7 +++++-- - src/lstack/core/lstack_thread_rpc.c | 20 +++++++++++++++----- - src/lstack/include/lstack_protocol_stack.h | 5 ++++- - src/lstack/include/lstack_thread_rpc.h | 11 ++++++----- - src/lstack/netif/lstack_ethdev.c | 10 +++++----- - src/lstack/netif/lstack_vdev.c | 2 +- - src/ltran/ltran_dfx.c | 3 ++- - 11 files changed, 62 insertions(+), 34 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index ac6ea5e..81d3426 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -93,7 +93,8 @@ struct gazelle_stack_aggregate_stats { - - struct gazelle_stat_pkts { - uint16_t conn_num; -- uint32_t mempool_freecnt; -+ uint32_t mbufpool_avail_cnt; -+ uint32_t rpcpool_avail_cnt; - uint64_t call_msg_cnt; - uint64_t recv_list_cnt; - uint64_t call_alloc_fail; -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 1811a9d..5107f1a 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -207,16 +207,16 @@ static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_ - - int32_t pktmbuf_pool_init(struct protocol_stack *stack) - { -- stack->rxtx_pktmbuf_pool = get_pktmbuf_mempool("rxtx_mbuf", stack->queue_id); -- if (stack->rxtx_pktmbuf_pool == NULL) { -- LSTACK_LOG(ERR, LSTACK, "rxtx_pktmbuf_pool is NULL\n"); -+ stack->rxtx_mbuf_pool = get_pktmbuf_mempool("rxtx_mbuf", stack->queue_id); -+ if (stack->rxtx_mbuf_pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "rxtx_mbuf_pool is NULL\n"); - return -1; - } - - if (use_ltran()) { - stack->reg_buf = create_reg_mempool("reg_ring_msg", stack->queue_id); - if (stack->reg_buf == NULL) { -- LSTACK_LOG(ERR, LSTACK, "rxtx_pktmbuf_pool is NULL\n"); -+ LSTACK_LOG(ERR, LSTACK, "rxtx_mbuf_pool is NULL\n"); - return -1; - } - } -@@ -292,6 +292,9 @@ int32_t create_shared_ring(struct protocol_stack *stack) - - int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num) - { -+ if (rte_mempool_avail_count(pool) < MBUFPOOL_RESERVE_NUM + num) { -+ return -ENOMEM; -+ } - int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:%s \n", -@@ -607,7 +610,7 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i - { - int32_t ret; - -- struct rte_mempool *rxtx_pktmbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx]; -+ struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx]; - - uint16_t socket_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); -@@ -617,7 +620,7 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i - socket_id = cfg->process_numa[idx]; - } - ret = rte_eth_rx_queue_setup(eth_params->port_id, idx, eth_params->nb_rx_desc, socket_id, -- ð_params->rx_conf, rxtx_pktmbuf_pool); -+ ð_params->rx_conf, rxtx_mbuf_pool); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot setup rx_queue %hu: %s\n", idx, rte_strerror(-ret)); - return -1; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index af9bf73..5d5ad73 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -143,7 +143,7 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - return false; - } - -- if (rte_pktmbuf_alloc_bulk(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt) != 0) { -+ if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt) != 0) { - stack->stats.tx_allocmbuf_fail++; - return true; - } -@@ -237,7 +237,7 @@ struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type typ - struct rte_mbuf *mbuf; - struct protocol_stack *stack = get_protocol_stack(); - -- if (rte_pktmbuf_alloc_bulk(stack->rxtx_pktmbuf_pool, &mbuf, 1) != 0) { -+ if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1) != 0) { - stack->stats.tx_allocmbuf_fail++; - return NULL; - } -@@ -362,7 +362,7 @@ static inline ssize_t app_direct_write(struct protocol_stack *stack, struct lwip - } - - /* first pbuf get from send_ring. and malloc pbufs attach to first pbuf */ -- if (rte_pktmbuf_alloc_bulk(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)&pbufs[1], write_num - 1) != 0) { -+ if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)&pbufs[1], write_num - 1) != 0) { - stack->stats.tx_allocmbuf_fail++; - free(pbufs); - return 0; -@@ -401,7 +401,7 @@ static inline ssize_t app_direct_attach(struct protocol_stack *stack, struct pbu - } - - /* first pbuf get from send_ring. and malloc pbufs attach to first pbuf */ -- if (rte_pktmbuf_alloc_bulk(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)pbufs, write_num) != 0) { -+ if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbufs, write_num) != 0) { - stack->stats.tx_allocmbuf_fail++; - free(pbufs); - return 0; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index dc8f143..f61e7a8 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -902,7 +902,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - continue; - } - -- ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); - if (ret != 0) { - stack->stats.rx_allocmbuf_fail++; - return; -@@ -914,7 +914,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - } -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1); - if (ret != 0) { - cur_stack->stats.rx_allocmbuf_fail++; - return; -@@ -947,7 +947,13 @@ void stack_mempool_size(struct rpc_msg *msg) - { - struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_0].p; - -- msg->result = rte_mempool_avail_count(stack->rxtx_pktmbuf_pool); -+ msg->result = rte_mempool_avail_count(stack->rxtx_mbuf_pool); -+} -+ -+void stack_rpcpool_size(struct rpc_msg *msg) -+{ -+ struct rpc_msg_pool *rpc_mem_pool = (struct rpc_msg_pool*)msg->args[MSG_ARG_0].p; -+ msg->result = rte_mempool_avail_count(rpc_mem_pool->mempool); - } - - void stack_create_shadow_fd(struct rpc_msg *msg) -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 3fd5903..45237b0 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -179,12 +179,15 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - int32_t rpc_call_result = rpc_call_msgcnt(stack); - dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_mempoolsize(stack); -- dfx->data.pkts.mempool_freecnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ rpc_call_result = rpc_call_mbufpoolsize(stack); -+ dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - - rpc_call_result = rpc_call_recvlistcnt(stack); - dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -+ rpc_call_result = rpc_call_rpcpool_size(stack); -+ dfx->data.pkts.rpcpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ - dfx->data.pkts.conn_num = stack->conn_num; - } - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 4dc3da3..473e908 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -29,7 +29,7 @@ static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct - { - int ret; - struct rpc_msg *msg = NULL; -- ret = rte_mempool_get(rpc_pool->rpc_pool, (void **)&msg); -+ ret = rte_mempool_get(rpc_pool->mempool, (void **)&msg); - if (ret < 0) { - LSTACK_LOG(INFO, LSTACK, "rpc pool empty!\n"); - errno = ENOMEM; -@@ -54,9 +54,9 @@ static struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func - return NULL; - } - -- g_rpc_pool->rpc_pool = create_mempool("rpc_pool", RPC_MSG_MAX, sizeof(struct rpc_msg), -+ g_rpc_pool->mempool = create_mempool("rpc_pool", RPC_MSG_MAX, sizeof(struct rpc_msg), - 0, rte_gettid()); -- if (g_rpc_pool->rpc_pool == NULL) { -+ if (g_rpc_pool->mempool == NULL) { - get_protocol_stack_group()->call_alloc_fail++; - return NULL; - } -@@ -67,7 +67,7 @@ static struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func - get_protocol_stack_group()->call_alloc_fail++; - return NULL; - } -- msg->pool = g_rpc_pool; -+ msg->rpcpool = g_rpc_pool; - - pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); - msg->func = func; -@@ -194,7 +194,7 @@ int32_t rpc_call_thread_regphase2(struct protocol_stack *stack, void *conn) - return rpc_sync_call(&stack->rpc_queue, msg); - } - --int32_t rpc_call_mempoolsize(struct protocol_stack *stack) -+int32_t rpc_call_mbufpoolsize(struct protocol_stack *stack) - { - struct rpc_msg *msg = rpc_msg_alloc(stack, stack_mempool_size); - if (msg == NULL) { -@@ -206,6 +206,16 @@ int32_t rpc_call_mempoolsize(struct protocol_stack *stack) - return rpc_sync_call(&stack->rpc_queue, msg); - } - -+int32_t rpc_call_rpcpool_size(struct protocol_stack *stack) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_rpcpool_size); -+ if (msg == NULL) { -+ return -1; -+ } -+ msg->args[MSG_ARG_0].p = g_rpc_pool; -+ return rpc_sync_call(&stack->rpc_queue, msg); -+} -+ - int32_t rpc_call_recvlistcnt(struct protocol_stack *stack) - { - struct rpc_msg *msg = rpc_msg_alloc(stack, stack_recvlist_count); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index e339b8d..6638984 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -31,6 +31,8 @@ - #define SOCK_SEND_REPLENISH_THRES (16) - #define WAKEUP_MAX_NUM (32) - -+#define MBUFPOOL_RESERVE_NUM 5000 -+ - struct rte_mempool; - struct rte_ring; - struct rte_mbuf; -@@ -45,7 +47,7 @@ struct protocol_stack { - cpu_set_t idle_cpuset; /* idle cpu in numa of stack, app thread bind to it */ - int32_t epollfd; /* kernel event thread epoll fd */ - -- struct rte_mempool *rxtx_pktmbuf_pool; -+ struct rte_mempool *rxtx_mbuf_pool; - struct rte_ring *rx_ring; - struct rte_ring *tx_ring; - struct rte_ring *reg_ring; -@@ -168,6 +170,7 @@ void stack_fcntl(struct rpc_msg *msg); - void stack_ioctl(struct rpc_msg *msg); - void stack_send(struct rpc_msg *msg); - void stack_mempool_size(struct rpc_msg *msg); -+void stack_rpcpool_size(struct rpc_msg *msg); - void stack_create_shadow_fd(struct rpc_msg *msg); - void stack_replenish_sendring(struct rpc_msg *msg); - void stack_get_conntable(struct rpc_msg *msg); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 13f5ec2..ca8a510 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -26,7 +26,7 @@ - #define MSG_ARG_4 (4) - #define RPM_MSG_ARG_SIZE (5) - --#define RPC_MSG_MAX 2048 -+#define RPC_MSG_MAX 4096 - #define RPC_MSG_MASK (RPC_MSG_MAX - 1) - - struct rpc_msg; -@@ -48,14 +48,14 @@ struct rpc_msg { - int8_t recall_flag : 1; - int64_t result; /* func return val */ - lockless_queue_node queue_node; -- struct rpc_msg_pool *pool; -+ struct rpc_msg_pool *rpcpool; - - rpc_msg_func func; /* msg handle func hook */ - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ - }; - - struct rpc_msg_pool { -- struct rte_mempool *rpc_pool; -+ struct rte_mempool *mempool; - }; - - struct protocol_stack; -@@ -87,7 +87,8 @@ int32_t rpc_call_setsockopt(int fd, int level, int optname, const void *optval, - int32_t rpc_call_fcntl(int fd, int cmd, long val); - int32_t rpc_call_ioctl(int fd, long cmd, void *argp); - int32_t rpc_call_replenish(struct protocol_stack *stack, struct lwip_sock *sock); --int32_t rpc_call_mempoolsize(struct protocol_stack *stack); -+int32_t rpc_call_mbufpoolsize(struct protocol_stack *stack); -+int32_t rpc_call_rpcpool_size(struct protocol_stack *stack); - - static inline __attribute__((always_inline)) void rpc_call(lockless_queue *queue, struct rpc_msg *msg) - { -@@ -97,7 +98,7 @@ static inline __attribute__((always_inline)) void rpc_call(lockless_queue *queue - static inline __attribute__((always_inline)) void rpc_msg_free(struct rpc_msg *msg) - { - pthread_spin_destroy(&msg->lock); -- rte_mempool_put(msg->pool->rpc_pool, (void *)msg); -+ rte_mempool_put(msg->rpcpool->mempool, (void *)msg); - } - - #endif -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 31856f2..2e11670 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -542,9 +542,9 @@ void parse_arp_and_transefer(char* buf) - int32_t ret; - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); - while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); - stack->stats.rx_allocmbuf_fail++; - } - copy_mbuf(mbuf_copy, mbuf); -@@ -571,9 +571,9 @@ void parse_tcp_and_transefer(char* buf) - struct rte_mbuf *mbuf_copy = NULL; - struct protocol_stack *stack = stack_group->stacks[stk_index]; - -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); - while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); - stack->stats.rx_allocmbuf_fail++; - } - -@@ -944,7 +944,7 @@ int32_t ethdev_init(struct protocol_stack *stack) - - if (use_ltran()) { - stack->rx_ring_used = 0; -- int32_t ret = fill_mbuf_to_ring(stack->rxtx_pktmbuf_pool, stack->rx_ring, RING_SIZE(VDEV_RX_QUEUE_SZ)); -+ int32_t ret = fill_mbuf_to_ring(stack->rxtx_mbuf_pool, stack->rx_ring, RING_SIZE(VDEV_RX_QUEUE_SZ)); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "fill mbuf to rx_ring failed ret=%d\n", ret); - return ret; -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index e1438da..ccf664a 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -57,7 +57,7 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - stack->rx_ring_used += rcvd_pkts; - if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) { - uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(DPDK_PKT_BURST_SIZE)); -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_pktmbuf_pool, (struct rte_mbuf **)free_buf, free_cnt); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)free_buf, free_cnt); - if (likely(ret == 0)) { - nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt); - stack->rx_ring_used -= nr_pkts; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index d3ff527..58ab14c 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -618,7 +618,8 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("call_alloc_fail: %-12"PRIu64" ", lstack_stat->data.pkts.call_alloc_fail); - printf("call_null: %-18"PRIu64" \n", lstack_stat->data.pkts.stack_stat.call_null); - printf("send_pkts_fail: %-13"PRIu64" ", lstack_stat->data.pkts.stack_stat.send_pkts_fail); -- printf("mempool_freecnt: %-12"PRIu32" \n", lstack_stat->data.pkts.mempool_freecnt); -+ printf("mbuf_pool_freecnt: %-10"PRIu32" ", lstack_stat->data.pkts.mbufpool_avail_cnt); -+ printf("rpc_pool_freecnt: %-12"PRIu32" \n", lstack_stat->data.pkts.rpcpool_avail_cnt); - } - - static void gazelle_print_lstack_stat_detail(struct gazelle_stack_dfx_data *lstack_stat, --- -2.27.0 - diff --git a/0073-dfx-gazellectl-c-support-ipv6.patch b/0073-dfx-gazellectl-c-support-ipv6.patch deleted file mode 100644 index 3f2a9d6..0000000 --- a/0073-dfx-gazellectl-c-support-ipv6.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 61bf27272a56a426909a809a8a20dcf4220a3273 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Wed, 29 Nov 2023 11:10:51 +0800 -Subject: [PATCH] dfx: gazellectl -c support ipv6 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - - 日期: Thu Dec 7 14:28:51 2023 +0800 ---- - src/common/gazelle_dfx_msg.h | 6 ++-- - src/common/gazelle_opt.h | 4 +++ - src/lstack/core/lstack_control_plane.c | 4 +-- - src/lstack/core/lstack_lwip.c | 8 +++--- - src/ltran/ltran_dfx.c | 39 ++++++++++++++++---------- - 5 files changed, 38 insertions(+), 23 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index ac6ea5e..698846f 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -16,6 +16,8 @@ - #include - #include - -+#include -+ - #define GAZELLE_CLIENT_NUM_MIN 1 - #define GAZELLE_LOG_LEVEL_MAX 10 - #define GAZELLECTL_TIMEOUT 5000 // millisecond -@@ -170,8 +172,8 @@ struct gazelle_stat_lstack_snmp { - /* same as define in lwip/tcp.h - struct tcp_pcb_dp */ - struct gazelle_stat_lstack_conn_info { - uint32_t state; -- uint32_t rip; -- uint32_t lip; -+ gz_addr_t rip; -+ gz_addr_t lip; - uint16_t r_port; - uint16_t l_port; - uint32_t in_send; -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 7316fc6..bb540f4 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -52,6 +52,10 @@ - #define STACK_THREAD_DEFAULT 4 - #define STACK_NIC_READ_DEFAULT 128 - -+/* same as define in lwip/ip_addr.h */ -+#define GZ_ADDR_TYPE_V4 0 -+#define GZ_ADDR_TYPE_V6 6 -+ - #define MTU_DEFAULT_DATA_LEN 1460 - #define VLAN_HEAD_LEN 4 - #define IPV6_EXTRA_HEAD_LEN 20 -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 4633834..e7fcd26 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -361,9 +361,9 @@ static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_ - continue; - } - qtuple.protocol = 0; -- qtuple.src_ip = conn->conn_list[i].lip; -+ qtuple.src_ip = conn->conn_list[i].lip.u_addr.ip4.addr; - qtuple.src_port = lwip_htons(conn->conn_list[i].l_port); -- qtuple.dst_ip = conn->conn_list[i].rip; -+ qtuple.dst_ip = conn->conn_list[i].rip.u_addr.ip4.addr; - qtuple.dst_port = lwip_htons(conn->conn_list[i].r_port); - - if ((table_state == LISTEN_LIST) && (!match_host_addr(qtuple.src_ip))) { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index af9bf73..5a3b703 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1135,8 +1135,8 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; - -- conn->lip = ip_2_ip4(&pcb->local_ip)->addr; -- conn->rip = ip_2_ip4(&pcb->remote_ip)->addr; -+ conn->lip = *((gz_addr_t *)&pcb->local_ip); -+ conn->rip = *((gz_addr_t *)&pcb->remote_ip); - conn->l_port = pcb->local_port; - conn->r_port = pcb->remote_port; - conn->in_send = pcb->snd_queuelen; -@@ -1229,11 +1229,11 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - for (struct tcp_pcb_listen *pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL && conn_num < max_num; - pcbl = pcbl->next) { - conn[conn_num].state = LISTEN_LIST; -- conn[conn_num].lip = ip_2_ip4(&pcbl->local_ip)->addr; -+ conn[conn_num].lip = *((gz_addr_t *)&pcbl->local_ip); - conn[conn_num].l_port = pcbl->local_port; - conn[conn_num].tcp_sub_state = pcbl->state; - struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -- conn[conn_num].fd = netconn != NULL ? netconn->socket : -1; -+ conn[conn_num].fd = netconn != NULL ? netconn->socket : -1; - if (netconn != NULL && netconn->acceptmbox != NULL) { - conn[conn_num].recv_cnt = rte_ring_count(netconn->acceptmbox->ring); - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index d3ff527..273eeaa 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -233,6 +233,7 @@ static int32_t dfx_connect_ltran(bool use_ltran, bool probe) - strlen(GAZELLE_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); -+ goto END; - } - } else { - ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), GAZELLE_REG_SOCK_FILENAME, -@@ -973,10 +974,11 @@ static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_ - static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - uint32_t i; -- struct in_addr rip; -- struct in_addr lip; -- char str_ip[GAZELLE_SUBNET_LENGTH_MAX] = {0}; -- char str_rip[GAZELLE_SUBNET_LENGTH_MAX] = {0}; -+ char str_ip[INET6_ADDRSTRLEN] = {0}; -+ char str_rip[INET6_ADDRSTRLEN] = {0}; -+ /* ip:port, 6 is the length reserved for port */ -+ char str_laddr[INET6_ADDRSTRLEN + 6] = {0}; -+ char str_raddr[INET6_ADDRSTRLEN + 6] = {0}; - struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; - struct gazelle_stat_lstack_conn *conn = &stat->data.conn; - struct timeval time = {0}; -@@ -986,30 +988,37 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - do { - printf("\n------ stack tid: %6u ------time=%lu\n", stat->tid, time.tv_sec * 1000000 + time.tv_usec); - printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" -- " lastack rcv_nxt events epoll_ev evlist fd Local Address " -- "Foreign Address State\n"); -+ " lastack rcv_nxt events epoll_ev evlist fd Local Address" -+ " Foreign Address State\n"); - uint32_t unread_pkts = 0; - uint32_t unsend_pkts = 0; - for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) { - struct gazelle_stat_lstack_conn_info *conn_info = &conn->conn_list[i]; - -- rip.s_addr = conn_info->rip; -- lip.s_addr = conn_info->lip; -+ uint32_t domain = conn_info->lip.type == GZ_ADDR_TYPE_V4 ? AF_INET : AF_INET6; -+ void *lip = (void *)&conn_info->lip; -+ void *rip = (void *)&conn_info->rip; -+ - if ((conn_info->state == GAZELLE_ACTIVE_LIST) || (conn_info->state == GAZELLE_TIME_WAIT_LIST)) { -+ inet_ntop(domain, lip, str_ip, sizeof(str_ip)); -+ inet_ntop(domain, rip, str_rip, sizeof(str_rip)); -+ sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); -+ sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); - printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -- "%s:%hu %s:%hu %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, -+ "%-52s %-52s %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, - conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, - conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, - conn_info->epoll_events, conn_info->eventlist, conn_info->fd, -- inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port, -- inet_ntop(AF_INET, &rip, str_rip, sizeof(str_rip)), conn_info->r_port, -- tcp_state_to_str(conn_info->tcp_sub_state)); -+ str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state)); - } else if (conn_info->state == GAZELLE_LISTEN_LIST) { -- printf("%-6utcp %-147u%-7d%s:%hu 0.0.0.0:* LISTEN\n", i, conn_info->recv_cnt, -- conn_info->fd, inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port); -+ inet_ntop(domain, lip, str_ip, sizeof(str_ip)); -+ sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); -+ sprintf_s(str_raddr, sizeof(str_raddr), "%s:*", domain == AF_INET ? "0.0.0.0" : "::0"); -+ printf("%-6utcp %-147u%-7d%-52s %-52s LISTEN\n", i, conn_info->recv_cnt, -+ conn_info->fd, str_laddr, str_raddr); - } else { - printf("Got unknow tcp conn::%s:%5hu, state:%u\n", -- inet_ntop(AF_INET, &lip, str_ip, sizeof(str_ip)), conn_info->l_port, conn_info->state); -+ inet_ntop(domain, lip, str_ip, sizeof(str_ip)), conn_info->l_port, conn_info->state); - } - unread_pkts += conn_info->recv_ring_cnt + conn_info->recv_cnt; - unsend_pkts += conn_info->send_ring_cnt + conn_info->in_send; --- -2.27.0 - diff --git a/0074-The-call-stack-is-not-printed-in-the-proactive-exit-.patch b/0074-The-call-stack-is-not-printed-in-the-proactive-exit-.patch deleted file mode 100644 index 1f823ee..0000000 --- a/0074-The-call-stack-is-not-printed-in-the-proactive-exit-.patch +++ /dev/null @@ -1,28 +0,0 @@ -From ef311f5a6c9d9c3578db836d68a3ad15727bdc15 Mon Sep 17 00:00:00 2001 -From: wuchangye -Date: Thu, 7 Dec 2023 14:17:49 +0800 -Subject: [PATCH] The call stack is not printed in the proactive exit scenario. - ---- - src/lstack/api/lstack_signal.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_signal.c -index 03118f5..285aaf3 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_signal.c -@@ -64,7 +64,10 @@ static void lstack_sig_default_handler(int sig) - dpdk_kni_release(); - } - control_fd_close(); -- dump_stack(); -+ /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ -+ if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { -+ dump_stack(); -+ } - lwip_exit(); - (void)kill(getpid(), sig); - } --- -2.27.0 - diff --git a/0075-dfx-fix-gazellectl-lstack-show-ip-failed.patch b/0075-dfx-fix-gazellectl-lstack-show-ip-failed.patch deleted file mode 100644 index 4aac242..0000000 --- a/0075-dfx-fix-gazellectl-lstack-show-ip-failed.patch +++ /dev/null @@ -1,69 +0,0 @@ -From f2080c02b864d6ce7f07b874e489bb5ea98b837a Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 6 Dec 2023 20:33:13 +0800 -Subject: [PATCH] dfx: fix 'gazellectl lstack show ip' failed - ---- - src/common/gazelle_dfx_msg.h | 3 ++- - src/ltran/ltran_dfx.c | 7 +++++-- - src/ltran/ltran_monitor.c | 2 +- - 3 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index ac6ea5e..d2c6ef9 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -35,9 +35,10 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LTRAN_LOG_LEVEL_SET, - GAZELLE_STAT_LTRAN_SHOW_SOCKTABLE, - GAZELLE_STAT_LTRAN_SHOW_CONNTABLE, -+ GAZELLE_STAT_LTRAN_SHOW_LSTACK, - -- GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, - GAZELLE_STAT_LSTACK_SHOW, -+ GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, - GAZELLE_STAT_LSTACK_SHOW_RATE, - GAZELLE_STAT_LSTACK_SHOW_SNMP, - GAZELLE_STAT_LSTACK_SHOW_CONN, -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index d3ff527..c200b1d 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -105,8 +105,11 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_LOG_LEVEL_SET, 0, gazelle_print_ltran_wait}, - {GAZELLE_STAT_LTRAN_SHOW_SOCKTABLE, sizeof(struct gazelle_stat_forward_table), gazelle_print_ltran_sock}, - {GAZELLE_STAT_LTRAN_SHOW_CONNTABLE, sizeof(struct gazelle_stat_forward_table), gazelle_print_ltran_conn}, -+ -+ {GAZELLE_STAT_LTRAN_SHOW_LSTACK, sizeof(struct gazelle_stat_lstack_total), gazelle_print_lstack_stat_total}, -+ {GAZELLE_STAT_LSTACK_SHOW, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_total}, -+ - {GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, 0, gazelle_print_ltran_wait}, -- {GAZELLE_STAT_LSTACK_SHOW, sizeof(struct gazelle_stat_lstack_total), gazelle_print_lstack_stat_total}, - {GAZELLE_STAT_LSTACK_SHOW_RATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_rate}, - {GAZELLE_STAT_LSTACK_SHOW_SNMP, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_snmp}, - {GAZELLE_STAT_LSTACK_SHOW_CONN, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_conn}, -@@ -1265,7 +1268,7 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - long int delay = 1; - - if (argc == GAZELLE_LSTACK_PARAM_NUM) { -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW; -+ req_msg[cmd_index++].stat_mode = g_use_ltran ? GAZELLE_STAT_LTRAN_SHOW_LSTACK : GAZELLE_STAT_LSTACK_SHOW; - return cmd_index; - } - -diff --git a/src/ltran/ltran_monitor.c b/src/ltran/ltran_monitor.c -index 792db89..b2bcc07 100644 ---- a/src/ltran/ltran_monitor.c -+++ b/src/ltran/ltran_monitor.c -@@ -338,7 +338,7 @@ static int32_t lstack_req_mode_process(int32_t fd, const struct gazelle_stat_msg - case GAZELLE_STAT_LTRAN_SHOW_LB_RATE: - handle_resp_lstack_total(req_msg, fd); - break; -- case GAZELLE_STAT_LSTACK_SHOW: -+ case GAZELLE_STAT_LTRAN_SHOW_LSTACK: - handle_resp_lstack_total(req_msg, fd); - handle_resp_lstack_transfer(req_msg, fd); - break; --- -2.27.0 - diff --git a/0076-gazellectl-add-connect-para.patch b/0076-gazellectl-add-connect-para.patch deleted file mode 100644 index 9e64bbf..0000000 --- a/0076-gazellectl-add-connect-para.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 175f3818dc8ea64b37c4aa804375ef1216601813 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Thu, 7 Dec 2023 00:38:00 +0800 -Subject: [PATCH] gazellectl add connect para - ---- - src/common/gazelle_dfx_msg.h | 2 ++ - src/lstack/core/lstack_lwip.c | 2 ++ - src/ltran/ltran_dfx.c | 8 +++++--- - 3 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index e2485ef..f91a661 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -194,6 +194,8 @@ struct gazelle_stat_lstack_conn_info { - uint32_t events; - uint32_t epoll_events; - uint32_t eventlist; -+ uint32_t keepalive; -+ uint32_t keep_idle; - }; - - struct gazelle_stat_lstack_conn { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 7fb164c..5a719ea 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1148,6 +1148,8 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->lastack = pcb->lastack; - conn->snd_nxt = pcb->snd_nxt; - conn->rcv_nxt = pcb->rcv_nxt; -+ conn->keepalive = (ip_get_option(pcb, SOF_KEEPALIVE) != 0); -+ conn->keep_idle = pcb->keep_idle; - - if (netconn != NULL && netconn->recvmbox != NULL) { - conn->recv_cnt = rte_ring_count(netconn->recvmbox->ring); -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index b999d20..fcbe857 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -993,7 +993,8 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - printf("\n------ stack tid: %6u ------time=%lu\n", stat->tid, time.tv_sec * 1000000 + time.tv_usec); - printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" - " lastack rcv_nxt events epoll_ev evlist fd Local Address" -- " Foreign Address State\n"); -+ " Foreign Address State" -+ " keep-alive keep-idle\n"); - uint32_t unread_pkts = 0; - uint32_t unsend_pkts = 0; - for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) { -@@ -1009,11 +1010,12 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); - sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); - printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -- "%-52s %-52s %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, -+ "%-52s %-52s %s %-5d %-9u\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, - conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, - conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, - conn_info->epoll_events, conn_info->eventlist, conn_info->fd, -- str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state)); -+ str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state), -+ conn_info->keepalive, conn_info->keep_idle); - } else if (conn_info->state == GAZELLE_LISTEN_LIST) { - inet_ntop(domain, lip, str_ip, sizeof(str_ip)); - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); --- -2.27.0 - diff --git a/0077-log-optimize-lstack-log.patch b/0077-log-optimize-lstack-log.patch deleted file mode 100644 index 6c2c0b3..0000000 --- a/0077-log-optimize-lstack-log.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 10db670bcca6be723361e710625452c42249002a Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 9 Dec 2023 22:31:02 +0800 -Subject: [PATCH] add - ---- - src/common/gazelle_reg_msg.h | 2 +- - src/lstack/core/lstack_lwip.c | 1 - - src/lstack/core/lstack_thread_rpc.c | 1 - - 3 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/src/common/gazelle_reg_msg.h b/src/common/gazelle_reg_msg.h -index a944d80..d849cea 100644 ---- a/src/common/gazelle_reg_msg.h -+++ b/src/common/gazelle_reg_msg.h -@@ -22,7 +22,7 @@ - - #define GAZELLE_MAX_REG_ARGS 32 - --#define ENQUEUE_RING_RETRY_TIMEOUT 500 // ms -+#define ENQUEUE_RING_RETRY_TIMEOUT 10 // ms - - #define OPT_BASE_VIRTADDR "--base-virtaddr" - #define OPT_FILE_PREFIX "--file-prefix" -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 5a719ea..026c870 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -797,7 +797,6 @@ static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) < 2) { - while (rpc_call_send(fd, NULL, len, flags) < 0) { - usleep(1000); // 1000: wait 1ms to exec again -- LSTACK_LOG(INFO, LSTACK, "rpc_call_send failed, try again\n"); - } - __sync_fetch_and_add(&sock->call_num, 1); - } -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 473e908..4aceee6 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -31,7 +31,6 @@ static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct - struct rpc_msg *msg = NULL; - ret = rte_mempool_get(rpc_pool->mempool, (void **)&msg); - if (ret < 0) { -- LSTACK_LOG(INFO, LSTACK, "rpc pool empty!\n"); - errno = ENOMEM; - return NULL; - } --- -2.27.0 - diff --git a/0078-support-show-nic-offload-and-features.patch b/0078-support-show-nic-offload-and-features.patch deleted file mode 100644 index 462b652..0000000 --- a/0078-support-show-nic-offload-and-features.patch +++ /dev/null @@ -1,209 +0,0 @@ -From e38f829d0c2f0e46b4c026044ed69ebbb4d2821d Mon Sep 17 00:00:00 2001 -From: wuchangye -Date: Fri, 8 Dec 2023 01:23:14 +0800 -Subject: [PATCH] support show nic offload and features - ---- - src/common/gazelle_dfx_msg.h | 8 ++++++++ - src/lstack/Makefile | 4 ++-- - src/lstack/core/lstack_control_plane.c | 3 ++- - src/lstack/core/lstack_dpdk.c | 17 +++++++++++++++++ - src/lstack/core/lstack_stack_stat.c | 10 +++++++--- - src/lstack/include/lstack_dpdk.h | 1 + - src/ltran/ltran_dfx.c | 23 +++++++++++++++++++++++ - 8 files changed, 61 insertions(+), 6 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index e2485ef..04fe996 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -48,6 +48,7 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LSTACK_LOW_POWER_MDF, - GAZELLE_STAT_LSTACK_SHOW_XSTATS, - GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, -+ GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, - - GAZELLE_STAT_MODE_MAX, - }; -@@ -236,6 +237,12 @@ struct nic_eth_xstats { - uint16_t port_id; - }; - -+struct nic_eth_features { -+ uint16_t port_id; -+ uint64_t rx_offload; -+ uint64_t tx_offload; -+}; -+ - struct gazelle_stack_dfx_data { - /* indicates whether the current message is the last */ - uint32_t eof; -@@ -250,6 +257,7 @@ struct gazelle_stack_dfx_data { - struct gazelle_stat_lstack_conn conn; - struct gazelle_stat_lstack_snmp snmp; - struct nic_eth_xstats nic_xstats; -+ struct nic_eth_features nic_features; - } data; - }; - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index 30965f8..d585040 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -29,9 +29,9 @@ LDFLAGS = -shared -ldl -lm -lpthread -lrt -lnuma -lconfig -lboundscheck - ARCH := $(shell uname -m) - - ifneq ($(CC),clang) -- SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wl,-z,relro, -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIC -D_FORTIFY_SOURCE=2 -+ SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wno-deprecated-declarations -Wl,-z,relro, -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIC -D_FORTIFY_SOURCE=2 - else -- SEC_FLAGS = -fstack-protector-strong -Werror -Wall -fPIC -+ SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wno-deprecated-declarations -fPIC - endif - $(info $(CC):$(SEC_FLAGS)) - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index e7fcd26..668ff80 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -586,7 +586,8 @@ static int32_t handle_stat_request(int32_t sockfd) - if (msg.stat_mode == GAZELLE_STAT_LSTACK_LOG_LEVEL_SET || - msg.stat_mode == GAZELLE_STAT_LSTACK_LOW_POWER_MDF) { - return handle_proc_cmd(sockfd, &msg); -- } else if (msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) { -+ } else if (msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS || -+ msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES) { - return handle_dpdk_cmd(sockfd, msg.stat_mode); - } else { - ret = handle_stack_cmd(sockfd, msg.stat_mode); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 5eff915..936fd89 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -881,3 +881,20 @@ void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - } - dfx->data.nic_xstats.len = len; - } -+ -+void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) -+{ -+ int ret; -+ struct rte_eth_conf dev_conf; -+ -+ ret = rte_eth_dev_conf_get(port_id, &dev_conf); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_conf_get failed:%d.\n", ret); -+ return; -+ } -+ -+ dfx->data.nic_features.port_id = port_id; -+ dfx->data.nic_features.tx_offload = dev_conf.txmode.offloads; -+ dfx->data.nic_features.rx_offload = dev_conf.rxmode.offloads; -+ return; -+} -\ No newline at end of file -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 45237b0..2d85efa 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -265,11 +265,15 @@ int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) - - if (stat_mode == GAZELLE_STAT_LSTACK_SHOW_XSTATS) { - dpdk_nic_xstats_get(&dfx, get_protocol_stack_group()->port_id); -- dfx.tid = 0; -- dfx.eof = 1; -- send_control_cmd_data(fd, &dfx); -+ } else if (stat_mode == GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES) { -+ dpdk_nic_features_get(&dfx, get_protocol_stack_group()->port_id); -+ } else { -+ return 0; - } - -+ dfx.tid = 0; -+ dfx.eof = 1; -+ send_control_cmd_data(fd, &dfx); - return 0; - } - -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 724ab24..05f5bc6 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -60,4 +60,5 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num); -+void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index b999d20..dfcdc0c 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "ltran_stat.h" - #include "ltran_base.h" -@@ -91,6 +92,7 @@ static void gazelle_print_ltran_sock(void *buf, const struct gazelle_stat_msg_re - static void gazelle_print_ltran_conn(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg); - - static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_SHOW, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_total}, -@@ -117,6 +119,7 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LSTACK_LOW_POWER_MDF, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_lpm}, - {GAZELLE_STAT_LSTACK_SHOW_XSTATS, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_xstats}, - {GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_aggregate}, -+ {GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_nic_features}, - }; - - static int32_t g_wait_reply = 1; -@@ -158,6 +161,23 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - printf("%s############################\n", nic_stats_border); - } - -+static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ struct nic_eth_features *f = &(((struct gazelle_stack_dfx_data *)buf)->data.nic_features); -+ printf("###### NIC offload and other features for port %-2d #########\n", f->port_id); -+ -+ printf("tx-ipv4-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -+ printf("tx-tcp_checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -+ printf("tx-tcp-tso: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_TSO) ? "on" : "off"); -+ printf("tx-udp-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -+ printf("tx-vlan-insert: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_VLAN_INSERT) ? "on" : "off"); -+ -+ printf("rx-ipv4-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -+ printf("rx-tcp-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -+ printf("rx-udp-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -+ printf("rx-vlan-strip: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_VLAN_STRIP) ? "on" : "off"); -+} -+ - static void gazelle_print_ltran_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - struct gazelle_stat_forward_table *table = (struct gazelle_stat_forward_table *)buf; -@@ -1069,6 +1089,7 @@ static void show_usage(void) - " -c, connect show lstack connect \n" - " -l, latency [time] show lstack latency \n" - " -x, xstats show lstack xstats \n" -+ " -k, nic-features show state of protocol offload and other features \n" - " -a, aggregatin [time] show lstack send/recv aggregation \n" - " set: \n" - " loglevel {error | info | debug} set lstack loglevel \n" -@@ -1316,6 +1337,8 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - if (parse_delay_arg(argc, argv, delay) != 0) { - return 0; - } -+ } else if (strcmp(param, "-k") == 0 || strcmp(param, "nic-features") == 0) { -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES; - } - - return cmd_index; --- -2.27.0 - diff --git a/0079-Fixed-an-issue-where-no-packet-is-sent-or-received-w.patch b/0079-Fixed-an-issue-where-no-packet-is-sent-or-received-w.patch deleted file mode 100644 index 3ccd973..0000000 --- a/0079-Fixed-an-issue-where-no-packet-is-sent-or-received-w.patch +++ /dev/null @@ -1,33 +0,0 @@ -From b8f23521a5454ba0b7b1d262dfad8aa59eb328ed Mon Sep 17 00:00:00 2001 -From: wuchangye -Date: Fri, 8 Dec 2023 09:43:43 +0800 -Subject: [PATCH] Fixed an issue where no packet is sent or received when UDP - traffic is sent - ---- - src/lstack/core/lstack_lwip.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 026c870..c4b1ebc 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -443,6 +443,7 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - for (int i = 0; i < write_num; i++) { - pbufs[i]->addr.u_addr.ip4.addr = saddr->sin_addr.s_addr; - pbufs[i]->port = lwip_ntohs((saddr)->sin_port); -+ IP_SET_TYPE(&pbufs[i]->addr, IPADDR_TYPE_V4); - } - } else if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; -@@ -450,6 +451,7 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - memcpy_s(pbufs[i]->addr.u_addr.ip6.addr, sizeof(pbufs[i]->addr.u_addr.ip6.addr), - saddr->sin6_addr.s6_addr, sizeof(saddr->sin6_addr.s6_addr)); - pbufs[i]->port = lwip_ntohs((saddr)->sin6_port); -+ IP_SET_TYPE(&pbufs[i]->addr, IPADDR_TYPE_V6); - } - } else { - return 0; --- -2.27.0 - diff --git a/0080-fix-example-print-error.patch b/0080-fix-example-print-error.patch deleted file mode 100644 index e19870a..0000000 --- a/0080-fix-example-print-error.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 881bf800f35c79f778b1cdb401ad7ff780b010e9 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 6 Dec 2023 12:23:51 +0800 -Subject: [PATCH] fix example print error - ---- - src/lstack/api/lstack_epoll.c | 7 +------ - src/lstack/api/lstack_wrap.c | 4 ++++ - 2 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index a2d2a9b..7825bed 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -941,12 +941,7 @@ static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_s - - int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval) - { -- if (maxfd == 0) { -- LSTACK_LOG(ERR, LSTACK, "select maxfd is zero\n"); -- return 0; -- } -- -- if (maxfd < 0 || maxfd > FD_SETSIZE || (readfds == NULL && writefds == NULL && exceptfds == NULL)) { -+ if (maxfd < 0 || maxfd > FD_SETSIZE) { - LSTACK_LOG(ERR, LSTACK, "select input param error, fd num=%d\n", maxfd); - GAZELLE_RETURN(EINVAL); - } -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index abbf8a1..69a1409 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -595,6 +595,10 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - - static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { -+ if ((select_posix_path() == PATH_KERNEL) || !(readfds || writefds || exceptfds) || nfds == 0) { -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ } -+ - return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - --- -2.27.0 - diff --git a/0081-dfx-fix-kernel_events-stat.patch b/0081-dfx-fix-kernel_events-stat.patch deleted file mode 100644 index b924ae3..0000000 --- a/0081-dfx-fix-kernel_events-stat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 3f93ac98b09a3bdb0dc557f9b93a008d809cd5c3 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sun, 10 Dec 2023 14:55:16 +0800 -Subject: [PATCH] dfx: fix kernel_events stat - ---- - src/lstack/core/lstack_stack_stat.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 2d85efa..e4ccc41 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -136,6 +136,7 @@ static void get_wakeup_stat(struct protocol_stack_group *stack_group, struct pro - struct wakeup_poll *wakeup = container_of(node, struct wakeup_poll, poll_list); - - if (wakeup->bind_stack == stack) { -+ stat->kernel_events += wakeup->stat.kernel_events; - stat->app_events += wakeup->stat.app_events; - stat->read_null += wakeup->stat.read_null; - stat->app_write_cnt += wakeup->stat.app_write_cnt; --- -2.27.0 - diff --git a/0082-add-keep-alive-info.patch b/0082-add-keep-alive-info.patch deleted file mode 100644 index c9cdf07..0000000 --- a/0082-add-keep-alive-info.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 5e6a73b66e0b231237ea3a3bbedfe4dd4d974f45 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 11 Dec 2023 05:03:04 +0800 -Subject: [PATCH] add keep-alive info - ---- - src/common/gazelle_dfx_msg.h | 2 ++ - src/lstack/core/lstack_lwip.c | 2 ++ - src/ltran/ltran_dfx.c | 25 ++++++++++++++++++++++--- - 3 files changed, 26 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 3d559c3..478c440 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -197,6 +197,8 @@ struct gazelle_stat_lstack_conn_info { - uint32_t eventlist; - uint32_t keepalive; - uint32_t keep_idle; -+ uint32_t keep_intvl; -+ uint32_t keep_cnt; - }; - - struct gazelle_stat_lstack_conn { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c4b1ebc..cbb771f 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1151,6 +1151,8 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->rcv_nxt = pcb->rcv_nxt; - conn->keepalive = (ip_get_option(pcb, SOF_KEEPALIVE) != 0); - conn->keep_idle = pcb->keep_idle; -+ conn->keep_intvl = pcb->keep_intvl; -+ conn->keep_cnt = pcb->keep_cnt; - - if (netconn != NULL && netconn->recvmbox != NULL) { - conn->recv_cnt = rte_ring_count(netconn->recvmbox->ring); -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index ebe1323..2a84cb8 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -52,6 +52,7 @@ - #define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins - - #define GAZELLE_DECIMAL 10 -+#define GAZELLE_KEEPALIVE_STR_LEN 35 - - static int32_t g_unix_fd = -1; - static int32_t g_ltran_rate_show_flag = GAZELLE_OFF; // not show when first get total statistics -@@ -995,6 +996,20 @@ static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_ - } while (true); - } - -+static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_stat_lstack_conn_info *conn_info) -+{ -+ if (conn_info->keepalive == 0) { -+ return; -+ } -+ int ret = sprintf_s(str, buff_len - 1, "(%u,%u,%u)", conn_info->keep_idle, conn_info->keep_intvl, -+ conn_info->keep_cnt); -+ if (ret < 0) { -+ printf("gazelle_keepalive_string sprintf_s fail ret=%d\n", ret); -+ return; -+ } -+ str[strlen(str)] = '\0'; -+} -+ - static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - uint32_t i; -@@ -1007,6 +1022,7 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - struct gazelle_stat_lstack_conn *conn = &stat->data.conn; - struct timeval time = {0}; - gettimeofday(&time, NULL); -+ char keepalive_info_str[GAZELLE_KEEPALIVE_STR_LEN] = {0}; - - printf("Active Internet connections (servers and established)\n"); - do { -@@ -1014,7 +1030,7 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" - " lastack rcv_nxt events epoll_ev evlist fd Local Address" - " Foreign Address State" -- " keep-alive keep-idle\n"); -+ " keep-alive keep-alive(idle,intvl,cnt)\n"); - uint32_t unread_pkts = 0; - uint32_t unsend_pkts = 0; - for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) { -@@ -1027,15 +1043,18 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - if ((conn_info->state == GAZELLE_ACTIVE_LIST) || (conn_info->state == GAZELLE_TIME_WAIT_LIST)) { - inet_ntop(domain, lip, str_ip, sizeof(str_ip)); - inet_ntop(domain, rip, str_rip, sizeof(str_rip)); -+ -+ gazelle_keepalive_string(keepalive_info_str, sizeof(keepalive_info_str)/sizeof(char), conn_info); -+ - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); - sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); - printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -- "%-52s %-52s %s %-5d %-9u\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, -+ "%-52s %-52s %s %-5d %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, - conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, - conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, - conn_info->epoll_events, conn_info->eventlist, conn_info->fd, - str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state), -- conn_info->keepalive, conn_info->keep_idle); -+ conn_info->keepalive, keepalive_info_str); - } else if (conn_info->state == GAZELLE_LISTEN_LIST) { - inet_ntop(domain, lip, str_ip, sizeof(str_ip)); - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); --- -2.27.0 - diff --git a/0083-fix-close-can-t-exit.patch b/0083-fix-close-can-t-exit.patch deleted file mode 100644 index 9bf3399..0000000 --- a/0083-fix-close-can-t-exit.patch +++ /dev/null @@ -1,137 +0,0 @@ -From f4abd3b3fd5004405cb186981b93f5d40e4648db Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 10 Dec 2023 17:47:56 +0800 -Subject: [PATCH] fix close can't exit - ---- - src/lstack/core/lstack_lwip.c | 12 ++++++++---- - src/lstack/core/lstack_protocol_stack.c | 25 +++++++++++++++---------- - src/lstack/core/lstack_thread_rpc.c | 6 +++--- - src/lstack/include/lstack_lwip.h | 4 ++-- - 4 files changed, 28 insertions(+), 19 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c4b1ebc..73a6f12 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -646,14 +646,18 @@ bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock * - return replenish_again; - } - --bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -- size_t len, int32_t flags) -+int do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -+ size_t len, int32_t flags) - { -+ ssize_t ret; - /* send all send_ring, so len set lwip send max. */ - if (NETCONN_IS_UDP(sock)) { -- (void)lwip_send(fd, sock, len, flags); -+ ret = lwip_send(fd, sock, len, flags); - } else { -- (void)lwip_send(fd, sock, UINT16_MAX, flags); -+ ret = lwip_send(fd, sock, UINT16_MAX, flags); -+ } -+ if (ret < 0 && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { -+ return -1; - } - - return do_lwip_replenish_sendring(stack, sock); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f61e7a8..8dbd9ad 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -699,10 +699,10 @@ void stack_close(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = get_socket(fd); - -- if (sock && NETCONN_IS_DATAOUT(sock)) { -+ if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -- return; -+ return; - } - - msg->result = lwip_close(fd); -@@ -860,27 +860,32 @@ void stack_send(struct rpc_msg *msg) - int32_t fd = msg->args[MSG_ARG_0].i; - size_t len = msg->args[MSG_ARG_1].size; - struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_3].p; -- bool replenish_again; -+ int replenish_again; - - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); -- rpc_msg_free(msg); -+ __sync_fetch_and_sub(&sock->call_num, 1); - return; - } - - replenish_again = do_lwip_send(stack, sock->conn->socket, sock, len, 0); -- __sync_fetch_and_sub(&sock->call_num, 1); -- if (!NETCONN_IS_DATAOUT(sock) && !replenish_again) { -+ if (replenish_again < 0) { -+ __sync_fetch_and_sub(&sock->call_num, 1); - return; -- } else { -- if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 0) { -- msg->recall_flag = 1; -+ } -+ -+ if (NETCONN_IS_DATAOUT(sock) || replenish_again > 0) { -+ if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { -+ msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); -- __sync_fetch_and_add(&sock->call_num, 1); -+ return; - } - } -+ -+ __sync_fetch_and_sub(&sock->call_num, 1); -+ return; - } - - /* any protocol stack thread receives arp packet and sync it to other threads so that it can have the arp table */ -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 4aceee6..0b2a62a 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -109,14 +109,14 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - } - - if (!msg->recall_flag) { -- if (msg->sync_flag) { -+ if (msg->sync_flag) { - pthread_spin_unlock(&msg->lock); - } else { - rpc_msg_free(msg); - } - } else { -- msg->recall_flag = 0; -- } -+ msg->recall_flag = 0; -+ } - } - } - -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 4a13204..a11489c 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -50,8 +50,8 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - - void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num); - void do_lwip_add_recvlist(int32_t fd); --bool do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -- size_t len, int32_t flags); -+int do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -+ size_t len, int32_t flags); - - uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint32_t max_num); - uint32_t do_lwip_get_connnum(void); --- -2.27.0 - diff --git a/0084-mod-unix-time-stamp-to-local-time.patch b/0084-mod-unix-time-stamp-to-local-time.patch deleted file mode 100644 index fda79e9..0000000 --- a/0084-mod-unix-time-stamp-to-local-time.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 95784bb047ae30ebff9d224ef178430fda91027e Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Fri, 15 Dec 2023 03:34:46 +0800 -Subject: [PATCH] mod unix time stamp to local time - ---- - src/ltran/ltran_dfx.c | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 2a84cb8..25d4f35 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -53,6 +53,7 @@ - - #define GAZELLE_DECIMAL 10 - #define GAZELLE_KEEPALIVE_STR_LEN 35 -+#define GAZELLE_TIME_STR_LEN 25 - - static int32_t g_unix_fd = -1; - static int32_t g_ltran_rate_show_flag = GAZELLE_OFF; // not show when first get total statistics -@@ -1001,13 +1002,27 @@ static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_sta - if (conn_info->keepalive == 0) { - return; - } -- int ret = sprintf_s(str, buff_len - 1, "(%u,%u,%u)", conn_info->keep_idle, conn_info->keep_intvl, -+ int ret = sprintf_s(str, buff_len, "(%u,%u,%u)", conn_info->keep_idle, conn_info->keep_intvl, - conn_info->keep_cnt); - if (ret < 0) { - printf("gazelle_keepalive_string sprintf_s fail ret=%d\n", ret); - return; - } -- str[strlen(str)] = '\0'; -+} -+ -+static void gazelle_localtime_string(char* str, int buff_len) -+{ -+ struct timeval time = {0}; -+ gettimeofday(&time, NULL); -+ struct tm* tm; -+ time_t t = time.tv_sec; -+ tm = localtime(&t); -+ int ret = sprintf_s(str, buff_len, "%d-%d-%d %d:%d:%d", -+ tm->tm_yday + 1900, tm->tm_mon + 1, tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec); -+ if (ret < 0) { -+ printf("gazelle_localtime_string sprintf_s fail ret=%d\n", ret); -+ return; -+ } - } - - static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) -@@ -1020,13 +1035,14 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - char str_raddr[INET6_ADDRSTRLEN + 6] = {0}; - struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; - struct gazelle_stat_lstack_conn *conn = &stat->data.conn; -- struct timeval time = {0}; -- gettimeofday(&time, NULL); -+ - char keepalive_info_str[GAZELLE_KEEPALIVE_STR_LEN] = {0}; -+ char sys_local_time_str[GAZELLE_TIME_STR_LEN] = {0}; -+ gazelle_localtime_string(sys_local_time_str, GAZELLE_TIME_STR_LEN); - - printf("Active Internet connections (servers and established)\n"); - do { -- printf("\n------ stack tid: %6u ------time=%lu\n", stat->tid, time.tv_sec * 1000000 + time.tv_usec); -+ printf("\n------ stack tid: %6u ------time=%s\n", stat->tid, sys_local_time_str); - printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" - " lastack rcv_nxt events epoll_ev evlist fd Local Address" - " Foreign Address State" --- -2.27.0 - diff --git a/0085-optimize-gazelle-exit-process.patch b/0085-optimize-gazelle-exit-process.patch deleted file mode 100644 index a8a68b5..0000000 --- a/0085-optimize-gazelle-exit-process.patch +++ /dev/null @@ -1,671 +0,0 @@ -From 95c0a884ff26b42a75ee35639d789b40af131fd3 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 12 Dec 2023 19:24:14 +0800 -Subject: [PATCH] optimize gazelle exit process 1. close all fds 2. lstack - thread exits, then gazelle process exits - ---- - src/common/gazelle_base_func.h | 2 + - src/common/gazelle_dfx_msg.c | 8 +- - src/lstack/api/dir.mk | 2 +- - src/lstack/api/lstack_dummy_api.c | 55 +++++++++++++ - src/lstack/api/lstack_rtc_api.c | 1 + - src/lstack/api/lstack_signal.c | 5 +- - src/lstack/api/lstack_wrap.c | 12 +++ - src/lstack/core/lstack_dpdk.c | 2 +- - src/lstack/core/lstack_init.c | 18 ++++- - src/lstack/core/lstack_lwip.c | 16 ++-- - src/lstack/core/lstack_protocol_stack.c | 93 ++++++++++++++++++---- - src/lstack/core/lstack_thread_rpc.c | 22 ++++- - src/lstack/include/lstack_dummy_api.h | 23 ++++++ - src/lstack/include/lstack_lwip.h | 4 +- - src/lstack/include/lstack_protocol_stack.h | 6 +- - src/lstack/include/lstack_thread_rpc.h | 3 +- - src/lstack/include/lstack_wrap.h | 1 + - 17 files changed, 237 insertions(+), 36 deletions(-) - create mode 100644 src/lstack/api/lstack_dummy_api.c - create mode 100644 src/lstack/include/lstack_dummy_api.h - -diff --git a/src/common/gazelle_base_func.h b/src/common/gazelle_base_func.h -index d21ef5f..2d629c1 100644 ---- a/src/common/gazelle_base_func.h -+++ b/src/common/gazelle_base_func.h -@@ -34,6 +34,8 @@ int32_t check_and_set_run_dir(void); - - int32_t filename_check(const char* args); - -+void gazelle_exit(void); -+ - #undef container_of - #define container_of(ptr, type, field) ((type *)(void*)(((char *)(ptr)) - offsetof(type, field))) - -diff --git a/src/common/gazelle_dfx_msg.c b/src/common/gazelle_dfx_msg.c -index 5fe4e06..ec23401 100644 ---- a/src/common/gazelle_dfx_msg.c -+++ b/src/common/gazelle_dfx_msg.c -@@ -29,19 +29,19 @@ int read_specied_len(int fd, char *buf, size_t target_size) - while (total_read < target_size) { - int ret = poll(fds, 1, GAZELLECTL_TIMEOUT); - if (ret < 0) { -- printf("read_specied_len:: poll ret=%d \n", ret); -+ printf("read_specied_len: poll ret=%d \n", ret); - return -1; - } else if (ret == 0) { -- printf("read_specied_len:: time out \n"); -+ printf("read_specied_len: time out \n"); - return -1; - } - if (fds[0].revents & POLLIN) { - int n = read(fd, buf + total_read, target_size - total_read); - if (n < 0) { -- printf("read_specied_len:: read ret=%d \n", ret); -+ printf("read_specied_len: read ret=%d \n", ret); - return -1; - } else if (n == 0) { -- printf("read_specied_len:: Connection closed \n"); -+ printf("read_specied_len: Connection closed \n"); - return -1; - } - total_read += n; -diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk -index ffbb137..729690d 100644 ---- a/src/lstack/api/dir.mk -+++ b/src/lstack/api/dir.mk -@@ -8,7 +8,7 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c -+SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c - - $(eval $(call register_dir, api, $(SRC))) - -diff --git a/src/lstack/api/lstack_dummy_api.c b/src/lstack/api/lstack_dummy_api.c -new file mode 100644 -index 0000000..f327916 ---- /dev/null -+++ b/src/lstack/api/lstack_dummy_api.c -@@ -0,0 +1,55 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+#include -+#include -+#include -+ -+#define DUMMY_SLEEP_S 5 -+ -+static inline ssize_t dummy_exit(void) -+{ -+ sleep(DUMMY_SLEEP_S); -+ errno = ENOTCONN; -+ return -1; -+} -+ -+int dummy_socket(int domain, int type, int protocol) -+{ -+ sleep(DUMMY_SLEEP_S); -+ return -1; -+} -+ -+ssize_t dummy_write(int s, const void *mem, size_t size) -+{ -+ return dummy_exit(); -+} -+ -+ssize_t dummy_writev(int s, const struct iovec *iov, int iovcnt) -+{ -+ return dummy_exit(); -+} -+ -+ssize_t dummy_send(int sockfd, const void *buf, size_t len, int flags) -+{ -+ return dummy_exit(); -+} -+ -+ssize_t dummy_sendmsg(int s, const struct msghdr *message, int flags) -+{ -+ return dummy_exit(); -+} -+ -+ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen) -+{ -+ return dummy_exit(); -+} -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 50d72bc..d29e51e 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -20,6 +20,7 @@ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_protocol_stack.h" -+#include "lstack_thread_rpc.h" - #include "lstack_rtc_api.h" - - int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_signal.c -index 285aaf3..6da6eb4 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_signal.c -@@ -18,6 +18,7 @@ - #include - #include - -+#include "gazelle_base_func.h" - #include "lstack_cfg.h" - #include "dpdk_common.h" - #include "lstack_log.h" -@@ -60,15 +61,13 @@ static void lstack_sig_default_handler(int sig) - if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { - delete_primary_path(); - } -- if (!use_ltran()) { -- dpdk_kni_release(); -- } - control_fd_close(); - /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ - if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { - dump_stack(); - } - lwip_exit(); -+ gazelle_exit(); - (void)kill(getpid(), sig); - } - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 65a0a5a..89f54f8 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -36,6 +36,7 @@ - - #include "lstack_rtc_api.h" - #include "lstack_rtw_api.h" -+#include "lstack_dummy_api.h" - - #ifndef SOCK_TYPE_MASK - #define SOCK_TYPE_MASK 0xf -@@ -112,6 +113,17 @@ void wrap_api_init(void) - } - } - -+void wrap_api_set_dummy(void) -+{ -+ g_wrap_api->socket_fn = dummy_socket; -+ g_wrap_api->send_fn = dummy_send; -+ g_wrap_api->write_fn = dummy_write; -+ g_wrap_api->writev_fn = dummy_writev; -+ g_wrap_api->send_msg = dummy_sendmsg; -+ g_wrap_api->send_to = dummy_sendto; -+ rte_wmb(); -+} -+ - static inline int32_t do_epoll_create1(int32_t flags) - { - if (select_posix_path() == PATH_KERNEL) { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 8950591..e20dea8 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -897,4 +897,4 @@ void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - dfx->data.nic_features.tx_offload = dev_conf.txmode.offloads; - dfx->data.nic_features.rx_offload = dev_conf.rxmode.offloads; - return; --} -\ No newline at end of file -+} -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index a3ca4ff..fef2942 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -107,10 +107,24 @@ static int32_t check_process_conflict(void) - return 0; - } - -+void gazelle_exit(void) -+{ -+ if (!get_global_cfg_params()->stack_mode_rtc) { -+ wrap_api_set_dummy(); -+ /* 1: wait until app thread call send functio complete */ -+ sleep(1); -+ stack_group_exit(); -+ } -+ if (!use_ltran()) { -+ dpdk_kni_release(); -+ } -+} -+ - __attribute__((destructor)) void gazelle_network_exit(void) - { - if (posix_api != NULL && !posix_api->ues_posix) { - lwip_exit(); -+ gazelle_exit(); - } - - if (!use_ltran()) { -@@ -118,8 +132,6 @@ __attribute__((destructor)) void gazelle_network_exit(void) - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "rte_pdump_uninit failed\n"); - } -- -- dpdk_kni_release(); - } - } - -@@ -289,6 +301,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - - if (!get_global_cfg_params()->stack_mode_rtc) { - if (stack_setup_thread() != 0) { -+ gazelle_exit(); - LSTACK_EXIT(1, "stack_setup_thread failed\n"); - } - } -@@ -301,6 +314,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - - if (set_process_start_flag() != 0) { -+ gazelle_exit(); - LSTACK_EXIT(1, "set_process_start_flag failed\n"); - } - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index fb286d6..15f99f9 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -201,7 +201,7 @@ void do_lwip_init_sock(int32_t fd) - init_list_node_null(&sock->event_list); - } - --void do_lwip_clean_sock(int32_t fd) -+void do_lwip_clean_sock(int fd) - { - struct lwip_sock *sock = get_socket_by_fd(fd); - if (sock == NULL || sock->stack == NULL) { -@@ -1193,7 +1193,15 @@ void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_soc - } - } - --int32_t do_lwip_socket(int domain, int type, int protocol) -+int do_lwip_close(int fd) -+{ -+ int ret = lwip_close(fd); -+ do_lwip_clean_sock(fd); -+ posix_api->close_fn(fd); -+ return ret; -+} -+ -+int do_lwip_socket(int domain, int type, int protocol) - { - int32_t fd = lwip_socket(domain, type, 0); - if (fd < 0) { -@@ -1204,9 +1212,7 @@ int32_t do_lwip_socket(int domain, int type, int protocol) - - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL || sock->stack == NULL) { -- lwip_close(fd); -- do_lwip_clean_sock(fd); -- posix_api->close_fn(fd); -+ do_lwip_close(fd); - return -1; - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 8dbd9ad..3123ca3 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -45,6 +45,22 @@ static struct protocol_stack_group g_stack_group = {0}; - - typedef void *(*stack_thread_func)(void *arg); - -+static void stack_set_state(struct protocol_stack *stack, enum rte_lcore_state_t state) -+{ -+ __atomic_store_n(&stack->state, state, __ATOMIC_RELEASE); -+} -+ -+static enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) -+{ -+ return __atomic_load_n(&stack->state, __ATOMIC_ACQUIRE); -+} -+ -+static void stack_wait_quit(struct protocol_stack *stack) -+{ -+ while (__atomic_load_n(&stack->state, __ATOMIC_ACQUIRE) != WAIT) { -+ rte_pause(); -+ } -+} - - void bind_to_stack_numa(struct protocol_stack *stack) - { -@@ -436,8 +452,9 @@ END: - return NULL; - } - --void stack_polling(uint32_t wakeup_tick) -+int stack_polling(uint32_t wakeup_tick) - { -+ int force_quit; - struct cfg_params *cfg = get_global_cfg_params(); - uint8_t use_ltran_flag = cfg->use_ltran; - bool kni_switch = cfg->kni_switch; -@@ -448,7 +465,7 @@ void stack_polling(uint32_t wakeup_tick) - uint32_t read_connect_number = cfg->read_connect_number; - struct protocol_stack *stack = get_protocol_stack(); - -- poll_rpc_msg(stack, rpc_number); -+ force_quit = poll_rpc_msg(stack, rpc_number); - gazelle_eth_dev_poll(stack, use_ltran_flag, nic_read_number); - sys_timer_run(); - if (cfg->low_power_mod != 0) { -@@ -456,7 +473,7 @@ void stack_polling(uint32_t wakeup_tick) - } - - if (stack_mode_rtc) { -- return; -+ return force_quit; - } - - do_lwip_read_recvlist(stack, read_connect_number); -@@ -482,7 +499,7 @@ void stack_polling(uint32_t wakeup_tick) - kni_handle_rx(stack->port_id); - } - } -- return; -+ return force_quit; - } - - static void* gazelle_stack_thread(void *arg) -@@ -512,11 +529,14 @@ static void* gazelle_stack_thread(void *arg) - return NULL; - } - -- for (;;) { -- stack_polling(wakeup_tick); -+ stack_set_state(stack, RUNNING); -+ -+ while (stack_polling(wakeup_tick) == 0) { - wakeup_tick++; - } - -+ stack_set_state(stack, WAIT); -+ - return NULL; - } - -@@ -576,6 +596,7 @@ int32_t stack_group_init(void) - LSTACK_LOG(ERR, LSTACK, "sem_init failed errno=%d\n", errno); - return -1; - } -+ - stack_group->stack_setup_fail = 0; - - if (get_global_cfg_params()->is_primary) { -@@ -705,14 +726,10 @@ void stack_close(struct rpc_msg *msg) - return; - } - -- msg->result = lwip_close(fd); -+ msg->result = do_lwip_close(fd); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } -- -- do_lwip_clean_sock(fd); -- -- posix_api->close_fn(fd); - } - - void stack_shutdown(struct rpc_msg *msg) -@@ -775,9 +792,7 @@ void stack_accept(struct rpc_msg *msg) - - struct lwip_sock *sock = get_socket(accept_fd); - if (sock == NULL || sock->stack == NULL) { -- lwip_close(accept_fd); -- do_lwip_clean_sock(accept_fd); -- posix_api->close_fn(accept_fd); -+ do_lwip_close(accept_fd); - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; - } -@@ -866,7 +881,6 @@ void stack_send(struct rpc_msg *msg) - if (sock == NULL) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); -- __sync_fetch_and_sub(&sock->call_num, 1); - return; - } - -@@ -1260,3 +1274,52 @@ int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *add - return stack_broadcast_accept4(fd, addr, addrlen, 0); - } - -+static void stack_all_fds_close(void) -+{ -+ for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { -+ struct lwip_sock *sock = get_socket(i); -+ if (sock && sock->stack == get_protocol_stack()) { -+ do_lwip_close(i); -+ } -+ } -+} -+ -+static void stack_exit(void) -+{ -+ stack_all_fds_close(); -+} -+ -+void stack_exit_by_rpc(struct rpc_msg *msg) -+{ -+ stack_exit(); -+} -+ -+void stack_group_exit(void) -+{ -+ int i; -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ for (i = 0; i < stack_group->stack_num; i++) { -+ if ((stack_group->stacks[i] == NULL) || -+ stack_get_state(stack_group->stacks[i]) != RUNNING) { -+ continue; -+ } -+ -+ if (stack != stack_group->stacks[i]) { -+ rpc_call_stack_exit(stack_group->stacks[i]); -+ } -+ } -+ -+ if (stack != NULL) { -+ stack_exit(); -+ } -+ -+ for (i = 0; i < stack_group->stack_num; i++) { -+ if (stack_group->stacks[i] == NULL || stack == stack_group->stacks[i]) { -+ continue; -+ } -+ /* wait stack thread quit */ -+ stack_wait_quit(stack_group->stacks[i]); -+ } -+} -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 0b2a62a..2af30d7 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -90,8 +90,9 @@ static inline __attribute__((always_inline)) int32_t rpc_sync_call(lockless_queu - return ret; - } - --void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) -+int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - { -+ int force_quit = 0; - struct rpc_msg *msg = NULL; - - while (max_num--) { -@@ -108,6 +109,10 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - stack->stats.call_null++; - } - -+ if (msg->func == stack_exit_by_rpc) { -+ force_quit = 1; -+ } -+ - if (!msg->recall_flag) { - if (msg->sync_flag) { - pthread_spin_unlock(&msg->lock); -@@ -118,6 +123,8 @@ void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - msg->recall_flag = 0; - } - } -+ -+ return force_quit; - } - - int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint32_t max_conn) -@@ -246,6 +253,7 @@ int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf) - int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol) - { - struct protocol_stack *stack = get_bind_protocol_stack(); -+ - struct rpc_msg *msg = rpc_msg_alloc(stack, stack_socket); - if (msg == NULL) { - return -1; -@@ -271,6 +279,18 @@ int32_t rpc_call_close(int fd) - return rpc_sync_call(&stack->rpc_queue, msg); - } - -+int32_t rpc_call_stack_exit(struct protocol_stack *stack) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(stack, stack_exit_by_rpc); -+ if (msg == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "rpc msg alloc failed\n"); -+ return -1; -+ } -+ -+ rpc_call(&stack->rpc_queue, msg); -+ return 0; -+} -+ - int32_t rpc_call_shutdown(int fd, int how) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -diff --git a/src/lstack/include/lstack_dummy_api.h b/src/lstack/include/lstack_dummy_api.h -new file mode 100644 -index 0000000..48bce31 ---- /dev/null -+++ b/src/lstack/include/lstack_dummy_api.h -@@ -0,0 +1,23 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_DUMMY_API_H_ -+#define _LSTACK_DUMMY_API_H_ -+ -+int dummy_socket(int domain, int type, int protocol); -+ssize_t dummy_write(int s, const void *mem, size_t size); -+ssize_t dummy_writev(int s, const struct iovec *iov, int iovcnt); -+ssize_t dummy_sendmsg(int s, const struct msghdr *message, int flags); -+ssize_t dummy_send(int sockfd, const void *buf, size_t len, int flags); -+ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen); -+#endif /* __LSTACK_DUMMY_API_H_ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index a11489c..0a82781 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -28,9 +28,9 @@ struct rpc_msg; - struct rte_mbuf; - struct protocol_stack; - --int32_t do_lwip_socket(int domain, int type, int protocol); -+int do_lwip_socket(int domain, int type, int protocol); -+int do_lwip_close(int32_t fd); - void do_lwip_init_sock(int32_t fd); --void do_lwip_clean_sock(int32_t fd); - void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); - - struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 6638984..8e2e807 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -46,6 +46,7 @@ struct protocol_stack { - uint32_t stack_idx; - cpu_set_t idle_cpuset; /* idle cpu in numa of stack, app thread bind to it */ - int32_t epollfd; /* kernel event thread epoll fd */ -+ volatile enum rte_lcore_state_t state; - - struct rte_mempool *rxtx_mbuf_pool; - struct rte_ring *rx_ring; -@@ -114,6 +115,7 @@ struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - - int32_t stack_group_init(void); -+void stack_group_exit(void); - int32_t stack_setup_thread(void); - int32_t stack_setup_app_thread(void); - -@@ -176,6 +178,8 @@ void stack_replenish_sendring(struct rpc_msg *msg); - void stack_get_conntable(struct rpc_msg *msg); - void stack_get_connnum(struct rpc_msg *msg); - void stack_recvlist_count(struct rpc_msg *msg); --void stack_polling(uint32_t wakeup_tick); -+void stack_exit_by_rpc(struct rpc_msg *msg); -+ -+int stack_polling(uint32_t wakeup_tick); - void kni_handle_tx(struct rte_mbuf *mbuf); - #endif -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index ca8a510..633ef93 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -62,7 +62,7 @@ struct protocol_stack; - struct rte_mbuf; - struct wakeup_poll; - struct lwip_sock; --void poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num); -+int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num); - void rpc_call_clean_epoll(struct protocol_stack *stack, struct wakeup_poll *wakeup); - int32_t rpc_call_msgcnt(struct protocol_stack *stack); - int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); -@@ -89,6 +89,7 @@ int32_t rpc_call_ioctl(int fd, long cmd, void *argp); - int32_t rpc_call_replenish(struct protocol_stack *stack, struct lwip_sock *sock); - int32_t rpc_call_mbufpoolsize(struct protocol_stack *stack); - int32_t rpc_call_rpcpool_size(struct protocol_stack *stack); -+int32_t rpc_call_stack_exit(struct protocol_stack *stack); - - static inline __attribute__((always_inline)) void rpc_call(lockless_queue *queue, struct rpc_msg *msg) - { -diff --git a/src/lstack/include/lstack_wrap.h b/src/lstack/include/lstack_wrap.h -index 80e5f3c..dab5222 100644 ---- a/src/lstack/include/lstack_wrap.h -+++ b/src/lstack/include/lstack_wrap.h -@@ -14,6 +14,7 @@ - #define _LSTACK_WRAP_H_ - - void wrap_api_init(void); -+void wrap_api_set_dummy(void); - - #endif - --- -2.27.0 - diff --git a/0086-fix-EPOLLIN-event-error.patch b/0086-fix-EPOLLIN-event-error.patch deleted file mode 100644 index c534f3e..0000000 --- a/0086-fix-EPOLLIN-event-error.patch +++ /dev/null @@ -1,52 +0,0 @@ -From a72ed2effc718023316452866632f52058ae8218 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Mon, 11 Dec 2023 13:24:33 +0000 -Subject: [PATCH] fix EPOLLIN event error - ---- - src/lstack/api/lstack_epoll.c | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7825bed..7dbef9d 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -61,6 +61,17 @@ void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE || (event & sock->epoll_events) == 0) { - return; - } -+ -+ if (!get_global_cfg_params()->stack_mode_rtc) { -+ if (event == EPOLLIN && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { -+ return; -+ } -+ -+ if (event == EPOLLOUT && !NETCONN_IS_OUTIDLE(sock)) { -+ return; -+ } -+ } -+ - sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events); - if (list_is_null(&sock->event_list)) { - list_add_node(&wakeup->event_list, &sock->event_list); -@@ -88,7 +99,16 @@ void add_sock_event(struct lwip_sock *sock, uint32_t event) - - void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - { -- sock->events &= ~event; -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ sock->events &= ~event; -+ } else { -+ if ((event & EPOLLOUT) && !NETCONN_IS_OUTIDLE(sock)) { -+ sock->events &= ~EPOLLOUT; -+ } -+ if ((event & EPOLLIN) && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { -+ sock->events &= ~EPOLLIN; -+ } -+ } - - if (sock->events == 0) { - list_del_node_null(&sock->event_list); --- -2.27.0 - diff --git a/0087-mod-time-err.patch b/0087-mod-time-err.patch deleted file mode 100644 index 9893b9a..0000000 --- a/0087-mod-time-err.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 1d578011ed2ee7e508af119d963e7283b1d0dc6f Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 18 Dec 2023 09:52:21 +0800 -Subject: [PATCH] mod time err - ---- - src/ltran/ltran_dfx.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 25d4f35..c8dc562 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1018,7 +1018,7 @@ static void gazelle_localtime_string(char* str, int buff_len) - time_t t = time.tv_sec; - tm = localtime(&t); - int ret = sprintf_s(str, buff_len, "%d-%d-%d %d:%d:%d", -- tm->tm_yday + 1900, tm->tm_mon + 1, tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec); -+ tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - if (ret < 0) { - printf("gazelle_localtime_string sprintf_s fail ret=%d\n", ret); - return; --- -2.27.0 - diff --git a/0088-fix-gazellectl-lstack-show-ip-r-with-ltran-error-log.patch b/0088-fix-gazellectl-lstack-show-ip-r-with-ltran-error-log.patch deleted file mode 100644 index a9076d1..0000000 --- a/0088-fix-gazellectl-lstack-show-ip-r-with-ltran-error-log.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 24b45463b653cf2aa204ca3ff303f8fe848d416f Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 16 Dec 2023 20:21:21 +0800 -Subject: [PATCH] fix gazellectl lstack show ip -r with ltran error && log info - display unknow error - ---- - src/lstack/core/lstack_stack_stat.c | 1 + - src/ltran/ltran_dfx.c | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index e4ccc41..23571b4 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -201,6 +201,7 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - switch (stat_mode) { - case GAZELLE_STAT_LSTACK_SHOW: - case GAZELLE_STAT_LSTACK_SHOW_RATE: -+ case GAZELLE_STAT_LTRAN_SHOW_LSTACK: - get_stack_stats(dfx, stack); - /* fall through */ - case GAZELLE_STAT_LSTACK_SHOW_AGGREGATE: -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 25d4f35..5291fe0 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -99,7 +99,7 @@ static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_st - static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_SHOW, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_total}, - {GAZELLE_STAT_LTRAN_SHOW_RATE, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_rate}, -- {GAZELLE_STAT_LTRAN_SHOW_LB_RATE, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_lb_rate}, -+ {GAZELLE_STAT_LTRAN_SHOW_LB_RATE, sizeof(struct gazelle_stat_lstack_total), gazelle_print_ltran_stat_lb_rate}, - {GAZELLE_STAT_LTRAN_SHOW_INSTANCE, sizeof(struct gazelle_stat_ltran_client), gazelle_print_ltran_stat_client}, - {GAZELLE_STAT_LTRAN_SHOW_BURST, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_burst}, - {GAZELLE_STAT_LTRAN_SHOW_LATENCY, sizeof(struct in_addr), gazelle_print_ltran_stat_latency}, --- -2.27.0 - diff --git a/0089-fix-udp-multicast-bind-error.patch b/0089-fix-udp-multicast-bind-error.patch deleted file mode 100644 index 37184ea..0000000 --- a/0089-fix-udp-multicast-bind-error.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d14e214a9cd32f05f097b023baa7c4a6d8629fce Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 18 Dec 2023 21:30:32 +0800 -Subject: [PATCH] fix udp multicast bind error - ---- - src/lstack/api/lstack_wrap.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 89f54f8..5feadc3 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -211,6 +211,12 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - return posix_api->bind_fn(s, name, namelen); - } - -+ /* select user path when udp enable and ip addr is multicast */ -+ if (IN_MULTICAST(ntohl(((struct sockaddr_in *)name)->sin_addr.s_addr))) { -+ SET_CONN_TYPE_LIBOS(sock->conn); -+ return g_wrap_api->bind_fn(s, name, namelen); -+ } -+ - if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { - /* maybe kni addr */ - if (posix_api->bind_fn(s, name, namelen) != 0) { --- -2.27.0 - diff --git a/0090-support-netperf.patch b/0090-support-netperf.patch deleted file mode 100644 index d0f70dc..0000000 --- a/0090-support-netperf.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 8dfa19585b0e5b23e7855e1d544c41dd7a6a1dd9 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 15 Dec 2023 17:56:30 +0800 -Subject: [PATCH] support netperf - ---- - src/lstack/api/lstack_wrap.c | 13 ++++++------- - src/lstack/core/lstack_lwip.c | 21 +++++++++++++++++++-- - src/lstack/core/lstack_protocol_stack.c | 19 +++++++++++-------- - src/lstack/include/posix/lstack_epoll.h | 19 +++++++++++++++++++ - src/ltran/ltran_dfx.c | 2 +- - 5 files changed, 56 insertions(+), 18 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 65a0a5a..a226dc4 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -276,11 +276,6 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - return posix_api->connect_fn(s, name, namelen); - } - -- if (!netconn_is_nonblocking(sock->conn)) { -- LSTACK_LOG(ERR, LSTACK, "connect does not support blocking fd currently\n"); -- GAZELLE_RETURN(EINVAL); -- } -- - int32_t ret = 0; - int32_t remote_port; - bool is_local = is_dst_ip_localhost(name); -@@ -347,7 +342,11 @@ static bool unsupport_optname(int32_t optname) - optname == SO_PROTOCOL || - optname == TCP_QUICKACK || - optname == SO_SNDTIMEO || -- optname == SO_RCVTIMEO) { -+ optname == SO_RCVTIMEO || -+ optname == SO_SNDBUF || -+ optname == TCP_INFO || -+ optname == TCP_MAXSEG || -+ optname == TCP_CONGESTION) { - return true; - } - return false; -@@ -615,7 +614,7 @@ static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set - return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - -- return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - - #define WRAP_VA_PARAM(_fd, _cmd, _lwip_fcntl, _fcntl_fn) \ -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index fb286d6..a944f7a 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -564,6 +564,12 @@ 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 (!netconn_is_nonblocking(sock->conn)) { -+ while (write_avail < write_num) { -+ write_avail = gazelle_ring_readable_count(sock->send_ring); -+ } -+ } -+ - /* send_ring is full, data attach last pbuf */ - if (write_avail == 0) { - if (!get_global_cfg_params()->expand_send_ring) { -@@ -1005,8 +1011,19 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - pbuf = sock->recv_lastdata; - sock->recv_lastdata = NULL; - } else { -- if (gazelle_ring_read(sock->recv_ring, (void **)&pbuf, 1) != 1) { -- break; -+ 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 || (sock->conn->pcb.tcp->flags & TF_FIN)) && !NETCONN_IS_DATAIN(sock)) { -+ return 0; -+ } -+ -+ lstack_block_wait(sock->wakeup); -+ } - } - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 8dbd9ad..414b5f8 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -268,12 +268,8 @@ static void wakeup_kernel_event(struct protocol_stack *stack) - continue; - } - -- __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE); -- if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- rte_mb(); -- pthread_mutex_unlock(&wakeup->wait); -- } -+ __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE); -+ lstack_block_wakeup(wakeup); - } - - return; -@@ -1233,14 +1229,21 @@ int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t - int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *addrlen, int flags) - { - int32_t ret = -1; -- -+ struct lwip_sock *min_sock = NULL; - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - errno = EINVAL; - return -1; - } - -- struct lwip_sock *min_sock = get_min_accept_sock(fd); -+ if (netconn_is_nonblocking(sock->conn)) { -+ min_sock = get_min_accept_sock(fd); -+ } else { -+ while ((min_sock = get_min_accept_sock(fd)) == NULL) { -+ lstack_block_wait(sock->wakeup); -+ } -+ } -+ - if (min_sock && min_sock->conn) { - ret = rpc_call_accept(min_sock->conn->socket, addr, addrlen, flags); - } -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index 9c34eb3..7591f0f 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -80,6 +80,25 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout); - int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval); - -+static inline void lstack_block_wait(struct wakeup_poll *wakeup) -+{ -+ if (wakeup == NULL) { -+ return; -+ } -+ -+ __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -+ pthread_mutex_lock(&wakeup->wait); -+} -+ -+static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) -+{ -+ if (wakeup && __atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -+ __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -+ rte_mb(); -+ pthread_mutex_unlock(&wakeup->wait); -+ } -+} -+ - #ifdef __cplusplus - } - #endif -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 2a84cb8..ee80359 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -168,7 +168,7 @@ static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_st - printf("###### NIC offload and other features for port %-2d #########\n", f->port_id); - - printf("tx-ipv4-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -- printf("tx-tcp_checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -+ printf("tx-tcp-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); - printf("tx-tcp-tso: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_TSO) ? "on" : "off"); - printf("tx-udp-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); - printf("tx-vlan-insert: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_VLAN_INSERT) ? "on" : "off"); --- -2.27.0 - diff --git a/0091-fix-alloc-not-free.patch b/0091-fix-alloc-not-free.patch deleted file mode 100644 index 33c3c55..0000000 --- a/0091-fix-alloc-not-free.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 053024d4cbedc106276e25a7ace5d833f8a62dea Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Wed, 20 Dec 2023 01:37:12 +0000 -Subject: [PATCH] fix alloc not free - ---- - src/lstack/core/lstack_cfg.c | 2 ++ - src/lstack/core/lstack_dpdk.c | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 6324c97..f639473 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1185,11 +1185,13 @@ static int32_t parse_bond_slave_mac(void) - if (k >= GAZELLE_MAX_BOND_NUM) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: too many slave mac address. The maximum number of mac address is %d.\n", - GAZELLE_MAX_BOND_NUM); -+ free(bond_slave_mac_tmp); - return -EINVAL; - } - ret = str_to_eth_addr(mac_addr, g_config_params.bond_slave_mac_addr[k].addr_bytes); - if (ret != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", mac_addr, ret); -+ free(bond_slave_mac_tmp); - return ret; - } - mac_addr = strtok_s(NULL, delim, &tmp); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index e20dea8..6933ecd 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -553,11 +553,13 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - int slave_id = rte_eth_bond_primary_get(port_id); - if (slave_id < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk get bond primary port failed port = %d\n", slave_id); -+ free(eth_params); - return slave_id; - } - ret = rte_eth_dev_info_get(slave_id, &slave_dev_info); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk get bond dev info failed ret = %d\n", ret); -+ free(eth_params); - return ret; - } - dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; --- -2.27.0 - diff --git a/0092-sigaction-fix-deprecated-signal-flags.patch b/0092-sigaction-fix-deprecated-signal-flags.patch deleted file mode 100644 index 899febb..0000000 --- a/0092-sigaction-fix-deprecated-signal-flags.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 3af406243bb2a4a6c8ac5b3f1d98a9cd7e0af295 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 20 Dec 2023 11:37:13 +0800 -Subject: [PATCH] sigaction: fix deprecated signal flags - ---- - src/lstack/api/lstack_signal.c | 10 +++++++++- - src/lstack/core/lstack_lwip.c | 7 ++++--- - 2 files changed, 13 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_signal.c -index 6da6eb4..314c14c 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_signal.c -@@ -57,7 +57,7 @@ static inline bool match_hijack_signal(int sig) - - static void lstack_sig_default_handler(int sig) - { -- LSTACK_LOG(ERR, LSTACK, "lstack dumped,caught signal:%d\n", sig); -+ LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); - if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { - delete_primary_path(); - } -@@ -94,5 +94,13 @@ int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigacti - new_action.sa_handler = lstack_sig_default_handler; - return posix_api->sigaction_fn(sig_num, &new_action, old_action); - } -+ -+ /* SA_INTERRUPT is deprecated, use SA_RESETHAND instead. */ -+ if ((match_hijack_signal(sig_num) != 0) && (action && action->sa_flags == SA_INTERRUPT)) { -+ new_action = *action; -+ new_action.sa_flags |= SA_RESETHAND; -+ return posix_api->sigaction_fn(sig_num, &new_action, old_action); -+ } -+ - return posix_api->sigaction_fn(sig_num, action, old_action); - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 34ec1bd..100f075 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -564,10 +564,11 @@ 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 (!netconn_is_nonblocking(sock->conn)) { -- while (write_avail < write_num) { -- write_avail = gazelle_ring_readable_count(sock->send_ring); -+ 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); - } - - /* send_ring is full, data attach last pbuf */ --- -2.27.0 - diff --git a/0093-fix-gazellectl-c-msg-error.patch b/0093-fix-gazellectl-c-msg-error.patch deleted file mode 100644 index 26cc6c0..0000000 --- a/0093-fix-gazellectl-c-msg-error.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 887130c90c7875b4c0860ed0667224418e690752 Mon Sep 17 00:00:00 2001 -From: jinag12 -Date: Thu, 21 Dec 2023 09:03:02 +0000 -Subject: [PATCH] fix gazellectl -c msg error - -Signed-off-by: jinag12 ---- - src/lstack/core/lstack_lwip.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 15f99f9..1913d03 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1158,15 +1158,14 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->keep_intvl = pcb->keep_intvl; - conn->keep_cnt = pcb->keep_cnt; - -- if (netconn != NULL && netconn->recvmbox != NULL) { -- conn->recv_cnt = rte_ring_count(netconn->recvmbox->ring); -+ if (netconn != NULL) { - conn->fd = netconn->socket; -- -+ conn->recv_cnt = (netconn->recvmbox == NULL) ? 0 : rte_ring_count(netconn->recvmbox->ring); - struct lwip_sock *sock = get_socket(netconn->socket); -- if (netconn->socket > 0 && sock != NULL && sock->recv_ring != NULL && sock->send_ring != NULL) { -- conn->recv_ring_cnt = gazelle_ring_readable_count(sock->recv_ring); -+ if (sock != NULL) { -+ conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); - conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; -- conn->send_ring_cnt = gazelle_ring_readover_count(sock->send_ring); -+ conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); - conn->events = sock->events; - conn->epoll_events = sock->epoll_events; - conn->eventlist = !list_is_null(&sock->event_list); --- -2.27.0 - diff --git a/0094-CFG-fix-check-func-strdup-return-value-is-NULL.patch b/0094-CFG-fix-check-func-strdup-return-value-is-NULL.patch deleted file mode 100644 index ddd4df6..0000000 --- a/0094-CFG-fix-check-func-strdup-return-value-is-NULL.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 43985056c5446c0ad45acb2309165543bd8e15e1 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 22 Dec 2023 15:42:40 +0800 -Subject: [PATCH] CFG:fix check func strdup return value is NULL - ---- - src/lstack/core/lstack_cfg.c | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 6324c97..6e97c96 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -145,6 +145,15 @@ static struct config_vector_t g_config_tbl[] = { - { NULL, NULL } - }; - -+static char* strdup_assert_return(const char* str) -+{ -+ char* result = strdup(str); -+ if (result == NULL) { -+ LSTACK_EXIT(1, "strdup_assert_return failed, func strdup return NULL!\n"); -+ } -+ return result; -+} -+ - struct cfg_params *get_global_cfg_params(void) - { - return &g_config_params; -@@ -336,15 +345,15 @@ static int32_t parse_stack_cpu_number(void) - if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { - int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); - if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(OPT_BIND_CORELIST); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); - g_config_params.dpdk_argc++; - -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(args); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); - g_config_params.dpdk_argc++; - } - } - -- char *tmp_arg = strdup(args); -+ char *tmp_arg = strdup_assert_return(args); - int32_t cnt = separate_str_to_array(tmp_arg, g_config_params.cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); - free(tmp_arg); - if (cnt <= 0 || cnt > CFG_MAX_CPUS) { -@@ -369,15 +378,15 @@ static int32_t parse_stack_cpu_number(void) - if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { - int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); - if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(OPT_BIND_CORELIST); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); - g_config_params.dpdk_argc++; - -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(args); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); - g_config_params.dpdk_argc++; - } - } - -- char *tmp_arg_send = strdup(args); -+ char *tmp_arg_send = strdup_assert_return(args); - int32_t send_cpu_cnt = separate_str_to_array(tmp_arg_send, g_config_params.send_cpus, - CFG_MAX_CPUS, CFG_MAX_CPUS); - free(tmp_arg_send); -@@ -396,15 +405,15 @@ static int32_t parse_stack_cpu_number(void) - if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { - int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); - if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(OPT_BIND_CORELIST); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); - g_config_params.dpdk_argc++; - -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup(args); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); - g_config_params.dpdk_argc++; - } - } - -- char *tmp_arg_recv = strdup(args); -+ char *tmp_arg_recv = strdup_assert_return(args); - int32_t recv_cpu_cnt = separate_str_to_array(tmp_arg_recv, g_config_params.recv_cpus, - CFG_MAX_CPUS, CFG_MAX_CPUS); - free(tmp_arg_recv); -@@ -450,7 +459,7 @@ static int32_t parse_app_exclude_cpus(void) - return -EINVAL; - } - -- tmp_arg = strdup(args); -+ tmp_arg = strdup_assert_return(args); - cnt = separate_str_to_array(tmp_arg, g_config_params.app_exclude_cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); - free(tmp_arg); - if (cnt <= 0 || cnt > CFG_MAX_CPUS) { -@@ -1176,7 +1185,7 @@ static int32_t parse_bond_slave_mac(void) - } - - int32_t k = 0; -- char *bond_slave_mac_tmp = strdup(bond_slave_mac); -+ char *bond_slave_mac_tmp = strdup_assert_return(bond_slave_mac); - char *tmp = NULL; - const char *delim = ";"; - --- -2.27.0 - diff --git a/0095-fix-func-separate_str_to_array-overflow-problem.patch b/0095-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index 1cfbaf7..0000000 --- a/0095-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,26 +0,0 @@ -From f6a7a9585bfb82680519034869b4141c514d9214 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 25 Dec 2023 00:34:55 +0800 -Subject: [PATCH] fix func separate_str_to_array overflow problem - ---- - src/common/gazelle_parse_config.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 42e12b5..77d0b82 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -80,6 +80,9 @@ int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, i - for (idx = min; idx <= max; idx++) { - array[count] = idx; - count++; -+ if (count > array_size) { -+ return -1; -+ } - } - min = array_size; - } else { --- -2.27.0 - diff --git a/0096-use-default-nonblock-mode.patch b/0096-use-default-nonblock-mode.patch deleted file mode 100644 index e9e1bb8..0000000 --- a/0096-use-default-nonblock-mode.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 47ab261c2b533975a59b34f06da0ccf83692bb78 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Tue, 26 Dec 2023 16:53:58 +0000 -Subject: [PATCH] use default nonblock mode - ---- - src/lstack/core/lstack_cfg.c | 12 ++++++++++++ - src/lstack/core/lstack_protocol_stack.c | 5 ++++- - src/lstack/include/lstack_cfg.h | 1 + - 3 files changed, 17 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index a292070..d9c23fb 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -80,6 +80,7 @@ static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); -+static int32_t parse_defaule_nonblock_mode(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -142,6 +143,7 @@ static struct config_vector_t g_config_tbl[] = { - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, - { "nic_vlan_mode", parse_nic_vlan_mode }, -+ { "nonblock_mode", parse_defaule_nonblock_mode }, - { NULL, NULL } - }; - -@@ -1280,3 +1282,13 @@ static int32_t parse_nic_vlan_mode(void) - return ret; - } - -+static int32_t parse_defaule_nonblock_mode(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.nonblock_mode, "nonblock_mode", 1, 0, 1, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid nonblock mode value %d. only support 0 or 1\n", \ -+ g_config_params.nonblock_mode); -+ } -+ return ret; -+} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 9158d20..a000224 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -1287,7 +1287,10 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - - int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen) - { -- return stack_broadcast_accept4(fd, addr, addrlen, 0); -+ if (get_global_cfg_params()->nonblock_mode) -+ return stack_broadcast_accept4(fd, addr, addrlen, O_NONBLOCK); -+ else -+ return stack_broadcast_accept4(fd, addr, addrlen, 0); - } - - static void stack_all_fds_close(void) -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index a6bdfd5..82e96d8 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -118,6 +118,7 @@ struct cfg_params { - bool udp_enable; - struct cfg_nic_params nic; - bool stack_mode_rtc; -+ bool nonblock_mode; - }; - - struct cfg_params *get_global_cfg_params(void); --- -2.27.0 - diff --git a/0097-fix-rte_ring_create-free-time-consuming.patch b/0097-fix-rte_ring_create-free-time-consuming.patch deleted file mode 100644 index 55b45a4..0000000 --- a/0097-fix-rte_ring_create-free-time-consuming.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 66b0ba4be7a5c3b79482eafdc28fd75e8f44e761 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 27 Dec 2023 10:26:07 +0800 -Subject: [PATCH] fix rte_ring_create/free time consuming - ---- - src/lstack/core/lstack_dpdk.c | 27 +++------------------------ - src/lstack/core/lstack_lwip.c | 14 ++++++-------- - src/lstack/include/lstack_dpdk.h | 1 - - 3 files changed, 9 insertions(+), 33 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 6933ecd..729a84c 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -245,43 +245,22 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si - return mempool; - } - --struct rte_ring *create_ring(const char *name, uint32_t count, uint32_t flags, int32_t queue_id) --{ -- char ring_name[RTE_RING_NAMESIZE] = {0}; -- struct rte_ring *ring; -- -- int32_t ret = snprintf_s(ring_name, sizeof(ring_name), RTE_RING_NAMESIZE - 1, -- "%s_%d_%d", name, get_global_cfg_params()->process_idx, queue_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); -- return NULL; -- } -- -- ring = rte_ring_create(ring_name, count, rte_socket_id(), flags); -- if (ring == NULL) { -- LSTACK_LOG(ERR, LSTACK, "%s create failed. errno: %d.\n", name, rte_errno); -- } -- -- return ring; --} -- - int32_t create_shared_ring(struct protocol_stack *stack) - { - lockless_queue_init(&stack->rpc_queue); - - if (use_ltran()) { -- stack->rx_ring = create_ring("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ, stack->queue_id); -+ stack->rx_ring = gazelle_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); - if (stack->rx_ring == NULL) { - return -1; - } - -- stack->tx_ring = create_ring("RING_TX", VDEV_TX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ, stack->queue_id); -+ stack->tx_ring = gazelle_ring_create_fast("RING_TX", VDEV_TX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); - if (stack->tx_ring == NULL) { - return -1; - } - -- stack->reg_ring = create_ring("SHARED_REG_RING", VDEV_REG_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ, -- stack->queue_id); -+ stack->reg_ring = gazelle_ring_create_fast("SHARED_REG_RING", VDEV_REG_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); - if (stack->reg_ring == NULL) { - return -1; - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c167ba4..4953f3d 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -72,13 +72,13 @@ static void reset_sock_data(struct lwip_sock *sock) - /* check null pointer in ring_free func */ - if (sock->recv_ring) { - free_ring_pbuf(sock->recv_ring); -- rte_ring_free(sock->recv_ring); -+ gazelle_ring_free_fast(sock->recv_ring); - sock->recv_ring = NULL; - } - - if (sock->send_ring) { - free_ring_pbuf(sock->send_ring); -- rte_ring_free(sock->send_ring); -+ gazelle_ring_free_fast(sock->send_ring); - sock->send_ring = NULL; - } - -@@ -169,7 +169,6 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - - void do_lwip_init_sock(int32_t fd) - { -- static _Atomic uint32_t name_tick = 0; - struct protocol_stack *stack = get_protocol_stack(); - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { -@@ -178,18 +177,17 @@ void do_lwip_init_sock(int32_t fd) - - reset_sock_data(sock); - -- sock->recv_ring = create_ring("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ, -- atomic_fetch_add(&name_tick, 1)); -+ sock->recv_ring = gazelle_ring_create_fast("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ); - if (sock->recv_ring == NULL) { - LSTACK_LOG(ERR, LSTACK, "sock_recv create failed. errno: %d.\n", rte_errno); - return; - } - -- sock->send_ring = create_ring("sock_send", -+ sock->send_ring = gazelle_ring_create_fast("sock_send", - get_global_cfg_params()->send_ring_size, -- RING_F_SP_ENQ | RING_F_SC_DEQ, -- atomic_fetch_add(&name_tick, 1)); -+ RING_F_SP_ENQ | RING_F_SC_DEQ); - if (sock->send_ring == NULL) { -+ gazelle_ring_free_fast(sock->recv_ring); - LSTACK_LOG(ERR, LSTACK, "sock_send create failed. errno: %d.\n", rte_errno); - return; - } -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 05f5bc6..4a160e0 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -44,7 +44,6 @@ struct rte_mbuf; - int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num); - int32_t dpdk_eal_init(void); - int32_t pktmbuf_pool_init(struct protocol_stack *stack); --struct rte_ring *create_ring(const char *name, uint32_t count, uint32_t flags, int32_t queue_id); - struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t size, - uint32_t flags, int32_t idx); - int32_t create_shared_ring(struct protocol_stack *stack); --- -2.27.0 - diff --git a/0098-optimize-shutdown-exit-process.patch b/0098-optimize-shutdown-exit-process.patch deleted file mode 100644 index e444784..0000000 --- a/0098-optimize-shutdown-exit-process.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5ca16b89699250a52d11ee5a181fef227fd399b6 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 18 Dec 2023 10:50:53 +0800 -Subject: [PATCH] optimize shutdown exit process - ---- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 8dbd9ad..564f055 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -722,7 +722,7 @@ void stack_shutdown(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = get_socket(fd); - -- if (sock && NETCONN_IS_DATAOUT(sock)) { -+ if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); - return; --- -2.27.0 - diff --git a/0099-fix-func-separate_str_to_array-overflow-problem.patch b/0099-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index a4d790f..0000000 --- a/0099-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,32 +0,0 @@ -From e4eeed95dcbb47b3413e51df6c82e85a735aa31c Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 25 Dec 2023 09:31:44 +0000 -Subject: [PATCH] fix func separate_str_to_array overflow problem - -Signed-off-by: yinbin6 ---- - src/common/gazelle_parse_config.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 77d0b82..82be52c 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -78,11 +78,11 @@ int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, i - min = idx; - } - for (idx = min; idx <= max; idx++) { -+ if (count > array_size) { -+ return -1; -+ } - array[count] = idx; - count++; -- if (count > array_size) { -- return -1; -- } - } - min = array_size; - } else { --- -2.27.0 - diff --git a/0100-fix-func-separate_str_to_array-overflow-problem.patch b/0100-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index 8f3b2a5..0000000 --- a/0100-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 89abb6f4e231cf378b1e7f7415cfa196fdf7b3da Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 25 Dec 2023 10:25:42 +0000 -Subject: [PATCH] fix func separate_str_to_array overflow problem - -Signed-off-by: yinbin6 ---- - src/common/gazelle_parse_config.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 82be52c..9772af9 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -79,8 +79,8 @@ int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, i - } - for (idx = min; idx <= max; idx++) { - if (count > array_size) { -- return -1; -- } -+ return -1; -+ } - array[count] = idx; - count++; - } --- -2.27.0 - diff --git a/0101-fix-func-separate_str_to_array-overflow-problem.patch b/0101-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index c0e7eb4..0000000 --- a/0101-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 58248cb2bae3d2c50f65b3ade360fc14716a0ce7 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 25 Dec 2023 11:06:18 +0000 -Subject: [PATCH] fix func separate_str_to_array overflow problem - -Signed-off-by: yinbin6 ---- - src/common/gazelle_parse_config.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 9772af9..16efdc8 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -78,7 +78,7 @@ int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, i - min = idx; - } - for (idx = min; idx <= max; idx++) { -- if (count > array_size) { -+ if (count >= array_size) { - return -1; - } - array[count] = idx; --- -2.27.0 - diff --git a/0102-fix-func-separate_str_to_array-overflow-problem.patch b/0102-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index 4266ac5..0000000 --- a/0102-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,26 +0,0 @@ -From fafd5c387910da2f81f38c320b3da01ffd97c6c2 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 25 Dec 2023 13:01:39 +0000 -Subject: [PATCH] fix func separate_str_to_array overflow problem - -Signed-off-by: yinbin6 ---- - src/common/gazelle_parse_config.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 16efdc8..1adce78 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -33,7 +33,7 @@ - - int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, int32_t max_value) - { -- uint32_t count = 0; -+ int32_t count = 0; - char *end = NULL; - int32_t min, max; - int32_t idx; --- -2.27.0 - diff --git a/0103-fix-func-stack_setup_thread-array-doesn-t-init.patch b/0103-fix-func-stack_setup_thread-array-doesn-t-init.patch deleted file mode 100644 index 5015c7a..0000000 --- a/0103-fix-func-stack_setup_thread-array-doesn-t-init.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 9ed5bee888ab4936372a81919d894d8fd291e7c1 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 26 Dec 2023 22:49:03 +0800 -Subject: [PATCH] fix func stack_setup_thread array doesn't init - ---- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 829313f..0aff1b4 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -648,7 +648,7 @@ int32_t stack_setup_thread(void) - int32_t ret; - char name[PATH_MAX]; - int queue_num = get_global_cfg_params()->num_queue; -- struct thread_params *t_params[queue_num]; -+ struct thread_params *t_params[queue_num] = {0}; - int process_index = get_global_cfg_params()->process_idx; - - for (uint32_t i = 0; i < queue_num; i++) { --- -2.27.0 - diff --git a/0104-fix-stack_setup_thread-array-range.patch b/0104-fix-stack_setup_thread-array-range.patch deleted file mode 100644 index 57b54ed..0000000 --- a/0104-fix-stack_setup_thread-array-range.patch +++ /dev/null @@ -1,21 +0,0 @@ -From f6df059cf18aa0019c5bdea8947a5b4a53c02bde Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 27 Dec 2023 09:58:30 +0800 -Subject: [PATCH] fix stack_setup_thread array range - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 0aff1b4..b5d4ea3 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -648,7 +648,7 @@ int32_t stack_setup_thread(void) - int32_t ret; - char name[PATH_MAX]; - int queue_num = get_global_cfg_params()->num_queue; -- struct thread_params *t_params[queue_num] = {0}; -+ struct thread_params *t_params[PROTOCOL_STACK_MAX] = {NULL}; - int process_index = get_global_cfg_params()->process_idx; - - for (uint32_t i = 0; i < queue_num; i++) { --- -2.27.0 - diff --git a/0105-fix-func-separate_str_to_array-overflow-problem.patch b/0105-fix-func-separate_str_to_array-overflow-problem.patch deleted file mode 100644 index 69a3de4..0000000 --- a/0105-fix-func-separate_str_to_array-overflow-problem.patch +++ /dev/null @@ -1,80 +0,0 @@ -From c6de43f7e7cb866f8d5ddd453c73783d5daafca0 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 27 Dec 2023 12:22:06 +0800 -Subject: [PATCH] fix func separate_str_to_array overflow problem - ---- - src/lstack/core/lstack_protocol_stack.c | 25 +++++++++++++++++++------ - 1 file changed, 19 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index b5d4ea3..f3d2452 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -651,44 +651,57 @@ int32_t stack_setup_thread(void) - struct thread_params *t_params[PROTOCOL_STACK_MAX] = {NULL}; - int process_index = get_global_cfg_params()->process_idx; - -+ for (uint32_t i = 0; i < queue_num; ++i) { -+ t_params[i] = malloc(sizeof(struct thread_params)); -+ if (t_params[i] == NULL) { -+ goto OUT; -+ } -+ } -+ - for (uint32_t i = 0; i < queue_num; i++) { - if (get_global_cfg_params()->seperate_send_recv) { - if (i % 2 == 0) { - ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_RECV_THREAD_NAME, process_index, i / 2); - if (ret < 0) { -- return -1; -+ goto OUT; - } - } else { - ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_SEND_THREAD_NAME, process_index, i / 2); - if (ret < 0) { -- return -1; -+ goto OUT; - } - } - } else { - ret = sprintf_s(name, sizeof(name), "%s", LSTACK_THREAD_NAME); - if (ret < 0) { -- return -1; -+ goto OUT; - } - } - -- t_params[i] = malloc(sizeof(struct thread_params)); - t_params[i]->idx = i; - t_params[i]->queue_id = process_index * queue_num + i; - - ret = create_thread((void *)t_params[i], name, gazelle_stack_thread); - if (ret != 0) { -- return ret; -+ goto OUT; - } - } - - /* 2: wait stack thread and kernel_event thread init finish */ - wait_sem_value(&g_stack_group.sem_stack_setup, queue_num * 2); - if (g_stack_group.stack_setup_fail) { -- return -1; -+ goto OUT; - } - g_stack_group.stack_num = queue_num; - - return 0; -+OUT: -+ for (int32_t i = 0; i < queue_num; ++i) { -+ if (t_params[i] != NULL) { -+ free(t_params[i]); -+ } -+ } -+ return -1; - } - - void stack_arp(struct rpc_msg *msg) --- -2.27.0 - diff --git a/0106-fix-dpdk_alloc_pktmbuf-time-consuming.patch b/0106-fix-dpdk_alloc_pktmbuf-time-consuming.patch deleted file mode 100644 index cc41030..0000000 --- a/0106-fix-dpdk_alloc_pktmbuf-time-consuming.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d40a2e46403547fc8d12ee1dacc6484eca1fbbeb Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Fri, 5 Jan 2024 10:15:22 +0800 -Subject: [PATCH] fix dpdk_alloc_pktmbuf time-consuming - ---- - src/lstack/core/lstack_dpdk.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 729a84c..3182bb5 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -271,9 +271,14 @@ int32_t create_shared_ring(struct protocol_stack *stack) - - int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num) - { -- if (rte_mempool_avail_count(pool) < MBUFPOOL_RESERVE_NUM + num) { -+ /* -+ * don't use rte_mempool_avail_count, it traverse cpu local cache, -+ * when RTE_MAX_LCORE is too large, it's time-consuming -+ */ -+ if (rte_ring_count(pool->pool_data) < MBUFPOOL_RESERVE_NUM + num) { - return -ENOMEM; - } -+ - int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:%s \n", --- -2.33.0 - diff --git a/0107-ltran-optimize-config-file-error-message.patch b/0107-ltran-optimize-config-file-error-message.patch deleted file mode 100644 index bc1572b..0000000 --- a/0107-ltran-optimize-config-file-error-message.patch +++ /dev/null @@ -1,46 +0,0 @@ -From e46c71fda9678df02d7373a1bb987cbc3979f1f6 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Fri, 5 Jan 2024 18:07:42 +0800 -Subject: [PATCH] ltran: optimize config file error message - ---- - src/ltran/ltran_param.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/src/ltran/ltran_param.c b/src/ltran/ltran_param.c -index 11a4bc8..1eaace4 100644 ---- a/src/ltran/ltran_param.c -+++ b/src/ltran/ltran_param.c -@@ -664,8 +664,15 @@ struct param_parser g_param_parse_tbl[] = { - int32_t parse_config_file_args(const char *conf_file_path, struct ltran_config *ltran_config) - { - config_t config; -- config_init(&config); - int32_t ret; -+ char real_path[PATH_MAX]; -+ -+ if (realpath(conf_file_path, real_path) == NULL) { -+ syslog(LOG_ERR, "Err: Config file path %s error, please check conf file path.\n", conf_file_path); -+ return -1; -+ } -+ -+ config_init(&config); - - ret = memset_s(ltran_config, sizeof(struct ltran_config), 0, sizeof(struct ltran_config)); - if (ret != 0) { -@@ -673,10 +680,10 @@ int32_t parse_config_file_args(const char *conf_file_path, struct ltran_config * - syslog(LOG_ERR, "memset_s failed\n"); - return ret; - } -- ret = config_read_file(&config, conf_file_path); -+ ret = config_read_file(&config, real_path); - if (ret == 0) { -+ syslog(LOG_ERR, "Err: Read config file \"%s\" error: %s\n", real_path, config_error_text(&config)); - config_destroy(&config); -- syslog(LOG_ERR, "Err: Config file path %s error, please check conf file path.\n", conf_file_path); - return -GAZELLE_EPATH; - } - --- -2.33.0 - diff --git a/0108-replace-with-gz_addr_t.patch b/0108-replace-with-gz_addr_t.patch deleted file mode 100644 index b72791f..0000000 --- a/0108-replace-with-gz_addr_t.patch +++ /dev/null @@ -1,224 +0,0 @@ -From fa28c2bf790466ab3a4cfc8fa39ed14764797e87 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Tue, 2 Jan 2024 17:10:44 +0800 -Subject: [PATCH] replace with gz_addr_t - ---- - src/common/gazelle_opt.h | 5 +---- - src/lstack/core/lstack_control_plane.c | 6 +++--- - src/lstack/core/lstack_lwip.c | 3 +-- - src/lstack/netif/lstack_vdev.c | 16 +++++++++------- - src/ltran/ltran_forward.c | 10 +++++----- - src/ltran/ltran_stat.c | 4 ++-- - src/ltran/ltran_tcp_conn.c | 4 ++-- - src/ltran/ltran_tcp_sock.c | 4 ++-- - src/ltran/ltran_timer.c | 4 ++-- - 9 files changed, 27 insertions(+), 29 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index bb540f4..36915c6 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -27,6 +27,7 @@ - #define KERNEL_EPOLL_MAX 512 - - #define ETHER_ADDR_LEN 6 -+#define IPV6_ADDR_LEN 16 - - #define DEFAULT_RING_SIZE (512) - #define DEFAULT_RING_MASK (511) -@@ -52,10 +53,6 @@ - #define STACK_THREAD_DEFAULT 4 - #define STACK_NIC_READ_DEFAULT 128 - --/* same as define in lwip/ip_addr.h */ --#define GZ_ADDR_TYPE_V4 0 --#define GZ_ADDR_TYPE_V6 6 -- - #define MTU_DEFAULT_DATA_LEN 1460 - #define VLAN_HEAD_LEN 4 - #define IPV6_EXTRA_HEAD_LEN 20 -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 668ff80..2d629c8 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -361,12 +361,12 @@ static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_ - continue; - } - qtuple.protocol = 0; -- qtuple.src_ip = conn->conn_list[i].lip.u_addr.ip4.addr; -+ qtuple.src_ip = conn->conn_list[i].lip; - qtuple.src_port = lwip_htons(conn->conn_list[i].l_port); -- qtuple.dst_ip = conn->conn_list[i].rip.u_addr.ip4.addr; -+ qtuple.dst_ip = conn->conn_list[i].rip; - qtuple.dst_port = lwip_htons(conn->conn_list[i].r_port); - -- if ((table_state == LISTEN_LIST) && (!match_host_addr(qtuple.src_ip))) { -+ if ((table_state == LISTEN_LIST) && (!match_host_addr(qtuple.src_ip.u_addr.ip4.addr))) { - continue; - } - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 4953f3d..87ec1f5 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -446,8 +446,7 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - } else if (addr->sa_family == AF_INET6) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; - for (int i = 0; i < write_num; i++) { -- memcpy_s(pbufs[i]->addr.u_addr.ip6.addr, sizeof(pbufs[i]->addr.u_addr.ip6.addr), -- saddr->sin6_addr.s6_addr, sizeof(saddr->sin6_addr.s6_addr)); -+ memcpy_s(pbufs[i]->addr.u_addr.ip6.addr, IPV6_ADDR_LEN, saddr->sin6_addr.s6_addr, IPV6_ADDR_LEN); - pbufs[i]->port = lwip_ntohs((saddr)->sin6_port); - IP_SET_TYPE(&pbufs[i]->addr, IPADDR_TYPE_V6); - } -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index ccf664a..9a79dc3 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -185,10 +185,12 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - delete_user_process_port(qtuple->src_port, PORT_CONNECT); - uint16_t queue_id = get_protocol_stack()->queue_id; - if (queue_id != 0) { -- transfer_delete_rule_info_to_process0(qtuple->dst_ip, qtuple->src_port, qtuple->dst_port); -+ transfer_delete_rule_info_to_process0(qtuple->dst_ip.u_addr.ip4.addr, -+ qtuple->src_port, qtuple->dst_port); - } - } else { -- transfer_delete_rule_info_to_process0(qtuple->dst_ip, qtuple->src_port, qtuple->dst_port); -+ transfer_delete_rule_info_to_process0(qtuple->dst_ip.u_addr.ip4.addr, -+ qtuple->src_port, qtuple->dst_port); - } - } - -@@ -197,12 +199,12 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - if (get_global_cfg_params()->is_primary) { - add_user_process_port(qtuple->src_port, get_global_cfg_params()->process_idx, PORT_CONNECT); - if (queue_id != 0) { -- transfer_create_rule_info_to_process0(queue_id, qtuple->src_ip, qtuple->dst_ip, -- qtuple->src_port, qtuple->dst_port); -+ transfer_create_rule_info_to_process0(queue_id, qtuple->src_ip.u_addr.ip4.addr, -+ qtuple->dst_ip.u_addr.ip4.addr, qtuple->src_port, qtuple->dst_port); - } - } else { -- transfer_create_rule_info_to_process0(queue_id, qtuple->src_ip, qtuple->dst_ip, -- qtuple->src_port, qtuple->dst_port); -+ transfer_create_rule_info_to_process0(queue_id, qtuple->src_ip.u_addr.ip4.addr, -+ qtuple->dst_ip.u_addr.ip4.addr, qtuple->src_port, qtuple->dst_port); - } - } - -@@ -228,7 +230,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - struct protocol_stack *stack = get_protocol_stack(); - - if (type == REG_RING_TCP_LISTEN || type == REG_RING_TCP_LISTEN_CLOSE) { -- if (!match_host_addr(qtuple->src_ip)) { -+ if (!match_host_addr(qtuple->src_ip.u_addr.ip4.addr)) { - LSTACK_LOG(INFO, LSTACK, "lstack ip not match in conf.\n"); - return 0; - } -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index a6f2d71..ee379b5 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -246,8 +246,8 @@ static __rte_always_inline int32_t tcp_handle(struct rte_mbuf *m, const struct r - struct gazelle_tcp_sock *tcp_sock = NULL; - struct gazelle_quintuple quintuple; - -- quintuple.dst_ip = ipv4_hdr->dst_addr; -- quintuple.src_ip = ipv4_hdr->src_addr; -+ quintuple.dst_ip.u_addr.ip4.addr = ipv4_hdr->dst_addr; -+ quintuple.src_ip.u_addr.ip4.addr = ipv4_hdr->src_addr; - quintuple.dst_port = tcp_hdr->dst_port; - quintuple.src_port = tcp_hdr->src_port; - quintuple.protocol = 0; -@@ -260,7 +260,7 @@ static __rte_always_inline int32_t tcp_handle(struct rte_mbuf *m, const struct r - } - - tcp_sock = gazelle_sock_get_by_min_conn(gazelle_get_tcp_sock_htable(), -- quintuple.dst_ip, quintuple.dst_port); -+ quintuple.dst_ip.u_addr.ip4.addr, quintuple.dst_port); - if (unlikely(tcp_sock == NULL)) { - return GAZELLE_ERR; - } -@@ -494,7 +494,7 @@ static void tcp_hash_table_modify(struct gazelle_stack *stack, const struct reg_ - case REG_RING_TCP_LISTEN: - /* add sock htable */ - tcp_sock = gazelle_sock_add_by_ipporttid(gazelle_get_tcp_sock_htable(), -- transfer_qtuple.dst_ip, transfer_qtuple.dst_port, msg->tid); -+ transfer_qtuple.dst_ip.u_addr.ip4.addr, transfer_qtuple.dst_port, msg->tid); - if (tcp_sock == NULL) { - LTRAN_ERR("add tcp sock htable failed\n"); - break; -@@ -506,7 +506,7 @@ static void tcp_hash_table_modify(struct gazelle_stack *stack, const struct reg_ - case REG_RING_TCP_LISTEN_CLOSE: - /* del sock htable */ - gazelle_sock_del_by_ipporttid(gazelle_get_tcp_sock_htable(), -- transfer_qtuple.dst_ip, transfer_qtuple.dst_port, msg->tid); -+ transfer_qtuple.dst_ip.u_addr.ip4.addr, transfer_qtuple.dst_port, msg->tid); - break; - case REG_RING_TCP_CONNECT: - /* add conn htable */ -diff --git a/src/ltran/ltran_stat.c b/src/ltran/ltran_stat.c -index 2a0c03a..dfd5fc9 100644 ---- a/src/ltran/ltran_stat.c -+++ b/src/ltran/ltran_stat.c -@@ -267,8 +267,8 @@ void handle_resp_ltran_conn(int32_t fd) - if (index < GAZELLE_LSTACK_MAX_CONN) { - forward_table.conn_list[index].protocol = conn->quintuple.protocol; - forward_table.conn_list[index].tid = conn->tid; -- forward_table.conn_list[index].dst_ip = conn->quintuple.dst_ip; -- forward_table.conn_list[index].src_ip = conn->quintuple.src_ip; -+ forward_table.conn_list[index].dst_ip = conn->quintuple.dst_ip.u_addr.ip4.addr; -+ forward_table.conn_list[index].src_ip = conn->quintuple.src_ip.u_addr.ip4.addr; - forward_table.conn_list[index].dst_port = ntohs(conn->quintuple.dst_port); - forward_table.conn_list[index].src_port = ntohs(conn->quintuple.src_port); - } -diff --git a/src/ltran/ltran_tcp_conn.c b/src/ltran/ltran_tcp_conn.c -index e0ad562..026d22a 100644 ---- a/src/ltran/ltran_tcp_conn.c -+++ b/src/ltran/ltran_tcp_conn.c -@@ -78,8 +78,8 @@ struct gazelle_tcp_conn_hbucket *gazelle_conn_hbucket_get(struct gazelle_tcp_con - const struct gazelle_quintuple *quintuple) - { - uint32_t index; -- index = tuple_hash_fn(quintuple->src_ip, quintuple->src_port, quintuple->dst_ip, quintuple->dst_port) % -- GAZELLE_MAX_CONN_HTABLE_SIZE; -+ index = tuple_hash_fn(quintuple->src_ip.u_addr.ip4.addr, quintuple->src_port, quintuple->dst_ip.u_addr.ip4.addr, -+ quintuple->dst_port) % GAZELLE_MAX_CONN_HTABLE_SIZE; - return &conn_htable->array[index]; - } - -diff --git a/src/ltran/ltran_tcp_sock.c b/src/ltran/ltran_tcp_sock.c -index d6a0d17..940ded8 100644 ---- a/src/ltran/ltran_tcp_sock.c -+++ b/src/ltran/ltran_tcp_sock.c -@@ -104,8 +104,8 @@ static void recover_sock_info_from_conn(struct gazelle_tcp_sock *tcp_sock) - head = &conn_htable->array[i].chain; - - hlist_for_each_entry(conn, node, head, conn_node) { -- if ((conn->quintuple.dst_ip != tcp_sock->ip) || (conn->quintuple.dst_port != tcp_sock->port) || -- (conn->tid != tcp_sock->tid)) { -+ if ((conn->quintuple.dst_ip.u_addr.ip4.addr != tcp_sock->ip) || -+ (conn->quintuple.dst_port != tcp_sock->port) || (conn->tid != tcp_sock->tid)) { - continue; - } - count++; -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 85ea324..96c622e 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -103,8 +103,8 @@ void gazelle_detect_conn_logout(struct gazelle_tcp_conn_htable *conn_htable) - conn_htable->array[i].chain_size--; - LTRAN_DEBUG("delete the tcp conn htable: tid %u quintuple[%u %u %u %u %u]\n", - conn->tid, conn->quintuple.protocol, -- conn->quintuple.src_ip, (uint32_t)ntohs(conn->quintuple.src_port), -- conn->quintuple.dst_ip, (uint32_t)ntohs(conn->quintuple.dst_port)); -+ conn->quintuple.src_ip.u_addr.ip4.addr, (uint32_t)ntohs(conn->quintuple.src_port), -+ conn->quintuple.dst_ip.u_addr.ip4.addr, (uint32_t)ntohs(conn->quintuple.dst_port)); - rte_free(conn); - } - } --- -2.33.0 - diff --git a/0109-match_host_addr-func-support-ipv6.patch b/0109-match_host_addr-func-support-ipv6.patch deleted file mode 100644 index 0e55ed2..0000000 --- a/0109-match_host_addr-func-support-ipv6.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 2489b4b21632c9016f87c6fe963d27ef3e20951b Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Fri, 5 Jan 2024 14:32:48 +0800 -Subject: [PATCH] match_host_addr func support ipv6 - ---- - src/lstack/api/lstack_wrap.c | 12 +++++++++++- - src/lstack/core/lstack_cfg.c | 12 +++++++++--- - src/lstack/core/lstack_control_plane.c | 2 +- - src/lstack/include/lstack_cfg.h | 2 +- - src/lstack/netif/lstack_vdev.c | 2 +- - 5 files changed, 23 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 56f89b2..3db62c7 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -217,7 +217,17 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - return g_wrap_api->bind_fn(s, name, namelen); - } - -- if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) { -+ ip_addr_t sock_addr = IPADDR_ANY_TYPE_INIT; -+ if (name->sa_family == AF_INET) { -+ sock_addr.type = IPADDR_TYPE_V4; -+ sock_addr.u_addr.ip4.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr; -+ } else if (name->sa_family == AF_INET6) { -+ sock_addr.type = IPADDR_TYPE_V6; -+ memcpy_s(sock_addr.u_addr.ip6.addr, IPV6_ADDR_LEN, -+ ((struct sockaddr_in6 *)name)->sin6_addr.s6_addr, IPV6_ADDR_LEN); -+ } -+ -+ if (match_host_addr(&sock_addr)) { - /* maybe kni addr */ - if (posix_api->bind_fn(s, name, namelen) != 0) { - SET_CONN_TYPE_LIBOS(sock->conn); -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index d9c23fb..c1f5680 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -253,11 +253,17 @@ static int32_t parse_host_addr6(void) - return 0; - } - --int32_t match_host_addr(uint32_t addr) -+int32_t match_host_addr(ip_addr_t *addr) - { - /* network byte order */ -- if (addr == g_config_params.host_addr.addr || addr == INADDR_ANY) { -- return 1; -+ if (IP_IS_V4_VAL(*addr)) { -+ if (ip4_addr_cmp(&addr->u_addr.ip4, &g_config_params.host_addr) || ip4_addr_isany_val(addr->u_addr.ip4)) { -+ return 1; -+ } -+ } else if (IP_IS_V6_VAL(*addr)) { -+ if (ip6_addr_cmp(&addr->u_addr.ip6, &g_config_params.host_addr6) || ip6_addr_isany_val(addr->u_addr.ip6)) { -+ return 1; -+ } - } - return 0; - } -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 2d629c8..a9a3814 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -366,7 +366,7 @@ static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_ - qtuple.dst_ip = conn->conn_list[i].rip; - qtuple.dst_port = lwip_htons(conn->conn_list[i].r_port); - -- if ((table_state == LISTEN_LIST) && (!match_host_addr(qtuple.src_ip.u_addr.ip4.addr))) { -+ if ((table_state == LISTEN_LIST) && (!match_host_addr((ip_addr_t *)&qtuple.src_ip))) { - continue; - } - -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 82e96d8..c1074f8 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -133,7 +133,7 @@ int gazelle_param_init(int *argc, char **argv); - int gazelle_copy_param(const char *param, bool is_double, - int *argc, char argv[][PATH_MAX]); - --int match_host_addr(uint32_t ipv4); -+int match_host_addr(ip_addr_t *addr); - int32_t init_stack_numa_cpuset(struct protocol_stack *stack); - - #endif /* GAZELLE_NET_CFG_H */ -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 9a79dc3..c845f7a 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -230,7 +230,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - struct protocol_stack *stack = get_protocol_stack(); - - if (type == REG_RING_TCP_LISTEN || type == REG_RING_TCP_LISTEN_CLOSE) { -- if (!match_host_addr(qtuple->src_ip.u_addr.ip4.addr)) { -+ if (!match_host_addr((ip_addr_t *)&qtuple->src_ip)) { - LSTACK_LOG(INFO, LSTACK, "lstack ip not match in conf.\n"); - return 0; - } --- -2.33.0 - diff --git a/0110-add-example-keep-alive-interval-para.patch b/0110-add-example-keep-alive-interval-para.patch deleted file mode 100644 index c97ee42..0000000 --- a/0110-add-example-keep-alive-interval-para.patch +++ /dev/null @@ -1,27 +0,0 @@ -From f2770a0dd75007d152bdb346e16009227a6d55fa Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Thu, 4 Jan 2024 16:08:02 +0800 -Subject: [PATCH] add example keep-alive interval para - ---- - src/ltran/ltran_dfx.c | 4 ++-- - 8 files changed, 47 insertions(+), 8 deletions(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 08c9da3..5e22e20 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1002,8 +1002,8 @@ static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_sta - if (conn_info->keepalive == 0) { - return; - } -- int ret = sprintf_s(str, buff_len, "(%u,%u,%u)", conn_info->keep_idle, conn_info->keep_intvl, -- conn_info->keep_cnt); -+ int ret = sprintf_s(str, buff_len, "(%u,%u,%u)", (conn_info->keep_idle) / 1000, -+ (conn_info->keep_intvl) / 1000, conn_info->keep_cnt); - if (ret < 0) { - printf("gazelle_keepalive_string sprintf_s fail ret=%d\n", ret); - return; --- -2.33.0 - diff --git a/0111-update-src-common-dpdk_common.c.patch b/0111-update-src-common-dpdk_common.c.patch deleted file mode 100644 index a7aa72c..0000000 --- a/0111-update-src-common-dpdk_common.c.patch +++ /dev/null @@ -1,68 +0,0 @@ -From c6a7e8224dd9faff9120be8814638fe939570908 Mon Sep 17 00:00:00 2001 -From: Caohongtao -Date: Thu, 4 Jan 2024 09:34:04 +0000 -Subject: [PATCH] update src/common/dpdk_common.c. - -Signed-off-by: Caohongtao ---- - src/common/dpdk_common.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index 50f0bf0..62278c2 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -65,13 +65,13 @@ static int32_t kni_config_network_interface(uint16_t port_id, uint8_t if_up) - g_bond_dev_started = true; - } - } else { -- COMMON_INFO("trying to start a started dev. \n"); -+ COMMON_INFO("Trying to start a started dev. \n"); - } - } else { /* Configure network interface down */ - if (g_kni_started) { - g_kni_started = false; - } else { -- COMMON_INFO("trying to stop a stopped dev. \n"); -+ COMMON_INFO("Trying to stop a stopped dev. \n"); - } - } - -@@ -154,7 +154,7 @@ void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev - conf->rxmode.offloads = rx_ol; - conf->txmode.offloads = tx_ol; - -- COMMON_INFO("set checksum offloads\n"); -+ COMMON_INFO("Set checksum offloads\n"); - } - - int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool) -@@ -179,14 +179,14 @@ int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool) - - ret = snprintf_s(conf.name, RTE_KNI_NAMESIZE, RTE_KNI_NAMESIZE - 1, "%s", GAZELLE_KNI_NAME); - if (ret < 0) { -- COMMON_ERR("snprintf_s failed. ret=%d\n", ret); -+ COMMON_ERR("Snprintf_s failed. ret=%d\n", ret); - return -1; - } - conf.mbuf_size = GAZELLE_MAX_PKT_SZ; - conf.group_id = port; - - if (rte_eth_dev_info_get(port, &dev_info) != 0) { -- COMMON_ERR("Fail rte_eth_dev_info_get\n"); -+ COMMON_ERR("Failed rte_eth_dev_info_get\n"); - return -1; - } - -@@ -204,7 +204,7 @@ int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool) - ops.port_id = port; - g_pkni = rte_kni_alloc(pool, &conf, &ops); - if (g_pkni == NULL) { -- COMMON_ERR("Fail to create kni for port: %hu \n", port); -+ COMMON_ERR("Failed to create kni for port: %hu \n", port); - return -1; - } - return 0; --- -2.33.0 - diff --git a/0112-listen_shadow-support-ipv6.patch b/0112-listen_shadow-support-ipv6.patch deleted file mode 100644 index 35949ab..0000000 --- a/0112-listen_shadow-support-ipv6.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0fddaa74aa71ec25ee9cb1db141dd8a778e6e76d Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 8 Jan 2024 15:08:24 +0800 -Subject: [PATCH] listen_shadow support ipv6 - ---- - src/lstack/core/lstack_protocol_stack.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f849bcd..e7b541e 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -1128,9 +1128,15 @@ int32_t stack_single_listen(int32_t fd, int32_t backlog) - /* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ - int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - { -+ typedef union sockaddr_union { -+ struct sockaddr sa; -+ struct sockaddr_in in; -+ struct sockaddr_in6 in6; -+ } sockaddr_t; -+ - struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); - struct protocol_stack *stack = NULL; -- struct sockaddr addr; -+ sockaddr_t addr; - socklen_t addr_len = sizeof(addr); - int32_t ret, clone_fd; - -@@ -1140,7 +1146,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - GAZELLE_RETURN(EINVAL); - } - -- ret = rpc_call_getsockname(fd, &addr, &addr_len); -+ ret = rpc_call_getsockname(fd, (struct sockaddr *)&addr, &addr_len); - if (ret != 0) { - return ret; - } -@@ -1154,7 +1160,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - continue; - } - if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(stack, fd, &addr, sizeof(addr)); -+ clone_fd = rpc_call_shadow_fd(stack, fd, (struct sockaddr *)&addr, addr_len); - if (clone_fd < 0) { - stack_broadcast_close(fd); - return clone_fd; --- -2.33.0 - diff --git a/0113-lstack_dpdk-limit-mbuf-max-num.patch b/0113-lstack_dpdk-limit-mbuf-max-num.patch deleted file mode 100644 index 6ced2f7..0000000 --- a/0113-lstack_dpdk-limit-mbuf-max-num.patch +++ /dev/null @@ -1,78 +0,0 @@ -From aa0bd688a6dae115e136771fda747c9428e65561 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Tue, 2 Jan 2024 09:32:00 +0800 -Subject: [PATCH] lstack_dpdk: limit mbuf max num - ---- - src/lstack/core/lstack_dpdk.c | 5 +++++ - src/lstack/include/lstack_dpdk.h | 18 ++++++++---------- - src/ltran/main.c | 2 +- - 3 files changed, 14 insertions(+), 11 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 729a84c..580dd1d 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -155,6 +155,11 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d \n", ret); - return NULL; - } -+ /* limit mbuf max num based on the dpdk capability */ -+ if (nb_mbuf > MBUF_MAX_NUM) { -+ LSTACK_LOG(ERR, LSTACK, "out of the dpdk mbuf quantity range\n"); -+ return NULL; -+ } - - /* time stamp before pbuf_custom as priv_data */ - uint16_t private_size = RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 4a160e0..2a44c6e 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -17,22 +17,20 @@ - #include "gazelle_opt.h" - #include "gazelle_dfx_msg.h" - --#define RXTX_CACHE_SZ (VDEV_RX_QUEUE_SZ) --#define KNI_NB_MBUF (DEFAULT_RING_SIZE << 4) -+#define RXTX_CACHE_SZ (VDEV_RX_QUEUE_SZ) - --#define RESERVE_NIC_RECV (1024) -+#define KNI_NB_MBUF (DEFAULT_RING_SIZE << 4) - --#define MBUF_HEADER_LEN 64 -- --#define MAX_PACKET_SZ 2048 -+#define MAX_PACKET_SZ 2048 - - #define RING_SIZE(x) ((x) - 1) - --#define MBUF_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) -+#define MBUF_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) - --#define MAX_CORE_NUM 256 --#define CALL_MSG_RING_SIZE (unsigned long long)32 --#define CALL_CACHE_SZ 0 -+/* DPDK limit ring head-tail distance in rte_ring_init. -+ * Max value is RTE_RING_SZ_MASK / HTD_MAX_DEF, RTE_RING_SZ_MASK is 0x7fffffff, HTD_MAX_DEF is 8. -+ */ -+#define MBUF_MAX_NUM 0xfffffff - - int thread_affinity_default(void); - int thread_affinity_init(int cpu_id); -diff --git a/src/ltran/main.c b/src/ltran/main.c -index 87f1e14..c2598a7 100644 ---- a/src/ltran/main.c -+++ b/src/ltran/main.c -@@ -55,7 +55,7 @@ static void print_stack(void) - - static void sig_default_handler(int32_t sig) - { -- LTRAN_ERR("ltran dumped,caught signal:%d.\n", sig); -+ LTRAN_ERR("ltran dumped, caught signal: %d.\n", sig); - print_stack(); - dpdk_kni_release(); - int ret = 0; --- -2.33.0 - diff --git a/0114-gazellectl-add-tcp_input-empty-ack-cnt.patch b/0114-gazellectl-add-tcp_input-empty-ack-cnt.patch deleted file mode 100644 index 8485e02..0000000 --- a/0114-gazellectl-add-tcp_input-empty-ack-cnt.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 295ad7d27233404457488089453a51d39e4d8038 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 8 Jan 2024 09:12:59 +0800 -Subject: [PATCH] gazellectl: add tcp_input empty ack cnt - ---- - src/common/gazelle_dfx_msg.h | 1 + - src/ltran/ltran_dfx.c | 29 +++++++++++++++-------------- - 2 files changed, 16 insertions(+), 14 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 478c440..d58a072 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -143,6 +143,7 @@ struct gazelle_stat_lstack_snmp { - uint32_t tcp_out_of_seq; - uint32_t tcp_acceptmbox_full; - uint32_t tcp_listen_drops; -+ uint32_t tcp_in_empty_acks; - - /* UDP */ - uint32_t udp_in_datagrams; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 08c9da3..5d4e74c 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -855,21 +855,22 @@ static void gazelle_print_lstack_stat_rate(void *buf, const struct gazelle_stat_ - - static void gazelle_print_lstack_tcp_stat(const struct gazelle_stat_lstack_snmp *snmp) - { -- printf("tcp_act_open: %u\n", snmp->tcp_act_open); -- printf("tcp_passive_open: %u\n", snmp->tcp_passive_open); -- printf("tcp_attempt_fail: %u\n", snmp->tcp_attempt_fail); -- printf("tcp_estab_rst: %u\n", snmp->tcp_estab_rst); -- printf("tcp_out_seg: %u\n", snmp->tcp_out_seg); -- printf("tcp_retran_seg: %u\n", snmp->tcp_retran_seg); -- printf("tcp_in_seg: %u\n", snmp->tcp_in_seg); -- printf("tcp_in_err: %u\n", snmp->tcp_in_err); -- printf("tcp_out_rst: %u\n", snmp->tcp_out_rst); -- printf("tcp_fin_ack_cnt: %u\n", snmp->tcp_fin_ack_cnt); -- printf("tcp_delay_ack_cnt: %u\n", snmp->tcp_delay_ack_cnt); -- printf("tcp_refused_cnt: %u\n", snmp->tcp_refused_cnt); -- printf("tcp_out_of_seq: %u\n", snmp->tcp_out_of_seq); -+ printf("tcp_act_open: %u\n", snmp->tcp_act_open); -+ printf("tcp_passive_open: %u\n", snmp->tcp_passive_open); -+ printf("tcp_attempt_fail: %u\n", snmp->tcp_attempt_fail); -+ printf("tcp_estab_rst: %u\n", snmp->tcp_estab_rst); -+ printf("tcp_out_seg: %u\n", snmp->tcp_out_seg); -+ printf("tcp_retran_seg: %u\n", snmp->tcp_retran_seg); -+ printf("tcp_in_seg: %u\n", snmp->tcp_in_seg); -+ printf("tcp_in_err: %u\n", snmp->tcp_in_err); -+ printf("tcp_out_rst: %u\n", snmp->tcp_out_rst); -+ printf("tcp_fin_ack_cnt: %u\n", snmp->tcp_fin_ack_cnt); -+ printf("tcp_delay_ack_cnt: %u\n", snmp->tcp_delay_ack_cnt); -+ printf("tcp_refused_cnt: %u\n", snmp->tcp_refused_cnt); -+ printf("tcp_out_of_seq: %u\n", snmp->tcp_out_of_seq); - printf("tcp_acceptmbox_full: %u\n", snmp->tcp_acceptmbox_full); -- printf("tcp_listen_drops: %u\n", snmp->tcp_listen_drops); -+ printf("tcp_listen_drops: %u\n", snmp->tcp_listen_drops); -+ printf("tcp_in_empty_acks: %u\n", snmp->tcp_in_empty_acks); - } - - static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_stat_msg_request *req_msg) --- -2.33.0 - diff --git a/0115-add-socket-accept-fail-cnt.patch b/0115-add-socket-accept-fail-cnt.patch deleted file mode 100644 index 4be8bde..0000000 --- a/0115-add-socket-accept-fail-cnt.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 53457e3ab329eb944579ffe55ddc4435e0bca0a1 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Wed, 10 Jan 2024 09:12:34 +0800 -Subject: [PATCH] add socket accept fail cnt - ---- - src/common/gazelle_dfx_msg.h | 1 + - src/lstack/core/lstack_protocol_stack.c | 2 ++ - src/ltran/ltran_dfx.c | 1 + - 3 files changed, 4 insertions(+) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 478c440..1d3249d 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -72,6 +72,7 @@ struct gazelle_stack_stat { - uint64_t tx_drop; - uint64_t tx; - uint64_t tx_prepare_fail; -+ uint64_t accept_fail; - }; - - struct gazelle_wakeup_stat { -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f849bcd..0d845dd 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -792,9 +792,11 @@ void stack_accept(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; - msg->result = -1; -+ struct protocol_stack *stack = get_protocol_stack(); - - int32_t accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); - if (accept_fd < 0) { -+ stack->stats.accept_fail++; - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 5e22e20..461912f 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -646,6 +646,7 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("send_pkts_fail: %-13"PRIu64" ", lstack_stat->data.pkts.stack_stat.send_pkts_fail); - printf("mbuf_pool_freecnt: %-10"PRIu32" ", lstack_stat->data.pkts.mbufpool_avail_cnt); - printf("rpc_pool_freecnt: %-12"PRIu32" \n", lstack_stat->data.pkts.rpcpool_avail_cnt); -+ printf("accpet_fail: %-12"PRIu64" \n", lstack_stat->data.pkts.stack_stat.accept_fail); - } - - static void gazelle_print_lstack_stat_detail(struct gazelle_stack_dfx_data *lstack_stat, --- -2.33.0 - diff --git a/0116-diff-lstack-and-ltran-dfx-sock.patch b/0116-diff-lstack-and-ltran-dfx-sock.patch deleted file mode 100644 index 5a7adaa..0000000 --- a/0116-diff-lstack-and-ltran-dfx-sock.patch +++ /dev/null @@ -1,137 +0,0 @@ -From db89062f34f8bcccf80a82d6589e5f3b5bc63cfe Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 13 Jan 2024 17:03:07 +0800 -Subject: [PATCH] diff lstack and ltran dfx sock - ---- - src/common/gazelle_opt.h | 9 +++++++-- - src/lstack/core/lstack_cfg.c | 10 ++++++++-- - src/ltran/ltran_base.h | 3 --- - src/ltran/ltran_dfx.c | 8 ++++---- - src/ltran/ltran_monitor.c | 8 ++++---- - src/ltran/ltran_param.c | 4 ++-- - 6 files changed, 25 insertions(+), 17 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 36915c6..1d1c5f5 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -85,8 +85,13 @@ - - #define GAZELLE_MAX_STACK_ARRAY_SIZE GAZELLE_CLIENT_NUM - --#define GAZELLE_REG_SOCK_PATHNAME "/var/run/gazelle/gazelle_client.sock" --#define GAZELLE_REG_SOCK_FILENAME "gazelle_client.sock" -+#define LTRAN_REG_SOCK_PATHNAME "/var/run/gazelle/ltran_client.sock" -+#define LTRAN_REG_SOCK_FILENAME "ltran_client.sock" -+#define LTRAN_DFX_SOCK_PATHNAME "/var/run/gazelle/ltran_cmd.sock" -+#define LTRAN_DFX_SOCK_FILENAME "ltran_cmd.sock" -+#define LSTACK_DFX_SOCK_PATHNAME "/var/run/gazelle/lstack_cmd.sock" -+#define LSTACK_DFX_SOCK_FILENAME "lstack_cmd.sock" -+ - #define GAZELLE_SOCK_FILENAME_MAXLEN 128 - - #define GAZELLE_RUN_DIR "/var/run/gazelle/" -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index c1f5680..87df790 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1043,8 +1043,14 @@ static int32_t parse_unix_prefix(void) - } - } - -- ret = strncat_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -- GAZELLE_REG_SOCK_FILENAME, strlen(GAZELLE_REG_SOCK_FILENAME) + 1); -+ if (g_config_params.use_ltran) { -+ ret = strncat_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -+ LTRAN_REG_SOCK_FILENAME, strlen(LTRAN_REG_SOCK_FILENAME) + 1); -+ } else { -+ ret = strncat_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -+ LSTACK_DFX_SOCK_FILENAME, strlen(LSTACK_DFX_SOCK_FILENAME) + 1); -+ } -+ - if (ret != EOK) { - return ret; - } -diff --git a/src/ltran/ltran_base.h b/src/ltran/ltran_base.h -index 6be9152..f174a40 100644 ---- a/src/ltran/ltran_base.h -+++ b/src/ltran/ltran_base.h -@@ -98,7 +98,4 @@ - - #define GAZELLE_INET_ADDRSTRLEN 16 - --#define GAZELLE_DFX_SOCK_PATHNAME "/var/run/gazelle/gazelle_cmd.sock" --#define GAZELLE_DFX_SOCK_FILENAME "gazelle_cmd.sock" -- - #endif /* ifndef __GAZELLE_BASE_H__ */ -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index a64c1d5..05234de 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -254,15 +254,15 @@ static int32_t dfx_connect_ltran(bool use_ltran, bool probe) - - addr.sun_family = AF_UNIX; - if (use_ltran) { -- ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), GAZELLE_DFX_SOCK_FILENAME, -- strlen(GAZELLE_DFX_SOCK_FILENAME) + 1); -+ ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), LTRAN_DFX_SOCK_FILENAME, -+ strlen(LTRAN_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - goto END; - } - } else { -- ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), GAZELLE_REG_SOCK_FILENAME, -- strlen(GAZELLE_REG_SOCK_FILENAME) + 1); -+ ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), LSTACK_DFX_SOCK_FILENAME, -+ strlen(LSTACK_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - goto END; -diff --git a/src/ltran/ltran_monitor.c b/src/ltran/ltran_monitor.c -index b2bcc07..ea31e84 100644 ---- a/src/ltran/ltran_monitor.c -+++ b/src/ltran/ltran_monitor.c -@@ -238,13 +238,13 @@ static void gazelle_ctl_destroy(void) - close(g_epoll_fd); - g_epoll_fd = -1; - -- ret = unlink(GAZELLE_DFX_SOCK_PATHNAME); -+ ret = unlink(LTRAN_DFX_SOCK_PATHNAME); - if (ret != 0) { -- LTRAN_WARN("unlink %s ERROR. errno: %d. ret=%d\n", GAZELLE_DFX_SOCK_PATHNAME, errno, ret); -+ LTRAN_WARN("unlink %s ERROR. errno: %d. ret=%d\n", LTRAN_DFX_SOCK_PATHNAME, errno, ret); - } -- ret = unlink(GAZELLE_REG_SOCK_PATHNAME); -+ ret = unlink(LTRAN_REG_SOCK_PATHNAME); - if (ret != 0) { -- LTRAN_WARN("unlink %s ERROR. errno: %d. ret=%d\n", GAZELLE_REG_SOCK_PATHNAME, errno, ret); -+ LTRAN_WARN("unlink %s ERROR. errno: %d. ret=%d\n", LTRAN_REG_SOCK_PATHNAME, errno, ret); - } - } - -diff --git a/src/ltran/ltran_param.c b/src/ltran/ltran_param.c -index 1eaace4..bd5a8e1 100644 ---- a/src/ltran/ltran_param.c -+++ b/src/ltran/ltran_param.c -@@ -598,14 +598,14 @@ static int32_t parse_unix_prefix(const config_t *config, const char *key, struct - } - - ret = strncat_s(ltran_config->unix_socket_filename, sizeof(ltran_config->unix_socket_filename), -- GAZELLE_REG_SOCK_FILENAME, strlen(GAZELLE_REG_SOCK_FILENAME) + 1); -+ LTRAN_REG_SOCK_FILENAME, strlen(LTRAN_REG_SOCK_FILENAME) + 1); - if (ret != EOK) { - gazelle_set_errno(GAZELLE_EINETATON); - return GAZELLE_ERR; - } - - ret = strncat_s(ltran_config->dfx_socket_filename, sizeof(ltran_config->dfx_socket_filename), -- GAZELLE_DFX_SOCK_FILENAME, strlen(GAZELLE_DFX_SOCK_FILENAME) + 1); -+ LTRAN_DFX_SOCK_FILENAME, strlen(LTRAN_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - gazelle_set_errno(GAZELLE_EINETATON); - return GAZELLE_ERR; --- -2.33.0 - diff --git a/0117-fix-host_addr6-can-be-assigned-a-multicast-address.patch b/0117-fix-host_addr6-can-be-assigned-a-multicast-address.patch deleted file mode 100644 index a99e7c1..0000000 --- a/0117-fix-host_addr6-can-be-assigned-a-multicast-address.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 7c8d80e76f93029437f9a52f04c9d02b0d55dd78 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Tue, 16 Jan 2024 23:52:23 +0800 -Subject: [PATCH] fix host_addr6 can be assigned a multicast address - ---- - src/lstack/core/lstack_cfg.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 87df790..5e30e89 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -250,6 +250,12 @@ static int32_t parse_host_addr6(void) - if (ip6addr_aton(value, &g_config_params.host_addr6) == 0) { - return -EINVAL; - } -+ -+ if (ip6_addr_ismulticast(&g_config_params.host_addr6)) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr6 cannot be a multicast address."); -+ return -EINVAL; -+ } -+ - return 0; - } - --- -2.33.0 - diff --git a/0118-udp-do-not-merge-data-into-last-pbuf.patch b/0118-udp-do-not-merge-data-into-last-pbuf.patch deleted file mode 100644 index a3f557a..0000000 --- a/0118-udp-do-not-merge-data-into-last-pbuf.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b90801a943f140a62761158a058d1076212dccf3 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 18 Jan 2024 10:01:52 +0800 -Subject: [PATCH] udp: do not merge data into last pbuf - ---- - src/lstack/core/lstack_lwip.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 87ec1f5..6ebe589 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -542,14 +542,14 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - } - - struct protocol_stack *stack = sock->stack; -- if (!stack|| len == 0) { -+ if (!stack || len == 0) { - return 0; - } - - ssize_t send_len = 0; - - /* merge data into last pbuf */ -- if (sock->remain_len) { -+ if (!NETCONN_IS_UDP(sock) && sock->remain_len) { - send_len = merge_data_lastpbuf(sock, (char *)buf, len); - if (send_len >= len) { - send_len = len; -@@ -1045,6 +1045,11 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ); - } - 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)) { -+ break; -+ } - } - } - --- -2.33.0 - diff --git a/0119-adpat-dpdk-23.11.patch b/0119-adpat-dpdk-23.11.patch deleted file mode 100644 index 07b81bd..0000000 --- a/0119-adpat-dpdk-23.11.patch +++ /dev/null @@ -1,969 +0,0 @@ -From bbb97803a36a5de0bb6ca6ce0518a6ef0666a22b Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 15 Jan 2024 09:37:20 +0800 -Subject: [PATCH] adpat dpdk 23.11 - ---- - src/common/dpdk_common.c | 171 +++++++++++---------- - src/common/gazelle_parse_config.c | 1 + - src/lstack/Makefile | 50 +++--- - src/lstack/core/lstack_dpdk.c | 34 ++-- - src/lstack/core/lstack_init.c | 2 + - src/lstack/core/lstack_protocol_stack.c | 12 +- - src/lstack/include/lstack_ethdev.h | 8 + - src/lstack/include/lstack_protocol_stack.h | 1 - - src/lstack/netif/lstack_ethdev.c | 8 + - src/lstack/netif/lstack_vdev.c | 4 +- - src/ltran/CMakeLists.txt | 33 +++- - src/ltran/ltran_dfx.c | 20 +-- - src/ltran/ltran_ethdev.c | 29 +++- - src/ltran/ltran_forward.c | 14 ++ - src/ltran/ltran_stack.c | 1 + - src/ltran/ltran_timer.c | 1 + - src/ltran/main.c | 6 + - 17 files changed, 254 insertions(+), 141 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index 62278c2..c0c4f63 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -10,18 +10,21 @@ - * See the Mulan PSL v2 for more details. - */ - --#include -+#include - #include - #include - #include - #include - #include --#include -+#include -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -+#include -+#endif -+ -+#include - - #include "dpdk_common.h" - --#define GAZELLE_KNI_IFACES_NUM 1 --#define GAZELLE_KNI_READ_SIZE 32 - #define GAZELLE_MAX_PKT_SZ 2048 - - #ifdef LTRAN_COMPILE -@@ -34,6 +37,9 @@ - #define COMMON_INFO(fmt, ...) LSTACK_LOG(INFO, LSTACK, fmt, ##__VA_ARGS__) - #endif - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -+#define GAZELLE_KNI_IFACES_NUM 1 -+#define GAZELLE_KNI_READ_SIZE 32 - struct rte_kni *g_pkni = NULL; - static volatile bool g_kni_started = false; - -@@ -79,84 +85,6 @@ static int32_t kni_config_network_interface(uint16_t port_id, uint8_t if_up) - return ret; - } - --void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info) --{ -- uint64_t rx_ol = 0; -- uint64_t tx_ol = 0; -- uint64_t rx_ol_capa = dev_info->rx_offload_capa; -- uint64_t tx_ol_capa = dev_info->tx_offload_capa; -- -- // rx ip -- if (rx_ol_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) { -- rx_ol |= DEV_RX_OFFLOAD_IPV4_CKSUM; -- COMMON_INFO("DEV_RX_OFFLOAD_IPV4_CKSUM\n"); -- } -- -- // rx tcp -- if (rx_ol_capa & DEV_RX_OFFLOAD_TCP_CKSUM) { -- rx_ol |= DEV_RX_OFFLOAD_TCP_CKSUM; -- COMMON_INFO("DEV_RX_OFFLOAD_TCP_CKSUM\n"); -- } -- -- // rx udp -- if (rx_ol_capa & DEV_RX_OFFLOAD_UDP_CKSUM) { -- rx_ol |= DEV_RX_OFFLOAD_UDP_CKSUM; -- COMMON_INFO("DEV_RX_OFFLOAD_UDP_CKSUM\n"); -- } -- -- // rx vlan -- if (rx_ol_capa & DEV_RX_OFFLOAD_VLAN_STRIP) { -- rx_ol |= DEV_RX_OFFLOAD_VLAN_STRIP; -- COMMON_INFO("DEV_RX_OFFLOAD_VLAN_STRIP\n"); -- } -- -- // tx ip -- if (tx_ol_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) { -- tx_ol |= DEV_TX_OFFLOAD_IPV4_CKSUM; -- COMMON_INFO("DEV_TX_OFFLOAD_IPV4_CKSUM\n"); -- } -- -- // tx tcp -- if (tx_ol_capa & DEV_TX_OFFLOAD_TCP_CKSUM) { -- tx_ol |= DEV_TX_OFFLOAD_TCP_CKSUM; -- COMMON_INFO("DEV_TX_OFFLOAD_TCP_CKSUM\n"); -- } -- -- // tx udp -- if (tx_ol_capa & DEV_TX_OFFLOAD_UDP_CKSUM) { -- tx_ol |= DEV_TX_OFFLOAD_UDP_CKSUM; -- COMMON_INFO("DEV_TX_OFFLOAD_UDP_CKSUM\n"); -- } -- -- // tx tso -- if (tx_ol_capa & DEV_TX_OFFLOAD_TCP_TSO) { -- tx_ol |= (DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_MULTI_SEGS); -- COMMON_INFO("DEV_TX_OFFLOAD_TCP_TSO\n"); -- } -- -- // tx vlan -- if (tx_ol_capa & DEV_TX_OFFLOAD_VLAN_INSERT) { -- tx_ol |= DEV_TX_OFFLOAD_VLAN_INSERT; -- COMMON_INFO("DEV_TX_OFFLOAD_VLAN_INSERT\n"); -- } -- -- if (!(rx_ol & DEV_RX_OFFLOAD_UDP_CKSUM) || -- !(rx_ol & DEV_RX_OFFLOAD_TCP_CKSUM) || -- !(rx_ol & DEV_RX_OFFLOAD_IPV4_CKSUM)) { -- rx_ol = 0; -- } -- if (!(tx_ol & DEV_TX_OFFLOAD_UDP_CKSUM) || -- !(tx_ol & DEV_TX_OFFLOAD_TCP_CKSUM) || -- !(tx_ol & DEV_TX_OFFLOAD_IPV4_CKSUM)) { -- tx_ol = 0; -- } -- -- conf->rxmode.offloads = rx_ol; -- conf->txmode.offloads = tx_ol; -- -- COMMON_INFO("Set checksum offloads\n"); --} -- - int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool) - { - int32_t ret; -@@ -262,3 +190,82 @@ void kni_process_rx(uint16_t port) - } - } - } -+#endif -+ -+void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info) -+{ -+ uint64_t rx_ol = 0; -+ uint64_t tx_ol = 0; -+ uint64_t rx_ol_capa = dev_info->rx_offload_capa; -+ uint64_t tx_ol_capa = dev_info->tx_offload_capa; -+ -+ // rx ip -+ if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) { -+ rx_ol |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM; -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_IPV4_CKSUM\n"); -+ } -+ -+ // rx tcp -+ if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) { -+ rx_ol |= RTE_ETH_RX_OFFLOAD_TCP_CKSUM; -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_TCP_CKSUM\n"); -+ } -+ -+ // rx udp -+ if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_UDP_CKSUM) { -+ rx_ol |= RTE_ETH_RX_OFFLOAD_UDP_CKSUM; -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_UDP_CKSUM\n"); -+ } -+ -+ // rx vlan -+ if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) { -+ rx_ol |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP; -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_VLAN_STRIP\n"); -+ } -+ -+ // tx ip -+ if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) { -+ tx_ol |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; -+ COMMON_INFO("RTE_ETH_TX_OFFLOAD_IPV4_CKSUM\n"); -+ } -+ -+ // tx tcp -+ if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) { -+ tx_ol |= RTE_ETH_TX_OFFLOAD_TCP_CKSUM; -+ COMMON_INFO("RTE_ETH_TX_OFFLOAD_TCP_CKSUM\n"); -+ } -+ -+ // tx udp -+ if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) { -+ tx_ol |= RTE_ETH_TX_OFFLOAD_UDP_CKSUM; -+ COMMON_INFO("RTE_ETH_TX_OFFLOAD_UDP_CKSUM\n"); -+ } -+ -+ // tx tso -+ if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_TCP_TSO) { -+ tx_ol |= (RTE_ETH_TX_OFFLOAD_TCP_TSO | RTE_ETH_TX_OFFLOAD_MULTI_SEGS); -+ COMMON_INFO("RTE_ETH_TX_OFFLOAD_TCP_TSO\n"); -+ } -+ -+ // tx vlan -+ if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) { -+ tx_ol |= RTE_ETH_TX_OFFLOAD_VLAN_INSERT; -+ COMMON_INFO("RTE_ETH_TX_OFFLOAD_VLAN_INSERT\n"); -+ } -+ -+ if (!(rx_ol & RTE_ETH_RX_OFFLOAD_UDP_CKSUM) || -+ !(rx_ol & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) || -+ !(rx_ol & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM)) { -+ rx_ol = 0; -+ } -+ if (!(tx_ol & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) || -+ !(tx_ol & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) || -+ !(tx_ol & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM)) { -+ tx_ol = 0; -+ } -+ -+ conf->rxmode.offloads = rx_ol; -+ conf->txmode.offloads = tx_ol; -+ -+ COMMON_INFO("Set checksum offloads\n"); -+} -diff --git a/src/common/gazelle_parse_config.c b/src/common/gazelle_parse_config.c -index 1adce78..0553f0d 100644 ---- a/src/common/gazelle_parse_config.c -+++ b/src/common/gazelle_parse_config.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index d585040..df1ddaa 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -7,17 +7,17 @@ - # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - # PURPOSE. - # See the Mulan PSL v2 for more details. -- - LSTACK_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) - ROOT_DIR := $(dir $(abspath $(LSTACK_DIR))) - - LWIP_INCLUDE_FILE ?= /usr/include/lwip - LIB_PATH ?= /usr/lib64 - --ifeq ($(DPDK_VERSION_1911), 1) -- DPDK_INCLUDE_FILE ?= /usr/include/dpdk -+DPDK_VERSION := $(shell rpm -q --queryformat '%{VERSION}' dpdk) -+ifeq ($(DPDK_VERSION),21.11) -+ DPDK_INCLUDE_FILE := /usr/local/include - else -- DPDK_INCLUDE_FILE ?= /usr/local/include/ -+ DPDK_INCLUDE_FILE := /usr/include/dpdk - endif - - AR = ar -@@ -77,34 +77,36 @@ LIBRTE_LIB = $(LIB_PATH)/librte_pci.so \ - $(LIB_PATH)/librte_gro.so \ - $(LIB_PATH)/librte_ring.so \ - $(LIB_PATH)/librte_mbuf.so \ -- $(LIB_PATH)/librte_kni.so \ - $(LIB_PATH)/librte_kvargs.so \ - $(LIB_PATH)/librte_bus_vdev.so \ - $(LIB_PATH)/librte_net.so \ - $(LIB_PATH)/librte_ethdev.so \ -- $(LIB_PATH)/librte_pdump.so \ -+ $(LIB_PATH)/librte_pdump.so -+ -+ifeq ($(shell expr $(DPDK_VERSION) \< 23.11), 1) -+ LIBRTE_LIB += $(LIB_PATH)/librte_kni.so -+endif - --ifeq ($(DPDK_VERSION_1911), 1) -- CFLAGS += -DDPDK_VERSION_1911=1 -+ifeq ($(DPDK_VERSION), 19.11) - LIBRTE_LIB += $(LIB_PATH)/librte_pmd_pcap.so \ -- $(LIB_PATH)/librte_pmd_bond.so \ -- $(LIB_PATH)/librte_pmd_hinic.so \ -- $(LIB_PATH)/librte_pmd_ixgbe.so \ -- $(LIB_PATH)/librte_pmd_virtio.so -- ifneq ($(ARCH), loongarch64) -- LIBRTE_LIB += $(LIB_PATH)/librte_pmd_i40e.so -- endif -+ $(LIB_PATH)/librte_pmd_bond.so \ -+ $(LIB_PATH)/librte_pmd_hinic.so \ -+ $(LIB_PATH)/librte_pmd_ixgbe.so \ -+ $(LIB_PATH)/librte_pmd_virtio.so -+ ifneq ($(ARCH), loongarch64) -+ LIBRTE_LIB += $(LIB_PATH)/librte_pmd_i40e.so -+ endif - else - LIBRTE_LIB += $(LIB_PATH)/librte_net_pcap.so \ -- $(LIB_PATH)/librte_net_bond.so \ -- $(LIB_PATH)/librte_net_hinic.so \ -- $(LIB_PATH)/librte_net_ixgbe.so \ -- $(LIB_PATH)/librte_net_virtio.so \ -- $(LIB_PATH)/librte_telemetry.so \ -- $(LIB_PATH)/librte_pcapng.so -- ifneq ($(ARCH), loongarch64) -- LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so -- endif -+ $(LIB_PATH)/librte_net_bond.so \ -+ $(LIB_PATH)/librte_net_hinic.so \ -+ $(LIB_PATH)/librte_net_ixgbe.so \ -+ $(LIB_PATH)/librte_net_virtio.so \ -+ $(LIB_PATH)/librte_telemetry.so \ -+ $(LIB_PATH)/librte_pcapng.so -+ ifneq ($(ARCH), loongarch64) -+ LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so -+ endif - endif - - DEP_LIBS = $(LWIP_LIB) $(LIBRTE_LIB) -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 630b043..7f1ceb8 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -27,7 +27,10 @@ - #include - #include - #include -+#include -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -+#endif - #include - #include - #include -@@ -35,6 +38,7 @@ - #include - #include - #include -+ - #include - #include - #include -@@ -59,8 +63,10 @@ struct eth_params { - struct rte_eth_rxconf rx_conf; - struct rte_eth_txconf tx_conf; - }; -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - struct rte_kni; - static struct rte_bus *g_pci_bus = NULL; -+#endif - - #define RSS_HASH_KEY_LEN 40 - static uint8_t g_default_rss_key[] = { -@@ -368,9 +374,9 @@ static struct eth_params *alloc_eth_params(uint16_t port_id, uint16_t nb_queues) - eth_params->nb_queues = nb_queues; - eth_params->nb_rx_desc = get_global_cfg_params()->nic.rxqueue_size; - eth_params->nb_tx_desc = get_global_cfg_params()->nic.txqueue_size; -- eth_params->conf.link_speeds = ETH_LINK_SPEED_AUTONEG; -- eth_params->conf.txmode.mq_mode = ETH_MQ_TX_NONE; -- eth_params->conf.rxmode.mq_mode = ETH_MQ_RX_NONE; -+ eth_params->conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; -+ eth_params->conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; -+ eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; - - return eth_params; - } -@@ -388,7 +394,7 @@ uint64_t get_eth_params_tx_ol(void) - static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info) - { - int rss_enable = 0; -- uint64_t def_rss_hf = ETH_RSS_TCP | ETH_RSS_UDP | ETH_RSS_IP; -+ uint64_t def_rss_hf = RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_IP; - struct rte_eth_rss_conf rss_conf = { - g_default_rss_key, - RSS_HASH_KEY_LEN, -@@ -404,7 +410,7 @@ static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *de - if (rss_conf.rss_hf) { - rss_enable = 1; - conf->rx_adv_conf.rss_conf = rss_conf; -- conf->rxmode.mq_mode = ETH_MQ_RX_RSS; -+ conf->rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; - - LSTACK_LOG(INFO, LSTACK, "set rss_hf: %lx\n", rss_conf.rss_hf); - } -@@ -427,8 +433,8 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - return; - } - -- reta_conf_size = dev_info.reta_size / RTE_RETA_GROUP_SIZE; -- if (dev_info.reta_size % RTE_RETA_GROUP_SIZE) { -+ reta_conf_size = dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE; -+ if (dev_info.reta_size % RTE_ETH_RETA_GROUP_SIZE) { - reta_conf_size += 1; - } - -@@ -438,8 +444,8 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - } - for (i = 0; i < dev_info.reta_size; i++) { - struct rte_eth_rss_reta_entry64 *one_reta_conf = -- &reta_conf[i / RTE_RETA_GROUP_SIZE]; -- one_reta_conf->reta[i % RTE_RETA_GROUP_SIZE] = i % nb_queues; -+ &reta_conf[i / RTE_ETH_RETA_GROUP_SIZE]; -+ one_reta_conf->reta[i % RTE_ETH_RETA_GROUP_SIZE] = i % nb_queues; - } - - for (i = 0; i < reta_conf_size; i++) { -@@ -518,7 +524,11 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - return -1; - } - -+#if RTE_VERSION >= RTE_VERSION_NUM(23, 11, 0, 0) -+ ret = rte_eth_bond_member_add(port_id, slave_port_id[i]); -+#else - ret = rte_eth_bond_slave_add(port_id, slave_port_id[i]); -+#endif - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk add slave port failed ret = %d\n", ret); - return -1; -@@ -671,6 +681,7 @@ int32_t dpdk_init_lstack_kni(void) - return 0; - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void) - { - /* when lstack init nic again, ltran can't read pkts from nic. unregister pci_bus to avoid init nic in lstack */ -@@ -686,6 +697,7 @@ void dpdk_restore_pci(void) - rte_bus_register(g_pci_bus); - } - } -+#endif - - int32_t init_dpdk_ethdev(void) - { -@@ -849,7 +861,11 @@ void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - if (strcmp(dev_info.driver_name, "net_bonding") == 0) { - uint16_t slaves[RTE_MAX_ETHPORTS]; - int slave_count; -+#if RTE_VERSION >= RTE_VERSION_NUM(23, 11, 0, 0) -+ slave_count = rte_eth_bond_members_get(port_id, slaves, RTE_MAX_ETHPORTS); -+#else - slave_count = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS); -+#endif - if (slave_count <= 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_slaves_get failed.\n"); - return; -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index fef2942..31fd91d 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -116,7 +116,9 @@ void gazelle_exit(void) - stack_group_exit(); - } - if (!use_ltran()) { -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_kni_release(); -+#endif - } - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 1fa7373..a24fc4c 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -13,8 +13,6 @@ - #include - #include - --#include -- - #include - #include - #include -@@ -38,6 +36,10 @@ - #include "lstack_stack_stat.h" - #include "lstack_protocol_stack.h" - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -+#include -+#endif -+ - #define KERNEL_EVENT_10us 10 - - static PER_THREAD struct protocol_stack *g_stack_p = NULL; -@@ -453,7 +455,9 @@ int stack_polling(uint32_t wakeup_tick) - int force_quit; - struct cfg_params *cfg = get_global_cfg_params(); - uint8_t use_ltran_flag = cfg->use_ltran; -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - bool kni_switch = cfg->kni_switch; -+#endif - bool use_sockmap = cfg->use_sockmap; - bool stack_mode_rtc = cfg->stack_mode_rtc; - uint32_t rpc_number = cfg->rpc_number; -@@ -486,6 +490,7 @@ int stack_polling(uint32_t wakeup_tick) - } - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - /* run to completion mode currently does not support kni */ - /* KNI requests are generally low-rate I/Os, - * so processing KNI requests only in the thread with queue_id No.0 is sufficient. */ -@@ -495,6 +500,7 @@ int stack_polling(uint32_t wakeup_tick) - kni_handle_rx(stack->port_id); - } - } -+#endif - return force_quit; - } - -@@ -950,7 +956,9 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - copy_mbuf(mbuf_copy, mbuf); -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - kni_handle_tx(mbuf_copy); -+#endif - return; - } - -diff --git a/src/lstack/include/lstack_ethdev.h b/src/lstack/include/lstack_ethdev.h -index 326bd1b..3252906 100644 ---- a/src/lstack/include/lstack_ethdev.h -+++ b/src/lstack/include/lstack_ethdev.h -@@ -13,6 +13,9 @@ - #ifndef __GAZELLE_ETHDEV_H__ - #define __GAZELLE_ETHDEV_H__ - -+#include -+#include -+ - #define INVAILD_PROCESS_IDX 255 - - enum port_type { -@@ -46,7 +49,12 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack); - - int recv_pkts_from_other_process(int process_index, void* arg); - int32_t check_params_from_primary(void); -+ -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void kni_handle_rx(uint16_t port_id); -+void kni_handle_tx(struct rte_mbuf *mbuf); -+#endif -+ - void delete_user_process_port(uint16_t dst_port, enum port_type type); - void add_user_process_port(uint16_t dst_port, uint8_t process_idx, enum port_type type); - void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 8e2e807..c681547 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -181,5 +181,4 @@ void stack_recvlist_count(struct rpc_msg *msg); - void stack_exit_by_rpc(struct rpc_msg *msg); - - int stack_polling(uint32_t wakeup_tick); --void kni_handle_tx(struct rte_mbuf *mbuf); - #endif -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 2e11670..5b0f83e 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -13,7 +13,11 @@ - #include - #include - -+#include -+#include -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -+#endif - #include - #include - #include -@@ -755,6 +759,7 @@ int distribute_pakages(struct rte_mbuf *mbuf) - return TRANSFER_KERNEL; - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void kni_handle_rx(uint16_t port_id) - { - struct rte_mbuf *pkts_burst[PACKET_READ_SIZE]; -@@ -793,6 +798,7 @@ void kni_handle_tx(struct rte_mbuf *mbuf) - rte_pktmbuf_free(mbuf); - } - } -+#endif - - /* optimized eth_dev_poll() in lstack */ - int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_flag, uint32_t nic_read_number) -@@ -835,7 +841,9 @@ int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_fla - if (likely(transfer_type == TRANSFER_CURRENT_THREAD)) { - eth_dev_recv(stack->pkts[i], stack); - } else if (transfer_type == TRANSFER_KERNEL) { -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - kni_handle_tx(stack->pkts[i]); -+#endif - } else { - /* transfer to other thread */ - } -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index c845f7a..fe17f59 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -22,6 +22,8 @@ - #include - #include - -+#include -+ - #include "lstack_cfg.h" - #include "lstack_dpdk.h" - #include "lstack_ethdev.h" -@@ -85,7 +87,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - - /* skip gro when tcp/ip cksum offloads disable */ - if (get_protocol_stack_group()->rx_offload == 0 || (get_global_cfg_params()->nic.vlan_mode >= 0 -- && !(get_protocol_stack_group()->rx_offload & DEV_RX_OFFLOAD_VLAN_STRIP))) { -+ && !(get_protocol_stack_group()->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP))) { - return pkt_num; - } - -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index e098a77..f739ceb 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -27,22 +27,38 @@ if($ENV{GAZELLE_COVERAGE_ENABLE}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs") - endif($ENV{GAZELLE_COVERAGE_ENABLE}) - --if($ENV{DPDK_VERSION_1911}) -+execute_process( -+ COMMAND rpm -qa dpdk -+ OUTPUT_VARIABLE DPDK_VERSION_FULL -+ OUTPUT_STRIP_TRAILING_WHITESPACE -+) -+string(REGEX MATCH "[0-9]+\\.[0-9]+" DPDK_VERSION ${DPDK_VERSION_FULL}) -+ -+if (DPDK_VERSION STREQUAL "21.11") -+ set(DPDK_DIR /usr/local/include/) -+else() - set(DPDK_DIR /usr/include/dpdk) -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDPDK_VERSION_1911=1") -+endif() -+ -+if (DPDK_VERSION STREQUAL "19.11") - set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_bond -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe \ - -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_virtio") - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") - set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_pmd_i40e") - endif() - else() -- set(DPDK_DIR /usr/local/include/) - set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ - -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry") - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") - set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_net_i40e") - endif() --endif($ENV{DPDK_VERSION_1911}) -+endif() -+ -+if (DPDK_VERSION GREATER_EQUAL 23.11) -+ set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_log -larchive -Wl,-lrte_eal") -+else() -+ set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_kni -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic") -+endif() - - add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_stat.c ltran_errno.c - ltran_monitor.c ltran_instance.c ltran_stack.c ltran_tcp_conn.c ltran_tcp_sock.c -@@ -55,16 +71,19 @@ target_compile_options(ltran PRIVATE -fno-strict-aliasing -D__ARM_FEATURE_CRC32= - -DRTE_MACHINE_CPUFLAG_SHA1 -DRTE_MACHINE_CPUFLAG_SHA2 -include rte_config.h - -D_GNU_SOURCE -W -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wold-style-definition - -Wpointer-arith -Wcast-qual -Wnested-externs -Wformat-nonliteral -Wformat-security -Wundef -- -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2) --if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64") -+ -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2 -Wno-error=deprecated-declarations) -+ -+# gcc coredump in openEuler-20.03-LTS-XX aarch64 when add -march=native -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64" ) - target_compile_options(ltran PRIVATE -march=native -Wcast-align) - endif() - - target_link_libraries(ltran PRIVATE config boundscheck rte_pdump -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines) -+ - set_target_properties(ltran PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -Wl,--no-whole-archive \ - -Wl,-lrte_meter -Wl,--whole-archive -Wl,-lrte_gro -Wl,-lrte_hash -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ethdev \ - -Wl,-lrte_net -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci \ -- -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic -Wl,-lrte_cmdline -Wl,-lrte_kni -Wl,-lrte_bus_pci \ -+ -Wl,-lrte_cmdline -Wl,-lrte_bus_pci\ - -Wl,-lrte_bus_vdev ${DPDK_LINK_FLAGS} \ - -Wl,--no-whole-archive -Wl,-lm -Wl,-lrt -Wl,-lnuma -Wl,-ldl -Wl,-export-dynamic -Wl,-export-dynamic \ - -Wl,--as-needed -Wl,-export-dynamic -Wl,-Map=ltran.map -Wl,--cref") -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 0d7ea7b..4b246a1 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -26,6 +26,8 @@ - #include - #include - -+#include -+ - #include "ltran_stat.h" - #include "ltran_base.h" - #include "gazelle_dfx_msg.h" -@@ -168,16 +170,16 @@ static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_st - struct nic_eth_features *f = &(((struct gazelle_stack_dfx_data *)buf)->data.nic_features); - printf("###### NIC offload and other features for port %-2d #########\n", f->port_id); - -- printf("tx-ipv4-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -- printf("tx-tcp-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -- printf("tx-tcp-tso: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_TCP_TSO) ? "on" : "off"); -- printf("tx-udp-checksum: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -- printf("tx-vlan-insert: %s\n", (f->tx_offload & DEV_TX_OFFLOAD_VLAN_INSERT) ? "on" : "off"); -+ printf("tx-ipv4-checksum: %s\n", (f->tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -+ printf("tx-tcp-checksum: %s\n", (f->tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -+ printf("tx-tcp-tso: %s\n", (f->tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) ? "on" : "off"); -+ printf("tx-udp-checksum: %s\n", (f->tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -+ printf("tx-vlan-insert: %s\n", (f->tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) ? "on" : "off"); - -- printf("rx-ipv4-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -- printf("rx-tcp-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -- printf("rx-udp-checksum: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -- printf("rx-vlan-strip: %s\n", (f->rx_offload & DEV_RX_OFFLOAD_VLAN_STRIP) ? "on" : "off"); -+ printf("rx-ipv4-checksum: %s\n", (f->rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) ? "on" : "off"); -+ printf("rx-tcp-checksum: %s\n", (f->rx_offload & RTE_ETH_RX_OFFLOAD_TCP_CKSUM) ? "on" : "off"); -+ printf("rx-udp-checksum: %s\n", (f->rx_offload & RTE_ETH_RX_OFFLOAD_UDP_CKSUM) ? "on" : "off"); -+ printf("rx-vlan-strip: %s\n", (f->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) ? "on" : "off"); - } - - static void gazelle_print_ltran_conn(void *buf, const struct gazelle_stat_msg_request *req_msg) -diff --git a/src/ltran/ltran_ethdev.c b/src/ltran/ltran_ethdev.c -index e2eb4a8..2fb7fab 100644 ---- a/src/ltran/ltran_ethdev.c -+++ b/src/ltran/ltran_ethdev.c -@@ -21,10 +21,15 @@ - #include - #include - #include -+#include -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -+#endif - #include - #include - -+#include -+ - #include "dpdk_common.h" - #include "ltran_param.h" - #include "ltran_log.h" -@@ -85,7 +90,11 @@ static int32_t ltran_mbuf_pool_init(void); - static int32_t ltran_single_slave_port_init(uint16_t port_num, struct rte_mempool *pktmbuf_rxpool); - static int32_t ltran_single_bond_port_init(uint16_t port_num, struct rte_mempool *pktmbuf_rxpool); - static int32_t ltran_slave_port_init(void); -+ -+ -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - static int32_t ltran_kni_init(void); -+#endif - static int32_t ltran_bond_port_init(void); - - static int32_t ltran_eal_init(void) -@@ -248,10 +257,10 @@ static int32_t ltran_single_slave_port_init(uint16_t port_num, struct rte_mempoo - } - - struct rte_eth_conf port_conf = {0}; -- port_conf.txmode.mq_mode = ETH_MQ_TX_NONE; -- port_conf.link_speeds = ETH_LINK_SPEED_AUTONEG; -+ port_conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; -+ port_conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; - eth_params_checksum(&port_conf, &dev_info); -- port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; -+ port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; - - struct ltran_config *ltran_config = get_ltran_config(); - ltran_config->dpdk.rx_offload = port_conf.rxmode.offloads; -@@ -311,7 +320,11 @@ static int32_t ltran_slave_port_init(void) - static int32_t ltran_eth_bond_slave(const struct port_info *port_info, uint16_t port_num, uint16_t bond_port_id) - { - for (uint32_t i = 0; i < port_info[port_num].num_ports; i++) { -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - int32_t ret = rte_eth_bond_slave_add(bond_port_id, port_info[port_num].id[i]); -+#else -+ int32_t ret = rte_eth_bond_member_add(bond_port_id, port_info[port_num].id[i]); -+#endif - if (ret < 0) { - return ret; - } -@@ -370,9 +383,9 @@ static int32_t ltran_bond_port_attr_set(uint16_t port_num, uint16_t bond_port_id - } - - struct rte_eth_conf port_conf = {0}; -- port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; -- port_conf.txmode.mq_mode = ETH_MQ_TX_NONE; -- port_conf.link_speeds = ETH_LINK_SPEED_AUTONEG; -+ port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; -+ port_conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; -+ port_conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; - eth_params_checksum(&port_conf, &dev_info); - - ret = rte_eth_dev_configure(bond_port_id, rx_queue_num, tx_queue_num, &port_conf); -@@ -469,6 +482,7 @@ static int32_t ltran_bond_port_init(void) - return GAZELLE_OK; - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - static int32_t ltran_kni_init(void) - { - // if not use kni. skip kni init and return -@@ -481,6 +495,7 @@ static int32_t ltran_kni_init(void) - - return dpdk_kni_init(bond_port[0], txpool[0]); - } -+#endif - - typedef int32_t (*ethdev_init_func)(void); - -@@ -492,7 +507,9 @@ static ethdev_init_func g_ltran_ethdev_init_tbl[] = { - ltran_mbuf_pool_init, - ltran_slave_port_init, - ltran_bond_port_init, -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - ltran_kni_init, -+#endif - }; - - int32_t ltran_ethdev_init(void) -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index ee379b5..a5756d7 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -13,7 +13,12 @@ - #include - #include - #include -+#include -+ -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -+#endif -+ - #include - #include - #include -@@ -195,6 +200,7 @@ static __rte_always_inline uint32_t pkt_bufs_enque_rx_ring(struct gazelle_stack - - static __rte_always_inline void flush_rx_ring(struct gazelle_stack *stack) - { -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (unlikely(stack == get_kni_stack())) { - // if fail, free mbuf inside - kni_process_tx(stack->pkt_buf, stack->pkt_cnt); -@@ -202,6 +208,7 @@ static __rte_always_inline void flush_rx_ring(struct gazelle_stack *stack) - stack->pkt_cnt = 0; - return; - } -+#endif - - /* first flush backup mbuf pointer avoid packet disorder */ - if (unlikely(stack->backup_pkt_cnt > 0)) { -@@ -414,9 +421,12 @@ static __rte_always_inline void upstream_forward_one(struct rte_mbuf *m) - } - - forward_to_kni: -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_ltran_config()->dpdk.kni_switch == GAZELLE_ON) { - enqueue_rx_packet(get_kni_stack(), m); - } -+#endif -+ return; - } - - static __rte_always_inline void msg_to_quintuple(struct gazelle_quintuple *transfer_qtuple, -@@ -653,10 +663,12 @@ void upstream_forward(const uint16_t *port) - upstream_forward_loop(port_id, queue_id); - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_ltran_config()->dpdk.kni_switch == GAZELLE_ON) { - flush_rx_ring(get_kni_stack()); - rte_kni_handle_request(get_gazelle_kni()); - } -+#endif - - now_time = get_current_time(); - if (now_time - aging_conn_last_time > GAZELLE_CONN_INTERVAL) { -@@ -755,11 +767,13 @@ int32_t downstream_forward(uint16_t *port) - uint32_t queue_num = get_ltran_config()->bond.tx_queue_num; - - while (get_ltran_stop_flag() != GAZELLE_TRUE) { -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - /* kni rx means read from kni and send to nic */ - if (get_ltran_config()->dpdk.kni_switch == GAZELLE_ON && - get_kni_started()) { - kni_process_rx(g_port_index); - } -+#endif - - for (uint32_t queue_id = 0; queue_id < queue_num; queue_id++) { - downstream_forward_loop(port_id, queue_id); -diff --git a/src/ltran/ltran_stack.c b/src/ltran/ltran_stack.c -index d4e935e..2aed6c9 100644 ---- a/src/ltran/ltran_stack.c -+++ b/src/ltran/ltran_stack.c -@@ -10,6 +10,7 @@ - * See the Mulan PSL v2 for more details. - */ - -+#include - #include - - #include "ltran_instance.h" -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 96c622e..0832c5f 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -10,6 +10,7 @@ - * See the Mulan PSL v2 for more details. - */ - -+#include - #include - #include - -diff --git a/src/ltran/main.c b/src/ltran/main.c -index c2598a7..6cc8bc9 100644 ---- a/src/ltran/main.c -+++ b/src/ltran/main.c -@@ -17,6 +17,8 @@ - #include - #include - #include -+#include -+#include - - #include "dpdk_common.h" - #include "ltran_log.h" -@@ -57,7 +59,9 @@ static void sig_default_handler(int32_t sig) - { - LTRAN_ERR("ltran dumped, caught signal: %d.\n", sig); - print_stack(); -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_kni_release(); -+#endif - int ret = 0; - ret = unlink(get_ltran_config()->unix_socket_filename); - if (ret) { -@@ -143,7 +147,9 @@ static void ltran_core_destroy(void) - gazelle_stack_htable_destroy(); - gazelle_tcp_conn_htable_destroy(); - gazelle_tcp_sock_htable_destroy(); -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_kni_release(); -+#endif - } - - static void wait_thread_finish(pthread_t ctrl_thread, uint32_t next_core) --- -2.33.0 - diff --git a/0120-modify-conf-vlan-default-vlaue.patch b/0120-modify-conf-vlan-default-vlaue.patch deleted file mode 100644 index a679ded..0000000 --- a/0120-modify-conf-vlan-default-vlaue.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 560eb7939415f3cd8b10bbc829fd57141b757727 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Fri, 19 Jan 2024 01:47:26 +0000 -Subject: [PATCH] modify conf vlan default vlaue - ---- - src/lstack/lstack.conf | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 3eb4685..ce86ec4 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -64,5 +64,5 @@ process_idx=0 - #tuple_filer=0, below cfg valid - listen_shadow=0 - --#vlan mode; only support 0~4094, 0 is disabled --nic_vlan_mode=0 -+#vlan mode; only support -1~4094, -1 is disabled -+nic_vlan_mode=-1 --- -2.33.0 - diff --git a/0121-remove-unused-variables-in-pbuf-and-reduce-mbuf-size.patch b/0121-remove-unused-variables-in-pbuf-and-reduce-mbuf-size.patch deleted file mode 100644 index 911f70c..0000000 --- a/0121-remove-unused-variables-in-pbuf-and-reduce-mbuf-size.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 2bfb7f1dcaab4436db7345d6f9fcb6f4a1d27681 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 21 Jan 2024 16:42:46 +0800 -Subject: [PATCH] remove unused variables in pbuf and reduce mbuf size - ---- - src/lstack/core/lstack_lwip.c | 10 ---------- - src/lstack/include/lstack_dpdk.h | 2 +- - src/lstack/netif/lstack_ethdev.c | 11 ----------- - 3 files changed, 1 insertion(+), 22 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 6ebe589..63044c2 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -114,14 +114,7 @@ static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, u - void *data = rte_pktmbuf_mtod(mbuf, void *); - struct pbuf *pbuf = pbuf_alloced_custom(layer, length, type, pbuf_custom, data, MAX_PACKET_SZ); - if (pbuf) { -- pbuf->ol_flags = 0; -- pbuf->l2_len = 0; -- pbuf->l3_len = 0; -- pbuf->l4_len = 0; -- pbuf->header_off = 0; -- pbuf->rexmit = 0; - pbuf->allow_in = 1; -- pbuf->head = 0; - pbuf->last = pbuf; - pbuf->addr = *IP_ANY_TYPE; - pbuf->port = 0; -@@ -290,7 +283,6 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - if (pbuf->tot_len > remain_size) { - pthread_spin_unlock(&pbuf->pbuf_lock); - *apiflags &= ~TCP_WRITE_FLAG_MORE; -- pbuf->head = 1; - return NULL; - } - if (pbuf->allow_in == 1) { -@@ -300,7 +292,6 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - } else { - if (pbuf->tot_len > remain_size) { - *apiflags &= ~TCP_WRITE_FLAG_MORE; -- pbuf->head = 1; - return NULL; - } - } -@@ -1354,7 +1345,6 @@ err_t netif_loop_output(struct netif *netif, struct pbuf *p) - LSTACK_LOG(ERR, LSTACK, "netif_loop_output: pbuf_alloc failed\n"); - return ERR_MEM; - } -- head->ol_flags = p->ol_flags; - memcpy_s(head->payload, head->len, p->payload, p->len); - - if ((flags & TCP_SYN) && !(flags & TCP_ACK)) { -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 2a44c6e..b39d199 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -21,7 +21,7 @@ - - #define KNI_NB_MBUF (DEFAULT_RING_SIZE << 4) - --#define MAX_PACKET_SZ 2048 -+#define MAX_PACKET_SZ 1530 - - #define RING_SIZE(x) ((x) - 1) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 5b0f83e..4d6f620 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -103,9 +103,6 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - } - next->tot_len = pkt_len; - pkt_len -= len; --#if CHECKSUM_CHECK_IP_HW || CHECKSUM_CHECK_TCP_HW -- next->ol_flags = m->ol_flags; --#endif - - if (head == NULL) { - head = next; -@@ -859,7 +856,6 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - struct protocol_stack *stack = get_protocol_stack(); - struct rte_mbuf *pre_mbuf = NULL; - struct rte_mbuf *first_mbuf = NULL; -- struct pbuf *first_pbuf = pbuf; - void *buf_addr; - - while (likely(pbuf != NULL)) { -@@ -867,8 +863,6 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - - mbuf->data_len = pbuf->len; - mbuf->pkt_len = pbuf->tot_len; -- mbuf->ol_flags = pbuf->ol_flags; -- mbuf->vlan_tci = pbuf->vlan_tci; - mbuf->next = NULL; - buf_addr = rte_pktmbuf_mtod(mbuf, void *); - -@@ -882,7 +876,6 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - - if (first_mbuf == NULL) { - first_mbuf = mbuf; -- first_pbuf = pbuf; - first_mbuf->nb_segs = 1; - } else { - first_mbuf->nb_segs++; -@@ -893,13 +886,9 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - mbuf->ol_flags |= RTE_MBUF_F_TX_TCP_SEG; - mbuf->tso_segsz = MBUF_MAX_DATA_LEN; - } -- mbuf->l2_len = first_pbuf->l2_len; -- mbuf->l3_len = first_pbuf->l3_len; -- mbuf->l4_len = first_pbuf->l4_len; - - pre_mbuf = mbuf; - rte_mbuf_refcnt_update(mbuf, 1); -- pbuf->rexmit = 1; - pbuf = pbuf->next; - } - --- -2.33.0 - diff --git a/0122-optimize-recv-exit-process-for-FIN-and-unsupport-SO_.patch b/0122-optimize-recv-exit-process-for-FIN-and-unsupport-SO_.patch deleted file mode 100644 index 03af162..0000000 --- a/0122-optimize-recv-exit-process-for-FIN-and-unsupport-SO_.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7499d04834da6c3774923972d927229b10189e62 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 22 Jan 2024 12:52:09 +0800 -Subject: [PATCH] optimize recv exit process for FIN and unsupport SO_RCVBUF - ---- - src/lstack/api/lstack_wrap.c | 1 + - src/lstack/core/lstack_lwip.c | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 3db62c7..372e102 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -372,6 +372,7 @@ static bool unsupport_optname(int32_t optname) - optname == SO_SNDTIMEO || - optname == SO_RCVTIMEO || - optname == SO_SNDBUF || -+ optname == SO_RCVBUF || - optname == TCP_INFO || - optname == TCP_MAXSEG || - optname == TCP_CONGESTION) { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 6ebe589..ce218f5 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1016,7 +1016,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - } 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 || (sock->conn->pcb.tcp->flags & TF_FIN)) && !NETCONN_IS_DATAIN(sock)) { -+ if (sock->errevent > 0 && !NETCONN_IS_DATAIN(sock)) { - return 0; - } - --- -2.33.0 - diff --git a/0123-remove-expand_send_ring.patch b/0123-remove-expand_send_ring.patch deleted file mode 100644 index 260061f..0000000 --- a/0123-remove-expand_send_ring.patch +++ /dev/null @@ -1,371 +0,0 @@ -From 744be87c712b7166eb921b2e7d537bea71005966 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 22 Jan 2024 17:08:42 +0800 -Subject: [PATCH] remove expand_send_ring - ---- - src/lstack/core/lstack_cfg.c | 9 -- - src/lstack/core/lstack_lwip.c | 191 ++----------------------------- - src/lstack/include/lstack_cfg.h | 1 - - src/lstack/include/lstack_lwip.h | 2 +- - src/lstack/lstack.conf | 4 - - 5 files changed, 12 insertions(+), 195 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 5e30e89..028ea26 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -66,7 +66,6 @@ static int32_t parse_nic_read_number(void); - static int32_t parse_tcp_conn_count(void); - static int32_t parse_mbuf_count_per_conn(void); - static int32_t parse_send_ring_size(void); --static int32_t parse_expand_send_ring(void); - static int32_t parse_num_process(void); - static int32_t parse_process_numa(void); - static int32_t parse_process_index(void); -@@ -130,7 +129,6 @@ static struct config_vector_t g_config_tbl[] = { - { "rpc_number", parse_rpc_number }, - { "nic_read_number", parse_nic_read_number }, - { "send_ring_size", parse_send_ring_size }, -- { "expand_send_ring", parse_expand_send_ring }, - { "num_process", parse_num_process }, - { "process_numa", parse_process_numa }, - { "process_idx", parse_process_index }, -@@ -888,13 +886,6 @@ static int32_t parse_send_ring_size(void) - return ret; - } - --static int32_t parse_expand_send_ring(void) --{ -- int32_t ret; -- PARSE_ARG(g_config_params.expand_send_ring, "expand_send_ring", 0, 0, 1, ret); -- return ret; --} -- - static int32_t parse_mbuf_count_per_conn(void) - { - int32_t ret; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 6ebe589..33b6abd 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -56,17 +56,6 @@ static void free_ring_pbuf(struct rte_ring *ring) - } while (gazelle_ring_readover_count(ring)); - } - --static void free_list_pbuf(struct pbuf *pbuf) --{ -- while (pbuf) { -- struct pbuf *del_pbuf = pbuf; -- pbuf = pbuf->next; -- -- del_pbuf->next = NULL; -- pbuf_free(del_pbuf); -- } --} -- - static void reset_sock_data(struct lwip_sock *sock) - { - /* check null pointer in ring_free func */ -@@ -82,11 +71,6 @@ static void reset_sock_data(struct lwip_sock *sock) - sock->send_ring = NULL; - } - -- if (sock->send_lastdata) { -- free_list_pbuf(sock->send_lastdata); -- sock->send_lastdata = NULL; -- } -- - if (sock->send_pre_del) { - pbuf_free(sock->send_pre_del); - sock->send_pre_del = NULL; -@@ -160,9 +144,7 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - pbuf_free(pbuf[i]); - } - -- if (!get_global_cfg_params()->expand_send_ring) { -- sem_post(&sock->snd_ring_sem); -- } -+ sem_post(&sock->snd_ring_sem); - - return false; - } -@@ -260,22 +242,6 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - } - pthread_spin_unlock(&pbuf->pbuf_lock); - -- if (pbuf->next) { -- sock->send_lastdata = pbuf->next; -- pbuf->next = NULL; -- } -- return pbuf; -- } -- -- if (sock->send_lastdata) { -- pbuf = sock->send_lastdata; -- if (pbuf->tot_len > remain_size) { -- *apiflags &= ~TCP_WRITE_FLAG_MORE; -- return NULL; -- } -- sock->send_pre_del = pbuf; -- sock->send_lastdata = pbuf->next; -- pbuf->next = NULL; - return pbuf; - } - -@@ -305,8 +271,6 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - } - } - -- sock->send_lastdata = pbuf->next; -- pbuf->next = NULL; - return pbuf; - } - -@@ -320,112 +284,25 @@ static ssize_t do_app_write(struct pbuf *pbufs[], void *buf, size_t len, uint32_ - { - ssize_t send_len = 0; - uint32_t i = 0; -- uint32_t expand_send_ring = get_global_cfg_params()->expand_send_ring; - - for (i = 0; i < write_num - 1; i++) { - rte_prefetch0(pbufs[i + 1]); - rte_prefetch0(pbufs[i + 1]->payload); - rte_prefetch0((char *)buf + send_len + MBUF_MAX_DATA_LEN); -- if (expand_send_ring) { -- pbuf_take(pbufs[i], (char *)buf + send_len, MBUF_MAX_DATA_LEN); -- } else { -- rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, MBUF_MAX_DATA_LEN); -- } -+ rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, MBUF_MAX_DATA_LEN); - pbufs[i]->tot_len = pbufs[i]->len = MBUF_MAX_DATA_LEN; - send_len += MBUF_MAX_DATA_LEN; - } - - /* reduce the branch in loop */ - uint16_t copy_len = len - send_len; -- if (expand_send_ring) { -- pbuf_take(pbufs[i], (char *)buf + send_len, copy_len); -- } else { -- rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, copy_len); -- } -+ rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, copy_len); - pbufs[i]->tot_len = pbufs[i]->len = copy_len; - send_len += copy_len; - - return send_len; - } - --static inline ssize_t app_direct_write(struct protocol_stack *stack, struct lwip_sock *sock, void *buf, -- size_t len, uint32_t write_num) --{ -- if (write_num == 0) { -- return 0; -- } -- struct pbuf **pbufs = (struct pbuf **)malloc(write_num * sizeof(struct pbuf *)); -- if (pbufs == NULL) { -- return 0; -- } -- -- /* first pbuf get from send_ring. and malloc pbufs attach to first pbuf */ -- if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)&pbufs[1], write_num - 1) != 0) { -- stack->stats.tx_allocmbuf_fail++; -- free(pbufs); -- return 0; -- } -- -- (void)gazelle_ring_read(sock->send_ring, (void **)&pbufs[0], 1); -- -- uint32_t i = 1; -- for (; i < write_num - 1; i++) { -- rte_prefetch0(mbuf_to_pbuf((void *)pbufs[i + 1])); -- pbufs[i] = init_mbuf_to_pbuf((struct rte_mbuf *)pbufs[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- pbufs[i - 1]->next = pbufs[i]; -- } -- pbufs[i] = init_mbuf_to_pbuf((struct rte_mbuf *)pbufs[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- pbufs[i - 1]->next = pbufs[i]; -- -- ssize_t send_len = do_app_write(pbufs, buf, len, write_num); -- -- gazelle_ring_read_over(sock->send_ring); -- -- pbufs[0]->last = pbufs[write_num - 1]; -- sock->remain_len = 0; -- free(pbufs); -- return send_len; --} -- --static inline ssize_t app_direct_attach(struct protocol_stack *stack, struct pbuf *attach_pbuf, void *buf, -- size_t len, uint32_t write_num) --{ -- if (write_num == 0) { -- return 0; -- } -- struct pbuf **pbufs = (struct pbuf **)malloc(write_num * sizeof(struct pbuf *)); -- if (pbufs == NULL) { -- return 0; -- } -- -- /* first pbuf get from send_ring. and malloc pbufs attach to first pbuf */ -- if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbufs, write_num) != 0) { -- stack->stats.tx_allocmbuf_fail++; -- free(pbufs); -- return 0; -- } -- -- pbufs[0] = init_mbuf_to_pbuf((struct rte_mbuf *)pbufs[0], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- uint32_t i = 1; -- for (; i < write_num - 1; i++) { -- rte_prefetch0(mbuf_to_pbuf((void *)pbufs[i + 1])); -- pbufs[i] = init_mbuf_to_pbuf((struct rte_mbuf *)pbufs[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- pbufs[i - 1]->next = pbufs[i]; -- } -- if (write_num > 1) { -- pbufs[i] = init_mbuf_to_pbuf((struct rte_mbuf *)pbufs[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- pbufs[i - 1]->next = pbufs[i]; -- } -- -- ssize_t send_len = do_app_write(pbufs, buf, len, write_num); -- -- attach_pbuf->last->next = pbufs[0]; -- attach_pbuf->last = pbufs[write_num - 1]; -- -- free(pbufs); -- return send_len; --} -- - static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t len, uint32_t write_num, - const struct sockaddr *addr, socklen_t addrlen) - { -@@ -496,12 +373,6 @@ static inline size_t merge_data_lastpbuf(struct lwip_sock *sock, void *buf, size - return 0; - } - -- if (last_pbuf->next || last_pbuf->len >= MBUF_MAX_DATA_LEN) { -- sock->remain_len = 0; -- gazelle_ring_lastover(last_pbuf); -- return 0; -- } -- - size_t send_len = MBUF_MAX_DATA_LEN - last_pbuf->len; - if (send_len >= len) { - sock->remain_len = send_len - len; -@@ -512,11 +383,7 @@ static inline size_t merge_data_lastpbuf(struct lwip_sock *sock, void *buf, size - - uint16_t offset = last_pbuf->len; - last_pbuf->tot_len = last_pbuf->len = offset + send_len; -- if (get_global_cfg_params()->expand_send_ring) { -- pbuf_take_at(last_pbuf, buf, send_len, offset); -- } else { -- rte_memcpy((char *)last_pbuf->payload + offset, buf, send_len); -- } -+ rte_memcpy((char *)last_pbuf->payload + offset, buf, send_len); - - gazelle_ring_lastover(last_pbuf); - -@@ -570,55 +437,19 @@ 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) { -- if (!get_global_cfg_params()->expand_send_ring) { -- sem_timedwait_nsecs(&sock->snd_ring_sem); -- if (likely(sock->send_ring != NULL)) { -- write_avail = gazelle_ring_readable_count(sock->send_ring); -- } -- goto END; -+ sem_timedwait_nsecs(&sock->snd_ring_sem); -+ if (likely(sock->send_ring != NULL)) { -+ write_avail = gazelle_ring_readable_count(sock->send_ring); - } -- if (unlikely(sock->send_ring == NULL)) { -- goto END; -- } -- struct pbuf *last_pbuf = gazelle_ring_readlast(sock->send_ring); -- if (last_pbuf) { -- send_len += app_direct_attach(stack, last_pbuf, (char *)buf + send_len, len - send_len, write_num); -- gazelle_ring_lastover(last_pbuf); -- if (wakeup) { -- wakeup->stat.app_write_cnt += write_num; -- } -- if (addr->sa_family == AF_INET) { -- struct sockaddr_in *saddr = (struct sockaddr_in *)addr; -- last_pbuf->addr.u_addr.ip4.addr = saddr->sin_addr.s_addr; -- last_pbuf->port = lwip_ntohs((saddr)->sin_port); -- } else if (addr->sa_family == AF_INET6) { -- struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; -- memcpy_s(last_pbuf->addr.u_addr.ip6.addr, sizeof(last_pbuf->addr.u_addr.ip6.addr), -- saddr->sin6_addr.s6_addr, sizeof(saddr->sin6_addr.s6_addr)); -- last_pbuf->port = lwip_ntohs((saddr)->sin6_port); -- } -- } else { -- (void)rpc_call_replenish(stack, sock); -- if (wakeup) { -- wakeup->stat.app_write_rpc++; -- } -- } -- sock->remain_len = 0; - goto END; - } - - /* send_ring have idle */ -- if (get_global_cfg_params()->expand_send_ring) { -- send_len += (write_num <= write_avail) ? -- app_buff_write(sock, (char *)buf + send_len, len - send_len, write_num, addr, addrlen) : -- app_direct_write(stack, sock, (char *)buf + send_len, len - send_len, write_num); -- } else { -- if (write_num > write_avail) { -- write_num = write_avail; -- len = write_num * MBUF_MAX_DATA_LEN; -- } -- send_len += app_buff_write(sock, (char *)buf + send_len, len - send_len, write_num, addr, addrlen); -+ if (write_num > write_avail) { -+ write_num = write_avail; -+ len = write_num * MBUF_MAX_DATA_LEN; - } -+ send_len += app_buff_write(sock, (char *)buf + send_len, len - send_len, write_num, addr, addrlen); - - if (wakeup) { - wakeup->stat.app_write_cnt += write_num; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index c1074f8..01d70fb 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -110,7 +110,6 @@ struct cfg_params { - struct secondary_attach_arg sec_attach_arg; - char unix_socket_filename[NAME_MAX]; - uint16_t send_ring_size; -- bool expand_send_ring; - bool tuple_filter; - int8_t bond_mode; - struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 0a82781..fa10e3f 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -18,7 +18,7 @@ - - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) - #define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || (sock->same_node_rx_ring != NULL && same_node_ring_count(sock))) --#define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_lastdata || (sock)->send_pre_del) -+#define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_pre_del) - #define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 3eb4685..7baa38d 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -24,10 +24,6 @@ mbuf_count_per_conn = 170 - # send ring size, default is 32, max is 2048 - send_ring_size = 32 - --# 0: when send ring full, send return --# 1: when send ring full, alloc mbuf from mempool to send data --expand_send_ring = 0 -- - #protocol stack thread per loop params - #read data form protocol stack into recv_ring - read_connect_number = 4 --- -2.33.0 - diff --git a/0124-set-ltran.patch b/0124-set-ltran.patch deleted file mode 100644 index c477d35..0000000 --- a/0124-set-ltran.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c565ac1ced3eba745f22cdca849c3d38aaf386f1 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Sat, 27 Jan 2024 02:22:11 +0000 -Subject: [PATCH] set ltran - ---- - src/lstack/lstack.conf | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index fc49944..60f3ee5 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -12,7 +12,7 @@ dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", - - stack_thread_mode="run-to-wakeup" - --use_ltran=1 -+use_ltran=0 - kni_switch=0 - - low_power_mode=0 --- -2.33.0 - diff --git a/0125-add-bond-doc.patch b/0125-add-bond-doc.patch deleted file mode 100644 index 6f71327..0000000 --- a/0125-add-bond-doc.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 44f8b983df75103b1bd3befbabeebe3ef406dbb1 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Sat, 27 Jan 2024 09:16:46 +0000 -Subject: [PATCH] add bond doc - ---- - src/lstack/lstack.conf | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 60f3ee5..a7f4e75 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -62,3 +62,8 @@ listen_shadow=0 - - #vlan mode; only support -1~4094, -1 is disabled - nic_vlan_mode=-1 -+ -+#bond mode; only support bond 4 or 6 mode ,-1 is disabled -+bond_mode=-1 -+#bond slave mac, separated by ; , only support 2 slave mac -+#bond_slave_mac="aa:bb:cc:dd:ee:ff;gg:hh:ii:jj:kk:ll" --- -2.33.0 - diff --git a/0126-cfg-host_addr-is-not-mandatory.patch b/0126-cfg-host_addr-is-not-mandatory.patch deleted file mode 100644 index 27a2f71..0000000 --- a/0126-cfg-host_addr-is-not-mandatory.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 1ad9802429cc2d2cf8eb90ec84cfed7d3c3d4feb Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 29 Jan 2024 15:01:05 +0800 -Subject: [PATCH] cfg: host_addr is not mandatory - ---- - src/lstack/core/lstack_cfg.c | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 028ea26..7e4482f 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -185,6 +185,10 @@ static int32_t parse_gateway_addr(void) - char *value; - bool ok; - -+ if (ip4_addr_isany_val(g_config_params.host_addr)) { -+ return 0; -+ } -+ - ok = config_lookup_string(&g_config, "gateway_addr", (const char **)&value); - if (!ok) { - return -EINVAL; -@@ -202,6 +206,10 @@ static int32_t parse_mask_addr(void) - uint32_t mask; - bool ok; - -+ if (ip4_addr_isany_val(g_config_params.host_addr)) { -+ return 0; -+ } -+ - ok = config_lookup_string(&g_config, "mask_addr", (const char **)&value); - if (!ok) { - return -EINVAL; -@@ -225,7 +233,7 @@ static int32_t parse_host_addr(void) - - ok = config_lookup_string(&g_config, "host_addr", (const char **)&value); - if (!ok) { -- return -EINVAL; -+ return 0; - } - - g_config_params.host_addr.addr = inet_addr(value); -@@ -242,7 +250,12 @@ static int32_t parse_host_addr6(void) - - ok = config_lookup_string(&g_config, "host_addr6", (const char **)&value); - if (!ok) { -- return 0; -+ if (ip4_addr_isany_val(g_config_params.host_addr)) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr and host_addr6 must have a valid one."); -+ return -EINVAL; -+ } else { -+ return 0; -+ } - } - - if (ip6addr_aton(value, &g_config_params.host_addr6) == 0) { --- -2.33.0 - diff --git a/0127-add-bond1-support.patch b/0127-add-bond1-support.patch deleted file mode 100644 index e609d70..0000000 --- a/0127-add-bond1-support.patch +++ /dev/null @@ -1,139 +0,0 @@ -From cfe5641d29e425c9da54b270b7945d17ab5d594b Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Mon, 22 Jan 2024 13:52:50 +0800 -Subject: [PATCH] add bond1 support - ---- - src/lstack/core/lstack_cfg.c | 28 ++++++++++++++++++++++++---- - src/lstack/core/lstack_dpdk.c | 24 ++++++++++++++++++++++++ - src/lstack/include/lstack_cfg.h | 1 + - 3 files changed, 49 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 7e4482f..b533a33 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -40,6 +40,8 @@ - #define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist" - #define DEV_MAC_LEN 17 - #define CPUS_MAX_NUM 256 -+#define BOND_MIIMON_MIN 1 -+#define BOND_MIIMON_MAX INT_MAX - - static struct cfg_params g_config_params; - -@@ -72,6 +74,7 @@ static int32_t parse_process_index(void); - static int32_t parse_seperate_sendrecv_args(void); - static int32_t parse_tuple_filter(void); - static int32_t parse_bond_mode(void); -+static int32_t parse_bond_miimon(void); - static int32_t parse_bond_slave_mac(void); - static int32_t parse_use_sockmap(void); - static int32_t parse_udp_enable(void); -@@ -134,6 +137,7 @@ static struct config_vector_t g_config_tbl[] = { - { "process_idx", parse_process_index }, - { "tuple_filter", parse_tuple_filter }, - { "bond_mode", parse_bond_mode }, -+ { "bond_miimon", parse_bond_miimon}, - { "bond_slave_mac", parse_bond_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, -@@ -1181,14 +1185,30 @@ static int32_t parse_bond_mode(void) - if (g_config_params.bond_mode == -1) { - return 0; - } -- if (g_config_params.bond_mode != BONDING_MODE_8023AD && g_config_params.bond_mode != BONDING_MODE_ALB) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid bond mode = %d. only supports bond mode = 4,6.\n", -- g_config_params.bond_mode); -- return -EINVAL; -+ -+ switch (g_config_params.bond_mode) { -+ case BONDING_MODE_ACTIVE_BACKUP: -+ case BONDING_MODE_8023AD: -+ case BONDING_MODE_ALB: -+ break; -+ default: -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid bond mode = %d. only supports bond mode = 1,4,6.\n", -+ g_config_params.bond_mode); -+ return -EINVAL; // Invalid bond mode - } - return 0; - } - -+static int32_t parse_bond_miimon(void) -+{ -+ int32_t ret; -+ if (g_config_params.bond_mode == -1) { -+ return 0; -+ } -+ PARSE_ARG(g_config_params.bond_miimon, "bond_miimon", 10, BOND_MIIMON_MIN, BOND_MIIMON_MAX, ret); -+ return ret; -+} -+ - static int32_t parse_bond_slave_mac(void) - { - if (g_config_params.bond_mode == -1) { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 7f1ceb8..e352850 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -462,6 +462,20 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - free(reta_conf); - } - -+int32_t dpdk_bond_primary_set(int port_id, int slave_port_id) -+{ -+ int32_t primary_port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); -+ if (slave_port_id == primary_port_id) { -+ int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret); -+ return -1; -+ } -+ return ret; -+ } -+ return 0; -+} -+ - int32_t dpdk_ethdev_init(int port_id, bool bond_port) - { - uint16_t nb_queues = get_global_cfg_params()->num_cpu; -@@ -533,6 +547,10 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - LSTACK_LOG(ERR, LSTACK, "dpdk add slave port failed ret = %d\n", ret); - return -1; - } -+ -+ if (get_global_cfg_params()->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -+ dpdk_bond_primary_set(port_id, slave_port_id[i]); -+ } - - ret = rte_eth_dev_start(slave_port_id[i]); - if (ret != 0) { -@@ -736,6 +754,12 @@ int32_t init_dpdk_ethdev(void) - } - } - -+ ret = rte_eth_bond_link_monitoring_set(bond_port_id, get_global_cfg_params()->bond_miimon); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond link monitoring failed ret = %d\n", ret); -+ return -1; -+ } -+ - ret = rte_eth_promiscuous_enable(bond_port_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk enable promiscuous failed ret = %d\n", ret); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 01d70fb..a00e47a 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -112,6 +112,7 @@ struct cfg_params { - uint16_t send_ring_size; - bool tuple_filter; - int8_t bond_mode; -+ int32_t bond_miimon; - struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; - bool use_sockmap; - bool udp_enable; --- -2.33.0 - diff --git a/0128-fix-t_params-double-free.patch b/0128-fix-t_params-double-free.patch deleted file mode 100644 index 6335292..0000000 --- a/0128-fix-t_params-double-free.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 8905d508d754a6d75516bbf26839848f4dfef282 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 29 Jan 2024 19:11:45 +0800 -Subject: [PATCH] fix t_params double free - ---- - src/lstack/core/lstack_protocol_stack.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 800872b..bb7ec17 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -660,7 +660,7 @@ int32_t stack_setup_thread(void) - for (uint32_t i = 0; i < queue_num; ++i) { - t_params[i] = malloc(sizeof(struct thread_params)); - if (t_params[i] == NULL) { -- goto OUT; -+ goto OUT1; - } - } - -@@ -669,18 +669,18 @@ int32_t stack_setup_thread(void) - if (i % 2 == 0) { - ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_RECV_THREAD_NAME, process_index, i / 2); - if (ret < 0) { -- goto OUT; -+ goto OUT1; - } - } else { - ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_SEND_THREAD_NAME, process_index, i / 2); - if (ret < 0) { -- goto OUT; -+ goto OUT1; - } - } - } else { - ret = sprintf_s(name, sizeof(name), "%s", LSTACK_THREAD_NAME); - if (ret < 0) { -- goto OUT; -+ goto OUT1; - } - } - -@@ -689,24 +689,26 @@ int32_t stack_setup_thread(void) - - ret = create_thread((void *)t_params[i], name, gazelle_stack_thread); - if (ret != 0) { -- goto OUT; -+ goto OUT1; - } - } - - /* 2: wait stack thread and kernel_event thread init finish */ - wait_sem_value(&g_stack_group.sem_stack_setup, queue_num * 2); - if (g_stack_group.stack_setup_fail) { -- goto OUT; -+ /* t_params free by stack thread */ -+ goto OUT2; - } - g_stack_group.stack_num = queue_num; - - return 0; --OUT: -+OUT1: - for (int32_t i = 0; i < queue_num; ++i) { - if (t_params[i] != NULL) { - free(t_params[i]); - } - } -+OUT2: - return -1; - } - --- -2.33.0 - diff --git a/0129-fix-receive-fin-packet-process-error.patch b/0129-fix-receive-fin-packet-process-error.patch deleted file mode 100644 index 4c8ec0e..0000000 --- a/0129-fix-receive-fin-packet-process-error.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 517d32ae3467596ca8173ff5f9300aa7d84d2b7f Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 22 Jan 2024 17:30:30 +0800 -Subject: [PATCH] fix receive fin packet process error - ---- - src/lstack/core/lstack_lwip.c | 67 +++++++++++++++++++++++------------ - 1 file changed, 45 insertions(+), 22 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index fe30edf..a7201aa 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -38,6 +38,8 @@ - #include "lstack_cfg.h" - #include "lstack_lwip.h" - -+static const uint8_t fin_packet = 0; -+ - static void free_ring_pbuf(struct rte_ring *ring) - { - void *pbufs[SOCK_RECV_RING_SIZE]; -@@ -509,13 +511,15 @@ static inline struct pbuf *pbuf_last(struct pbuf *pbuf) - ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apiflags) - { - if (sock->conn->recvmbox == NULL) { -- return 0; -+ sock->conn->pending_err = ERR_CONN; -+ GAZELLE_RETURN(ENOTCONN); - } - - free_recv_ring_readover(sock->recv_ring); - - uint32_t free_count = gazelle_ring_free_count(sock->recv_ring); - if (free_count == 0) { -+ sock->conn->pending_err = ERR_WOULDBLOCK; - GAZELLE_RETURN(EAGAIN); - } - -@@ -534,12 +538,19 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl - err = netconn_recv_tcp_pbuf_flags(sock->conn, &pbufs[i], apiflags); - } - if (err != ERR_OK) { -- if (recv_len > 0) { -- /* already received data, return that (this trusts in getting the same error from -- netconn layer again next time netconn_recv is called) */ -+ /* fin has been read from recvmbox, put it to recv_ring */ -+ if (!NETCONN_IS_UDP(sock) && -+ (netconn_is_flag_set(sock->conn, NETCONN_FIN_RX_PENDING) || err == ERR_CLSD)) { -+ /* fin has been read, lwip don't need to process fin packet */ -+ netconn_clear_flags(sock->conn, NETCONN_FIN_RX_PENDING); -+ pbufs[i] = NULL; -+ read_count++; - break; - } -- return (err == ERR_CLSD) ? 0 : -1; -+ -+ /* store err to pending_err again, clear it after app read */ -+ sock->conn->pending_err = err; -+ GAZELLE_RETURN(err_to_errno(err)); - } - - recv_len += pbufs[i]->tot_len; -@@ -551,25 +562,17 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl - } - - uint32_t enqueue_num = gazelle_ring_sp_enqueue(sock->recv_ring, (void **)pbufs, read_count); -- for (uint32_t i = enqueue_num; i < read_count; i++) { -- if (NETCONN_IS_UDP(sock)) { -- pbuf_free(pbufs[i]); -- } else { -- /* update receive window */ -- tcp_recved(sock->conn->pcb.tcp, pbufs[i]->tot_len); -- pbuf_free(pbufs[i]); -- } -- sock->stack->stats.read_lwip_drop++; -+ if (enqueue_num != read_count) { -+ LSTACK_LOG(ERR, LSTACK, "Code shouldn't get here!\n"); - } - - for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_LWIP); -+ if (pbufs[i] != NULL) { -+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_LWIP); -+ } - } - - sock->stack->stats.read_lwip_cnt += read_count; -- if (recv_len == 0) { -- GAZELLE_RETURN(EAGAIN); -- } - return recv_len; - } - -@@ -817,7 +820,8 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - bool latency_enable = get_protocol_stack_group()->latency_start; - - if (sock->errevent > 0 && !NETCONN_IS_DATAIN(sock)) { -- return 0; -+ errno = err_to_errno(netconn_err(sock->conn)); -+ return -1; - } - - thread_bind_stack(sock); -@@ -839,7 +843,8 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - 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)) { -- return 0; -+ errno = err_to_errno(netconn_err(sock->conn)); -+ return -1; - } - - lstack_block_wait(sock->wakeup); -@@ -847,6 +852,23 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - } - } - -+ /* 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; -+ } -+ -+ /* pending fin */ -+ if (unlikely(pbuf == (void *)&fin_packet)) { -+ return 0; -+ } -+ - copy_len = (recv_left > pbuf->tot_len) ? pbuf->tot_len : recv_left; - if (copy_len > UINT16_MAX) { - copy_len = UINT16_MAX; -@@ -946,10 +968,11 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - } else { - len = lwip_recv(sock->conn->socket, NULL, 0, 0); - } -- if (len == 0) { -+ if (len < 0 && errno != EAGAIN) { - sock->errevent = 1; - add_sock_event(sock, EPOLLERR); -- } else if (len > 0) { -+ /* = 0: fin */ -+ } else if (len >= 0) { - add_sock_event(sock, EPOLLIN); - } - } --- -2.33.0 - diff --git a/0130-support-netperf-UDP_STREAM-and-UDP_RR.patch b/0130-support-netperf-UDP_STREAM-and-UDP_RR.patch deleted file mode 100644 index 0d75020..0000000 --- a/0130-support-netperf-UDP_STREAM-and-UDP_RR.patch +++ /dev/null @@ -1,129 +0,0 @@ -From abbd69fdbc7b43229093a1ec57ea6d0dd952db8d Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 26 Jan 2024 17:21:38 +0800 -Subject: [PATCH] support netperf UDP_STREAM and UDP_RR - ---- - src/lstack/api/lstack_rtw_api.c | 7 +++---- - src/lstack/api/lstack_wrap.c | 1 + - src/lstack/core/lstack_lwip.c | 21 +++++++++++++++------ - 3 files changed, 19 insertions(+), 10 deletions(-) - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 04944d5..839d320 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -160,10 +160,10 @@ static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, - - while (1) { - ret = do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -- if (ret > 0) { -+ if (ret >= 0) { - return ret; - } -- if (ret <= 0 && errno != EAGAIN) { -+ if (ret < 0 && errno != EAGAIN) { - return -1; - } - sock = sock->listen_next; -@@ -205,7 +205,6 @@ ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, - return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); - } - -- - int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) - { - return lstack_rtw_epoll_wait(epfd, events, maxevents, timeout); -@@ -234,7 +233,7 @@ int rtw_shutdown(int fd, int how) - { - struct lwip_sock *sock = get_socket_by_fd(fd); - if (sock && sock->wakeup && sock->wakeup->epollfd == fd) { -- GAZELLE_RETURN(ENOTSOCK); -+ GAZELLE_RETURN(ENOTSOCK); - } - - return stack_broadcast_shutdown(fd, how); -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 372e102..8992e39 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -375,6 +375,7 @@ static bool unsupport_optname(int32_t optname) - optname == SO_RCVBUF || - optname == TCP_INFO || - optname == TCP_MAXSEG || -+ optname == SO_DONTROUTE || - optname == TCP_CONGESTION) { - return true; - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a7201aa..22605dd 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -402,7 +402,7 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - } - - struct protocol_stack *stack = sock->stack; -- if (!stack || len == 0) { -+ if (!stack) { - return 0; - } - -@@ -421,6 +421,11 @@ 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); -@@ -454,7 +459,7 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - } - - END: -- if (send_len == 0) { -+ if (send_len == 0 && !NETCONN_IS_UDP(sock)) { - errno = EAGAIN; - return -1; - } -@@ -735,19 +740,18 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - GAZELLE_RETURN(EINVAL); - } - -- if (len == 0) { -+ struct lwip_sock *sock = get_socket_by_fd(fd); -+ if (len == 0 && !NETCONN_IS_UDP(sock)) { - return 0; - } - -- struct lwip_sock *sock = get_socket_by_fd(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) { -+ if (send < 0 || (send == 0 && !NETCONN_IS_UDP(sock))) { - return send; - } - -@@ -852,6 +856,11 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - } - } - -+ /* if udp recv a packet whose len is 0, return 0 */ -+ if (NETCONN_IS_UDP(sock) && pbuf->tot_len == 0) { -+ return 0; -+ } -+ - /* fin */ - if (unlikely(pbuf == NULL)) { - if (recvd > 0) { --- -2.33.0 - diff --git a/0131-adapt-lwip-2.2.0.patch b/0131-adapt-lwip-2.2.0.patch deleted file mode 100644 index dbbe0ea..0000000 --- a/0131-adapt-lwip-2.2.0.patch +++ /dev/null @@ -1,131 +0,0 @@ -From feaa11fb77f6134639885c378d87903fc2301331 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 6 Feb 2024 09:55:23 +0800 -Subject: [PATCH] adapt lwip-2.2.0 - ---- - src/lstack/api/lstack_rtw_api.c | 2 +- - src/lstack/core/lstack_lwip.c | 16 ++++++++-------- - src/lstack/core/lstack_protocol_stack.c | 8 ++++---- - 3 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 839d320..10bc613 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -168,7 +168,7 @@ static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, - } - sock = sock->listen_next; - if (sock != NULL && sock->conn != NULL) { -- sockfd = sock->conn->socket; -+ sockfd = sock->conn->callback_arg.socket; - } else { - if (sock == NULL) { - errno = EAGAIN; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 22605dd..2ba18e2 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -973,9 +973,9 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - - ssize_t len = 0; - if (NETCONN_IS_UDP(sock)) { -- len = lwip_recv(sock->conn->socket, NULL, SSIZE_MAX, 0); -+ len = lwip_recv(sock->conn->callback_arg.socket, NULL, SSIZE_MAX, 0); - } else { -- len = lwip_recv(sock->conn->socket, NULL, 0, 0); -+ len = lwip_recv(sock->conn->callback_arg.socket, NULL, 0, 0); - } - if (len < 0 && errno != EAGAIN) { - sock->errevent = 1; -@@ -993,7 +993,7 @@ void do_lwip_connected_callback(struct netconn *conn) - return; - } - -- int32_t fd = conn->socket; -+ int32_t fd = conn->callback_arg.socket; - struct lwip_sock *sock = get_socket_by_fd(fd); - if (sock == NULL || sock->conn == NULL) { - return; -@@ -1033,9 +1033,9 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->keep_cnt = pcb->keep_cnt; - - if (netconn != NULL) { -- conn->fd = netconn->socket; -+ conn->fd = netconn->callback_arg.socket; - conn->recv_cnt = (netconn->recvmbox == NULL) ? 0 : rte_ring_count(netconn->recvmbox->ring); -- struct lwip_sock *sock = get_socket(netconn->socket); -+ struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); - if (sock != NULL) { - conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); - conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; -@@ -1121,7 +1121,7 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - conn[conn_num].l_port = pcbl->local_port; - conn[conn_num].tcp_sub_state = pcbl->state; - struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -- conn[conn_num].fd = netconn != NULL ? netconn->socket : -1; -+ conn[conn_num].fd = netconn != NULL ? netconn->callback_arg.socket : -1; - if (netconn != NULL && netconn->acceptmbox != NULL) { - conn[conn_num].recv_cnt = rte_ring_count(netconn->acceptmbox->ring); - } -@@ -1319,7 +1319,7 @@ err_t same_node_ring_create(struct rte_ring **ring, int size, int port, char *na - static void init_same_node_ring(struct tcp_pcb *pcb) - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = get_socket(netconn->socket); -+ struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); - - pcb->client_rx_ring = NULL; - pcb->client_tx_ring = NULL; -@@ -1334,7 +1334,7 @@ static void init_same_node_ring(struct tcp_pcb *pcb) - err_t create_same_node_ring(struct tcp_pcb *pcb) - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = get_socket(netconn->socket); -+ struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); - - if (same_node_ring_create(&pcb->client_rx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "rx") != 0) { - goto END; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 9e2197c..8b99e82 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -903,7 +903,7 @@ void stack_send(struct rpc_msg *msg) - return; - } - -- replenish_again = do_lwip_send(stack, sock->conn->socket, sock, len, 0); -+ replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); - if (replenish_again < 0) { - __sync_fetch_and_sub(&sock->call_num, 1); - return; -@@ -1102,7 +1102,7 @@ int32_t stack_broadcast_close(int32_t fd) - if (sock == NULL || sock->conn == NULL) { - break; - } -- fd = sock->conn->socket; -+ fd = sock->conn->callback_arg.socket; - } while (sock); - - return ret; -@@ -1125,7 +1125,7 @@ int stack_broadcast_shutdown(int fd, int how) - if (sock == NULL || sock->conn == NULL) { - break; - } -- fd = sock->conn->socket; -+ fd = sock->conn->callback_arg.socket; - } while (sock); - - return ret; -@@ -1290,7 +1290,7 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - } - - if (min_sock && min_sock->conn) { -- ret = rpc_call_accept(min_sock->conn->socket, addr, addrlen, flags); -+ ret = rpc_call_accept(min_sock->conn->callback_arg.socket, addr, addrlen, flags); - } - - if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) { --- -2.33.0 - diff --git a/0132-add-observable-method-of-data-aggregation.patch b/0132-add-observable-method-of-data-aggregation.patch deleted file mode 100644 index b46fc91..0000000 --- a/0132-add-observable-method-of-data-aggregation.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 36d2ddc58cd0f467d6d7682689cc10947a8a1973 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Tue, 6 Feb 2024 11:29:26 +0800 -Subject: [PATCH] add observable method of data aggregation - ---- - src/common/gazelle_dfx_msg.h | 2 ++ - src/lstack/core/lstack_lwip.c | 2 ++ - src/ltran/ltran_dfx.c | 4 +++- - 3 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index d465efa..1ca210b 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -73,6 +73,8 @@ struct gazelle_stack_stat { - uint64_t tx; - uint64_t tx_prepare_fail; - uint64_t accept_fail; -+ uint64_t sock_rx_drop; -+ uint64_t sock_tx_merge; - }; - - struct gazelle_wakeup_stat { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 63044c2..4523907 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -541,6 +541,7 @@ static ssize_t do_lwip_fill_sendring(struct lwip_sock *sock, const void *buf, si - - /* merge data into last pbuf */ - if (!NETCONN_IS_UDP(sock) && sock->remain_len) { -+ sock->stack->stats.sock_tx_merge++; - send_len = merge_data_lastpbuf(sock, (char *)buf, len); - if (send_len >= len) { - send_len = len; -@@ -1039,6 +1040,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - - /* 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; - } - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 4b246a1..9f12096 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -648,7 +648,9 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("send_pkts_fail: %-13"PRIu64" ", lstack_stat->data.pkts.stack_stat.send_pkts_fail); - printf("mbuf_pool_freecnt: %-10"PRIu32" ", lstack_stat->data.pkts.mbufpool_avail_cnt); - printf("rpc_pool_freecnt: %-12"PRIu32" \n", lstack_stat->data.pkts.rpcpool_avail_cnt); -- printf("accpet_fail: %-12"PRIu64" \n", lstack_stat->data.pkts.stack_stat.accept_fail); -+ printf("accpet_fail: %-16"PRIu64" ", lstack_stat->data.pkts.stack_stat.accept_fail); -+ printf("sock_rx_drop: %-15"PRIu64" ", lstack_stat->data.pkts.stack_stat.sock_rx_drop); -+ printf("sock_tx_merge: %-16"PRIu64" \n", lstack_stat->data.pkts.stack_stat.sock_tx_merge); - } - - static void gazelle_print_lstack_stat_detail(struct gazelle_stack_dfx_data *lstack_stat, --- -2.27.0 - diff --git a/0133-try-to-ensure-arp-packet-can-be-sent.patch b/0133-try-to-ensure-arp-packet-can-be-sent.patch deleted file mode 100644 index ef48dd5..0000000 --- a/0133-try-to-ensure-arp-packet-can-be-sent.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 1a7bb2f60a459c2cca6646ccbe04a52fcd8272f6 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 31 Jan 2024 14:49:40 +0800 -Subject: [PATCH] try to ensure arp packet can be sent - ---- - src/lstack/core/lstack_dpdk.c | 18 ++++++++++-------- - src/lstack/core/lstack_lwip.c | 13 ++++++++++--- - src/lstack/core/lstack_protocol_stack.c | 4 ++-- - src/lstack/include/lstack_dpdk.h | 2 +- - src/lstack/include/lstack_protocol_stack.h | 2 +- - src/lstack/netif/lstack_ethdev.c | 8 ++++---- - src/lstack/netif/lstack_vdev.c | 2 +- - 7 files changed, 29 insertions(+), 20 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index e352850..74e033b 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -280,14 +280,16 @@ int32_t create_shared_ring(struct protocol_stack *stack) - return 0; - } - --int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num) -+int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve) - { -- /* -- * don't use rte_mempool_avail_count, it traverse cpu local cache, -- * when RTE_MAX_LCORE is too large, it's time-consuming -- */ -- if (rte_ring_count(pool->pool_data) < MBUFPOOL_RESERVE_NUM + num) { -- return -ENOMEM; -+ if (reserve) { -+ /* -+ * don't use rte_mempool_avail_count, it traverse cpu local cache, -+ * when RTE_MAX_LCORE is too large, it's time-consuming -+ */ -+ if (rte_ring_count(pool->pool_data) < MBUFPOOL_RESERVE_NUM + num) { -+ return -ENOMEM; -+ } - } - - int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); -@@ -310,7 +312,7 @@ int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, ui - while (remain > 0) { - batch = LWIP_MIN(remain, RING_SIZE(FREE_RX_QUEUE_SZ)); - -- ret = dpdk_alloc_pktmbuf(mempool, free_buf, batch); -+ ret = dpdk_alloc_pktmbuf(mempool, free_buf, batch, true); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "cannot alloc mbuf for ring, count: %u ret=%d\n", batch, ret); - return -1; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 3f76424..da50fec 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -101,7 +102,6 @@ static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, u - struct pbuf *pbuf = pbuf_alloced_custom(layer, length, type, pbuf_custom, data, MAX_PACKET_SZ); - if (pbuf) { - pbuf->allow_in = 1; -- pbuf->last = pbuf; - pbuf->addr = *IP_ANY_TYPE; - pbuf->port = 0; - pthread_spin_init(&pbuf->pbuf_lock, PTHREAD_PROCESS_SHARED); -@@ -122,7 +122,7 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - return false; - } - -- if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt) != 0) { -+ if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt, true) != 0) { - stack->stats.tx_allocmbuf_fail++; - return true; - } -@@ -209,10 +209,17 @@ void do_lwip_free_pbuf(struct pbuf *pbuf) - - struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type) - { -+ int ret; - struct rte_mbuf *mbuf; - struct protocol_stack *stack = get_protocol_stack(); - -- if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1) != 0) { -+ /* ensure arp packet can be sent */ -+ if (layer == PBUF_LINK && length == SIZEOF_ETHARP_HDR) { -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1, false); -+ } else { -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1, true); -+ } -+ if (ret != 0) { - stack->stats.tx_allocmbuf_fail++; - return NULL; - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 8b99e82..cb39928 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -940,7 +940,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - continue; - } - -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - if (ret != 0) { - stack->stats.rx_allocmbuf_fail++; - return; -@@ -952,7 +952,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - } -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - if (ret != 0) { - cur_stack->stats.rx_allocmbuf_fail++; - return; -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index b39d199..c40f3c0 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -56,6 +56,6 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); - - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); --int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num); -+int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve); - void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index c681547..0a523b7 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -31,7 +31,7 @@ - #define SOCK_SEND_REPLENISH_THRES (16) - #define WAKEUP_MAX_NUM (32) - --#define MBUFPOOL_RESERVE_NUM 5000 -+#define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->nic.rxqueue_size + 1024) - - struct rte_mempool; - struct rte_ring; -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 4d6f620..acf3c10 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -543,9 +543,9 @@ void parse_arp_and_transefer(char* buf) - int32_t ret; - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - stack->stats.rx_allocmbuf_fail++; - } - copy_mbuf(mbuf_copy, mbuf); -@@ -572,9 +572,9 @@ void parse_tcp_and_transefer(char* buf) - struct rte_mbuf *mbuf_copy = NULL; - struct protocol_stack *stack = stack_group->stacks[stk_index]; - -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1); -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - stack->stats.rx_allocmbuf_fail++; - } - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index fe17f59..f78e48a 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -59,7 +59,7 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - stack->rx_ring_used += rcvd_pkts; - if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) { - uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(DPDK_PKT_BURST_SIZE)); -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)free_buf, free_cnt); -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)free_buf, free_cnt, true); - if (likely(ret == 0)) { - nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt); - stack->rx_ring_used -= nr_pkts; --- -2.27.0 - diff --git a/0134-gazellectl-support-send-latency-show.patch b/0134-gazellectl-support-send-latency-show.patch deleted file mode 100644 index 5950ca7..0000000 --- a/0134-gazellectl-support-send-latency-show.patch +++ /dev/null @@ -1,345 +0,0 @@ -From 03eabf12b7d486278598ad44d2b7d8e310ff0abf Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Sun, 4 Feb 2024 13:29:15 +0800 -Subject: [PATCH] gazellectl: support send latency show - ---- - src/common/dpdk_common.h | 10 +++ - src/common/gazelle_dfx_msg.h | 20 ++++- - src/lstack/core/lstack_lwip.c | 14 +++- - src/lstack/core/lstack_stack_stat.c | 15 ++-- - src/lstack/netif/lstack_ethdev.c | 4 + - src/ltran/ltran_dfx.c | 110 +++++++++++++++------------- - 6 files changed, 111 insertions(+), 62 deletions(-) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index 38f09ae..a79a0f2 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -95,6 +95,16 @@ static __rte_always_inline void time_stamp_into_mbuf(uint32_t rx_count, struct r - } - } - -+static __rte_always_inline void time_stamp_into_pbuf(uint32_t tx_count, struct pbuf *buf[], uint64_t time_stamp) -+{ -+ struct latency_timestamp *lt; -+ for (uint32_t i = 0; i < tx_count; i++) { -+ lt = &pbuf_to_private(buf[i])->lt; -+ lt->stamp = time_stamp; -+ lt->check = ~(time_stamp); -+ } -+} -+ - bool get_kni_started(void); - struct rte_kni* get_gazelle_kni(void); - int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool); -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index d465efa..d47ed9a 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -24,6 +24,10 @@ - /* maybe it should be consistent with MEMP_NUM_TCP_PCB */ - #define GAZELLE_LSTACK_MAX_CONN (20000 + 2000) // same as MAX_CLIENTS + RESERVED_CLIENTS in lwipopts.h - -+#define GAZELLE_RESULT_LEN 4096 -+#define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins -+#define GAZELLE_RESULT_LINE_LEN 80 // for a single row, the max len of result is 80 -+ - enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LTRAN_SHOW = 0, - GAZELLE_STAT_LTRAN_SHOW_RATE, -@@ -54,8 +58,11 @@ enum GAZELLE_STAT_MODE { - }; - - enum GAZELLE_LATENCY_TYPE { -- GAZELLE_LATENCY_LWIP, -- GAZELLE_LATENCY_READ, -+ GAZELLE_LATENCY_READ_LWIP, -+ GAZELLE_LATENCY_READ_LSTACK, -+ GAZELLE_LATENCY_WRITE_LWIP, -+ GAZELLE_LATENCY_WRITE_LSTACK, -+ GAZELLE_LATENCY_MAX, - }; - - struct gazelle_stack_stat { -@@ -216,9 +223,14 @@ struct stack_latency { - uint64_t latency_total; - }; - -+struct gazelle_latency_result { -+ int latency_stat_index; -+ struct stack_latency latency_stat_record; -+ char latency_stat_result[GAZELLE_RESULT_LEN]; -+}; -+ - struct gazelle_stack_latency { -- struct stack_latency read_latency; -- struct stack_latency lwip_latency; -+ struct stack_latency latency[GAZELLE_LATENCY_MAX]; - uint64_t start_time; - uint64_t g_cycles_per_us; - }; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 22605dd..be2c6de 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -244,6 +244,11 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - if (pbuf == NULL) { - return NULL; - } -+ -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP); -+ } -+ - sock->send_pre_del = pbuf; - - if (!gazelle_ring_readover_count(sock->send_ring)) { -@@ -303,6 +308,11 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - - (void)gazelle_ring_read(sock->send_ring, (void **)pbufs, write_num); - -+ if (get_protocol_stack_group()->latency_start) { -+ uint64_t time_stamp = get_current_time(); -+ time_stamp_into_pbuf(write_num, pbufs, time_stamp); -+ } -+ - ssize_t send_len = do_app_write(pbufs, buf, len, write_num); - - if (addr) { -@@ -573,7 +583,7 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl - - for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) { - if (pbufs[i] != NULL) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_LWIP); -+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP); - } - } - -@@ -895,7 +905,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - sock->wakeup->stat.app_read_cnt += 1; - } - if (latency_enable) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ); -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK); - } - gazelle_ring_read_over(sock->recv_ring); - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 23571b4..cb11dc3 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -53,8 +53,9 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - { - uint64_t latency; - const struct latency_timestamp *lt; -+ struct stack_latency *latency_stat; - -- if (pbuf == NULL) { -+ if (pbuf == NULL || type >= GAZELLE_LATENCY_MAX) { - return; - } - -@@ -62,10 +63,9 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time) { - return; - } -- latency = get_current_time() - lt->stamp; - -- struct stack_latency *latency_stat = (type == GAZELLE_LATENCY_LWIP) ? -- &stack_latency->lwip_latency : &stack_latency->read_latency; -+ latency = get_current_time() - lt->stamp; -+ latency_stat = &stack_latency->latency[type]; - - latency_stat->latency_total += latency; - latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency; -@@ -118,8 +118,11 @@ static void set_latency_start_flag(bool start) - LSTACK_LOG(ERR, LSTACK, "memset_s faile\n"); - } - stack->latency.start_time = get_current_time(); -- stack->latency.lwip_latency.latency_min = ~((uint64_t)0); -- stack->latency.read_latency.latency_min = ~((uint64_t)0); -+ -+ for (uint32_t j = 0; j < GAZELLE_LATENCY_MAX; j++) { -+ stack->latency.latency[j].latency_min = ~((uint64_t)0); -+ } -+ - memset_s(&stack->aggregate_stats, sizeof(struct gazelle_stack_aggregate_stats), - 0, sizeof(stack->aggregate_stats)); - } -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 4d6f620..94ecffc 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -889,6 +889,10 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - - pre_mbuf = mbuf; - rte_mbuf_refcnt_update(mbuf, 1); -+ -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LSTACK); -+ } - pbuf = pbuf->next; - } - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 4b246a1..ecdb5f9 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -50,9 +50,6 @@ - #define GAZELLE_CMD_MAX 5 - #define CMD_WAIT_TIME 1 // sec - --#define GAZELLE_RESULT_LEN 8291 --#define GAZELLE_MAX_LATENCY_TIME 1800 // max latency time 30mins -- - #define GAZELLE_DECIMAL 10 - #define GAZELLE_KEEPALIVE_STR_LEN 35 - #define GAZELLE_TIME_STR_LEN 25 -@@ -702,8 +699,8 @@ static void parse_thread_latency_result(const struct stack_latency *latency, cha - { - if (latency->latency_pkts > 0) { - *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_pkts); -- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", latency->latency_min); -- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", latency->latency_max); -+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_min); -+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", latency->latency_max); - *pos += sprintf_s(result + *pos, max_len, "%-6.2f \n", - (double)latency->latency_total / latency->latency_pkts); - } else { -@@ -719,52 +716,53 @@ static void parse_thread_latency_result(const struct stack_latency *latency, cha - static void parse_latency_total_result(char *result, size_t max_len, int32_t *pos, - const struct stack_latency *record) - { -+ if (max_len < GAZELLE_RESULT_LINE_LEN) { -+ printf("total latency result show failed, out of memory bounds\n"); -+ return; -+ } -+ - if (record->latency_pkts > 0) { -- *pos += sprintf_s(result + *pos, max_len, " total: "); -+ *pos += sprintf_s(result + *pos, max_len, " total: "); - *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_pkts); -- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", record->latency_min); -- *pos += sprintf_s(result + *pos, max_len, "%-6"PRIu64" ", record->latency_max); -- *pos += sprintf_s(result + *pos, max_len, "%-6.2f \n\n\n", -+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_min); -+ *pos += sprintf_s(result + *pos, max_len, "%-8"PRIu64" ", record->latency_max); -+ *pos += sprintf_s(result + *pos, max_len, "%-6.2f \n\n", - (double)record->latency_total / record->latency_pkts); - } else { -- *pos += sprintf_s(result + *pos, max_len, " total: 0\n\n\n"); -+ *pos += sprintf_s(result + *pos, max_len, " total: 0\n\n"); - } - } - --static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg) -+static void gazelle_show_latency_result(const struct gazelle_stat_msg_request *req_msg, -+ struct gazelle_stack_dfx_data *stat, struct stack_latency *latency, -+ struct gazelle_latency_result *res) - { -- struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -- struct gazelle_stack_latency *latency = &stat->data.latency; -- int32_t ret = GAZELLE_OK; -- int32_t lwip_index = 0; -- int32_t read_index = 0; -- struct stack_latency lwip_record = {0}; -- struct stack_latency read_record = {0}; -- char str_ip[GAZELLE_SUBNET_LENGTH_MAX] = {0}; -+ char str_ip[GAZELLE_SUBNET_LENGTH_MAX] = { 0 }; - -- read_record.latency_min = ~((uint64_t)0); -- lwip_record.latency_min = ~((uint64_t)0); -- -- char *lwip_result = calloc(GAZELLE_RESULT_LEN, sizeof(char)); -- if (lwip_result == NULL) { -- return; -- } -- char *read_result = calloc(GAZELLE_RESULT_LEN, sizeof(char)); -- if (read_result == NULL) { -- free(lwip_result); -+ if (GAZELLE_RESULT_LEN - res->latency_stat_index < GAZELLE_RESULT_LINE_LEN) { -+ printf("too many threads show latency result, out of memory bounds\n"); - return; - } - -- do { -- lwip_index += sprintf_s(lwip_result + lwip_index, (size_t)(GAZELLE_RESULT_LEN - lwip_index), -- "ip: %-15s tid: %-8u ", inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid); -- parse_thread_latency_result(&latency->lwip_latency, lwip_result, (size_t)(GAZELLE_RESULT_LEN - lwip_index), -- &lwip_index, &lwip_record); -+ res->latency_stat_index += sprintf_s(res->latency_stat_result + res->latency_stat_index, -+ (size_t)(GAZELLE_RESULT_LEN - res->latency_stat_index), "ip: %-15s tid: %-8u ", -+ inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid); - -- read_index += sprintf_s(read_result + read_index, (size_t)(GAZELLE_RESULT_LEN - read_index), -- "ip: %-15s tid: %-8u ", inet_ntop(AF_INET, &req_msg->ip, str_ip, sizeof(str_ip)), stat->tid); -- parse_thread_latency_result(&latency->read_latency, read_result, (size_t)(GAZELLE_RESULT_LEN - read_index), -- &read_index, &read_record); -+ parse_thread_latency_result(latency, res->latency_stat_result, -+ (size_t)(GAZELLE_RESULT_LEN - res->latency_stat_index), &res->latency_stat_index, &res->latency_stat_record); -+} -+ -+static void gazelle_show_latency_result_total(void *buf, const struct gazelle_stat_msg_request *req_msg, -+ struct gazelle_latency_result *res) -+{ -+ int ret = GAZELLE_OK; -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct gazelle_stack_latency *latency = &stat->data.latency; -+ -+ do { -+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) { -+ gazelle_show_latency_result(req_msg, stat, &latency->latency[i], &res[i]); -+ } - - if ((stat->eof != 0) || (ret != GAZELLE_OK)) { - break; -@@ -772,21 +770,33 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st - ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); - } while (true); - -- parse_latency_total_result(lwip_result, (size_t)(GAZELLE_RESULT_LEN - lwip_index), &lwip_index, &lwip_record); -- parse_latency_total_result(read_result, (size_t)(GAZELLE_RESULT_LEN - read_index), &read_index, &read_record); -+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) { -+ parse_latency_total_result(res[i].latency_stat_result, (size_t)(GAZELLE_RESULT_LEN - res[i].latency_stat_index), -+ &res[i].latency_stat_index, &res[i].latency_stat_record); -+ } -+} -+ -+static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ struct gazelle_latency_result *res = calloc(GAZELLE_LATENCY_MAX, sizeof(struct gazelle_latency_result)); -+ if (res == NULL) { -+ return; -+ } -+ -+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) { -+ res[i].latency_stat_record.latency_min = ~((uint64_t)0); -+ } - -- printf("Statistics of lstack latency: t0--->t3 \ -- (t0:read form nic t1:into lstask queue t2:into app queue t3:app read)\n"); -- printf(" pkts min(us) max(us) average(us)\n%s", -- read_result); -+ gazelle_show_latency_result_total(buf, req_msg, res); - -- printf("Statistics of lstack latency: t0--->t2 \ -- (t0:read form nic t1:into lstask queue t2:into app queue t3:app read)\n"); -- printf(" pkts min(us) max(us) average(us)\n%s", -- lwip_result); -+ printf("Statistics of lstack latency pkts min(us) max(us) average(us)\n"); -+ printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -+ printf("range: t0--->t2\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -+ printf("range: t3--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LSTACK].latency_stat_result); -+ printf("range: t2--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LWIP].latency_stat_result); -+ printf("t0:read form/send to nic t1:into/out of lstask queue t2:into/out of app queue t3:app read/send\n"); - -- free(read_result); -- free(lwip_result); -+ free(res); - } - - static void gazelle_print_lstack_stat_lpm(void *buf, const struct gazelle_stat_msg_request *req_msg) --- -2.27.0 - diff --git a/0135-rpc-function-does-not-depend-on-protocol-stack.patch b/0135-rpc-function-does-not-depend-on-protocol-stack.patch deleted file mode 100644 index 1ca8ca5..0000000 --- a/0135-rpc-function-does-not-depend-on-protocol-stack.patch +++ /dev/null @@ -1,1336 +0,0 @@ -From fe39b43f897be7d29f9b51e79d51395e43b83e23 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 4 Feb 2024 19:46:17 +0800 -Subject: [PATCH] rpc function does not depend on protocol stack diff rpc queue - and dfx rpc queue - ---- - src/common/gazelle_dfx_msg.h | 1 - - src/lstack/api/lstack_rtw_api.c | 36 ++- - src/lstack/core/lstack_control_plane.c | 10 +- - src/lstack/core/lstack_dpdk.c | 4 +- - src/lstack/core/lstack_lwip.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 92 ++++---- - src/lstack/core/lstack_stack_stat.c | 18 +- - src/lstack/core/lstack_thread_rpc.c | 241 ++++++++------------- - src/lstack/include/lstack_control_plane.h | 3 - - src/lstack/include/lstack_protocol_stack.h | 36 +-- - src/lstack/include/lstack_rpc_proc.h | 46 ++++ - src/lstack/include/lstack_thread_rpc.h | 79 +++---- - src/lstack/netif/lstack_ethdev.c | 6 +- - src/ltran/ltran_dfx.c | 3 +- - 14 files changed, 292 insertions(+), 285 deletions(-) - create mode 100644 src/lstack/include/lstack_rpc_proc.h - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 1ca210b..a91a30f 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -101,7 +101,6 @@ struct gazelle_stack_aggregate_stats { - struct gazelle_stat_pkts { - uint16_t conn_num; - uint32_t mbufpool_avail_cnt; -- uint32_t rpcpool_avail_cnt; - uint64_t call_msg_cnt; - uint64_t recv_list_cnt; - uint64_t call_alloc_fail; -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 10bc613..8498b8e 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -28,7 +28,11 @@ - - int rtw_socket(int domain, int type, int protocol) - { -- return rpc_call_socket(domain, type, protocol); -+ struct protocol_stack *stack = get_bind_protocol_stack(); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ return rpc_call_socket(&stack->rpc_queue, domain, type, protocol); - } - - int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -@@ -64,27 +68,47 @@ int rtw_listen(int s, int backlog) - - int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) - { -- return rpc_call_connect(s, name, namelen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(s); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_connect(&stack->rpc_queue, s, name, namelen); - } - - int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) - { -- return rpc_call_setsockopt(s, level, optname, optval, optlen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(s); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_setsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - - int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) - { -- return rpc_call_getsockopt(s, level, optname, optval, optlen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(s); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - - int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) - { -- return rpc_call_getpeername(s, name, namelen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(s); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getpeername(&stack->rpc_queue, s, name, namelen); - } - - int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) - { -- return rpc_call_getsockname(s, name, namelen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(s); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getsockname(&stack->rpc_queue, s, name, namelen); - } - - ssize_t rtw_read(int s, void *mem, size_t len) -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index a9a3814..025291d 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -611,9 +611,10 @@ static int32_t thread_register(void) - /* register all connected conn before listen conn, avoid creating new conn */ - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - for (int32_t i = 0; i < stack_group->stack_num; i++) { -- conn->conn_num = rpc_call_conntable(stack_group->stacks[i], conn->conn_list, GAZELLE_LSTACK_MAX_CONN); -+ conn->conn_num = rpc_call_conntable(&stack_group->stacks[i]->rpc_queue, -+ conn->conn_list, GAZELLE_LSTACK_MAX_CONN); - -- ret = rpc_call_thread_regphase1(stack_group->stacks[i], conn); -+ ret = rpc_call_thread_regphase1(&stack_group->stacks[i]->rpc_queue, conn); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "thread_register_phase1 failed ret=%d!\n", ret); - free(conn); -@@ -622,9 +623,10 @@ static int32_t thread_register(void) - } - - for (int32_t i = 0; i < stack_group->stack_num; i++) { -- conn->conn_num = rpc_call_conntable(stack_group->stacks[i], conn->conn_list, GAZELLE_LSTACK_MAX_CONN); -+ conn->conn_num = rpc_call_conntable(&stack_group->stacks[i]->rpc_queue, -+ conn->conn_list, GAZELLE_LSTACK_MAX_CONN); - -- ret = rpc_call_thread_regphase2(stack_group->stacks[i], conn); -+ ret = rpc_call_thread_regphase2(&stack_group->stacks[i]->rpc_queue, conn); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "thread_register_phase2 failed ret=%d!\n", ret); - free(conn); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index e352850..985f1a5 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -45,7 +45,6 @@ - - #include "lstack_log.h" - #include "dpdk_common.h" --#include "lstack_lockless_queue.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" - #include "lstack_lwip.h" -@@ -258,7 +257,8 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si - - int32_t create_shared_ring(struct protocol_stack *stack) - { -- lockless_queue_init(&stack->rpc_queue); -+ rpc_queue_init(&stack->rpc_queue); -+ rpc_queue_init(&stack->dfx_rpc_queue); - - if (use_ltran()) { - stack->rx_ring = gazelle_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 3f76424..b79cdef 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -636,7 +636,7 @@ static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t - { - // 2: call_num >= 2, don't need add new rpc send - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) < 2) { -- while (rpc_call_send(fd, NULL, len, flags) < 0) { -+ while (rpc_call_send(&sock->stack->rpc_queue, fd, NULL, len, flags) < 0) { - usleep(1000); // 1000: wait 1ms to exec again - } - __sync_fetch_and_add(&sock->call_num, 1); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 8b99e82..f63fcb0 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -465,7 +465,10 @@ int stack_polling(uint32_t wakeup_tick) - uint32_t read_connect_number = cfg->read_connect_number; - struct protocol_stack *stack = get_protocol_stack(); - -- force_quit = poll_rpc_msg(stack, rpc_number); -+ /* 2: one dfx consumes two rpc */ -+ rpc_poll_msg(&stack->dfx_rpc_queue, 2); -+ force_quit = rpc_poll_msg(&stack->rpc_queue, rpc_number); -+ - gazelle_eth_dev_poll(stack, use_ltran_flag, nic_read_number); - sys_timer_run(); - if (cfg->low_power_mod != 0) { -@@ -715,7 +718,7 @@ OUT2: - void stack_arp(struct rpc_msg *msg) - { - struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; -- struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_1].p; -+ struct protocol_stack *stack = get_protocol_stack(); - - eth_dev_recv(mbuf, stack); - } -@@ -893,7 +896,7 @@ void stack_send(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; - size_t len = msg->args[MSG_ARG_1].size; -- struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_3].p; -+ struct protocol_stack *stack = get_protocol_stack(); - int replenish_again; - - struct lwip_sock *sock = get_socket(fd); -@@ -947,7 +950,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - } - copy_mbuf(mbuf_copy, mbuf); - -- ret = rpc_call_arp(stack, mbuf_copy); -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); - if (ret != 0) { - return; - } -@@ -971,7 +974,7 @@ void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup) - - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- rpc_call_clean_epoll(stack, wakeup); -+ rpc_call_clean_epoll(&stack->rpc_queue, wakeup); - } - } - -@@ -985,17 +988,11 @@ void stack_clean_epoll(struct rpc_msg *msg) - - void stack_mempool_size(struct rpc_msg *msg) - { -- struct protocol_stack *stack = (struct protocol_stack*)msg->args[MSG_ARG_0].p; -+ struct protocol_stack *stack = get_protocol_stack(); - - msg->result = rte_mempool_avail_count(stack->rxtx_mbuf_pool); - } - --void stack_rpcpool_size(struct rpc_msg *msg) --{ -- struct rpc_msg_pool *rpc_mem_pool = (struct rpc_msg_pool*)msg->args[MSG_ARG_0].p; -- msg->result = rte_mempool_avail_count(rpc_mem_pool->mempool); --} -- - void stack_create_shadow_fd(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; -@@ -1049,8 +1046,8 @@ void stack_create_shadow_fd(struct rpc_msg *msg) - - void stack_replenish_sendring(struct rpc_msg *msg) - { -- struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_0].p; -- struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_1].p; -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p; - - msg->result = do_lwip_replenish_sendring(stack, sock); - } -@@ -1070,7 +1067,7 @@ void stack_get_connnum(struct rpc_msg *msg) - - void stack_recvlist_count(struct rpc_msg *msg) - { -- struct protocol_stack *stack = (struct protocol_stack *)msg->args[MSG_ARG_0].p; -+ struct protocol_stack *stack = get_protocol_stack(); - struct list_node *list = &stack->recv_list; - uint32_t count = 0; - struct list_node *node; -@@ -1086,16 +1083,16 @@ void stack_recvlist_count(struct rpc_msg *msg) - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ - int32_t stack_broadcast_close(int32_t fd) - { -- struct lwip_sock *sock = get_socket(fd); - int32_t ret = 0; -- -+ struct lwip_sock *sock = get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { -- return -1; -+ GAZELLE_RETURN(EBADF); - } - - do { - sock = sock->listen_next; -- if (rpc_call_close(fd)) { -+ if (stack == NULL || rpc_call_close(&stack->rpc_queue, fd)) { - ret = -1; - } - -@@ -1103,7 +1100,8 @@ int32_t stack_broadcast_close(int32_t fd) - break; - } - fd = sock->conn->callback_arg.socket; -- } while (sock); -+ stack = get_protocol_stack_by_fd(fd); -+ } while (1); - - return ret; - } -@@ -1112,13 +1110,14 @@ int stack_broadcast_shutdown(int fd, int how) - { - int32_t ret = 0; - struct lwip_sock *sock = get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { -- return -1; -+ GAZELLE_RETURN(EBADF); - } - - do { - sock = sock->listen_next; -- if (rpc_call_shutdown(fd, how)) { -+ if (stack == NULL || rpc_call_shutdown(&stack->rpc_queue, fd, how)) { - ret = -1; - } - -@@ -1126,7 +1125,8 @@ int stack_broadcast_shutdown(int fd, int how) - break; - } - fd = sock->conn->callback_arg.socket; -- } while (sock); -+ stack = get_protocol_stack_by_fd(fd); -+ } while (1); - - return ret; - } -@@ -1134,7 +1134,11 @@ int stack_broadcast_shutdown(int fd, int how) - /* choice one stack listen */ - int32_t stack_single_listen(int32_t fd, int32_t backlog) - { -- return rpc_call_listen(fd, backlog); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_listen(&stack->rpc_queue, fd, backlog); - } - - /* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ -@@ -1153,12 +1157,12 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - int32_t ret, clone_fd; - - struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null\n", get_stack_tid(), fd); -- GAZELLE_RETURN(EINVAL); -+ if (sock == NULL || cur_stack == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ GAZELLE_RETURN(EBADF); - } - -- ret = rpc_call_getsockname(fd, (struct sockaddr *)&addr, &addr_len); -+ ret = rpc_call_getsockname(&cur_stack->rpc_queue, fd, (struct sockaddr *)&addr, &addr_len); - if (ret != 0) { - return ret; - } -@@ -1172,7 +1176,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - continue; - } - if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(stack, fd, (struct sockaddr *)&addr, addr_len); -+ clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, (struct sockaddr *)&addr, addr_len); - if (clone_fd < 0) { - stack_broadcast_close(fd); - return clone_fd; -@@ -1187,7 +1191,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - get_socket_by_fd(clone_fd)->conn->is_master_fd = 0; - } - -- ret = rpc_call_listen(clone_fd, backlog); -+ ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); - if (ret < 0) { - stack_broadcast_close(fd); - return ret; -@@ -1234,7 +1238,11 @@ static void inline del_accept_in_event(struct lwip_sock *sock) - /* choice one stack bind */ - int32_t stack_single_bind(int32_t fd, const struct sockaddr *name, socklen_t namelen) - { -- return rpc_call_bind(fd, name, namelen); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_bind(&stack->rpc_queue, fd, name, namelen); - } - - /* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ -@@ -1245,12 +1253,12 @@ int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t - int32_t ret, clone_fd; - - struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null\n", get_stack_tid(), fd); -- GAZELLE_RETURN(EINVAL); -+ if (sock == NULL || cur_stack == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ GAZELLE_RETURN(EBADF); - } - -- ret = rpc_call_bind(fd, name, namelen); -+ ret = rpc_call_bind(&cur_stack->rpc_queue, fd, name, namelen); - if (ret < 0) { - close(fd); - return ret; -@@ -1260,7 +1268,7 @@ int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t - for (int32_t i = 0; i < stack_group->stack_num; ++i) { - stack = stack_group->stacks[i]; - if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(stack, fd, name, namelen); -+ clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, name, namelen); - if (clone_fd < 0) { - stack_broadcast_close(fd); - return clone_fd; -@@ -1276,9 +1284,9 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - int32_t ret = -1; - struct lwip_sock *min_sock = NULL; - struct lwip_sock *sock = get_socket(fd); -+ struct protocol_stack *stack = NULL; - if (sock == NULL) { -- errno = EINVAL; -- return -1; -+ GAZELLE_RETURN(EBADF); - } - - if (netconn_is_nonblocking(sock->conn)) { -@@ -1290,7 +1298,11 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - } - - if (min_sock && min_sock->conn) { -- ret = rpc_call_accept(min_sock->conn->callback_arg.socket, addr, addrlen, flags); -+ stack = get_protocol_stack_by_fd(min_sock->conn->callback_arg.socket); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); - } - - if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) { -@@ -1344,7 +1356,7 @@ void stack_group_exit(void) - } - - if (stack != stack_group->stacks[i]) { -- rpc_call_stack_exit(stack_group->stacks[i]); -+ rpc_call_stack_exit(&stack_group->stacks[i]->rpc_queue); - } - } - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 23571b4..01ac6fb 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -175,20 +175,17 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - - get_wakeup_stat(stack_group, stack, &dfx->data.pkts.wakeup_stat); - -- dfx->data.pkts.call_alloc_fail = stack_group->call_alloc_fail; -+ dfx->data.pkts.call_alloc_fail = rpc_stats_get()->call_alloc_fail; - -- int32_t rpc_call_result = rpc_call_msgcnt(stack); -+ int32_t rpc_call_result = rpc_msgcnt(&stack->rpc_queue); - dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_mbufpoolsize(stack); -+ rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); - dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_recvlistcnt(stack); -+ rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); - dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_rpcpool_size(stack); -- dfx->data.pkts.rpcpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -- - dfx->data.pkts.conn_num = stack->conn_num; - } - -@@ -219,9 +216,10 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - } - break; - case GAZELLE_STAT_LSTACK_SHOW_CONN: -- rpc_call_result = rpc_call_conntable(stack, dfx->data.conn.conn_list, GAZELLE_LSTACK_MAX_CONN); -+ rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, -+ GAZELLE_LSTACK_MAX_CONN); - dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -- rpc_call_result = rpc_call_connnum(stack); -+ rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); - dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; - break; - case GAZELLE_STAT_LSTACK_SHOW_LATENCY: -@@ -296,7 +294,7 @@ int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) - } - - dfx.tid = stack->tid; -- dfx.stack_id = i; -+ dfx.stack_id = i; - if (i == stack_group->stack_num - 1) { - dfx.eof = 1; - } -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 2af30d7..1fdb037 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -9,21 +9,20 @@ - * PURPOSE. - * See the Mulan PSL v2 for more details. - */ --#include --#include - #include --#include - #include - - #include "lstack_log.h" --#include "lstack_lwip.h" --#include "lstack_protocol_stack.h" --#include "lstack_control_plane.h" --#include "gazelle_base_func.h" - #include "lstack_dpdk.h" -+#include "lstack_rpc_proc.h" - #include "lstack_thread_rpc.h" - - static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; -+static struct rpc_stats g_rpc_stats; -+struct rpc_stats *rpc_stats_get(void) -+{ -+ return &g_rpc_stats; -+} - - static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) - { -@@ -37,33 +36,29 @@ static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct - return msg; - } - --static struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func func) -+static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - { - struct rpc_msg *msg = NULL; - -- if (stack == NULL) { -- return NULL; -- } -- - if (g_rpc_pool == NULL) { - g_rpc_pool = calloc(1, sizeof(struct rpc_msg_pool)); - if (g_rpc_pool == NULL) { - LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); -- get_protocol_stack_group()->call_alloc_fail++; -+ g_rpc_stats.call_alloc_fail++; - return NULL; - } - - g_rpc_pool->mempool = create_mempool("rpc_pool", RPC_MSG_MAX, sizeof(struct rpc_msg), - 0, rte_gettid()); - if (g_rpc_pool->mempool == NULL) { -- get_protocol_stack_group()->call_alloc_fail++; -+ g_rpc_stats.call_alloc_fail++; - return NULL; - } - } - - msg = get_rpc_msg(g_rpc_pool); - if (msg == NULL) { -- get_protocol_stack_group()->call_alloc_fail++; -+ g_rpc_stats.call_alloc_fail++; - return NULL; - } - msg->rpcpool = g_rpc_pool; -@@ -75,7 +70,7 @@ static struct rpc_msg *rpc_msg_alloc(struct protocol_stack *stack, rpc_msg_func - return msg; - } - --static inline __attribute__((always_inline)) int32_t rpc_sync_call(lockless_queue *queue, struct rpc_msg *msg) -+static inline __attribute__((always_inline)) int32_t rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - { - int32_t ret; - -@@ -90,13 +85,18 @@ static inline __attribute__((always_inline)) int32_t rpc_sync_call(lockless_queu - return ret; - } - --int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) -+int32_t rpc_msgcnt(rpc_queue *queue) -+{ -+ return lockless_queue_count(queue); -+} -+ -+int rpc_poll_msg(rpc_queue *queue, uint32_t max_num) - { - int force_quit = 0; - struct rpc_msg *msg = NULL; - - while (max_num--) { -- lockless_queue_node *node = lockless_queue_mpsc_pop(&stack->rpc_queue); -+ lockless_queue_node *node = lockless_queue_mpsc_pop(queue); - if (node == NULL) { - break; - } -@@ -106,7 +106,7 @@ int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - if (msg->func) { - msg->func(msg); - } else { -- stack->stats.call_null++; -+ g_rpc_stats.call_null++; - } - - if (msg->func == stack_exit_by_rpc) { -@@ -127,9 +127,9 @@ int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num) - return force_quit; - } - --int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint32_t max_conn) -+int32_t rpc_call_conntable(rpc_queue *queue, void *conn_table, uint32_t max_conn) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_get_conntable); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_get_conntable); - if (msg == NULL) { - return -1; - } -@@ -137,22 +137,22 @@ int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint3 - msg->args[MSG_ARG_0].p = conn_table; - msg->args[MSG_ARG_1].u = max_conn; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_connnum(struct protocol_stack *stack) -+int32_t rpc_call_connnum(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_get_connnum); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_get_connnum); - if (msg == NULL) { - return -1; - } - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) -+int32_t rpc_call_shadow_fd(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_create_shadow_fd); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_create_shadow_fd); - if (msg == NULL) { - return -1; - } -@@ -161,100 +161,67 @@ int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struc - msg->args[MSG_ARG_1].cp = addr; - msg->args[MSG_ARG_2].socklen = addrlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); --} -- --static void rpc_msgcnt(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- msg->result = lockless_queue_count(&stack->rpc_queue); --} -- --int32_t rpc_call_msgcnt(struct protocol_stack *stack) --{ -- struct rpc_msg *msg = rpc_msg_alloc(stack, rpc_msgcnt); -- if (msg == NULL) { -- return -1; -- } -- -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_thread_regphase1(struct protocol_stack *stack, void *conn) -+int32_t rpc_call_thread_regphase1(rpc_queue *queue, void *conn) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, thread_register_phase1); -+ struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase1); - if (msg == NULL) { - return -1; - } - msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_thread_regphase2(struct protocol_stack *stack, void *conn) -+int32_t rpc_call_thread_regphase2(rpc_queue *queue, void *conn) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, thread_register_phase2); -+ struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase2); - if (msg == NULL) { - return -1; - } - msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_mbufpoolsize(struct protocol_stack *stack) -+int32_t rpc_call_mbufpoolsize(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_mempool_size); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_mempool_size); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].p = stack; -- -- return rpc_sync_call(&stack->rpc_queue, msg); --} -- --int32_t rpc_call_rpcpool_size(struct protocol_stack *stack) --{ -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_rpcpool_size); -- if (msg == NULL) { -- return -1; -- } -- msg->args[MSG_ARG_0].p = g_rpc_pool; -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_recvlistcnt(struct protocol_stack *stack) -+int32_t rpc_call_recvlistcnt(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_recvlist_count); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_recvlist_count); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].p = stack; -- -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf) -+int32_t rpc_call_arp(rpc_queue *queue, void *mbuf) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_arp); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_arp); - if (msg == NULL) { - return -1; - } - - msg->sync_flag = 0; - msg->args[MSG_ARG_0].p = mbuf; -- msg->args[MSG_ARG_1].p = stack; - -- rpc_call(&stack->rpc_queue, msg); -+ rpc_call(queue, msg); - - return 0; - } - --int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol) -+int32_t rpc_call_socket(rpc_queue *queue, int32_t domain, int32_t type, int32_t protocol) - { -- struct protocol_stack *stack = get_bind_protocol_stack(); -- -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_socket); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_socket); - if (msg == NULL) { - return -1; - } -@@ -263,39 +230,35 @@ int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol) - msg->args[MSG_ARG_1].i = type; - msg->args[MSG_ARG_2].i = protocol; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_close(int fd) -+int32_t rpc_call_close(rpc_queue *queue, int fd) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_close); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_close); - if (msg == NULL) { - return -1; - } - - msg->args[MSG_ARG_0].i = fd; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_stack_exit(struct protocol_stack *stack) -+int32_t rpc_call_stack_exit(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_exit_by_rpc); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_exit_by_rpc); - if (msg == NULL) { -- LSTACK_LOG(INFO, LSTACK, "rpc msg alloc failed\n"); - return -1; - } - -- rpc_call(&stack->rpc_queue, msg); -+ rpc_call(queue, msg); - return 0; - } - --int32_t rpc_call_shutdown(int fd, int how) -+int32_t rpc_call_shutdown(rpc_queue *queue, int fd, int how) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_shutdown); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_shutdown); - if (msg == NULL) { - return -1; - } -@@ -303,25 +266,24 @@ int32_t rpc_call_shutdown(int fd, int how) - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].i = how; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --void rpc_call_clean_epoll(struct protocol_stack *stack, struct wakeup_poll *wakeup) -+void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_clean_epoll); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_clean_epoll); - if (msg == NULL) { - return; - } - - msg->args[MSG_ARG_0].p = wakeup; - -- rpc_sync_call(&stack->rpc_queue, msg); -+ rpc_sync_call(queue, msg); - } - --int32_t rpc_call_bind(int32_t fd, const struct sockaddr *addr, socklen_t addrlen) -+int32_t rpc_call_bind(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_bind); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_bind); - if (msg == NULL) { - return -1; - } -@@ -330,13 +292,12 @@ int32_t rpc_call_bind(int32_t fd, const struct sockaddr *addr, socklen_t addrlen - msg->args[MSG_ARG_1].cp = addr; - msg->args[MSG_ARG_2].socklen = addrlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_listen(int s, int backlog) -+int32_t rpc_call_listen(rpc_queue *queue, int s, int backlog) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_listen); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_listen); - if (msg == NULL) { - return -1; - } -@@ -344,13 +305,12 @@ int32_t rpc_call_listen(int s, int backlog) - msg->args[MSG_ARG_0].i = s; - msg->args[MSG_ARG_1].i = backlog; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -+int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_accept); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_accept); - if (msg == NULL) { - return -1; - } -@@ -360,13 +320,12 @@ int32_t rpc_call_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int f - msg->args[MSG_ARG_2].p = addrlen; - msg->args[MSG_ARG_3].i = flags; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) -+int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_connect); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_connect); - if (msg == NULL) { - return -1; - } -@@ -375,7 +334,7 @@ int32_t rpc_call_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) - msg->args[MSG_ARG_1].cp = addr; - msg->args[MSG_ARG_2].socklen = addrlen; - -- int32_t ret = rpc_sync_call(&stack->rpc_queue, msg); -+ int32_t ret = rpc_sync_call(queue, msg); - if (ret < 0) { - errno = -ret; - return -1; -@@ -383,10 +342,9 @@ int32_t rpc_call_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) - return ret; - } - --int32_t rpc_call_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) -+int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_getpeername); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_getpeername); - if (msg == NULL) { - return -1; - } -@@ -395,13 +353,12 @@ int32_t rpc_call_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen) - msg->args[MSG_ARG_1].p = addr; - msg->args[MSG_ARG_2].p = addrlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) -+int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_getsockname); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_getsockname); - if (msg == NULL) { - return -1; - } -@@ -410,13 +367,12 @@ int32_t rpc_call_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen) - msg->args[MSG_ARG_1].p = addr; - msg->args[MSG_ARG_2].p = addrlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen) -+int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_getsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_getsockopt); - if (msg == NULL) { - return -1; - } -@@ -427,13 +383,12 @@ int32_t rpc_call_getsockopt(int fd, int level, int optname, void *optval, sockle - msg->args[MSG_ARG_3].p = optval; - msg->args[MSG_ARG_4].p = optlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) -+int32_t rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_setsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_setsockopt); - if (msg == NULL) { - return -1; - } -@@ -444,13 +399,12 @@ int32_t rpc_call_setsockopt(int fd, int level, int optname, const void *optval, - msg->args[MSG_ARG_3].cp = optval; - msg->args[MSG_ARG_4].socklen = optlen; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_fcntl(int fd, int cmd, long val) -+int32_t rpc_call_fcntl(rpc_queue *queue, int fd, int cmd, long val) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_fcntl); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_fcntl); - if (msg == NULL) { - return -1; - } -@@ -459,13 +413,12 @@ int32_t rpc_call_fcntl(int fd, int cmd, long val) - msg->args[MSG_ARG_1].i = cmd; - msg->args[MSG_ARG_2].l = val; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_ioctl(int fd, long cmd, void *argp) -+int32_t rpc_call_ioctl(rpc_queue *queue, int fd, long cmd, void *argp) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_ioctl); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_ioctl); - if (msg == NULL) { - return -1; - } -@@ -474,27 +427,24 @@ int32_t rpc_call_ioctl(int fd, long cmd, void *argp) - msg->args[MSG_ARG_1].l = cmd; - msg->args[MSG_ARG_2].p = argp; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_replenish(struct protocol_stack *stack, struct lwip_sock *sock) -+int32_t rpc_call_replenish(rpc_queue *queue, void *sock) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_replenish_sendring); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_replenish_sendring); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].p = stack; -- msg->args[MSG_ARG_1].p = sock; -+ msg->args[MSG_ARG_0].p = sock; - -- return rpc_sync_call(&stack->rpc_queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_send(int fd, const void *buf, size_t len, int flags) -+int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int flags) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- -- struct rpc_msg *msg = rpc_msg_alloc(stack, stack_send); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_send); - if (msg == NULL) { - return -1; - } -@@ -502,10 +452,9 @@ int32_t rpc_call_send(int fd, const void *buf, size_t len, int flags) - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].size = len; - msg->args[MSG_ARG_2].i = flags; -- msg->args[MSG_ARG_3].p = stack; - msg->sync_flag = 0; - -- rpc_call(&stack->rpc_queue, msg); -+ rpc_call(queue, msg); - - return 0; - } -diff --git a/src/lstack/include/lstack_control_plane.h b/src/lstack/include/lstack_control_plane.h -index aed5443..548d725 100644 ---- a/src/lstack/include/lstack_control_plane.h -+++ b/src/lstack/include/lstack_control_plane.h -@@ -23,14 +23,11 @@ enum vdev_request { - VDEV_NONE, - }; - --struct rpc_msg; - int client_reg_thrd_ring(void); - int32_t control_init_client(bool is_reconnect); - void control_client_thread(void *arg); - void control_server_thread(void *arg); - bool get_register_state(void); --void thread_register_phase1(struct rpc_msg *msg); --void thread_register_phase2(struct rpc_msg *msg); - void control_fd_close(void); - void delete_primary_path(void); - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index c681547..7489f2a 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -21,7 +21,7 @@ - #include - - #include "gazelle_dfx_msg.h" --#include "lstack_lockless_queue.h" -+#include "lstack_thread_rpc.h" - #include "lstack_ethdev.h" - #include "gazelle_opt.h" - -@@ -59,13 +59,15 @@ struct protocol_stack { - volatile bool low_power; - bool is_send_thread; - -- lockless_queue rpc_queue __rte_cache_aligned; -- char pad __rte_cache_aligned; -+ char pad1 __rte_cache_aligned; -+ rpc_queue dfx_rpc_queue; -+ rpc_queue rpc_queue; -+ char pad2 __rte_cache_aligned; - - /* kernel event thread read/write frequently */ - struct epoll_event kernel_events[KERNEL_EPOLL_MAX]; - int32_t kernel_event_num; -- char pad1 __rte_cache_aligned; -+ char pad3 __rte_cache_aligned; - - struct netif netif; - struct lstack_dev_ops dev_ops; -@@ -149,36 +151,10 @@ void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup); - - void stack_send_pkts(struct protocol_stack *stack); - --struct rpc_msg; - struct thread_params { - uint16_t queue_id; - uint16_t idx; - }; --void stack_clean_epoll(struct rpc_msg *msg); --void stack_arp(struct rpc_msg *msg); --void stack_socket(struct rpc_msg *msg); --void stack_close(struct rpc_msg *msg); --void stack_shutdown(struct rpc_msg *msg); --void stack_bind(struct rpc_msg *msg); --void stack_listen(struct rpc_msg *msg); --void stack_accept(struct rpc_msg *msg); --void stack_connect(struct rpc_msg *msg); --void stack_recv(struct rpc_msg *msg); --void stack_getpeername(struct rpc_msg *msg); --void stack_getsockname(struct rpc_msg *msg); --void stack_getsockopt(struct rpc_msg *msg); --void stack_setsockopt(struct rpc_msg *msg); --void stack_fcntl(struct rpc_msg *msg); --void stack_ioctl(struct rpc_msg *msg); --void stack_send(struct rpc_msg *msg); --void stack_mempool_size(struct rpc_msg *msg); --void stack_rpcpool_size(struct rpc_msg *msg); --void stack_create_shadow_fd(struct rpc_msg *msg); --void stack_replenish_sendring(struct rpc_msg *msg); --void stack_get_conntable(struct rpc_msg *msg); --void stack_get_connnum(struct rpc_msg *msg); --void stack_recvlist_count(struct rpc_msg *msg); --void stack_exit_by_rpc(struct rpc_msg *msg); - - int stack_polling(uint32_t wakeup_tick); - #endif -diff --git a/src/lstack/include/lstack_rpc_proc.h b/src/lstack/include/lstack_rpc_proc.h -new file mode 100644 -index 0000000..71f0c58 ---- /dev/null -+++ b/src/lstack/include/lstack_rpc_proc.h -@@ -0,0 +1,46 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __GAZELLE_RPC_PROC_H__ -+#define __GAZELLE_RPC_PROC_H__ -+#include "lstack_thread_rpc.h" -+ -+void stack_clean_epoll(struct rpc_msg *msg); -+void stack_arp(struct rpc_msg *msg); -+void stack_socket(struct rpc_msg *msg); -+void stack_close(struct rpc_msg *msg); -+void stack_shutdown(struct rpc_msg *msg); -+void stack_bind(struct rpc_msg *msg); -+void stack_listen(struct rpc_msg *msg); -+void stack_accept(struct rpc_msg *msg); -+void stack_connect(struct rpc_msg *msg); -+void stack_recv(struct rpc_msg *msg); -+void stack_getpeername(struct rpc_msg *msg); -+void stack_getsockname(struct rpc_msg *msg); -+void stack_getsockopt(struct rpc_msg *msg); -+void stack_setsockopt(struct rpc_msg *msg); -+void stack_fcntl(struct rpc_msg *msg); -+void stack_ioctl(struct rpc_msg *msg); -+void stack_send(struct rpc_msg *msg); -+void stack_mempool_size(struct rpc_msg *msg); -+void stack_rpcpool_size(struct rpc_msg *msg); -+void stack_create_shadow_fd(struct rpc_msg *msg); -+void stack_replenish_sendring(struct rpc_msg *msg); -+void stack_get_conntable(struct rpc_msg *msg); -+void stack_get_connnum(struct rpc_msg *msg); -+void stack_recvlist_count(struct rpc_msg *msg); -+void stack_exit_by_rpc(struct rpc_msg *msg); -+ -+void thread_register_phase1(struct rpc_msg *msg); -+void thread_register_phase2(struct rpc_msg *msg); -+ -+#endif -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 633ef93..30caa66 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -28,6 +28,12 @@ - - #define RPC_MSG_MAX 4096 - #define RPC_MSG_MASK (RPC_MSG_MAX - 1) -+typedef struct lockless_queue rpc_queue; -+ -+struct rpc_stats { -+ uint16_t call_null; -+ uint64_t call_alloc_fail; -+}; - - struct rpc_msg; - typedef void (*rpc_msg_func)(struct rpc_msg *msg); -@@ -41,7 +47,9 @@ union rpc_msg_arg { - socklen_t socklen; - size_t size; - }; --struct rpc_msg_pool; -+struct rpc_msg_pool { -+ struct rte_mempool *mempool; -+}; - struct rpc_msg { - pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */ - int8_t sync_flag : 1; -@@ -54,44 +62,41 @@ struct rpc_msg { - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ - }; - --struct rpc_msg_pool { -- struct rte_mempool *mempool; --}; -+static inline void rpc_queue_init(rpc_queue *queue) -+{ -+ lockless_queue_init(queue); -+} - --struct protocol_stack; --struct rte_mbuf; --struct wakeup_poll; --struct lwip_sock; --int poll_rpc_msg(struct protocol_stack *stack, uint32_t max_num); --void rpc_call_clean_epoll(struct protocol_stack *stack, struct wakeup_poll *wakeup); --int32_t rpc_call_msgcnt(struct protocol_stack *stack); --int32_t rpc_call_shadow_fd(struct protocol_stack *stack, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_recvlistcnt(struct protocol_stack *stack); --int32_t rpc_call_thread_regphase1(struct protocol_stack *stack, void *conn); --int32_t rpc_call_thread_regphase2(struct protocol_stack *stack, void *conn); --int32_t rpc_call_conntable(struct protocol_stack *stack, void *conn_table, uint32_t max_conn); --int32_t rpc_call_connnum(struct protocol_stack *stack); --int32_t rpc_call_arp(struct protocol_stack *stack, struct rte_mbuf *mbuf); --int32_t rpc_call_socket(int32_t domain, int32_t type, int32_t protocol); --int32_t rpc_call_close(int32_t fd); --int32_t rpc_call_shutdown(int fd, int how); --int32_t rpc_call_bind(int32_t fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_listen(int s, int backlog); --int32_t rpc_call_accept(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); --int32_t rpc_call_connect(int fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_send(int fd, const void *buf, size_t len, int flags); --int32_t rpc_call_getpeername(int fd, struct sockaddr *addr, socklen_t *addrlen); --int32_t rpc_call_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen); --int32_t rpc_call_getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlen); --int32_t rpc_call_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen); --int32_t rpc_call_fcntl(int fd, int cmd, long val); --int32_t rpc_call_ioctl(int fd, long cmd, void *argp); --int32_t rpc_call_replenish(struct protocol_stack *stack, struct lwip_sock *sock); --int32_t rpc_call_mbufpoolsize(struct protocol_stack *stack); --int32_t rpc_call_rpcpool_size(struct protocol_stack *stack); --int32_t rpc_call_stack_exit(struct protocol_stack *stack); -+struct rpc_stats *rpc_stats_get(void); -+int32_t rpc_msgcnt(rpc_queue *queue); -+int rpc_poll_msg(rpc_queue *queue, uint32_t max_num); -+void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup); -+int32_t rpc_call_shadow_fd(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); -+int32_t rpc_call_recvlistcnt(rpc_queue *queue); -+int32_t rpc_call_thread_regphase1(rpc_queue *queue, void *conn); -+int32_t rpc_call_thread_regphase2(rpc_queue *queue, void *conn); -+int32_t rpc_call_conntable(rpc_queue *queue, void *conn_table, uint32_t max_conn); -+int32_t rpc_call_connnum(rpc_queue *queue); -+int32_t rpc_call_arp(rpc_queue *queue, void *mbuf); -+int32_t rpc_call_socket(rpc_queue *queue, int32_t domain, int32_t type, int32_t protocol); -+int32_t rpc_call_close(rpc_queue *queue, int32_t fd); -+int32_t rpc_call_shutdown(rpc_queue *queue, int fd, int how); -+int32_t rpc_call_bind(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); -+int32_t rpc_call_listen(rpc_queue *queue, int s, int backlog); -+int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); -+int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); -+int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int flags); -+int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); -+int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); -+int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen); -+int32_t rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen); -+int32_t rpc_call_fcntl(rpc_queue *queue, int fd, int cmd, long val); -+int32_t rpc_call_ioctl(rpc_queue *queue, int fd, long cmd, void *argp); -+int32_t rpc_call_replenish(rpc_queue *queue, void *sock); -+int32_t rpc_call_mbufpoolsize(rpc_queue *queue); -+int32_t rpc_call_stack_exit(rpc_queue *queue); - --static inline __attribute__((always_inline)) void rpc_call(lockless_queue *queue, struct rpc_msg *msg) -+static inline __attribute__((always_inline)) void rpc_call(rpc_queue *queue, struct rpc_msg *msg) - { - lockless_queue_mpsc_push(queue, &msg->queue_node); - } -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 4d6f620..965de58 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -529,7 +529,7 @@ void transfer_tcp_to_thread(struct rte_mbuf *mbuf, uint16_t stk_idx) - struct protocol_stack *stack = get_protocol_stack_group()->stacks[stk_idx]; - int ret = -1; - while(ret != 0) { -- ret = rpc_call_arp(stack, mbuf); -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf); - printf("transfer_tcp_to_thread, ret : %d \n", ret); - } - } -@@ -550,10 +550,10 @@ void parse_arp_and_transefer(char* buf) - } - copy_mbuf(mbuf_copy, mbuf); - -- ret = rpc_call_arp(stack, mbuf_copy); -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); - - while (ret != 0) { -- rpc_call_arp(stack, mbuf_copy);; -+ rpc_call_arp(&stack->rpc_queue, mbuf_copy); - } - } - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 9f12096..bea0dc7 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -646,8 +646,7 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("call_alloc_fail: %-12"PRIu64" ", lstack_stat->data.pkts.call_alloc_fail); - printf("call_null: %-18"PRIu64" \n", lstack_stat->data.pkts.stack_stat.call_null); - printf("send_pkts_fail: %-13"PRIu64" ", lstack_stat->data.pkts.stack_stat.send_pkts_fail); -- printf("mbuf_pool_freecnt: %-10"PRIu32" ", lstack_stat->data.pkts.mbufpool_avail_cnt); -- printf("rpc_pool_freecnt: %-12"PRIu32" \n", lstack_stat->data.pkts.rpcpool_avail_cnt); -+ printf("mbuf_pool_freecnt: %-10"PRIu32" \n", lstack_stat->data.pkts.mbufpool_avail_cnt); - printf("accpet_fail: %-16"PRIu64" ", lstack_stat->data.pkts.stack_stat.accept_fail); - printf("sock_rx_drop: %-15"PRIu64" ", lstack_stat->data.pkts.stack_stat.sock_rx_drop); - printf("sock_tx_merge: %-16"PRIu64" \n", lstack_stat->data.pkts.stack_stat.sock_tx_merge); --- -2.27.0 - diff --git a/0136-readv-return-1-errno-is-EAGAIN-when-recvring-no-data.patch b/0136-readv-return-1-errno-is-EAGAIN-when-recvring-no-data.patch deleted file mode 100644 index 0d311c8..0000000 --- a/0136-readv-return-1-errno-is-EAGAIN-when-recvring-no-data.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 61888e1e0d4810d3f0dbe5aa1d43a2dbcf2ad0f5 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 21 Feb 2024 07:44:59 +0800 -Subject: [PATCH] readv return -1, errno is EAGAIN when recvring no data - ---- - src/lstack/api/lstack_rtw_api.c | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 8498b8e..e50fe37 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -127,12 +127,7 @@ ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; -- ssize_t result = do_lwip_recvmsg_from_stack(s, &msg, 0); -- if (result == -1 && errno == EAGAIN) { -- errno = 0; -- return 0; -- } -- return result; -+ return do_lwip_recvmsg_from_stack(s, &msg, 0); - } - - ssize_t rtw_write(int s, const void *mem, size_t size) --- -2.27.0 - diff --git a/0137-split-the-flow-fules-related-functions-into-separate.patch b/0137-split-the-flow-fules-related-functions-into-separate.patch deleted file mode 100644 index 1bf499d..0000000 --- a/0137-split-the-flow-fules-related-functions-into-separate.patch +++ /dev/null @@ -1,1707 +0,0 @@ -From 409b6155a1ec9324bd68aae97a07e33560c19028 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 21 Feb 2024 08:05:03 +0800 -Subject: [PATCH] split the flow fules related functions into separate file - ---- - src/lstack/core/lstack_init.c | 1 + - src/lstack/core/lstack_protocol_stack.c | 25 +- - src/lstack/include/lstack_ethdev.h | 27 - - src/lstack/include/lstack_flow.h | 51 ++ - src/lstack/include/lstack_vdev.h | 9 - - src/lstack/netif/dir.mk | 2 +- - src/lstack/netif/lstack_ethdev.c | 687 +----------------------- - src/lstack/netif/lstack_flow.c | 680 +++++++++++++++++++++++ - src/lstack/netif/lstack_vdev.c | 1 + - 9 files changed, 747 insertions(+), 736 deletions(-) - create mode 100644 src/lstack/include/lstack_flow.h - create mode 100644 src/lstack/netif/lstack_flow.c - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 31fd91d..d22a295 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -48,6 +48,7 @@ - #include "lstack_protocol_stack.h" - #include "lstack_preload.h" - #include "lstack_wrap.h" -+#include "lstack_flow.h" - - static void check_process_start(void) - { -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 18e5df7..a545b73 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -454,14 +454,12 @@ int stack_polling(uint32_t wakeup_tick) - { - int force_quit; - struct cfg_params *cfg = get_global_cfg_params(); -- uint8_t use_ltran_flag = cfg->use_ltran; - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - bool kni_switch = cfg->kni_switch; - #endif - bool use_sockmap = cfg->use_sockmap; - bool stack_mode_rtc = cfg->stack_mode_rtc; - uint32_t rpc_number = cfg->rpc_number; -- uint32_t nic_read_number = cfg->nic_read_number; - uint32_t read_connect_number = cfg->read_connect_number; - struct protocol_stack *stack = get_protocol_stack(); - -@@ -469,7 +467,7 @@ int stack_polling(uint32_t wakeup_tick) - rpc_poll_msg(&stack->dfx_rpc_queue, 2); - force_quit = rpc_poll_msg(&stack->rpc_queue, rpc_number); - -- gazelle_eth_dev_poll(stack, use_ltran_flag, nic_read_number); -+ eth_dev_poll(); - sys_timer_run(); - if (cfg->low_power_mod != 0) { - low_power_idling(stack); -@@ -525,10 +523,6 @@ static void* gazelle_stack_thread(void *arg) - } - sem_post(&g_stack_group.sem_stack_setup); - -- if (!use_ltran() && queue_id == 0) { -- init_listen_and_user_ports(); -- } -- - LSTACK_LOG(INFO, LSTACK, "stack_%02hu init success\n", queue_id); - if (get_global_cfg_params()->stack_mode_rtc) { - return NULL; -@@ -545,12 +539,6 @@ static void* gazelle_stack_thread(void *arg) - return NULL; - } - --static void gazelle_listen_thread(void *arg) --{ -- struct cfg_params *cfg_param = get_global_cfg_params(); -- recv_pkts_from_other_process(cfg_param->process_idx, arg); --} -- - int32_t stack_group_init_mempool(void) - { - struct cfg_params *global_cfg_parmas = get_global_cfg_params(); -@@ -611,17 +599,6 @@ int32_t stack_group_init(void) - } - } - -- /* run to completion mode does not currently support multiple process */ -- if (!use_ltran() && !get_global_cfg_params()->stack_mode_rtc) { -- char name[PATH_MAX]; -- sem_init(&stack_group->sem_listen_thread, 0, 0); -- sprintf_s(name, sizeof(name), "%s", "listen_thread"); -- struct sys_thread *thread = sys_thread_new(name, gazelle_listen_thread, -- (void*)(&stack_group->sem_listen_thread), 0, 0); -- free(thread); -- sem_wait(&stack_group->sem_listen_thread); -- } -- - return 0; - } - -diff --git a/src/lstack/include/lstack_ethdev.h b/src/lstack/include/lstack_ethdev.h -index 3252906..0c3d906 100644 ---- a/src/lstack/include/lstack_ethdev.h -+++ b/src/lstack/include/lstack_ethdev.h -@@ -16,25 +16,6 @@ - #include - #include - --#define INVAILD_PROCESS_IDX 255 -- --enum port_type { -- PORT_LISTEN, -- PORT_CONNECT, --}; -- --enum PACKET_TRANSFER_TYPE { -- TRANSFER_KERNEL = -1, -- TRANSFER_OTHER_THREAD, -- TRANSFER_CURRENT_THREAD, --}; -- --enum TRANSFER_MESSAGE_RESULT { -- CONNECT_ERROR = -2, -- REPLY_ERROR = -1, -- TRANSFER_SUCESS = 0, --}; -- - struct protocol_stack; - struct rte_mbuf; - struct lstack_dev_ops { -@@ -44,21 +25,13 @@ struct lstack_dev_ops { - - int32_t ethdev_init(struct protocol_stack *stack); - int32_t eth_dev_poll(void); --int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_flag, uint32_t nic_read_number); - void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack); - --int recv_pkts_from_other_process(int process_index, void* arg); --int32_t check_params_from_primary(void); -- - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void kni_handle_rx(uint16_t port_id); - void kni_handle_tx(struct rte_mbuf *mbuf); - #endif - --void delete_user_process_port(uint16_t dst_port, enum port_type type); --void add_user_process_port(uint16_t dst_port, uint8_t process_idx, enum port_type type); --void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); --void config_flow_director(uint16_t queue_id, uint32_t src_ip, uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); - void netif_poll(struct netif *netif); - - #endif /* __GAZELLE_ETHDEV_H__ */ -diff --git a/src/lstack/include/lstack_flow.h b/src/lstack/include/lstack_flow.h -new file mode 100644 -index 0000000..ad35cdf ---- /dev/null -+++ b/src/lstack/include/lstack_flow.h -@@ -0,0 +1,51 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __LSTACK_FLOW_H__ -+#define __LSTACK_FLOW_H__ -+ -+#include -+ -+enum port_type { -+ PORT_LISTEN, -+ PORT_CONNECT, -+}; -+ -+enum PACKET_TRANSFER_TYPE { -+ TRANSFER_KERNEL = -1, -+ TRANSFER_OTHER_THREAD, -+ TRANSFER_CURRENT_THREAD, -+}; -+ -+enum TRANSFER_MESSAGE_RESULT { -+ CONNECT_ERROR = -2, -+ REPLY_ERROR = -1, -+ TRANSFER_SUCESS = 0, -+}; -+ -+int distribute_pakages(struct rte_mbuf *mbuf); -+void flow_init(void); -+int32_t check_params_from_primary(void); -+ -+int recv_pkts_from_other_process(int process_index, void* arg); -+void transfer_delete_rule_info_to_process0(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); -+void transfer_create_rule_info_to_process0(uint16_t queue_id, uint32_t src_ip, -+ uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); -+void transfer_add_or_delete_listen_port_to_process0(uint16_t listen_port, uint8_t process_idx, uint8_t is_add); -+void transfer_arp_to_other_process(struct rte_mbuf *mbuf); -+ -+void add_user_process_port(uint16_t dst_port, uint8_t process_idx, enum port_type type); -+void delete_user_process_port(uint16_t dst_port, enum port_type type); -+ -+void gazelle_listen_thread(void *arg); -+ -+#endif -diff --git a/src/lstack/include/lstack_vdev.h b/src/lstack/include/lstack_vdev.h -index 007eec7..4e5d191 100644 ---- a/src/lstack/include/lstack_vdev.h -+++ b/src/lstack/include/lstack_vdev.h -@@ -13,19 +13,10 @@ - #ifndef _GAZELLE_VDEV_H_ - #define _GAZELLE_VDEV_H_ - --#include -- - struct lstack_dev_ops; - struct gazelle_quintuple; - enum reg_ring_type; - void vdev_dev_ops_init(struct lstack_dev_ops *dev_ops); - int vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple); - --int recv_pkts_from_other_process(int process_index, void* arg); --void transfer_delete_rule_info_to_process0(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); --void transfer_create_rule_info_to_process0(uint16_t queue_id, uint32_t src_ip, -- uint32_t dst_ip, uint16_t src_port, uint16_t dst_port); --void transfer_add_or_delete_listen_port_to_process0(uint16_t listen_port, uint8_t process_idx, uint8_t is_add); --void init_listen_and_user_ports(); -- - #endif /* _GAZELLE_VDEV_H_ */ -diff --git a/src/lstack/netif/dir.mk b/src/lstack/netif/dir.mk -index ec7c4ad..20fb5d6 100644 ---- a/src/lstack/netif/dir.mk -+++ b/src/lstack/netif/dir.mk -@@ -8,5 +8,5 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_ethdev.c lstack_vdev.c -+SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c - $(eval $(call register_dir, netif, $(SRC))) -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 25c94eb..2e938b0 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -10,74 +10,36 @@ - * See the Mulan PSL v2 for more details. - */ - --#include --#include -- - #include - #include - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include - #endif - #include --#include --#include - --#include - #include - #include - #include - #include --#include --#include - - #include --#include --#include - -+#include "dpdk_common.h" - #include "lstack_cfg.h" - #include "lstack_vdev.h" - #include "lstack_stack_stat.h" - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_lwip.h" --#include "dpdk_common.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" -+#include "lstack_flow.h" - #include "lstack_ethdev.h" - - /* FRAME_MTU + 14byte header */ - #define MBUF_MAX_LEN 1514 --#define MAX_PATTERN_NUM 4 --#define MAX_ACTION_NUM 2 --#define FULL_MASK 0xffffffff /* full mask */ --#define EMPTY_MASK 0x0 /* empty mask */ --#define LSTACK_MBUF_LEN 64 --#define TRANSFER_TCP_MUBF_LEN (LSTACK_MBUF_LEN + 3) --#define DELETE_FLOWS_PARAMS_NUM 3 --#define DELETE_FLOWS_PARAMS_LENGTH 30 --#define CREATE_FLOWS_PARAMS_NUM 6 --#define CREATE_FLOWS_PARAMS_LENGTH 60 --#define ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH 25 --#define ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM 3 --#define REPLY_LEN 10 --#define SUCCESS_REPLY "success" --#define ERROR_REPLY "error" - #define PACKET_READ_SIZE 32 - --#define GET_LSTACK_NUM 14 --#define GET_LSTACK_NUM_STRING "get_lstack_num" -- --#define SERVER_PATH "/var/run/gazelle/server.socket" --#define SPLIT_DELIM "," -- --#define UNIX_TCP_PORT_MAX 65535 -- --#define IPV4_VERSION_OFFSET 4 --#define IPV4_VERSION 4 -- --static uint8_t g_user_ports[UNIX_TCP_PORT_MAX] = {INVAILD_PROCESS_IDX, }; --static uint8_t g_listen_ports[UNIX_TCP_PORT_MAX] = {INVAILD_PROCESS_IDX, }; -- - void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - { - int32_t ret; -@@ -126,636 +88,6 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - } - } - --int32_t eth_dev_poll(void) --{ -- uint32_t nr_pkts; -- struct cfg_params *cfg = get_global_cfg_params(); -- struct protocol_stack *stack = get_protocol_stack(); -- -- nr_pkts = stack->dev_ops.rx_poll(stack, stack->pkts, cfg->nic_read_number); -- if (nr_pkts == 0) { -- return 0; -- } -- -- if (!cfg->use_ltran && get_protocol_stack_group()->latency_start) { -- uint64_t time_stamp = get_current_time(); -- time_stamp_into_mbuf(nr_pkts, stack->pkts, time_stamp); -- } -- -- for (uint32_t i = 0; i < nr_pkts; i++) { -- /* copy arp into other stack */ -- if (!cfg->use_ltran) { -- struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); -- if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == ethh->ether_type)) { -- stack_broadcast_arp(stack->pkts[i], stack); -- } -- } -- -- eth_dev_recv(stack->pkts[i], stack); -- } -- -- stack->stats.rx += nr_pkts; -- -- return nr_pkts; --} -- --/* flow rule map */ --#define RULE_KEY_LEN 23 --struct flow_rule { -- char rule_key[RULE_KEY_LEN]; -- struct rte_flow *flow; -- UT_hash_handle hh; --}; -- --static uint16_t g_flow_num = 0; --struct flow_rule *g_flow_rules = NULL; --struct flow_rule *find_rule(char *rule_key) --{ -- struct flow_rule *fl; -- HASH_FIND_STR(g_flow_rules, rule_key, fl); -- return fl; --} -- --void add_rule(char* rule_key, struct rte_flow *flow) --{ -- struct flow_rule *rule; -- HASH_FIND_STR(g_flow_rules, rule_key, rule); -- if (rule == NULL) { -- rule = (struct flow_rule*)malloc(sizeof(struct flow_rule)); -- strcpy_s(rule->rule_key, RULE_KEY_LEN, rule_key); -- HASH_ADD_STR(g_flow_rules, rule_key, rule); -- } -- rule->flow = flow; --} -- --void delete_rule(char* rule_key) --{ -- struct flow_rule *rule = NULL; -- HASH_FIND_STR(g_flow_rules, rule_key, rule); -- if (rule != NULL) { -- HASH_DEL(g_flow_rules, rule); -- free(rule); -- } --} -- --void init_listen_and_user_ports(void) --{ -- memset_s(g_user_ports, sizeof(g_user_ports), INVAILD_PROCESS_IDX, sizeof(g_user_ports)); -- memset_s(g_listen_ports, sizeof(g_listen_ports), INVAILD_PROCESS_IDX, sizeof(g_listen_ports)); --} -- --int transfer_pkt_to_other_process(char *buf, int process_index, int write_len, bool need_reply) --{ -- /* other process queue_id */ -- struct sockaddr_un serun; -- int sockfd; -- int ret = 0; -- -- sockfd = posix_api->socket_fn(AF_UNIX, SOCK_STREAM, 0); -- memset_s(&serun, sizeof(serun), 0, sizeof(serun)); -- serun.sun_family = AF_UNIX; -- sprintf_s(serun.sun_path, PATH_MAX, "%s%d", SERVER_PATH, process_index); -- int32_t len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path); -- if (posix_api->connect_fn(sockfd, (struct sockaddr *)&serun, len) < 0) { -- return CONNECT_ERROR; -- } -- posix_api->write_fn(sockfd, buf, write_len); -- if (need_reply) { -- char reply_message[REPLY_LEN]; -- int32_t read_result = posix_api->read_fn(sockfd, reply_message, REPLY_LEN); -- if (read_result > 0) { -- if (strcmp(reply_message, SUCCESS_REPLY) == 0) { -- ret = TRANSFER_SUCESS; -- } else if (strcmp(reply_message, ERROR_REPLY) == 0) { -- ret = REPLY_ERROR; -- } else { -- ret = atoi(reply_message); -- } -- } else { -- ret = REPLY_ERROR; -- } -- } -- posix_api->close_fn(sockfd); -- -- return ret; --} -- --int32_t check_params_from_primary(void) --{ -- struct cfg_params *cfg = get_global_cfg_params(); -- if (cfg->is_primary) { -- return 0; -- } -- // check lstack num -- char get_lstack_num[GET_LSTACK_NUM]; -- sprintf_s(get_lstack_num, GET_LSTACK_NUM, "%s", GET_LSTACK_NUM_STRING); -- int32_t ret = transfer_pkt_to_other_process(get_lstack_num, 0, GET_LSTACK_NUM, true); -- if (ret != cfg->num_cpu) { -- return -1; -- } -- return 0; --} -- --struct rte_flow *create_flow_director(uint16_t port_id, uint16_t queue_id, -- uint32_t src_ip, uint32_t dst_ip, -- uint16_t src_port, uint16_t dst_port, -- struct rte_flow_error *error) --{ -- struct rte_flow_attr attr; -- struct rte_flow_item pattern[MAX_PATTERN_NUM]; -- struct rte_flow_action action[MAX_ACTION_NUM]; -- struct rte_flow *flow = NULL; -- struct rte_flow_action_queue queue = { .index = queue_id }; -- struct rte_flow_item_ipv4 ip_spec; -- struct rte_flow_item_ipv4 ip_mask; -- -- struct rte_flow_item_tcp tcp_spec; -- struct rte_flow_item_tcp tcp_mask; -- int res; -- -- memset_s(pattern, sizeof(pattern), 0, sizeof(pattern)); -- memset_s(action, sizeof(action), 0, sizeof(action)); -- -- /* -- * set the rule attribute. -- * in this case only ingress packets will be checked. -- */ -- memset_s(&attr, sizeof(struct rte_flow_attr), 0, sizeof(struct rte_flow_attr)); -- attr.ingress = 1; -- -- /* -- * create the action sequence. -- * one action only, move packet to queue -- */ -- action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; -- action[0].conf = &queue; -- action[1].type = RTE_FLOW_ACTION_TYPE_END; -- -- // not limit eth header -- pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; -- -- // ip header -- memset_s(&ip_spec, sizeof(struct rte_flow_item_ipv4), 0, sizeof(struct rte_flow_item_ipv4)); -- memset_s(&ip_mask, sizeof(struct rte_flow_item_ipv4), 0, sizeof(struct rte_flow_item_ipv4)); -- ip_spec.hdr.dst_addr = dst_ip; -- ip_mask.hdr.dst_addr = FULL_MASK; -- ip_spec.hdr.src_addr = src_ip; -- ip_mask.hdr.src_addr = FULL_MASK; -- pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; -- pattern[1].spec = &ip_spec; -- pattern[1].mask = &ip_mask; -- -- // tcp header, full mask 0xffff -- memset_s(&tcp_spec, sizeof(struct rte_flow_item_tcp), 0, sizeof(struct rte_flow_item_tcp)); -- memset_s(&tcp_mask, sizeof(struct rte_flow_item_tcp), 0, sizeof(struct rte_flow_item_tcp)); -- pattern[2].type = RTE_FLOW_ITEM_TYPE_TCP; // 2: pattern 2 is tcp header -- tcp_spec.hdr.src_port = src_port; -- tcp_spec.hdr.dst_port = dst_port; -- tcp_mask.hdr.src_port = rte_flow_item_tcp_mask.hdr.src_port; -- tcp_mask.hdr.dst_port = rte_flow_item_tcp_mask.hdr.dst_port; -- pattern[2].spec = &tcp_spec; -- pattern[2].mask = &tcp_mask; -- -- /* the final level must be always type end */ -- pattern[3].type = RTE_FLOW_ITEM_TYPE_END; -- res = rte_flow_validate(port_id, &attr, pattern, action, error); -- if (!res) { -- flow = rte_flow_create(port_id, &attr, pattern, action, error); -- } else { -- LSTACK_LOG(ERR, LSTACK, "rte_flow_create.rte_flow_validate error, res %d \n", res); -- } -- -- return flow; --} -- --void config_flow_director(uint16_t queue_id, uint32_t src_ip, -- uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) --{ -- uint16_t port_id = get_protocol_stack_group()->port_id; -- char rule_key[RULE_KEY_LEN] = {0}; -- sprintf_s(rule_key, sizeof(rule_key), "%u_%u_%u", src_ip, src_port, dst_port); -- struct flow_rule *fl_exist = find_rule(rule_key); -- if (fl_exist != NULL) { -- return; -- } -- -- LSTACK_LOG(INFO, LSTACK, -- "config_flow_director, flow queue_id %u, src_ip %u,src_port_ntohs:%u, dst_port_ntohs:%u\n", -- queue_id, src_ip, ntohs(src_port), ntohs(dst_port)); -- -- struct rte_flow_error error; -- struct rte_flow *flow = create_flow_director(port_id, queue_id, src_ip, dst_ip, src_port, dst_port, &error); -- if (!flow) { -- LSTACK_LOG(ERR, LSTACK,"flow can not be created. queue_id %u, src_ip %u, src_port %u," -- "dst_port %u, dst_port_ntohs :%u, type %d. message: %s\n", -- queue_id, src_ip, src_port, dst_port, ntohs(dst_port), -- error.type, error.message ? error.message : "(no stated reason)"); -- return; -- } -- __sync_fetch_and_add(&g_flow_num, 1); -- add_rule(rule_key, flow); --} -- --void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) --{ -- uint16_t port_id = get_protocol_stack_group()->port_id; -- char rule_key[RULE_KEY_LEN] = {0}; -- sprintf_s(rule_key, RULE_KEY_LEN, "%u_%u_%u",dst_ip, dst_port, src_port); -- struct flow_rule *fl = find_rule(rule_key); -- -- if(fl != NULL){ -- struct rte_flow_error error; -- int ret = rte_flow_destroy(port_id, fl->flow, &error); -- if(ret != 0){ -- LSTACK_LOG(ERR, LSTACK, "Flow can't be delete %d message: %s\n", -- error.type, error.message ? error.message : "(no stated reason)"); -- } -- delete_rule(rule_key); -- __sync_fetch_and_sub(&g_flow_num, 1); -- } --} -- --/* if process 0, delete directly, else transfer 'dst_ip,src_port,dst_port' to process 0. */ --void transfer_delete_rule_info_to_process0(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) --{ -- if (get_global_cfg_params()->is_primary) { -- delete_flow_director(dst_ip, src_port, dst_port); -- } else { -- char process_server_path[DELETE_FLOWS_PARAMS_LENGTH]; -- sprintf_s(process_server_path, DELETE_FLOWS_PARAMS_LENGTH, "%u%s%u%s%u", -- dst_ip, SPLIT_DELIM, src_port, SPLIT_DELIM, dst_port); -- int ret = transfer_pkt_to_other_process(process_server_path, 0, DELETE_FLOWS_PARAMS_LENGTH, false); -- if(ret != TRANSFER_SUCESS){ -- LSTACK_LOG(ERR, LSTACK, "error. tid %d. dst_ip %u, src_port: %u, dst_port %u\n", -- rte_gettid(), dst_ip, src_port, dst_port); -- } -- } --} -- --// if process 0, add directly, else transfer 'src_ip,dst_ip,src_port,dst_port,queue_id' to process 0. --void transfer_create_rule_info_to_process0(uint16_t queue_id, uint32_t src_ip, -- uint32_t dst_ip, uint16_t src_port, -- uint16_t dst_port) --{ -- char process_server_path[CREATE_FLOWS_PARAMS_LENGTH]; -- /* exchage src_ip and dst_ip, src_port and dst_port */ -- uint8_t process_idx = get_global_cfg_params()->process_idx; -- sprintf_s(process_server_path, CREATE_FLOWS_PARAMS_LENGTH, "%u%s%u%s%u%s%u%s%u%s%u", -- dst_ip, SPLIT_DELIM, src_ip, SPLIT_DELIM, -- dst_port, SPLIT_DELIM, src_port, SPLIT_DELIM, -- queue_id, SPLIT_DELIM, process_idx); -- int ret = transfer_pkt_to_other_process(process_server_path, 0, CREATE_FLOWS_PARAMS_LENGTH, true); -- if (ret != TRANSFER_SUCESS) { -- LSTACK_LOG(ERR, LSTACK, "error. tid %d. src_ip %u, dst_ip %u, src_port: %u, dst_port %u," -- "queue_id %u, process_idx %u\n", -- rte_gettid(), src_ip, dst_ip, src_port, dst_port, queue_id, process_idx); -- } --} -- --void transfer_add_or_delete_listen_port_to_process0(uint16_t listen_port, uint8_t process_idx, uint8_t is_add) --{ -- char process_server_path[ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH]; -- sprintf_s(process_server_path, ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH, -- "%u%s%u%s%u", listen_port, SPLIT_DELIM, process_idx, SPLIT_DELIM, is_add); -- int ret = transfer_pkt_to_other_process(process_server_path, 0, ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH, true); -- if(ret != TRANSFER_SUCESS) { -- LSTACK_LOG(ERR, LSTACK, "error. tid %d. listen_port %u, process_idx %u\n", -- rte_gettid(), listen_port, process_idx); -- } --} -- --static int str_to_array(char *args, uint32_t *array, int size) --{ -- int val; -- uint16_t cnt = 0; -- char *elem = NULL; -- char *next_token = NULL; -- -- memset_s(array, sizeof(*array) * size, 0, sizeof(*array) * size); -- elem = strtok_s((char *)args, SPLIT_DELIM, &next_token); -- while (elem != NULL) { -- if (cnt >= size) { -- return -1; -- } -- val = atoi(elem); -- if (val < 0) { -- return -1; -- } -- array[cnt] = (uint32_t)val; -- cnt++; -- -- elem = strtok_s(NULL, SPLIT_DELIM, &next_token); -- } -- -- return cnt; --} -- --void parse_and_delete_rule(char* buf) --{ -- uint32_t array[DELETE_FLOWS_PARAMS_NUM]; -- str_to_array(buf, array, DELETE_FLOWS_PARAMS_NUM); -- uint32_t dst_ip = array[0]; -- uint16_t src_port = array[1]; -- uint16_t dst_port = array[2]; -- delete_flow_director(dst_ip, src_port, dst_port); --} -- --void add_user_process_port(uint16_t dst_port, uint8_t process_idx, enum port_type type) --{ -- if (type == PORT_LISTEN) { -- g_listen_ports[dst_port] = process_idx; -- } else { -- g_user_ports[dst_port] = process_idx; -- } --} -- --void delete_user_process_port(uint16_t dst_port, enum port_type type) --{ -- if (type == PORT_LISTEN) { -- g_listen_ports[dst_port] = INVAILD_PROCESS_IDX; -- } else { -- g_user_ports[dst_port] = INVAILD_PROCESS_IDX; -- } --} -- --void parse_and_create_rule(char* buf) --{ -- uint32_t array[CREATE_FLOWS_PARAMS_NUM]; -- str_to_array(buf, array, CREATE_FLOWS_PARAMS_NUM); -- uint32_t src_ip = array[0]; -- uint32_t dst_ip = array[1]; -- uint16_t src_port = array[2]; -- uint16_t dst_port = array[3]; -- uint16_t queue_id = array[4]; -- uint8_t process_idx = array[5]; -- config_flow_director(queue_id, src_ip, dst_ip, src_port, dst_port); -- add_user_process_port(dst_port, process_idx, PORT_CONNECT); --} -- --void parse_and_add_or_delete_listen_port(char* buf) --{ -- uint32_t array[ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM]; -- str_to_array(buf, array, ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM); -- uint16_t listen_port = array[0]; -- uint8_t process_idx = array[1]; -- uint8_t is_add = array[2]; -- if (is_add == 1) { -- add_user_process_port(listen_port, process_idx, PORT_LISTEN); -- } else { -- delete_user_process_port(listen_port, PORT_LISTEN); -- } -- --} -- --void transfer_arp_to_other_process(struct rte_mbuf *mbuf) --{ -- struct cfg_params *cfgs = get_global_cfg_params(); -- -- for(int i = 1; i < cfgs->num_process; i++){ -- char arp_mbuf[LSTACK_MBUF_LEN] = {0}; -- sprintf_s(arp_mbuf, sizeof(arp_mbuf), "%lu", mbuf); -- int result = transfer_pkt_to_other_process(arp_mbuf, i, LSTACK_MBUF_LEN, false); -- if (result == CONNECT_ERROR) { -- LSTACK_LOG(INFO, LSTACK,"connect process %d failed, ensure the process is started.\n", i); -- } else if (result == REPLY_ERROR) { -- LSTACK_LOG(ERR, LSTACK,"transfer arp pakages to process %d error. %m\n", i); -- } -- } --} -- --void transfer_tcp_to_thread(struct rte_mbuf *mbuf, uint16_t stk_idx) --{ -- /* current process queue_id */ -- struct protocol_stack *stack = get_protocol_stack_group()->stacks[stk_idx]; -- int ret = -1; -- while(ret != 0) { -- ret = rpc_call_arp(&stack->rpc_queue, mbuf); -- printf("transfer_tcp_to_thread, ret : %d \n", ret); -- } --} -- --void parse_arp_and_transefer(char* buf) --{ -- struct rte_mbuf *mbuf = (struct rte_mbuf *)atoll(buf); -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- struct rte_mbuf *mbuf_copy = NULL; -- struct protocol_stack *stack = NULL; -- int32_t ret; -- for (int32_t i = 0; i < stack_group->stack_num; i++) { -- stack = stack_group->stacks[i]; -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- stack->stats.rx_allocmbuf_fail++; -- } -- copy_mbuf(mbuf_copy, mbuf); -- -- ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -- -- while (ret != 0) { -- rpc_call_arp(&stack->rpc_queue, mbuf_copy); -- } -- } --} -- --void parse_tcp_and_transefer(char* buf) --{ -- char *next_token = NULL; -- char *elem = strtok_s(buf, SPLIT_DELIM, &next_token); -- struct rte_mbuf *mbuf = (struct rte_mbuf *) atoll(elem); -- elem = strtok_s(NULL, SPLIT_DELIM, &next_token); -- uint16_t queue_id = atoll(elem); -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- uint16_t num_queue = get_global_cfg_params()->num_queue; -- uint16_t stk_index = queue_id % num_queue; -- struct rte_mbuf *mbuf_copy = NULL; -- struct protocol_stack *stack = stack_group->stacks[stk_index]; -- -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- stack->stats.rx_allocmbuf_fail++; -- } -- -- copy_mbuf(mbuf_copy,mbuf); -- -- transfer_tcp_to_thread(mbuf_copy, stk_index); --} -- --int recv_pkts_from_other_process(int process_index, void* arg) --{ -- struct sockaddr_un serun, cliun; -- socklen_t cliun_len; -- int listenfd, connfd, size; -- char buf[132]; -- /* socket */ -- if ((listenfd = posix_api->socket_fn(AF_UNIX, SOCK_STREAM, 0)) < 0) { -- perror("socket error"); -- return -1; -- } -- /* bind */ -- memset_s(&serun, sizeof(serun), 0, sizeof(serun)); -- serun.sun_family = AF_UNIX; -- char process_server_path[PATH_MAX]; -- sprintf_s(process_server_path, sizeof(process_server_path), "%s%d", SERVER_PATH, process_index); -- strcpy_s(serun.sun_path, sizeof(serun.sun_path), process_server_path); -- size = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path); -- unlink(process_server_path); -- if (posix_api->bind_fn(listenfd, (struct sockaddr *)&serun, size) < 0) { -- perror("bind error"); -- return -1; -- } -- if (posix_api->listen_fn(listenfd, 20) < 0) { /* 20: max backlog */ -- perror("listen error"); -- return -1; -- } -- sem_post((sem_t *)arg); -- /* block */ -- while(1) { -- cliun_len = sizeof(cliun); -- if ((connfd = posix_api->accept_fn(listenfd, (struct sockaddr *)&cliun, &cliun_len)) < 0) { -- perror("accept error"); -- continue; -- } -- while(1) { -- int n = posix_api->read_fn(connfd, buf, sizeof(buf)); -- if (n < 0) { -- perror("read error"); -- break; -- } else if (n == 0) { -- break; -- } -- -- if(n == LSTACK_MBUF_LEN) { -- /* arp */ -- parse_arp_and_transefer(buf); -- } else if (n == TRANSFER_TCP_MUBF_LEN) { -- /* tcp. lstack_mbuf_queue_id */ -- parse_tcp_and_transefer(buf); -- } else if (n == DELETE_FLOWS_PARAMS_LENGTH) { -- /* delete rule */ -- parse_and_delete_rule(buf); -- } else if(n == CREATE_FLOWS_PARAMS_LENGTH) { -- /* add rule */ -- parse_and_create_rule(buf); -- char reply_buf[REPLY_LEN]; -- sprintf_s(reply_buf, sizeof(reply_buf), "%s", SUCCESS_REPLY); -- posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -- } else if (n == GET_LSTACK_NUM) { -- char reply_buf[REPLY_LEN]; -- sprintf_s(reply_buf, sizeof(reply_buf), "%d", get_global_cfg_params()->num_cpu); -- posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -- } else { -- /* add port */ -- parse_and_add_or_delete_listen_port(buf); -- char reply_buf[REPLY_LEN]; -- sprintf_s(reply_buf, sizeof(reply_buf), "%s", SUCCESS_REPLY); -- posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -- } -- -- } -- posix_api->close_fn(connfd); -- } -- posix_api->close_fn(listenfd); -- return 0; --} -- --void concat_mbuf_and_queue_id(struct rte_mbuf *mbuf, uint16_t queue_id, -- char* mbuf_and_queue_id, int write_len) --{ -- sprintf_s(mbuf_and_queue_id, write_len, "%lu%s%u", mbuf, SPLIT_DELIM, queue_id); --} -- --static int mbuf_to_idx(struct rte_mbuf *mbuf, uint16_t *dst_port) --{ -- struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); -- u16_t type = rte_be_to_cpu_16(ethh->ether_type); -- uint32_t index = 0; -- if (type == RTE_ETHER_TYPE_IPV4) { -- struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -- uint8_t ip_version = (iph->version_ihl & 0xf0) >> IPV4_VERSION_OFFSET; -- if (likely(ip_version == IPV4_VERSION)) { -- if (likely(iph->next_proto_id == IPPROTO_TCP)) { -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -- *dst_port = tcp_hdr->dst_port; -- -- if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -- uint32_t src_ip = iph->src_addr; -- uint16_t src_port = tcp_hdr->src_port; -- index = rte_jhash_3words(src_ip, src_port | ((*dst_port) << 16), 0, 0); -- } else { -- return -1; -- } -- } -- } -- } else if (type == RTE_ETHER_TYPE_IPV6) { -- struct rte_ipv6_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr)); -- if (likely(iph->proto == IPPROTO_TCP)) { -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr)); -- *dst_port = tcp_hdr->dst_port; -- -- if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -- uint32_t *src_ip = (uint32_t *) &iph->src_addr; -- uint16_t src_port = tcp_hdr->src_port; -- uint32_t v = rte_jhash_3words(src_ip[0], src_ip[1], src_ip[2], 0); -- index = rte_jhash_3words(src_ip[3], src_port | ((*dst_port) << 16), v, 0); -- } else { -- return -1; -- } -- } -- } else { -- return -1; -- } -- return index; --} -- --int distribute_pakages(struct rte_mbuf *mbuf) --{ -- uint16_t dst_port = 0; -- uint32_t index = mbuf_to_idx(mbuf, &dst_port); -- if (index == -1) { -- return TRANSFER_CURRENT_THREAD; -- } -- -- uint16_t queue_id = 0; -- uint32_t user_process_idx = 0; -- int each_process_queue_num = get_global_cfg_params()->num_queue; -- index = index % each_process_queue_num; -- if (g_listen_ports[dst_port] != INVAILD_PROCESS_IDX) { -- user_process_idx = g_listen_ports[dst_port]; -- } else { -- user_process_idx = g_user_ports[dst_port]; -- } -- -- if (user_process_idx == INVAILD_PROCESS_IDX) { -- return TRANSFER_KERNEL; -- } -- -- if (get_global_cfg_params()->seperate_send_recv) { -- queue_id = user_process_idx * each_process_queue_num + (index / 2) * 2; -- } else { -- queue_id = user_process_idx * each_process_queue_num + index; -- } -- if (queue_id != 0) { -- if (user_process_idx == 0) { -- transfer_tcp_to_thread(mbuf, queue_id); -- } else { -- char mbuf_and_queue_id[TRANSFER_TCP_MUBF_LEN]; -- concat_mbuf_and_queue_id(mbuf, queue_id, mbuf_and_queue_id, TRANSFER_TCP_MUBF_LEN); -- transfer_pkt_to_other_process(mbuf_and_queue_id, user_process_idx, -- TRANSFER_TCP_MUBF_LEN, false); -- } -- return TRANSFER_OTHER_THREAD; -- } else { -- return TRANSFER_CURRENT_THREAD; -- } -- -- return TRANSFER_KERNEL; --} -- - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void kni_handle_rx(uint16_t port_id) - { -@@ -797,17 +129,18 @@ void kni_handle_tx(struct rte_mbuf *mbuf) - } - #endif - --/* optimized eth_dev_poll() in lstack */ --int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_flag, uint32_t nic_read_number) -+int32_t eth_dev_poll(void) - { - uint32_t nr_pkts; -+ struct cfg_params *cfg = get_global_cfg_params(); -+ struct protocol_stack *stack = get_protocol_stack(); - -- nr_pkts = stack->dev_ops.rx_poll(stack, stack->pkts, nic_read_number); -+ nr_pkts = stack->dev_ops.rx_poll(stack, stack->pkts, cfg->nic_read_number); - if (nr_pkts == 0) { - return 0; - } - -- if (!use_ltran_flag && get_protocol_stack_group()->latency_start) { -+ if (!use_ltran() && get_protocol_stack_group()->latency_start) { - uint64_t time_stamp = get_current_time(); - time_stamp_into_mbuf(nr_pkts, stack->pkts, time_stamp); - } -@@ -816,7 +149,7 @@ int32_t gazelle_eth_dev_poll(struct protocol_stack *stack, uint8_t use_ltran_fla - /* 1 current thread recv; 0 other thread recv; -1 kni recv; */ - int transfer_type = TRANSFER_CURRENT_THREAD; - /* copy arp into other stack */ -- if (!use_ltran_flag) { -+ if (!use_ltran()) { - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); - u16_t type; - type = ethh->ether_type; -@@ -946,6 +279,10 @@ int32_t ethdev_init(struct protocol_stack *stack) - LSTACK_LOG(ERR, LSTACK, "fill mbuf to rx_ring failed ret=%d\n", ret); - return ret; - } -+ } else { -+ if (cfg->tuple_filter && stack->queue_id == 0) { -+ flow_init(); -+ } - } - - netif_set_default(&stack->netif); -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -new file mode 100644 -index 0000000..4e04209 ---- /dev/null -+++ b/src/lstack/netif/lstack_flow.c -@@ -0,0 +1,680 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "dpdk_common.h" -+#include "lstack_log.h" -+#include "lstack_dpdk.h" -+#include "lstack_cfg.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_flow.h" -+ -+#define MAX_PATTERN_NUM 4 -+#define MAX_ACTION_NUM 2 -+#define FULL_MASK 0xffffffff /* full mask */ -+#define EMPTY_MASK 0x0 /* empty mask */ -+#define LSTACK_MBUF_LEN 64 -+#define TRANSFER_TCP_MUBF_LEN (LSTACK_MBUF_LEN + 3) -+#define DELETE_FLOWS_PARAMS_NUM 3 -+#define DELETE_FLOWS_PARAMS_LENGTH 30 -+#define CREATE_FLOWS_PARAMS_NUM 6 -+#define CREATE_FLOWS_PARAMS_LENGTH 60 -+#define ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH 25 -+#define ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM 3 -+#define REPLY_LEN 10 -+#define SUCCESS_REPLY "success" -+#define ERROR_REPLY "error" -+ -+#define GET_LSTACK_NUM 14 -+#define GET_LSTACK_NUM_STRING "get_lstack_num" -+ -+#define SERVER_PATH "/var/run/gazelle/server.socket" -+#define SPLIT_DELIM "," -+ -+#define UNIX_TCP_PORT_MAX 65535 -+ -+#define INVAILD_PROCESS_IDX 255 -+ -+#define IPV4_VERSION_OFFSET 4 -+#define IPV4_VERSION 4 -+ -+static uint8_t g_user_ports[UNIX_TCP_PORT_MAX] = {INVAILD_PROCESS_IDX, }; -+static uint8_t g_listen_ports[UNIX_TCP_PORT_MAX] = {INVAILD_PROCESS_IDX, }; -+ -+/* flow rule map */ -+#define RULE_KEY_LEN 23 -+struct flow_rule { -+ char rule_key[RULE_KEY_LEN]; -+ struct rte_flow *flow; -+ UT_hash_handle hh; -+}; -+ -+static uint16_t g_flow_num = 0; -+static struct flow_rule *g_flow_rules = NULL; -+static struct flow_rule *find_rule(char *rule_key) -+{ -+ struct flow_rule *fl; -+ HASH_FIND_STR(g_flow_rules, rule_key, fl); -+ return fl; -+} -+ -+static void add_rule(char* rule_key, struct rte_flow *flow) -+{ -+ struct flow_rule *rule; -+ HASH_FIND_STR(g_flow_rules, rule_key, rule); -+ if (rule == NULL) { -+ rule = (struct flow_rule*)malloc(sizeof(struct flow_rule)); -+ strcpy_s(rule->rule_key, RULE_KEY_LEN, rule_key); -+ HASH_ADD_STR(g_flow_rules, rule_key, rule); -+ } -+ rule->flow = flow; -+} -+ -+static void delete_rule(char* rule_key) -+{ -+ struct flow_rule *rule = NULL; -+ HASH_FIND_STR(g_flow_rules, rule_key, rule); -+ if (rule != NULL) { -+ HASH_DEL(g_flow_rules, rule); -+ free(rule); -+ } -+} -+ -+static void init_listen_and_user_ports(void) -+{ -+ memset_s(g_user_ports, sizeof(g_user_ports), INVAILD_PROCESS_IDX, sizeof(g_user_ports)); -+ memset_s(g_listen_ports, sizeof(g_listen_ports), INVAILD_PROCESS_IDX, sizeof(g_listen_ports)); -+} -+ -+static int transfer_pkt_to_other_process(char *buf, int process_index, int write_len, bool need_reply) -+{ -+ /* other process queue_id */ -+ struct sockaddr_un serun; -+ int sockfd; -+ int ret = 0; -+ -+ sockfd = posix_api->socket_fn(AF_UNIX, SOCK_STREAM, 0); -+ memset_s(&serun, sizeof(serun), 0, sizeof(serun)); -+ serun.sun_family = AF_UNIX; -+ sprintf_s(serun.sun_path, PATH_MAX, "%s%d", SERVER_PATH, process_index); -+ int32_t len = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path); -+ if (posix_api->connect_fn(sockfd, (struct sockaddr *)&serun, len) < 0) { -+ return CONNECT_ERROR; -+ } -+ posix_api->write_fn(sockfd, buf, write_len); -+ if (need_reply) { -+ char reply_message[REPLY_LEN]; -+ int32_t read_result = posix_api->read_fn(sockfd, reply_message, REPLY_LEN); -+ if (read_result > 0) { -+ if (strcmp(reply_message, SUCCESS_REPLY) == 0) { -+ ret = TRANSFER_SUCESS; -+ } else if (strcmp(reply_message, ERROR_REPLY) == 0) { -+ ret = REPLY_ERROR; -+ } else { -+ ret = atoi(reply_message); -+ } -+ } else { -+ ret = REPLY_ERROR; -+ } -+ } -+ posix_api->close_fn(sockfd); -+ -+ return ret; -+} -+ -+int32_t check_params_from_primary(void) -+{ -+ struct cfg_params *cfg = get_global_cfg_params(); -+ if (cfg->is_primary) { -+ return 0; -+ } -+ // check lstack num -+ char get_lstack_num[GET_LSTACK_NUM]; -+ sprintf_s(get_lstack_num, GET_LSTACK_NUM, "%s", GET_LSTACK_NUM_STRING); -+ int32_t ret = transfer_pkt_to_other_process(get_lstack_num, 0, GET_LSTACK_NUM, true); -+ if (ret != cfg->num_cpu) { -+ return -1; -+ } -+ return 0; -+} -+ -+static struct rte_flow *create_flow_director(uint16_t port_id, uint16_t queue_id, -+ uint32_t src_ip, uint32_t dst_ip, -+ uint16_t src_port, uint16_t dst_port, -+ struct rte_flow_error *error) -+{ -+ struct rte_flow_attr attr; -+ struct rte_flow_item pattern[MAX_PATTERN_NUM]; -+ struct rte_flow_action action[MAX_ACTION_NUM]; -+ struct rte_flow *flow = NULL; -+ struct rte_flow_action_queue queue = { .index = queue_id }; -+ struct rte_flow_item_ipv4 ip_spec; -+ struct rte_flow_item_ipv4 ip_mask; -+ -+ struct rte_flow_item_tcp tcp_spec; -+ struct rte_flow_item_tcp tcp_mask; -+ int res; -+ -+ memset_s(pattern, sizeof(pattern), 0, sizeof(pattern)); -+ memset_s(action, sizeof(action), 0, sizeof(action)); -+ -+ /* -+ * set the rule attribute. -+ * in this case only ingress packets will be checked. -+ */ -+ memset_s(&attr, sizeof(struct rte_flow_attr), 0, sizeof(struct rte_flow_attr)); -+ attr.ingress = 1; -+ -+ /* -+ * create the action sequence. -+ * one action only, move packet to queue -+ */ -+ action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; -+ action[0].conf = &queue; -+ action[1].type = RTE_FLOW_ACTION_TYPE_END; -+ -+ // not limit eth header -+ pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; -+ -+ // ip header -+ memset_s(&ip_spec, sizeof(struct rte_flow_item_ipv4), 0, sizeof(struct rte_flow_item_ipv4)); -+ memset_s(&ip_mask, sizeof(struct rte_flow_item_ipv4), 0, sizeof(struct rte_flow_item_ipv4)); -+ ip_spec.hdr.dst_addr = dst_ip; -+ ip_mask.hdr.dst_addr = FULL_MASK; -+ ip_spec.hdr.src_addr = src_ip; -+ ip_mask.hdr.src_addr = FULL_MASK; -+ pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; -+ pattern[1].spec = &ip_spec; -+ pattern[1].mask = &ip_mask; -+ -+ // tcp header, full mask 0xffff -+ memset_s(&tcp_spec, sizeof(struct rte_flow_item_tcp), 0, sizeof(struct rte_flow_item_tcp)); -+ memset_s(&tcp_mask, sizeof(struct rte_flow_item_tcp), 0, sizeof(struct rte_flow_item_tcp)); -+ pattern[2].type = RTE_FLOW_ITEM_TYPE_TCP; // 2: pattern 2 is tcp header -+ tcp_spec.hdr.src_port = src_port; -+ tcp_spec.hdr.dst_port = dst_port; -+ tcp_mask.hdr.src_port = rte_flow_item_tcp_mask.hdr.src_port; -+ tcp_mask.hdr.dst_port = rte_flow_item_tcp_mask.hdr.dst_port; -+ pattern[2].spec = &tcp_spec; -+ pattern[2].mask = &tcp_mask; -+ -+ /* the final level must be always type end */ -+ pattern[3].type = RTE_FLOW_ITEM_TYPE_END; -+ res = rte_flow_validate(port_id, &attr, pattern, action, error); -+ if (!res) { -+ flow = rte_flow_create(port_id, &attr, pattern, action, error); -+ } else { -+ LSTACK_LOG(ERR, LSTACK, "rte_flow_create.rte_flow_validate error, res %d \n", res); -+ } -+ -+ return flow; -+} -+ -+static void config_flow_director(uint16_t queue_id, uint32_t src_ip, -+ uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) -+{ -+ uint16_t port_id = get_protocol_stack_group()->port_id; -+ char rule_key[RULE_KEY_LEN] = {0}; -+ sprintf_s(rule_key, sizeof(rule_key), "%u_%u_%u", src_ip, src_port, dst_port); -+ struct flow_rule *fl_exist = find_rule(rule_key); -+ if (fl_exist != NULL) { -+ return; -+ } -+ -+ LSTACK_LOG(INFO, LSTACK, -+ "config_flow_director, flow queue_id %u, src_ip %u,src_port_ntohs:%u, dst_port_ntohs:%u\n", -+ queue_id, src_ip, ntohs(src_port), ntohs(dst_port)); -+ -+ struct rte_flow_error error; -+ struct rte_flow *flow = create_flow_director(port_id, queue_id, src_ip, dst_ip, src_port, dst_port, &error); -+ if (!flow) { -+ LSTACK_LOG(ERR, LSTACK,"flow can not be created. queue_id %u, src_ip %u, src_port %u," -+ "dst_port %u, dst_port_ntohs :%u, type %d. message: %s\n", -+ queue_id, src_ip, src_port, dst_port, ntohs(dst_port), -+ error.type, error.message ? error.message : "(no stated reason)"); -+ return; -+ } -+ __sync_fetch_and_add(&g_flow_num, 1); -+ add_rule(rule_key, flow); -+} -+ -+static void delete_flow_director(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) -+{ -+ uint16_t port_id = get_protocol_stack_group()->port_id; -+ char rule_key[RULE_KEY_LEN] = {0}; -+ sprintf_s(rule_key, RULE_KEY_LEN, "%u_%u_%u",dst_ip, dst_port, src_port); -+ struct flow_rule *fl = find_rule(rule_key); -+ -+ if(fl != NULL) { -+ struct rte_flow_error error; -+ int ret = rte_flow_destroy(port_id, fl->flow, &error); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "Flow can't be delete %d message: %s\n", -+ error.type, error.message ? error.message : "(no stated reason)"); -+ } -+ delete_rule(rule_key); -+ __sync_fetch_and_sub(&g_flow_num, 1); -+ } -+} -+ -+/* if process 0, delete directly, else transfer 'dst_ip,src_port,dst_port' to process 0. */ -+void transfer_delete_rule_info_to_process0(uint32_t dst_ip, uint16_t src_port, uint16_t dst_port) -+{ -+ if (get_global_cfg_params()->is_primary) { -+ delete_flow_director(dst_ip, src_port, dst_port); -+ } else { -+ char process_server_path[DELETE_FLOWS_PARAMS_LENGTH]; -+ sprintf_s(process_server_path, DELETE_FLOWS_PARAMS_LENGTH, "%u%s%u%s%u", -+ dst_ip, SPLIT_DELIM, src_port, SPLIT_DELIM, dst_port); -+ int ret = transfer_pkt_to_other_process(process_server_path, 0, DELETE_FLOWS_PARAMS_LENGTH, false); -+ if (ret != TRANSFER_SUCESS) { -+ LSTACK_LOG(ERR, LSTACK, "error. tid %d. dst_ip %u, src_port: %u, dst_port %u\n", -+ rte_gettid(), dst_ip, src_port, dst_port); -+ } -+ } -+} -+ -+// if process 0, add directly, else transfer 'src_ip,dst_ip,src_port,dst_port,queue_id' to process 0. -+void transfer_create_rule_info_to_process0(uint16_t queue_id, uint32_t src_ip, -+ uint32_t dst_ip, uint16_t src_port, -+ uint16_t dst_port) -+{ -+ char process_server_path[CREATE_FLOWS_PARAMS_LENGTH]; -+ /* exchage src_ip and dst_ip, src_port and dst_port */ -+ uint8_t process_idx = get_global_cfg_params()->process_idx; -+ sprintf_s(process_server_path, CREATE_FLOWS_PARAMS_LENGTH, "%u%s%u%s%u%s%u%s%u%s%u", -+ dst_ip, SPLIT_DELIM, src_ip, SPLIT_DELIM, -+ dst_port, SPLIT_DELIM, src_port, SPLIT_DELIM, -+ queue_id, SPLIT_DELIM, process_idx); -+ int ret = transfer_pkt_to_other_process(process_server_path, 0, CREATE_FLOWS_PARAMS_LENGTH, true); -+ if (ret != TRANSFER_SUCESS) { -+ LSTACK_LOG(ERR, LSTACK, "error. tid %d. src_ip %u, dst_ip %u, src_port: %u, dst_port %u," -+ "queue_id %u, process_idx %u\n", -+ rte_gettid(), src_ip, dst_ip, src_port, dst_port, queue_id, process_idx); -+ } -+} -+ -+void transfer_add_or_delete_listen_port_to_process0(uint16_t listen_port, uint8_t process_idx, uint8_t is_add) -+{ -+ char process_server_path[ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH]; -+ sprintf_s(process_server_path, ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH, -+ "%u%s%u%s%u", listen_port, SPLIT_DELIM, process_idx, SPLIT_DELIM, is_add); -+ int ret = transfer_pkt_to_other_process(process_server_path, 0, ADD_OR_DELETE_LISTEN_PORT_PARAMS_LENGTH, true); -+ if (ret != TRANSFER_SUCESS) { -+ LSTACK_LOG(ERR, LSTACK, "error. tid %d. listen_port %u, process_idx %u\n", -+ rte_gettid(), listen_port, process_idx); -+ } -+} -+ -+static int str_to_array(char *args, uint32_t *array, int size) -+{ -+ int val; -+ uint16_t cnt = 0; -+ char *elem = NULL; -+ char *next_token = NULL; -+ -+ memset_s(array, sizeof(*array) * size, 0, sizeof(*array) * size); -+ elem = strtok_s((char *)args, SPLIT_DELIM, &next_token); -+ while (elem != NULL) { -+ if (cnt >= size) { -+ return -1; -+ } -+ val = atoi(elem); -+ if (val < 0) { -+ return -1; -+ } -+ array[cnt] = (uint32_t)val; -+ cnt++; -+ -+ elem = strtok_s(NULL, SPLIT_DELIM, &next_token); -+ } -+ -+ return cnt; -+} -+ -+static void parse_and_delete_rule(char* buf) -+{ -+ uint32_t array[DELETE_FLOWS_PARAMS_NUM]; -+ str_to_array(buf, array, DELETE_FLOWS_PARAMS_NUM); -+ uint32_t dst_ip = array[0]; -+ uint16_t src_port = array[1]; -+ uint16_t dst_port = array[2]; -+ delete_flow_director(dst_ip, src_port, dst_port); -+} -+ -+void add_user_process_port(uint16_t dst_port, uint8_t process_idx, enum port_type type) -+{ -+ if (type == PORT_LISTEN) { -+ g_listen_ports[dst_port] = process_idx; -+ } else { -+ g_user_ports[dst_port] = process_idx; -+ } -+} -+ -+void delete_user_process_port(uint16_t dst_port, enum port_type type) -+{ -+ if (type == PORT_LISTEN) { -+ g_listen_ports[dst_port] = INVAILD_PROCESS_IDX; -+ } else { -+ g_user_ports[dst_port] = INVAILD_PROCESS_IDX; -+ } -+} -+ -+static void parse_and_create_rule(char* buf) -+{ -+ uint32_t array[CREATE_FLOWS_PARAMS_NUM]; -+ str_to_array(buf, array, CREATE_FLOWS_PARAMS_NUM); -+ uint32_t src_ip = array[0]; -+ uint32_t dst_ip = array[1]; -+ uint16_t src_port = array[2]; -+ uint16_t dst_port = array[3]; -+ uint16_t queue_id = array[4]; -+ uint8_t process_idx = array[5]; -+ config_flow_director(queue_id, src_ip, dst_ip, src_port, dst_port); -+ add_user_process_port(dst_port, process_idx, PORT_CONNECT); -+} -+ -+static void parse_and_add_or_delete_listen_port(char* buf) -+{ -+ uint32_t array[ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM]; -+ str_to_array(buf, array, ADD_OR_DELETE_LISTEN_PORT_PARAMS_NUM); -+ uint16_t listen_port = array[0]; -+ uint8_t process_idx = array[1]; -+ uint8_t is_add = array[2]; -+ if (is_add == 1) { -+ add_user_process_port(listen_port, process_idx, PORT_LISTEN); -+ } else { -+ delete_user_process_port(listen_port, PORT_LISTEN); -+ } -+} -+ -+void transfer_arp_to_other_process(struct rte_mbuf *mbuf) -+{ -+ struct cfg_params *cfgs = get_global_cfg_params(); -+ -+ for (int i = 1; i < cfgs->num_process; i++) { -+ char arp_mbuf[LSTACK_MBUF_LEN] = {0}; -+ sprintf_s(arp_mbuf, sizeof(arp_mbuf), "%lu", mbuf); -+ int result = transfer_pkt_to_other_process(arp_mbuf, i, LSTACK_MBUF_LEN, false); -+ if (result == CONNECT_ERROR) { -+ LSTACK_LOG(INFO, LSTACK,"connect process %d failed, ensure the process is started.\n", i); -+ } else if (result == REPLY_ERROR) { -+ LSTACK_LOG(ERR, LSTACK,"transfer arp pakages to process %d error. %m\n", i); -+ } -+ } -+} -+ -+static void transfer_tcp_to_thread(struct rte_mbuf *mbuf, uint16_t stk_idx) -+{ -+ /* current process queue_id */ -+ struct protocol_stack *stack = get_protocol_stack_group()->stacks[stk_idx]; -+ int ret = -1; -+ while (ret != 0) { -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf); -+ printf("transfer_tcp_to_thread, ret : %d \n", ret); -+ } -+} -+ -+static void parse_arp_and_transefer(char* buf) -+{ -+ struct rte_mbuf *mbuf = (struct rte_mbuf *)atoll(buf); -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct rte_mbuf *mbuf_copy = NULL; -+ struct protocol_stack *stack = NULL; -+ int32_t ret; -+ for (int32_t i = 0; i < stack_group->stack_num; i++) { -+ stack = stack_group->stacks[i]; -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ while (ret != 0) { -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ stack->stats.rx_allocmbuf_fail++; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ -+ while (ret != 0) { -+ rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ } -+ } -+} -+ -+static void parse_tcp_and_transefer(char* buf) -+{ -+ char *next_token = NULL; -+ char *elem = strtok_s(buf, SPLIT_DELIM, &next_token); -+ struct rte_mbuf *mbuf = (struct rte_mbuf *) atoll(elem); -+ elem = strtok_s(NULL, SPLIT_DELIM, &next_token); -+ uint16_t queue_id = atoll(elem); -+ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ uint16_t num_queue = get_global_cfg_params()->num_queue; -+ uint16_t stk_index = queue_id % num_queue; -+ struct rte_mbuf *mbuf_copy = NULL; -+ struct protocol_stack *stack = stack_group->stacks[stk_index]; -+ -+ int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ while (ret != 0) { -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ stack->stats.rx_allocmbuf_fail++; -+ } -+ -+ copy_mbuf(mbuf_copy,mbuf); -+ transfer_tcp_to_thread(mbuf_copy, stk_index); -+} -+ -+int recv_pkts_from_other_process(int process_index, void* arg) -+{ -+ struct sockaddr_un serun, cliun; -+ socklen_t cliun_len; -+ int listenfd, connfd, size; -+ char buf[132]; -+ /* socket */ -+ if ((listenfd = posix_api->socket_fn(AF_UNIX, SOCK_STREAM, 0)) < 0) { -+ perror("socket error"); -+ return -1; -+ } -+ /* bind */ -+ memset_s(&serun, sizeof(serun), 0, sizeof(serun)); -+ serun.sun_family = AF_UNIX; -+ char process_server_path[PATH_MAX]; -+ sprintf_s(process_server_path, sizeof(process_server_path), "%s%d", SERVER_PATH, process_index); -+ strcpy_s(serun.sun_path, sizeof(serun.sun_path), process_server_path); -+ size = offsetof(struct sockaddr_un, sun_path) + strlen(serun.sun_path); -+ unlink(process_server_path); -+ if (posix_api->bind_fn(listenfd, (struct sockaddr *)&serun, size) < 0) { -+ perror("bind error"); -+ return -1; -+ } -+ if (posix_api->listen_fn(listenfd, 20) < 0) { /* 20: max backlog */ -+ perror("listen error"); -+ return -1; -+ } -+ sem_post((sem_t *)arg); -+ /* block */ -+ while (1) { -+ cliun_len = sizeof(cliun); -+ if ((connfd = posix_api->accept_fn(listenfd, (struct sockaddr *)&cliun, &cliun_len)) < 0) { -+ perror("accept error"); -+ continue; -+ } -+ while (1) { -+ int n = posix_api->read_fn(connfd, buf, sizeof(buf)); -+ if (n < 0) { -+ perror("read error"); -+ break; -+ } else if (n == 0) { -+ break; -+ } -+ -+ if (n == LSTACK_MBUF_LEN) { -+ /* arp */ -+ parse_arp_and_transefer(buf); -+ } else if (n == TRANSFER_TCP_MUBF_LEN) { -+ /* tcp. lstack_mbuf_queue_id */ -+ parse_tcp_and_transefer(buf); -+ } else if (n == DELETE_FLOWS_PARAMS_LENGTH) { -+ /* delete rule */ -+ parse_and_delete_rule(buf); -+ } else if (n == CREATE_FLOWS_PARAMS_LENGTH) { -+ /* add rule */ -+ parse_and_create_rule(buf); -+ char reply_buf[REPLY_LEN]; -+ sprintf_s(reply_buf, sizeof(reply_buf), "%s", SUCCESS_REPLY); -+ posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -+ } else if (n == GET_LSTACK_NUM) { -+ char reply_buf[REPLY_LEN]; -+ sprintf_s(reply_buf, sizeof(reply_buf), "%d", get_global_cfg_params()->num_cpu); -+ posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -+ } else { -+ /* add port */ -+ parse_and_add_or_delete_listen_port(buf); -+ char reply_buf[REPLY_LEN]; -+ sprintf_s(reply_buf, sizeof(reply_buf), "%s", SUCCESS_REPLY); -+ posix_api->write_fn(connfd, reply_buf, REPLY_LEN); -+ } -+ -+ } -+ posix_api->close_fn(connfd); -+ } -+ posix_api->close_fn(listenfd); -+ return 0; -+} -+ -+void concat_mbuf_and_queue_id(struct rte_mbuf *mbuf, uint16_t queue_id, -+ char* mbuf_and_queue_id, int write_len) -+{ -+ sprintf_s(mbuf_and_queue_id, write_len, "%lu%s%u", mbuf, SPLIT_DELIM, queue_id); -+} -+ -+static int mbuf_to_idx(struct rte_mbuf *mbuf, uint16_t *dst_port) -+{ -+ struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *); -+ u16_t type = rte_be_to_cpu_16(ethh->ether_type); -+ uint32_t index = 0; -+ if (type == RTE_ETHER_TYPE_IPV4) { -+ struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv4_hdr *, sizeof(struct rte_ether_hdr)); -+ uint8_t ip_version = (iph->version_ihl & 0xf0) >> IPV4_VERSION_OFFSET; -+ if (likely(ip_version == IPV4_VERSION)) { -+ if (likely(iph->next_proto_id == IPPROTO_TCP)) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -+ *dst_port = tcp_hdr->dst_port; -+ -+ if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -+ uint32_t src_ip = iph->src_addr; -+ uint16_t src_port = tcp_hdr->src_port; -+ index = rte_jhash_3words(src_ip, src_port | ((*dst_port) << 16), 0, 0); -+ } else { -+ return -1; -+ } -+ } -+ } -+ } else if (type == RTE_ETHER_TYPE_IPV6) { -+ struct rte_ipv6_hdr *iph = rte_pktmbuf_mtod_offset(mbuf, struct rte_ipv6_hdr *, sizeof(struct rte_ether_hdr)); -+ if (likely(iph->proto == IPPROTO_TCP)) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(mbuf, struct rte_tcp_hdr *, -+ sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr)); -+ *dst_port = tcp_hdr->dst_port; -+ -+ if (unlikely(tcp_hdr->tcp_flags == TCP_SYN)) { -+ uint32_t *src_ip = (uint32_t *) &iph->src_addr; -+ uint16_t src_port = tcp_hdr->src_port; -+ uint32_t v = rte_jhash_3words(src_ip[0], src_ip[1], src_ip[2], 0); -+ index = rte_jhash_3words(src_ip[3], src_port | ((*dst_port) << 16), v, 0); -+ } else { -+ return -1; -+ } -+ } -+ } else { -+ return -1; -+ } -+ return index; -+} -+ -+int distribute_pakages(struct rte_mbuf *mbuf) -+{ -+ uint16_t dst_port = 0; -+ uint32_t index = mbuf_to_idx(mbuf, &dst_port); -+ if (index == -1) { -+ return TRANSFER_CURRENT_THREAD; -+ } -+ -+ uint16_t queue_id = 0; -+ uint32_t user_process_idx = 0; -+ int each_process_queue_num = get_global_cfg_params()->num_queue; -+ index = index % each_process_queue_num; -+ if (g_listen_ports[dst_port] != INVAILD_PROCESS_IDX) { -+ user_process_idx = g_listen_ports[dst_port]; -+ } else { -+ user_process_idx = g_user_ports[dst_port]; -+ } -+ -+ if (user_process_idx == INVAILD_PROCESS_IDX) { -+ return TRANSFER_KERNEL; -+ } -+ -+ if (get_global_cfg_params()->seperate_send_recv) { -+ queue_id = user_process_idx * each_process_queue_num + (index / 2) * 2; -+ } else { -+ queue_id = user_process_idx * each_process_queue_num + index; -+ } -+ if (queue_id != 0) { -+ if (user_process_idx == 0) { -+ transfer_tcp_to_thread(mbuf, queue_id); -+ } else { -+ char mbuf_and_queue_id[TRANSFER_TCP_MUBF_LEN]; -+ concat_mbuf_and_queue_id(mbuf, queue_id, mbuf_and_queue_id, TRANSFER_TCP_MUBF_LEN); -+ transfer_pkt_to_other_process(mbuf_and_queue_id, user_process_idx, -+ TRANSFER_TCP_MUBF_LEN, false); -+ } -+ return TRANSFER_OTHER_THREAD; -+ } else { -+ return TRANSFER_CURRENT_THREAD; -+ } -+ -+ return TRANSFER_KERNEL; -+} -+ -+void gazelle_listen_thread(void *arg) -+{ -+ struct cfg_params *cfg_param = get_global_cfg_params(); -+ recv_pkts_from_other_process(cfg_param->process_idx, arg); -+} -+ -+void flow_init(void) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ init_listen_and_user_ports(); -+ -+ /* run to completion mode does not currently support multiple process */ -+ if (!use_ltran() && !get_global_cfg_params()->stack_mode_rtc) { -+ char name[PATH_MAX]; -+ sem_init(&stack_group->sem_listen_thread, 0, 0); -+ sprintf_s(name, sizeof(name), "%s", "listen_thread"); -+ struct sys_thread *thread = sys_thread_new(name, gazelle_listen_thread, -+ (void*)(&stack_group->sem_listen_thread), 0, 0); -+ free(thread); -+ sem_wait(&stack_group->sem_listen_thread); -+ } -+} -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index f78e48a..3703092 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -33,6 +33,7 @@ - #include "lstack_protocol_stack.h" - #include "gazelle_reg_msg.h" - #include "lstack_lwip.h" -+#include "lstack_flow.h" - #include "lstack_vdev.h" - - /* INUSE_TX_PKTS_WATERMARK < VDEV_RX_QUEUE_SZ; --- -2.27.0 - diff --git a/0138-fix-coreddump-when-stack-setup-failed-in-rtc-mode.patch b/0138-fix-coreddump-when-stack-setup-failed-in-rtc-mode.patch deleted file mode 100644 index 1e4c192..0000000 --- a/0138-fix-coreddump-when-stack-setup-failed-in-rtc-mode.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 52fafeafd51ed5363081064076dff4ed276a99c1 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 22 Feb 2024 21:22:44 +0800 -Subject: [PATCH] fix coreddump when stack setup failed in rtc mode - ---- - src/lstack/api/lstack_rtc_api.c | 6 +++--- - src/lstack/core/lstack_init.c | 11 +++++------ - 2 files changed, 8 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index d29e51e..2e10e30 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -45,7 +45,7 @@ int rtc_socket(int domain, int type, int protocol) - int ret; - - if (stack_setup_app_thread() < 0) { -- LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ exit(1); - } - - /* need call stack thread init function */ -@@ -74,7 +74,7 @@ int rtc_shutdown(int fd, int how) - int rtc_epoll_create(int flags) - { - if (stack_setup_app_thread() < 0) { -- LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ exit(1); - } - - return lstack_epoll_create(flags); -@@ -83,7 +83,7 @@ int rtc_epoll_create(int flags) - int rtc_epoll_create1(int flags) - { - if (stack_setup_app_thread() < 0) { -- LSTACK_EXIT(1, "stack_setup_app_thread failed!\n"); -+ exit(1); - } - - return lstack_epoll_create1(flags); -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 31fd91d..bd9ba8a 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -109,12 +109,11 @@ static int32_t check_process_conflict(void) - - void gazelle_exit(void) - { -- if (!get_global_cfg_params()->stack_mode_rtc) { -- wrap_api_set_dummy(); -- /* 1: wait until app thread call send functio complete */ -- sleep(1); -- stack_group_exit(); -- } -+ wrap_api_set_dummy(); -+ /* 1: wait until app thread call send functio complete */ -+ sleep(1); -+ stack_group_exit(); -+ - if (!use_ltran()) { - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_kni_release(); --- -2.27.0 - diff --git a/0139-diff-udp-and-tcp-read-from-stack.patch b/0139-diff-udp-and-tcp-read-from-stack.patch deleted file mode 100644 index ff642fe..0000000 --- a/0139-diff-udp-and-tcp-read-from-stack.patch +++ /dev/null @@ -1,277 +0,0 @@ -From 472e2f00b3fda7dad4396704fd94715d91be4642 Mon Sep 17 00:00:00 2001 -From: jiangheng -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 - diff --git a/0140-FAULT-INJECT-gazelle-add-packet-delay-and-packet-dro.patch b/0140-FAULT-INJECT-gazelle-add-packet-delay-and-packet-dro.patch deleted file mode 100644 index cb42a61..0000000 --- a/0140-FAULT-INJECT-gazelle-add-packet-delay-and-packet-dro.patch +++ /dev/null @@ -1,798 +0,0 @@ -From f28b880f3be68377003c60005011a835eb18e105 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Sun, 18 Feb 2024 17:11:05 +0800 -Subject: [PATCH] FAULT INJECT: gazelle add packet delay and packet drop - ---- - src/common/gazelle_dfx_msg.h | 15 ++ - src/common/gazelle_fault_inject_common.h | 75 +++++++ - src/lstack/Makefile | 5 + - src/lstack/core/lstack_control_plane.c | 13 +- - src/lstack/include/lstack_fault_inject.h | 20 ++ - src/lstack/include/lstack_vdev.h | 1 + - src/lstack/netif/dir.mk | 3 + - src/lstack/netif/lstack_fault_inject.c | 187 ++++++++++++++++ - src/lstack/netif/lstack_vdev.c | 2 +- - src/ltran/CMakeLists.txt | 5 + - src/ltran/ltran_dfx.c | 274 ++++++++++++++++++++++- - 11 files changed, 595 insertions(+), 5 deletions(-) - create mode 100644 src/common/gazelle_fault_inject_common.h - create mode 100644 src/lstack/include/lstack_fault_inject.h - create mode 100644 src/lstack/netif/lstack_fault_inject.c - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 7f8422a..8d528d6 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -18,6 +18,10 @@ - - #include - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+#include "gazelle_fault_inject_common.h" -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - #define GAZELLE_CLIENT_NUM_MIN 1 - #define GAZELLE_LOG_LEVEL_MAX 10 - #define GAZELLECTL_TIMEOUT 5000 // millisecond -@@ -54,6 +58,11 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, - GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ GAZELLE_STAT_FAULT_INJECT_SET, -+ GAZELLE_STAT_FAULT_INJECT_UNSET, -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - GAZELLE_STAT_MODE_MAX, - }; - -@@ -277,6 +286,9 @@ struct gazelle_stack_dfx_data { - struct gazelle_stat_lstack_snmp snmp; - struct nic_eth_xstats nic_xstats; - struct nic_eth_features nic_features; -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ struct gazelle_fault_inject_data inject; -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ - } data; - }; - -@@ -307,6 +319,9 @@ struct gazelle_stat_msg_request { - union stat_param { - char log_level[GAZELLE_LOG_LEVEL_MAX]; - uint16_t low_power_mod; -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ struct gazelle_fault_inject_data inject; -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ - } data; - }; - -diff --git a/src/common/gazelle_fault_inject_common.h b/src/common/gazelle_fault_inject_common.h -new file mode 100644 -index 0000000..3a77f39 ---- /dev/null -+++ b/src/common/gazelle_fault_inject_common.h -@@ -0,0 +1,75 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __GAZELLE_INJECT_COMMON_H__ -+#define __GAZELLE_INJECT_COMMON_H__ -+ -+#include -+ -+enum GAZELLE_FAULT_INJECT_TYPE { -+ GAZELLE_FAULT_INJECT_TYPE_ERR = 0, -+ GAZELLE_FAULT_INJECT_PACKET_DELAY, -+ GAZELLE_FAULT_INJECT_PACKET_LOSS, -+ GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, -+ GAZELLE_FAULT_INJECT_PACKET_REORDER, -+ GAZELLE_FAULT_INJECT_TYPE_MAX, -+}; -+ -+enum GAZELLE_FAULT_INJECT_RULE { -+ INJECT_RULE_ERR = 0, -+ /* packet delay rule */ -+ INJECT_DELAY_RANDOM, -+ /* packet loss rule */ -+ INJECT_LOSS_RANDOM, -+ /* packet duplicate */ -+ INJECT_DUPLICATE_RANDOM, -+ /* packet reorder */ -+ INJECT_REORDER_RANDOM, -+}; -+ -+/* fault inject delay: packet delay's time and range, time unit is "ms" */ -+struct delay_data { -+ uint32_t delay_time; -+ uint32_t delay_range; -+}; -+ -+/* fault inject loss: packet loss rate */ -+struct loss_data { -+ double loss_rate; -+ uint32_t loss_sigle_count; -+}; -+ -+/* fault inject duplicate: packet duplicate rate and duplicate count */ -+struct duplicate_data { -+ double duplicate_rate; -+ uint32_t duplicate_sigle_count; -+}; -+ -+/* fault inject reorder: packet reorder rate and reorder count */ -+struct reorder_data { -+ double reorder_rate; -+ uint32_t reorder_sigle_count; -+}; -+ -+struct gazelle_fault_inject_data { -+ int32_t fault_inject_on; -+ enum GAZELLE_FAULT_INJECT_TYPE inject_type; -+ enum GAZELLE_FAULT_INJECT_RULE inject_rule; -+ union { -+ struct delay_data delay; -+ struct loss_data loss; -+ struct duplicate_data duplicate; -+ struct reorder_data reorder; -+ } inject_data; -+}; -+ -+#endif /* __GAZELLE_INJECT_COMMON_H__ */ -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index df1ddaa..d2c039d 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -47,6 +47,11 @@ ifeq ($(GAZELLE_COVERAGE_ENABLE), 1) - CFLAGS += -fprofile-arcs -ftest-coverage - endif - -+ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1) -+ LDFLAGS += -DGAZELLE_FAULT_INJECT_ENABLE -+ CFLAGS += -DGAZELLE_FAULT_INJECT_ENABLE -+endif -+ - ifeq ($(shell $(CC) -dumpmachine | cut -d"-" -f1), x86_64) - CFLAGS += -mssse3 - endif -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 025291d..783f21c 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -34,6 +34,10 @@ - #include "lstack_protocol_stack.h" - #include "lstack_control_plane.h" - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+#include "lstack_fault_inject.h" -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - /* intervals between two connection attempts and two registration attempts, in second */ - #define CONNECT_TO_LTRAN_INFINITE (-1) - #define CONNECT_TO_LTRAN_RETRY_INTERVAL 1 -@@ -582,7 +586,14 @@ static int32_t handle_stat_request(int32_t sockfd) - LSTACK_LOG(ERR, LSTACK, "recv wrong stat mode %d\n", (int32_t)msg.stat_mode); - return 0; - } -- -+ -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ if (msg.stat_mode == GAZELLE_STAT_FAULT_INJECT_SET || -+ msg.stat_mode == GAZELLE_STAT_FAULT_INJECT_UNSET) { -+ return handle_fault_inject_cmd(sockfd, &msg); -+ } -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - if (msg.stat_mode == GAZELLE_STAT_LSTACK_LOG_LEVEL_SET || - msg.stat_mode == GAZELLE_STAT_LSTACK_LOW_POWER_MDF) { - return handle_proc_cmd(sockfd, &msg); -diff --git a/src/lstack/include/lstack_fault_inject.h b/src/lstack/include/lstack_fault_inject.h -new file mode 100644 -index 0000000..d54f1f2 ---- /dev/null -+++ b/src/lstack/include/lstack_fault_inject.h -@@ -0,0 +1,20 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __GAZELLE_INJECT_H__ -+#define __GAZELLE_INJECT_H__ -+ -+#include -+ -+int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_stat_msg_request *msg); -+ -+#endif /* __GAZELLE_INJECT_H__ */ -diff --git a/src/lstack/include/lstack_vdev.h b/src/lstack/include/lstack_vdev.h -index 4e5d191..1a8342a 100644 ---- a/src/lstack/include/lstack_vdev.h -+++ b/src/lstack/include/lstack_vdev.h -@@ -18,5 +18,6 @@ struct gazelle_quintuple; - enum reg_ring_type; - void vdev_dev_ops_init(struct lstack_dev_ops *dev_ops); - int vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple); -+uint32_t vdev_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts); - - #endif /* _GAZELLE_VDEV_H_ */ -diff --git a/src/lstack/netif/dir.mk b/src/lstack/netif/dir.mk -index 20fb5d6..1e67734 100644 ---- a/src/lstack/netif/dir.mk -+++ b/src/lstack/netif/dir.mk -@@ -9,4 +9,7 @@ - # See the Mulan PSL v2 for more details. - - SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c -+ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1) -+ SRC += lstack_fault_inject.c -+endif - $(eval $(call register_dir, netif, $(SRC))) -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -new file mode 100644 -index 0000000..4daad10 ---- /dev/null -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -0,0 +1,187 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "lstack_cfg.h" -+#include "lstack_log.h" -+#include "lstack_vdev.h" -+ -+#define INJECT_MODULO 1000 /* used in modulus operator */ -+#define INJECT_US_TO_MS 1000 /* transefer time unit us to ms */ -+ -+typedef int32_t (*inject_xmit_func)(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data); -+struct inject_tbl { -+ struct gazelle_fault_inject_data inject_data; -+ inject_xmit_func inject_func; -+}; -+static struct inject_tbl g_inject_tbl[GAZELLE_FAULT_INJECT_TYPE_MAX]; -+ -+struct inject_func_tbl { -+ enum GAZELLE_FAULT_INJECT_TYPE type; -+ enum GAZELLE_FAULT_INJECT_RULE rule; -+ inject_xmit_func inject_func; -+}; -+ -+static int32_t inject_packet_delay_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data); -+static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data); -+ -+static struct inject_func_tbl g_inject_func_tbl[] = { -+ {GAZELLE_FAULT_INJECT_PACKET_LOSS, INJECT_LOSS_RANDOM, inject_packet_loss_random}, -+ {GAZELLE_FAULT_INJECT_PACKET_DELAY, INJECT_DELAY_RANDOM, inject_packet_delay_random}, -+}; -+ -+static int32_t inject_func_tbl_update() -+{ -+ int32_t func_count = sizeof(g_inject_func_tbl) / sizeof(g_inject_func_tbl[0]); -+ -+ for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ if (!g_inject_tbl[i].inject_data.fault_inject_on) { -+ continue; -+ } -+ for (int32_t j = 0; j < func_count; ++j) { -+ if (g_inject_func_tbl[j].type == g_inject_tbl[i].inject_data.inject_type && -+ g_inject_func_tbl[j].rule == g_inject_tbl[i].inject_data.inject_rule) { -+ g_inject_tbl[i].inject_func = g_inject_func_tbl[j].inject_func; -+ } -+ } -+ } -+ return 0; -+} -+ -+static uint32_t inject_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) -+{ -+ for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ if (g_inject_tbl[i].inject_data.fault_inject_on) { -+ int32_t xmit_pkts = 0; -+ xmit_pkts = g_inject_tbl[i].inject_func(stack, pkts, nr_pkts, -+ g_inject_tbl[i].inject_data); -+ if (xmit_pkts == nr_pkts) { -+ continue; -+ } -+ return xmit_pkts; -+ } -+ } -+ if (rte_mbuf_refcnt_read(*pkts) == 1) { -+ return nr_pkts; -+ } -+ return vdev_tx_xmit(stack, pkts, nr_pkts); -+} -+ -+static int32_t inject_strategy_update() -+{ -+ inject_func_tbl_update(); -+ -+ int32_t inject_on = 0; -+ for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ if (g_inject_tbl[i].inject_data.fault_inject_on) { -+ inject_on = 1; -+ break; -+ } -+ } -+ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ -+ if (inject_on) { -+ for (uint32_t i = 0; i < stack_group->stack_num; ++i) { -+ struct protocol_stack *stack = stack_group->stacks[i]; -+ stack->dev_ops.tx_xmit = inject_tx_xmit; -+ } -+ return 0; -+ } -+ -+ for (uint32_t i = 0; i < stack_group->stack_num; ++i) { -+ struct protocol_stack *stack = stack_group->stacks[i]; -+ vdev_dev_ops_init(&stack->dev_ops); -+ } -+ -+ return 0; -+} -+ -+static int32_t inject_packet_delay_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data) -+{ -+ /* while *pkts->refcnt == 1, other inject type is on, and the packets have been loss. */ -+ if (rte_mbuf_refcnt_read(*pkts) == 1) { -+ return nr_pkts; -+ } -+ int32_t delay_time = data.inject_data.delay.delay_time; -+ int32_t delay_range = data.inject_data.delay.delay_range; -+ int32_t rand_num = rte_rand(); -+ rand_num %= INJECT_MODULO; -+ delay_time += delay_range * rand_num / INJECT_MODULO; -+ rte_delay_us(delay_time * INJECT_US_TO_MS); -+ -+ return nr_pkts; -+} -+ -+static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data) -+{ -+ double loss_rate = data.inject_data.loss.loss_rate; -+ int32_t boundary = (int32_t) (loss_rate * INJECT_MODULO); -+ -+ uint32_t rand_num = rte_rand(); -+ rand_num %= INJECT_MODULO; -+ -+ if (rand_num > boundary) { -+ return nr_pkts; -+ } -+ -+ for (int32_t i = 0; i < nr_pkts; ++i) { -+ rte_pktmbuf_free(pkts[i]); -+ } -+ return nr_pkts; -+} -+ -+int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_stat_msg_request *msg) -+{ -+ struct gazelle_stack_dfx_data rsp = {0}; -+ int32_t ret = 0; -+ -+ ret = memcpy_s(&g_inject_tbl[msg->data.inject.inject_type].inject_data, -+ sizeof(struct gazelle_fault_inject_data), -+ &msg->data.inject, sizeof(struct gazelle_fault_inject_data)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject memcpy_s error, ret = %d", ret); -+ return -1; -+ } -+ -+ inject_strategy_update(); -+ -+ for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ ret = memcpy_s(&rsp.data.inject, sizeof(struct gazelle_fault_inject_data), -+ &g_inject_tbl[i].inject_data, sizeof(struct gazelle_fault_inject_data)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject memcpy_s error, ret = %d", ret); -+ return -1; -+ } -+ if (i == GAZELLE_FAULT_INJECT_TYPE_MAX -1) { -+ rsp.eof = 1; -+ } -+ ret = (int32_t) posix_api->write_fn(sockfd, (void *)&rsp, sizeof(rsp)); -+ if (ret <= 0) { -+ LSTACK_LOG(ERR, LSTACK, "write msg from peer failed, errno %d. ret=%d\n", errno, ret); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 3703092..107ee8c 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -150,7 +150,7 @@ static uint32_t ltran_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pk - return sent_pkts; - } - --static uint32_t vdev_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) -+uint32_t vdev_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) - { - uint32_t sent_pkts = 0; - -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index f739ceb..a484ae3 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -27,6 +27,11 @@ if($ENV{GAZELLE_COVERAGE_ENABLE}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs") - endif($ENV{GAZELLE_COVERAGE_ENABLE}) - -+if($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -+ message("Enable Fault inject option") -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGAZELLE_FAULT_INJECT_ENABLE") -+endif($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -+ - execute_process( - COMMAND rpm -qa dpdk - OUTPUT_VARIABLE DPDK_VERSION_FULL -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 344afb2..413bf89 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -60,6 +60,46 @@ static struct gazelle_stat_ltran_total g_last_ltran_total; - static struct gazelle_stat_lstack_total g_last_lstack_total[GAZELLE_MAX_STACK_ARRAY_SIZE]; - static struct gazelle_stack_dfx_data g_last_lstack_data[GAZELLE_MAX_STACK_ARRAY_SIZE]; - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+#define INJECT_NAME_SIZE 32 -+#define INJECT_RULE_SIZE 32 -+ -+typedef int32_t (*inject_parse_digit_fun)(char*, char*, struct gazelle_stat_msg_request *req_msg); -+static int32_t parse_inject_packet_delay_digit(char *time, char *range, struct gazelle_stat_msg_request *req_msg); -+static int32_t parse_inject_packet_loss_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg); -+static int32_t parse_inject_packet_duplicate_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg); -+static int32_t parse_inject_packet_reorder_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg); -+ -+struct gazelle_fault_inject_type_list { -+ char inject_type_item[INJECT_NAME_SIZE]; -+ enum GAZELLE_FAULT_INJECT_TYPE inject_type_parsed; -+ inject_parse_digit_fun parse_digit_func; -+}; -+ -+static struct gazelle_fault_inject_type_list inject_type_list[] = { -+ {"delay", GAZELLE_FAULT_INJECT_PACKET_DELAY, parse_inject_packet_delay_digit}, -+ {"loss", GAZELLE_FAULT_INJECT_PACKET_LOSS, parse_inject_packet_loss_digit}, -+ {"duplicate", GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, parse_inject_packet_duplicate_digit}, -+ {"reorder", GAZELLE_FAULT_INJECT_PACKET_REORDER, parse_inject_packet_reorder_digit}, -+}; -+ -+struct gazelle_fault_inject_rule_list { -+ char inject_rule_item[INJECT_RULE_SIZE]; -+ enum GAZELLE_FAULT_INJECT_RULE inject_rule_parsed; -+ enum GAZELLE_FAULT_INJECT_TYPE rule_parse_assit; -+}; -+ -+static struct gazelle_fault_inject_rule_list g_gazelle_fault_inject_rule_list[] = { -+ {"random", INJECT_DELAY_RANDOM, GAZELLE_FAULT_INJECT_PACKET_DELAY}, -+ {"random", INJECT_LOSS_RANDOM, GAZELLE_FAULT_INJECT_PACKET_LOSS}, -+ {"random", INJECT_DUPLICATE_RANDOM, GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE}, -+ {"random", INJECT_REORDER_RANDOM, GAZELLE_FAULT_INJECT_PACKET_REORDER}, -+}; -+ -+static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -+ -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - static bool g_use_ltran = false; - - static char* g_unix_prefix; -@@ -95,6 +135,11 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg); - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_fault_inject_unset_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LTRAN_SHOW, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_total}, - {GAZELLE_STAT_LTRAN_SHOW_RATE, sizeof(struct gazelle_stat_ltran_total), gazelle_print_ltran_stat_rate}, -@@ -121,6 +166,11 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LSTACK_SHOW_XSTATS, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_xstats}, - {GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_aggregate}, - {GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_nic_features}, -+ -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ {GAZELLE_STAT_FAULT_INJECT_SET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_set_status}, -+ {GAZELLE_STAT_FAULT_INJECT_UNSET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_unset_status}, -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ - }; - - static int32_t g_wait_reply = 1; -@@ -1121,7 +1171,10 @@ static void show_usage(void) - { - printf("Usage: gazellectl [-h | help] \n" - " or: gazellectl ltran {quit | show | set} [LTRAN_OPTIONS] [-u UNIX_PREFIX]\n" -- " or: gazellectl lstack {show | set} ip [LSTACK_OPTIONS] [-u UNIX_PREFIX]\n \n" -+ " or: gazellectl lstack {show | set} ip [LSTACK_OPTIONS] [-u UNIX_PREFIX]\n\n" -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ " or: gazellectl inject [inject_type] [digit_param_1] [digit_param_2] [inject_rule]\n\n" -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ - " quit ltran process exit \n \n" - " where LTRAN_OPTIONS := \n" - " show: \n" -@@ -1146,7 +1199,13 @@ static void show_usage(void) - " set: \n" - " loglevel {error | info | debug} set lstack loglevel \n" - " lowpower {0 | 1} set lowpower enable \n" -- " [time] measure latency time default 1S, maximum 30mins \n"); -+ " [time] measure latency time default 1S, maximum 30mins \n\n" -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ " *inject params*\n" -+ " |inject_type | digit_param_1 | digit_param_2 | inject_rule |\n" -+ " | delay | delay_time(unit: ms) | delay_range(unit: ms) | random |\n" -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ ); - } - - static int32_t parse_dfx_ltran_set_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) -@@ -1436,6 +1495,211 @@ static int32_t parse_dfx_lstack_args(int32_t argc, char *argv[], struct gazelle_ - return num_cmd; - } - -+ -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ -+#define GAZELLE_SET_FAULT_INJECT_PARAM_COUNT 6 -+#define GAZELLE_UNSET_FAULT_INJECT_PARAM_COUNT 4 -+#define INJECT_TYPE_INDEX 2 -+#define INJECT_DIGITAL_FIRST_INDEX 3 -+#define INJECT_DIGITAL_SECOND_INDEX 4 -+#define INJECT_RULE_INDEX 5 -+ -+ -+static void gazelle_print_fault_inject_type_info(struct gazelle_fault_inject_data *inject) -+{ -+ if (!inject->fault_inject_on) { -+ return; -+ } -+ -+ if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_DELAY) { -+ printf("\t| inject_type: delay | delay_time: %-7d | delay_range: %-3d | " -+ "inject_rule: random |\n", inject->inject_data.delay.delay_time, -+ inject->inject_data.delay.delay_range); -+ } -+ -+#define INJECT_PERCENT 100 -+ -+ if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_LOSS) { -+ printf("\t| inject_type: loss | loss_rate: %-3.1f%% | loss_single_count: %-3d | " -+ "inject_rule: random |\n", inject->inject_data.loss.loss_rate * INJECT_PERCENT, -+ inject->inject_data.loss.loss_sigle_count); -+ } -+ printf("\n"); -+} -+ -+static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t ret; -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct gazelle_fault_inject_data *inject = &stat->data.inject; -+ -+ printf("\n\n\t\t\t\t\t **** FAULT INJECT INFO **** \n\n"); -+ do { -+ gazelle_print_fault_inject_type_info(inject); -+ if (stat->eof != 0) { -+ break; -+ } -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); -+ if (ret != GAZELLE_OK) { -+ return; -+ } -+ } while (true); -+} -+ -+static void gazelle_print_fault_inject_unset_status(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ return; -+} -+ -+static int32_t parse_inject_packet_delay_digit(char* time, char* range, struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t parse_success = 0; -+ int32_t delay_time = atoi(time); -+ if (delay_time <= 0) { -+ printf("FAULT INJECT error: delay time error -- %d, need positive integer.\n", delay_time); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.delay.delay_time = (uint32_t) delay_time; -+ -+ int32_t delay_range = atoi(range); -+ if (delay_range < 0) { -+ printf("FAULT INJECT error: delay range error -- %d, need positive integer.\n", delay_range); -+ return parse_success; -+ } -+ if (delay_time - delay_range <= 0) { -+ printf("FAULT INJECT error: delay range should lower than delay time.\n"); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.delay.delay_range = delay_range; -+ -+ return ++parse_success; -+} -+ -+#define INJECT_RATE_LOWER 0.001 -+ -+static int32_t parse_inject_packet_loss_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t parse_success = 0; -+ double loss_rate = atof(rate); -+ if (loss_rate < INJECT_RATE_LOWER || loss_rate >= 1) { -+ printf("FAULT INJECT error: loss rate error, range in [0.001, 1), now is %f\n", loss_rate); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.loss.loss_rate = loss_rate; -+ -+ int32_t loss_counts = atoi(count); -+ if (loss_counts <= 0) { -+ printf("FAULT INJECT error: single loss counts wrong --%d, need positive integer.", loss_counts); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.loss.loss_sigle_count = loss_counts; -+ -+ return ++parse_success; -+} -+ -+static int32_t parse_inject_packet_duplicate_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t parse_success = 0; -+ double duplicate_rate = atof(rate); -+ if (duplicate_rate < INJECT_RATE_LOWER || duplicate_rate >= 1) { -+ printf("FAULT INJECT error: duplicate rate error, range in [0.001, 1), now is %f\n", duplicate_rate); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.duplicate.duplicate_rate = duplicate_rate; -+ -+ int32_t duplicate_counts = atoi(count); -+ if (duplicate_counts <= 0) { -+ printf("FAULT INJECT error: single duplicate counts wrong --%d, need positive integer.", duplicate_counts); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.duplicate.duplicate_sigle_count = duplicate_counts; -+ -+ return ++parse_success; -+} -+ -+static int32_t parse_inject_packet_reorder_digit(char *rate, char *count, struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t parse_success = 0; -+ double reorder_rate = atof(rate); -+ if (reorder_rate < INJECT_RATE_LOWER || reorder_rate >= 1) { -+ printf("FAULT INJECT error: reorder rate error, range in [0.001, 1), now is %f\n", reorder_rate); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.reorder.reorder_rate = reorder_rate; -+ -+ int32_t reorder_counts = atoi(count); -+ if (reorder_counts <= 0) { -+ printf("FAULT INJECT error: single duplicate counts wrong --%d, need positive integer.", reorder_counts); -+ return parse_success; -+ } -+ req_msg->data.inject.inject_data.reorder.reorder_sigle_count = reorder_counts; -+ -+ return ++parse_success; -+} -+ -+static int32_t parse_fault_inject_digital_data(char *argv[], struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t parse_success = 0; -+ int32_t func_count = sizeof(inject_type_list) / sizeof(inject_type_list[0]); -+ for (int32_t i = 0; i < func_count; ++i) { -+ if (inject_type_list[i].inject_type_parsed == req_msg->data.inject.inject_type) { -+ parse_success = inject_type_list[i].parse_digit_func(argv[INJECT_DIGITAL_FIRST_INDEX], -+ argv[INJECT_DIGITAL_SECOND_INDEX], req_msg); -+ break; -+ } -+ } -+ -+ return parse_success; -+} -+ -+static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t num_cmd = 0; /* while parse error, num_cmd will return as 0, or num_cmd should be returned as 1. */ -+ -+ req_msg->data.inject.fault_inject_on = 1; /* set fault inject on */ -+ -+ if (argc == GAZELLE_SET_FAULT_INJECT_PARAM_COUNT) { -+ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_SET; -+ } else if (argc == GAZELLE_UNSET_FAULT_INJECT_PARAM_COUNT) { -+ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_UNSET; -+ } else { -+ printf("FAULT_INJECT error: Count of params wrong , correct count is 6 or 4, now is %d\n", argc); -+ return num_cmd; -+ } -+ -+ int32_t inject_type_count = sizeof(inject_type_list) / sizeof(inject_type_list[0]); -+ for (int32_t i = 0; i < inject_type_count; ++i) { -+ if (strcmp(inject_type_list[i].inject_type_item, argv[INJECT_TYPE_INDEX]) == 0) { -+ req_msg->data.inject.inject_type = inject_type_list[i].inject_type_parsed; -+ break; -+ } -+ } -+ if (req_msg->data.inject.inject_type == GAZELLE_FAULT_INJECT_TYPE_ERR) { -+ printf("FAULT_INJECT error: input inject type is wrong -- %s\n", argv[INJECT_TYPE_INDEX]); -+ return num_cmd; -+ } -+ -+ int32_t inject_rule_count = sizeof(g_gazelle_fault_inject_rule_list) / sizeof(g_gazelle_fault_inject_rule_list[0]); -+ for (int32_t i = 0; i < inject_rule_count; ++i) { -+ if (strcmp(g_gazelle_fault_inject_rule_list[i].inject_rule_item, argv[INJECT_RULE_INDEX]) == 0 && -+ g_gazelle_fault_inject_rule_list[i].rule_parse_assit == req_msg->data.inject.inject_type) { -+ req_msg->data.inject.inject_rule = g_gazelle_fault_inject_rule_list[i].inject_rule_parsed; -+ break; -+ } -+ } -+ if (req_msg->data.inject.inject_rule == INJECT_RULE_ERR) { -+ printf("FAULT_INJECT error: input inject rule is wrong -- %s\n", argv[INJECT_RULE_INDEX]); -+ return num_cmd; -+ } -+ -+ num_cmd = parse_fault_inject_digital_data(argv, req_msg); -+ -+ return num_cmd; -+} -+ -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -+ - static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) - { - int32_t num_cmd = 0; -@@ -1451,7 +1715,11 @@ static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_sta - if (strcmp(param, "lstack") == 0) { - num_cmd = parse_dfx_lstack_args(argc, argv, req_msg); - } -- -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+ if (strcmp(param, "inject") == 0) { -+ num_cmd = parse_dfx_fault_inject_args(argc, argv, req_msg); -+ } -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ - return num_cmd; - } - --- -2.27.0 - diff --git a/0141-recv-support-MSG_DONTWAIT.patch b/0141-recv-support-MSG_DONTWAIT.patch deleted file mode 100644 index 403b96b..0000000 --- a/0141-recv-support-MSG_DONTWAIT.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 34c272bf7f0484a1371033c187719adc72f061d5 Mon Sep 17 00:00:00 2001 -From: li_yunqing -Date: Tue, 27 Feb 2024 16:58:59 +0800 -Subject: [PATCH] recv support MSG_DONTWAIT - ---- - src/lstack/core/lstack_lwip.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 0b339fe..7715cf3 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -993,6 +993,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - { - ssize_t recvd = 0; - struct lwip_sock *sock = get_socket_by_fd(fd); -+ bool noblock = (flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn); - - if (recv_break_for_err(sock)) { - return -1; -@@ -1005,9 +1006,9 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - } - - if (NETCONN_IS_UDP(sock)) { -- recvd = recv_ring_udp_read(sock, buf, len, netconn_is_nonblocking(sock->conn), addr, addrlen); -+ recvd = recv_ring_udp_read(sock, buf, len, noblock, addr, addrlen); - } else { -- recvd = recv_ring_tcp_read(sock, buf, len, netconn_is_nonblocking(sock->conn)); -+ recvd = recv_ring_tcp_read(sock, buf, len, noblock); - } - - /* rte_ring_count reduce lock */ --- -2.27.0 - diff --git a/0142-do_setsockopt-function-no-longer-checks-the-results-.patch b/0142-do_setsockopt-function-no-longer-checks-the-results-.patch deleted file mode 100644 index 8a87350..0000000 --- a/0142-do_setsockopt-function-no-longer-checks-the-results-.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 712a3c23451ed79449cea9322586d958c27c679f Mon Sep 17 00:00:00 2001 -From: jiangjixiang -Date: Fri, 1 Mar 2024 10:10:01 +0800 -Subject: [PATCH] do_setsockopt function no longer checks the results of the - kernel. - ---- - src/lstack/api/lstack_wrap.c | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8992e39..1e36d3d 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -398,10 +398,7 @@ static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, c - } - - /* we both set kernel and lwip */ -- int32_t ret = posix_api->setsockopt_fn(s, level, optname, optval, optlen); -- if (ret != 0) { -- return ret; -- } -+ posix_api->setsockopt_fn(s, level, optname, optval, optlen); - - return g_wrap_api->setsockopt_fn(s, level, optname, optval, optlen); - } --- -2.27.0 - diff --git a/0143-FAUT-INJECT-add-fault-inject-unset-method.patch b/0143-FAUT-INJECT-add-fault-inject-unset-method.patch deleted file mode 100644 index 31a8c4b..0000000 --- a/0143-FAUT-INJECT-add-fault-inject-unset-method.patch +++ /dev/null @@ -1,254 +0,0 @@ -From c2cf2ef0cc9f28a8322e17870d209f546ad6711d Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 4 Mar 2024 11:15:34 +0800 -Subject: [PATCH] FAUT INJECT: add fault inject unset method - ---- - src/lstack/core/lstack_control_plane.c | 2 +- - src/lstack/include/lstack_fault_inject.h | 2 +- - src/lstack/netif/lstack_fault_inject.c | 60 ++++++++++++---- - src/ltran/ltran_dfx.c | 92 +++++++++++++++++++++--- - 4 files changed, 131 insertions(+), 25 deletions(-) - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 783f21c..9f0c313 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -590,7 +590,7 @@ static int32_t handle_stat_request(int32_t sockfd) - #ifdef GAZELLE_FAULT_INJECT_ENABLE - if (msg.stat_mode == GAZELLE_STAT_FAULT_INJECT_SET || - msg.stat_mode == GAZELLE_STAT_FAULT_INJECT_UNSET) { -- return handle_fault_inject_cmd(sockfd, &msg); -+ return handle_fault_inject_cmd(sockfd, msg.data.inject, msg.stat_mode); - } - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ - -diff --git a/src/lstack/include/lstack_fault_inject.h b/src/lstack/include/lstack_fault_inject.h -index d54f1f2..afd8faf 100644 ---- a/src/lstack/include/lstack_fault_inject.h -+++ b/src/lstack/include/lstack_fault_inject.h -@@ -15,6 +15,6 @@ - - #include - --int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_stat_msg_request *msg); -+int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_fault_inject_data inject, enum GAZELLE_STAT_MODE stat_mode); - - #endif /* __GAZELLE_INJECT_H__ */ -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -index 4daad10..41e7d95 100644 ---- a/src/lstack/netif/lstack_fault_inject.c -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -150,21 +150,10 @@ static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rt - return nr_pkts; - } - --int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_stat_msg_request *msg) -+static int32_t inject_respond_msg(int32_t sockfd) - { - struct gazelle_stack_dfx_data rsp = {0}; - int32_t ret = 0; -- -- ret = memcpy_s(&g_inject_tbl[msg->data.inject.inject_type].inject_data, -- sizeof(struct gazelle_fault_inject_data), -- &msg->data.inject, sizeof(struct gazelle_fault_inject_data)); -- if (ret != EOK) { -- LSTACK_LOG(ERR, LSTACK, "fault inject memcpy_s error, ret = %d", ret); -- return -1; -- } -- -- inject_strategy_update(); -- - for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { - ret = memcpy_s(&rsp.data.inject, sizeof(struct gazelle_fault_inject_data), - &g_inject_tbl[i].inject_data, sizeof(struct gazelle_fault_inject_data)); -@@ -185,3 +174,50 @@ int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_stat_msg_request - return 0; - } - -+static int32_t inject_unset_cmd(int32_t sockfd, struct gazelle_fault_inject_data inject) -+{ -+ if (inject.inject_type == GAZELLE_FAULT_INJECT_TYPE_MAX) { -+ /* means unset all kinds of fault inject type */ -+ for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ g_inject_tbl[i].inject_data.fault_inject_on = 0; -+ } -+ } else { -+ int32_t ret = 0; -+ ret = memcpy_s(&g_inject_tbl[inject.inject_type].inject_data, -+ sizeof(struct gazelle_fault_inject_data), -+ &inject, sizeof(struct gazelle_fault_inject_data)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject memcpy_s error, ret = %d", ret); -+ return -1; -+ } -+ } -+ -+ inject_strategy_update(); -+ -+ return inject_respond_msg(sockfd); -+} -+ -+static int32_t inject_set_cmd(int32_t sockfd, struct gazelle_fault_inject_data inject) -+{ -+ int32_t ret = 0; -+ ret = memcpy_s(&g_inject_tbl[inject.inject_type].inject_data, -+ sizeof(struct gazelle_fault_inject_data), -+ &inject, sizeof(struct gazelle_fault_inject_data)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject memcpy_s error, ret = %d", ret); -+ return -1; -+ } -+ -+ inject_strategy_update(); -+ -+ return inject_respond_msg(sockfd); -+} -+ -+int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_fault_inject_data inject, enum GAZELLE_STAT_MODE stat_mode) -+{ -+ if (stat_mode == GAZELLE_STAT_FAULT_INJECT_UNSET) { -+ return inject_unset_cmd(sockfd, inject); -+ } -+ return inject_set_cmd(sockfd, inject); -+} -+ -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 413bf89..96509e5 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -97,7 +97,7 @@ static struct gazelle_fault_inject_rule_list g_gazelle_fault_inject_rule_list[] - }; - - static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -- -+static void gazelle_print_fault_inject_unset_status(void *buf, const struct gazelle_stat_msg_request *req_msg); - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ - - static bool g_use_ltran = false; -@@ -1504,6 +1504,7 @@ static int32_t parse_dfx_lstack_args(int32_t argc, char *argv[], struct gazelle_ - #define INJECT_DIGITAL_FIRST_INDEX 3 - #define INJECT_DIGITAL_SECOND_INDEX 4 - #define INJECT_RULE_INDEX 5 -+#define INJECT_UNSET_TYPE_INDEX 3 - - - static void gazelle_print_fault_inject_type_info(struct gazelle_fault_inject_data *inject) -@@ -1549,6 +1550,33 @@ static void gazelle_print_fault_inject_set_status(void *buf, const struct gazell - - static void gazelle_print_fault_inject_unset_status(void *buf, const struct gazelle_stat_msg_request *req_msg) - { -+ int32_t ret; -+ static int32_t inject_enable[GAZELLE_FAULT_INJECT_TYPE_MAX]; -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct gazelle_fault_inject_data *inject = &stat->data.inject; -+ -+ printf("\n\t\t\t\t\t **** INJECT ENABLE ITEM **** \n\n"); -+ do { -+ inject_enable[inject->inject_type] = inject->fault_inject_on; -+ gazelle_print_fault_inject_type_info(inject); -+ if (stat->eof != 0) { -+ break; -+ } -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); -+ if (ret != GAZELLE_OK) { -+ return; -+ } -+ } while (true); -+ -+ printf("\n\n\t\t\t\t\t **** INJECT DISABLE ITEM **** \n\n"); -+ printf("\tThe currently closed inject types are: "); -+ for (int32_t i = 1; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -+ if (!inject_enable[i]) { -+ /* i - 1 means fault inject type mapping inject_type_item name */ -+ printf("\"%s\" ", inject_type_list[i - 1].inject_type_item); -+ } -+ } -+ printf("\n"); - return; - } - -@@ -1653,21 +1681,45 @@ static int32_t parse_fault_inject_digital_data(char *argv[], struct gazelle_stat - return parse_success; - } - --static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) -+static int32_t parse_fault_inject_unset_type(char *argv[], struct gazelle_stat_msg_request *req_msg) - { -- int32_t num_cmd = 0; /* while parse error, num_cmd will return as 0, or num_cmd should be returned as 1. */ -- -- req_msg->data.inject.fault_inject_on = 1; /* set fault inject on */ -+ int32_t num_cmd = 0; -+ -+ if (strcmp(argv[INJECT_TYPE_INDEX], "unset") != 0) { -+ printf("FAULT_INJECT error: unrecognized input -- %s, should be \"unset\"\n", argv[INJECT_TYPE_INDEX]); -+ return num_cmd; -+ } -+ -+ req_msg->data.inject.fault_inject_on = 0; /* unset fault inject */ -+ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_UNSET; -+ -+ if (strcmp(argv[INJECT_UNSET_TYPE_INDEX], "all") == 0) { -+ req_msg->data.inject.inject_type = GAZELLE_FAULT_INJECT_TYPE_MAX; -+ return ++num_cmd; -+ } - -- if (argc == GAZELLE_SET_FAULT_INJECT_PARAM_COUNT) { -- req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_SET; -- } else if (argc == GAZELLE_UNSET_FAULT_INJECT_PARAM_COUNT) { -- req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_UNSET; -- } else { -- printf("FAULT_INJECT error: Count of params wrong , correct count is 6 or 4, now is %d\n", argc); -+ int32_t inject_type_count = sizeof(inject_type_list) / sizeof(inject_type_list[0]); -+ for (int32_t i = 0; i < inject_type_count; ++i) { -+ if (strcmp(inject_type_list[i].inject_type_item, argv[INJECT_UNSET_TYPE_INDEX]) == 0) { -+ req_msg->data.inject.inject_type = inject_type_list[i].inject_type_parsed; -+ break; -+ } -+ } -+ if (req_msg->data.inject.inject_type == GAZELLE_FAULT_INJECT_TYPE_ERR) { -+ printf("FAULT_INJECT error: input inject type is wrong -- %s\n", argv[INJECT_TYPE_INDEX]); - return num_cmd; - } - -+ return ++num_cmd; -+} -+ -+static int32_t parse_fault_inject_set_type(char *argv[], struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t num_cmd = 0; -+ -+ req_msg->data.inject.fault_inject_on = 1; /* set fault inject on */ -+ req_msg->stat_mode = GAZELLE_STAT_FAULT_INJECT_SET; -+ - int32_t inject_type_count = sizeof(inject_type_list) / sizeof(inject_type_list[0]); - for (int32_t i = 0; i < inject_type_count; ++i) { - if (strcmp(inject_type_list[i].inject_type_item, argv[INJECT_TYPE_INDEX]) == 0) { -@@ -1698,6 +1750,24 @@ static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct ga - return num_cmd; - } - -+static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t num_cmd = 0; /* while parse error, num_cmd will return as 0, or num_cmd should be returned as 1. */ -+ -+ if (argc == GAZELLE_UNSET_FAULT_INJECT_PARAM_COUNT) { -+ num_cmd = parse_fault_inject_unset_type(argv, req_msg); -+ return num_cmd; -+ } -+ -+ if (argc == GAZELLE_SET_FAULT_INJECT_PARAM_COUNT) { -+ num_cmd = parse_fault_inject_set_type(argv, req_msg); -+ return num_cmd; -+ } -+ -+ printf("FAULT_INJECT error: Count of params wrong , correct count is 6 or 4, now is %d\n", argc); -+ return num_cmd; -+} -+ - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ - - static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) --- -2.27.0 - diff --git a/0144-support-udp-pkglen-mtu.patch b/0144-support-udp-pkglen-mtu.patch deleted file mode 100644 index c03fd04..0000000 --- a/0144-support-udp-pkglen-mtu.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 5ba19529acaf76a681313245a9a278356b615687 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 4 Mar 2024 14:10:43 +0800 -Subject: [PATCH] support udp pkglen > mtu - ---- - src/lstack/core/lstack_lwip.c | 20 ++++++++++++++++++-- - src/lstack/include/lstack_dpdk.h | 2 +- - 2 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 7715cf3..f4199f8 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -252,6 +252,13 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - return NULL; - } - -+ /* udp send a pbuf chain, dequeue all pbufs except head pbuf */ -+ if (NETCONN_IS_UDP(sock) && remain_size > MBUF_MAX_DATA_LEN) { -+ int size = (remain_size + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN - 1; -+ struct pbuf *pbuf_used[size]; -+ gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf_used, size); -+ } -+ - if (get_protocol_stack_group()->latency_start) { - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP); - } -@@ -285,7 +292,7 @@ void do_lwip_get_from_sendring_over(struct lwip_sock *sock) - sock->stack->stats.write_lwip_cnt++; - } - --static ssize_t do_app_write(struct pbuf *pbufs[], void *buf, size_t len, uint32_t write_num) -+static ssize_t do_app_write(struct lwip_sock *sock, struct pbuf *pbufs[], void *buf, size_t len, uint32_t write_num) - { - ssize_t send_len = 0; - uint32_t i = 0; -@@ -297,6 +304,11 @@ static ssize_t do_app_write(struct pbuf *pbufs[], void *buf, size_t len, uint32_ - rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, MBUF_MAX_DATA_LEN); - pbufs[i]->tot_len = pbufs[i]->len = MBUF_MAX_DATA_LEN; - send_len += MBUF_MAX_DATA_LEN; -+ -+ /* if udp pkg len > mtu, use pbuf chain to send it */ -+ if (NETCONN_IS_UDP(sock) && i > 0) { -+ pbuf_cat(pbufs[0], pbufs[i]); -+ } - } - - /* reduce the branch in loop */ -@@ -305,6 +317,10 @@ static ssize_t do_app_write(struct pbuf *pbufs[], void *buf, size_t len, uint32_ - pbufs[i]->tot_len = pbufs[i]->len = copy_len; - send_len += copy_len; - -+ if (NETCONN_IS_UDP(sock) && i > 0) { -+ pbuf_cat(pbufs[0], pbufs[i]); -+ } -+ - return send_len; - } - -@@ -320,7 +336,7 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - time_stamp_into_pbuf(write_num, pbufs, time_stamp); - } - -- ssize_t send_len = do_app_write(pbufs, buf, len, write_num); -+ ssize_t send_len = do_app_write(sock, pbufs, buf, len, write_num); - - if (addr) { - if (addr->sa_family == AF_INET) { -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index c40f3c0..c7cfbdf 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -21,7 +21,7 @@ - - #define KNI_NB_MBUF (DEFAULT_RING_SIZE << 4) - --#define MAX_PACKET_SZ 1530 -+#define MAX_PACKET_SZ 1538 - - #define RING_SIZE(x) ((x) - 1) - --- -2.27.0 - diff --git a/0145-add-limit-with-level-for-sockopt.patch b/0145-add-limit-with-level-for-sockopt.patch deleted file mode 100644 index c58bbc7..0000000 --- a/0145-add-limit-with-level-for-sockopt.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 5e4b2366417b5f951ffd5ee45c0917ae67bd502e Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sun, 3 Mar 2024 21:40:23 +0800 -Subject: [PATCH] add limit with level for sockopt - ---- - src/lstack/api/lstack_wrap.c | 49 +++++++++++++++++++++++++----------- - 2 files changed, 35 insertions(+), 16 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 1e36d3d..49bbf91 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -364,27 +364,46 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - return posix_api->getsockname_fn(s, name, namelen); - } - --static bool unsupport_optname(int32_t optname) --{ -- if (optname == SO_BROADCAST || -- optname == SO_PROTOCOL || -- optname == TCP_QUICKACK || -- optname == SO_SNDTIMEO || -- optname == SO_RCVTIMEO || -- optname == SO_SNDBUF || -- optname == SO_RCVBUF || -- optname == TCP_INFO || -- optname == TCP_MAXSEG || -- optname == SO_DONTROUTE || -- optname == TCP_CONGESTION) { -+static bool unsupport_tcp_optname(int32_t optname) -+{ -+ if ((optname == TCP_QUICKACK) || -+ (optname == TCP_INFO) || -+ (optname == TCP_MAXSEG) || -+ (optname == TCP_CONGESTION)) { -+ return true; -+ } -+ return false; -+} -+ -+static bool unsupport_socket_optname(int32_t optname) -+{ -+ if ((optname == SO_BROADCAST) || -+ (optname == SO_PROTOCOL) || -+ (optname == SO_SNDTIMEO) || -+ (optname == SO_RCVTIMEO) || -+ (optname == SO_SNDBUF) || -+ (optname == SO_RCVBUF) || -+ (optname == SO_DONTROUTE)) { - return true; - } - return false; - } - -+static bool unsupport_optname(int32_t level, int32_t optname) -+{ -+ if (level == SOL_TCP) { -+ return unsupport_tcp_optname(optname); -+ } -+ -+ if (level == SOL_SOCKET) { -+ return unsupport_socket_optname(optname); -+ } -+ return false; -+} -+ - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { -- if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(optname)) { -+ if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(level, optname)) { - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -393,7 +412,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v - - static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, const void *optval, socklen_t optlen) - { -- if (select_fd_posix_path(s, NULL) == PATH_KERNEL || unsupport_optname(optname)) { -+ if (select_fd_posix_path(s, NULL) == PATH_KERNEL || unsupport_optname(level, optname)) { - return posix_api->setsockopt_fn(s, level, optname, optval, optlen); - } - --- -2.27.0 - diff --git a/0146-udp-add-restriction-message-too-long.patch b/0146-udp-add-restriction-message-too-long.patch deleted file mode 100644 index a74c49c..0000000 --- a/0146-udp-add-restriction-message-too-long.patch +++ /dev/null @@ -1,42 +0,0 @@ -From a37c451e63bed06a70e887aba6364183d71f414f Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 11 Mar 2024 11:18:54 +0800 -Subject: [PATCH] udp add restriction: message too long - ---- - src/common/gazelle_opt.h | 2 ++ - src/lstack/core/lstack_lwip.c | 5 +++++ - 2 files changed, 7 insertions(+) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 1d1c5f5..6d787b9 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -60,6 +60,8 @@ - - #define DPDK_PKT_BURST_SIZE 512 - -+#define GAZELLE_UDP_PKGLEN_MAX (65535 - IP_HLEN - UDP_HLEN) -+ - /* total:33 client, index 32 is invaild client */ - #define GAZELLE_CLIENT_NUM_ALL 33 - #define GAZELLE_NULL_CLIENT (GAZELLE_CLIENT_NUM_ALL - 1) -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index f4199f8..8aae433 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -779,6 +779,11 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - return 0; - } - -+ if (NETCONN_IS_UDP(sock) && (len > GAZELLE_UDP_PKGLEN_MAX)) { -+ LSTACK_LOG(ERR, LSTACK, "Message too long\n"); -+ GAZELLE_RETURN(EMSGSIZE); -+ } -+ - thread_bind_stack(sock); - - if (sock->same_node_tx_ring != NULL) { --- -2.27.0 - diff --git a/0147-dfx-improve-log-readability-when-connect-ltran-lstac.patch b/0147-dfx-improve-log-readability-when-connect-ltran-lstac.patch deleted file mode 100644 index f21edae..0000000 --- a/0147-dfx-improve-log-readability-when-connect-ltran-lstac.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 9d68f6bca1adfba6802e85aa213dbba5002cb289 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 27 Feb 2024 22:48:19 +0800 -Subject: [PATCH] dfx: improve log readability when connect ltran/lstack failed - ---- - src/ltran/ltran_dfx.c | 152 +++++++++++++++++++++++++++--------------- - 1 file changed, 99 insertions(+), 53 deletions(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 96509e5..a429866 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -101,6 +101,8 @@ static void gazelle_print_fault_inject_unset_status(void *buf, const struct gaze - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ - - static bool g_use_ltran = false; -+static char g_ltran_unix_path[PATH_MAX]; -+static char g_lstack_unix_path[PATH_MAX]; - - static char* g_unix_prefix; - -@@ -268,24 +270,16 @@ static void gazelle_print_ltran_sock(void *buf, const struct gazelle_stat_msg_re - printf("ltran sock table num: %u\n", table->conn_num); - } - --static int32_t dfx_connect_ltran(bool use_ltran, bool probe) -+static int dfx_make_unix_addr(struct sockaddr_un *addr, bool use_ltran) - { -- int32_t ret, fd; -- struct sockaddr_un addr; -- -- fd = socket(AF_UNIX, SOCK_STREAM, 0); -- if (fd == -1) { -- printf("create socket failed. errno: %d\n", errno); -- return GAZELLE_ERR; -- } -- -- ret = memset_s(&addr, sizeof(addr), 0, sizeof(struct sockaddr_un)); -+ int ret; -+ ret = memset_s(addr, sizeof(*addr), 0, sizeof(struct sockaddr_un)); - if (ret != EOK) { - printf("%s:%d memset_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - goto END; - } - -- ret = strncpy_s(addr.sun_path, sizeof(addr.sun_path), GAZELLE_RUN_DIR, -+ ret = strncpy_s(addr->sun_path, sizeof(addr->sun_path), GAZELLE_RUN_DIR, - strlen(GAZELLE_RUN_DIR) + 1); - if (ret != EOK) { - printf("%s:%d strncpy_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); -@@ -293,7 +287,7 @@ static int32_t dfx_connect_ltran(bool use_ltran, bool probe) - } - - if (g_unix_prefix) { -- ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), g_unix_prefix, -+ ret = strncat_s(addr->sun_path, sizeof(addr->sun_path), g_unix_prefix, - strlen(g_unix_prefix) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); -@@ -301,43 +295,89 @@ static int32_t dfx_connect_ltran(bool use_ltran, bool probe) - } - } - -- addr.sun_family = AF_UNIX; -+ addr->sun_family = AF_UNIX; - if (use_ltran) { -- ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), LTRAN_DFX_SOCK_FILENAME, -+ ret = strncat_s(addr->sun_path, sizeof(addr->sun_path), LTRAN_DFX_SOCK_FILENAME, - strlen(LTRAN_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - goto END; - } -+ memcpy_s(g_ltran_unix_path, PATH_MAX, addr->sun_path, sizeof(addr->sun_path)); - } else { -- ret = strncat_s(addr.sun_path, sizeof(addr.sun_path), LSTACK_DFX_SOCK_FILENAME, -+ ret = strncat_s(addr->sun_path, sizeof(addr->sun_path), LSTACK_DFX_SOCK_FILENAME, - strlen(LSTACK_DFX_SOCK_FILENAME) + 1); - if (ret != EOK) { - printf("%s:%d strncat_s fail ret=%d\n", __FUNCTION__, __LINE__, ret); - goto END; - } -+ memcpy_s(g_lstack_unix_path, PATH_MAX, addr->sun_path, sizeof(addr->sun_path)); - } -+ return 0; -+END: -+ return -1; -+} -+ -+static int32_t dfx_connect_server(bool use_ltran) -+{ -+ int32_t ret, fd; -+ struct sockaddr_un addr; -+ -+ fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (fd == -1) { -+ printf("create socket failed. errno: %d\n", errno); -+ return GAZELLE_ERR; -+ } -+ -+ ret = dfx_make_unix_addr(&addr, use_ltran); -+ if (ret != 0) { -+ goto END; -+ } - - ret = connect(fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)); -- if (ret == -1) { -- if (!probe) { -- printf("connect ltran failed. errno: %d ret=%d\n", errno, ret); -- printf("You may need to use the -u parameter to specify the UNIX_PREFIX that matches the configuration.\n"); -- } -+ if (ret != 0) { - goto END; - } - - return fd; - END: -+ ret = errno; - close(fd); -- return GAZELLE_ERR; -+ return -ret; -+} -+ -+static int dfx_connect_probe(void) -+{ -+ int32_t ret1; -+ int32_t ret2; -+ ret1 = dfx_connect_server(true); -+ if (ret1 > 0) { -+ close(ret1); -+ return 1; -+ } -+ ret2 = dfx_connect_server(false); -+ if (ret2 > 0) { -+ close(ret2); -+ return 0; -+ } -+ -+ printf("Connect lstack(path:%s), errno: %d; Connect ltran(path:%s) failed, errno: %d\n", -+ g_lstack_unix_path, -ret2, g_ltran_unix_path, -ret1); -+ printf("Please ensure the process is started; If use ltran mode, \ -+ set use_ltran=1 in lstack.conf, otherwise set use_ltran=0\n"); -+ return -1; - } - - static int32_t dfx_stat_conn_to_ltran(struct gazelle_stat_msg_request *req_msg) - { -- int32_t fd = dfx_connect_ltran(g_use_ltran, false); -+ int32_t fd = dfx_connect_server(g_use_ltran); - if (fd < 0) { -- return fd; -+ if (g_use_ltran) { -+ printf("Connect ltran(path:%s) failed. errno: %d\n", g_ltran_unix_path, -fd); -+ } else { -+ printf("Connect lstack(path:%s) failed. errno: %d\n", g_lstack_unix_path, -fd); -+ } -+ return GAZELLE_ERR; - } - - int32_t ret = write_specied_len(fd, (char *)req_msg, sizeof(*req_msg)); -@@ -1417,12 +1457,12 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - char *param = argv[GAZELLE_OPTIONS1_ARG_IDX]; - if (strcmp(param, "rate") == 0 || strcmp(param, "-r") == 0) { - if (g_use_ltran) { -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_LB_RATE; -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_SHOW_LB_RATE; - } else { -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; -- req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_RATE; -- } -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_START_LATENCY; -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LTRAN_STOP_LATENCY; -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_RATE; -+ } - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; - } else if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_SNMP; -@@ -1495,7 +1535,6 @@ static int32_t parse_dfx_lstack_args(int32_t argc, char *argv[], struct gazelle_ - return num_cmd; - } - -- - #ifdef GAZELLE_FAULT_INJECT_ENABLE - - #define GAZELLE_SET_FAULT_INJECT_PARAM_COUNT 6 -@@ -1770,19 +1809,48 @@ static int32_t parse_dfx_fault_inject_args(int32_t argc, char *argv[], struct ga - - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ - -+static void parse_unix_arg(int32_t *argc, char *argv[]) -+{ -+ int unix_arg = 0; -+ for (int i = 1; i < *argc; i++) { -+ if (unix_arg == 0) { -+ if (!strcmp(argv[i], "-u")) { -+ unix_arg++; -+ } -+ } else if (unix_arg == 1) { -+ g_unix_prefix = argv[i]; -+ unix_arg++; -+ } else { -+ argv[i - unix_arg] = argv[i]; -+ } -+ } -+ -+ argv[*argc - unix_arg] = argv[*argc]; -+ *argc -= unix_arg; -+} -+ - static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) - { -- int32_t num_cmd = 0; -+ int num_cmd = 0; -+ int ret; - - if (argc < GAZELLE_PARAM_MINNUM) { - return num_cmd; - } - -+ parse_unix_arg(&argc, argv); -+ - char *param = argv[GAZELLE_TARGET_ARG_IDX]; - if (strcmp(param, "ltran") == 0) { -+ g_use_ltran = true; - num_cmd = parse_dfx_ltran_args(argc, argv, req_msg); - } - if (strcmp(param, "lstack") == 0) { -+ ret = dfx_connect_probe(); -+ if (ret < 0) { -+ exit(0); -+ } -+ g_use_ltran = ret; - num_cmd = parse_dfx_lstack_args(argc, argv, req_msg); - } - #ifdef GAZELLE_FAULT_INJECT_ENABLE -@@ -1846,28 +1914,6 @@ int32_t main(int32_t argc, char *argv[]) - struct gazelle_stat_msg_request req_msg[GAZELLE_CMD_MAX] = {0}; - int32_t req_msg_num; - -- int unix_arg = 0; -- for (int32_t i = 1; i < argc; i++) { -- if (unix_arg == 0) { -- if (!strcmp(argv[i], "-u")) { -- unix_arg++; -- } -- } else if (unix_arg == 1) { -- g_unix_prefix = argv[i]; -- unix_arg++; -- } else { -- argv[i - unix_arg] = argv[i]; -- } -- } -- -- argv[argc - unix_arg] = argv[argc]; -- argc -= unix_arg; -- -- int32_t fd = dfx_connect_ltran(true, true); -- if (fd > 0) { -- g_use_ltran = true; -- close(fd); -- } - req_msg_num = parse_dfx_cmd_args(argc, argv, req_msg); - if (req_msg_num <= 0 || req_msg_num > GAZELLE_CMD_MAX) { - show_usage(); --- -2.27.0 - diff --git a/0148-fix-rpc_pool-create-failed-coredump.patch b/0148-fix-rpc_pool-create-failed-coredump.patch deleted file mode 100644 index b52c089..0000000 --- a/0148-fix-rpc_pool-create-failed-coredump.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 98b8e8cea061d65ece3865ce8e772f5b4226199e Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 27 Feb 2024 22:37:47 +0800 -Subject: [PATCH] fix rpc_pool create failed coredump - ---- - src/lstack/core/lstack_thread_rpc.c | 34 ++++++++++++++++++++------ - src/lstack/include/lstack_thread_rpc.h | 6 ++++- - 2 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 1fdb037..20c5a43 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -36,6 +36,27 @@ static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct - return msg; - } - -+static void rpc_msg_init(struct rpc_msg *msg, rpc_msg_func func, struct rpc_msg_pool *pool) -+{ -+ msg->rpcpool = pool; -+ pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); -+ msg->func = func; -+ msg->sync_flag = 1; -+ msg->recall_flag = 0; -+} -+ -+static struct rpc_msg *rpc_msg_alloc_except(rpc_msg_func func) -+{ -+ struct rpc_msg *msg = calloc(1, sizeof(struct rpc_msg)); -+ if (msg == NULL) { -+ return NULL; -+ } -+ -+ rpc_msg_init(msg, func, NULL); -+ -+ return msg; -+} -+ - static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - { - struct rpc_msg *msg = NULL; -@@ -45,14 +66,15 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - if (g_rpc_pool == NULL) { - LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); - g_rpc_stats.call_alloc_fail++; -- return NULL; -+ exit(-1); - } - - g_rpc_pool->mempool = create_mempool("rpc_pool", RPC_MSG_MAX, sizeof(struct rpc_msg), - 0, rte_gettid()); - if (g_rpc_pool->mempool == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); - g_rpc_stats.call_alloc_fail++; -- return NULL; -+ exit(-1); - } - } - -@@ -61,12 +83,8 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - g_rpc_stats.call_alloc_fail++; - return NULL; - } -- msg->rpcpool = g_rpc_pool; -+ rpc_msg_init(msg, func, g_rpc_pool); - -- pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); -- msg->func = func; -- msg->sync_flag = 1; -- msg->recall_flag = 0; - return msg; - } - -@@ -247,7 +265,7 @@ int32_t rpc_call_close(rpc_queue *queue, int fd) - - int32_t rpc_call_stack_exit(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_exit_by_rpc); -+ struct rpc_msg *msg = rpc_msg_alloc_except(stack_exit_by_rpc); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 30caa66..4d89604 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -104,7 +104,11 @@ static inline __attribute__((always_inline)) void rpc_call(rpc_queue *queue, str - static inline __attribute__((always_inline)) void rpc_msg_free(struct rpc_msg *msg) - { - pthread_spin_destroy(&msg->lock); -- rte_mempool_put(msg->rpcpool->mempool, (void *)msg); -+ if (msg->rpcpool != NULL && msg->rpcpool->mempool != NULL) { -+ rte_mempool_put(msg->rpcpool->mempool, (void *)msg); -+ } else { -+ free(msg); -+ } - } - - #endif --- -2.27.0 - diff --git a/0149-ensure-the-bond-interface-flow_type_rss_offloads-mat.patch b/0149-ensure-the-bond-interface-flow_type_rss_offloads-mat.patch deleted file mode 100644 index 7585389..0000000 --- a/0149-ensure-the-bond-interface-flow_type_rss_offloads-mat.patch +++ /dev/null @@ -1,24 +0,0 @@ -From f8321fa815ca33267bd5b829fd8c06b75ab215d1 Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Tue, 12 Mar 2024 19:51:57 +0800 -Subject: [PATCH] ensure the bond interface flow_type_rss_offloads match slave - ---- - src/lstack/core/lstack_dpdk.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 5811918..a774d45 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -584,6 +584,7 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; - dev_info.tx_offload_capa = slave_dev_info.tx_offload_capa; - dev_info.reta_size = slave_dev_info.reta_size; -+ dev_info.flow_type_rss_offloads = slave_dev_info.flow_type_rss_offloads; - } - - eth_params_checksum(ð_params->conf, &dev_info); --- -2.33.0 - diff --git a/0150-FAULT-INJECT-add-duplicate-and-reorder-methods.patch b/0150-FAULT-INJECT-add-duplicate-and-reorder-methods.patch deleted file mode 100644 index 17a1818..0000000 --- a/0150-FAULT-INJECT-add-duplicate-and-reorder-methods.patch +++ /dev/null @@ -1,315 +0,0 @@ -From 1929cc2a07a8e6d6a81b13a8338d816d7f09e709 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Wed, 6 Mar 2024 10:51:42 +0800 -Subject: [PATCH] FAULT INJECT: add duplicate and reorder methods - ---- - src/common/gazelle_fault_inject_common.h | 4 +- - src/lstack/netif/lstack_fault_inject.c | 162 ++++++++++++++++++++++- - src/ltran/ltran_dfx.c | 20 ++- - 3 files changed, 174 insertions(+), 12 deletions(-) - -diff --git a/src/common/gazelle_fault_inject_common.h b/src/common/gazelle_fault_inject_common.h -index 3a77f39..72d778c 100644 ---- a/src/common/gazelle_fault_inject_common.h -+++ b/src/common/gazelle_fault_inject_common.h -@@ -17,10 +17,10 @@ - - enum GAZELLE_FAULT_INJECT_TYPE { - GAZELLE_FAULT_INJECT_TYPE_ERR = 0, -- GAZELLE_FAULT_INJECT_PACKET_DELAY, - GAZELLE_FAULT_INJECT_PACKET_LOSS, -- GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, - GAZELLE_FAULT_INJECT_PACKET_REORDER, -+ GAZELLE_FAULT_INJECT_PACKET_DELAY, -+ GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, - GAZELLE_FAULT_INJECT_TYPE_MAX, - }; - -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -index 41e7d95..4edc6cc 100644 ---- a/src/lstack/netif/lstack_fault_inject.c -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -9,7 +9,7 @@ - * PURPOSE. - * See the Mulan PSL v2 for more details. - */ -- -+#include - #include - #include - #include -@@ -31,6 +31,15 @@ struct inject_tbl { - }; - static struct inject_tbl g_inject_tbl[GAZELLE_FAULT_INJECT_TYPE_MAX]; - -+struct reorder_stat { -+ int32_t enable; -+ int32_t arr_size; -+ int32_t cur_cnt; -+ struct rte_mbuf **array; -+}; -+ -+static struct reorder_stat g_reorder[PROTOCOL_STACK_MAX]; -+ - struct inject_func_tbl { - enum GAZELLE_FAULT_INJECT_TYPE type; - enum GAZELLE_FAULT_INJECT_RULE rule; -@@ -41,10 +50,16 @@ static int32_t inject_packet_delay_random(struct protocol_stack *stack, struct r - uint32_t nr_pkts, struct gazelle_fault_inject_data data); - static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rte_mbuf **pkts, - uint32_t nr_pkts, struct gazelle_fault_inject_data data); -+static int32_t inject_packet_duplicate_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data); -+static int32_t inject_packet_reorder_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data); - - static struct inject_func_tbl g_inject_func_tbl[] = { - {GAZELLE_FAULT_INJECT_PACKET_LOSS, INJECT_LOSS_RANDOM, inject_packet_loss_random}, - {GAZELLE_FAULT_INJECT_PACKET_DELAY, INJECT_DELAY_RANDOM, inject_packet_delay_random}, -+ {GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, INJECT_DUPLICATE_RANDOM, inject_packet_duplicate_random}, -+ {GAZELLE_FAULT_INJECT_PACKET_REORDER, INJECT_REORDER_RANDOM, inject_packet_reorder_random}, - }; - - static int32_t inject_func_tbl_update() -@@ -68,16 +83,16 @@ static int32_t inject_func_tbl_update() - static uint32_t inject_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) - { - for (int32_t i = 0; i < GAZELLE_FAULT_INJECT_TYPE_MAX; ++i) { -- if (g_inject_tbl[i].inject_data.fault_inject_on) { -+ if (g_inject_tbl[i].inject_data.fault_inject_on && g_inject_tbl[i].inject_func) { - int32_t xmit_pkts = 0; -- xmit_pkts = g_inject_tbl[i].inject_func(stack, pkts, nr_pkts, -- g_inject_tbl[i].inject_data); -+ xmit_pkts = g_inject_tbl[i].inject_func(stack, pkts, nr_pkts, g_inject_tbl[i].inject_data); - if (xmit_pkts == nr_pkts) { - continue; - } - return xmit_pkts; - } - } -+ - if (rte_mbuf_refcnt_read(*pkts) == 1) { - return nr_pkts; - } -@@ -105,7 +120,7 @@ static int32_t inject_strategy_update() - } - return 0; - } -- -+ - for (uint32_t i = 0; i < stack_group->stack_num; ++i) { - struct protocol_stack *stack = stack_group->stacks[i]; - vdev_dev_ops_init(&stack->dev_ops); -@@ -150,6 +165,132 @@ static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rt - return nr_pkts; - } - -+static int32_t inject_packet_duplicate_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data) -+{ -+ if (rte_mbuf_refcnt_read(*pkts) == 1) { -+ return nr_pkts; -+ } -+ -+ double duplicate_rate = data.inject_data.duplicate.duplicate_rate; -+ int32_t boundary = (int32_t) (duplicate_rate * INJECT_MODULO); -+ int32_t count_max = data.inject_data.duplicate.duplicate_sigle_count; -+ -+ uint32_t rand_num = rte_rand() % INJECT_MODULO; -+ if (rand_num > boundary) { -+ return nr_pkts; -+ } -+ -+ struct rte_mempool *mp = stack->rxtx_mbuf_pool; -+ struct rte_mbuf *mbuf_clone = NULL; -+ int32_t ret = 0; -+ -+ for (int32_t i = 0; i < nr_pkts; ++i) { -+ int32_t count = count_max; -+ while (count--) { -+ mbuf_clone = rte_pktmbuf_clone(pkts[i], mp); -+ rte_pktmbuf_free(pkts[i]); -+ if (mbuf_clone == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject mbuf_clone fail.\n"); -+ return 0; -+ } -+ ret = vdev_tx_xmit(stack, &mbuf_clone, 1); -+ if (ret < 1) { -+ rte_pktmbuf_free(mbuf_clone); -+ return ret; -+ } -+ } -+ } -+ return nr_pkts; -+} -+ -+static int32_t send_reorder_array(struct protocol_stack *stack) -+{ -+ int32_t idx = stack->stack_idx; -+ int32_t ret = 0; -+ -+ for (int32_t i = 0; i < g_reorder[idx].cur_cnt; ++i) { -+ ret = vdev_tx_xmit(stack, g_reorder[idx].array + i, 1); -+ if (ret < 1) { -+ rte_pktmbuf_free(*(g_reorder[idx].array + i)); -+ } -+ } -+ g_reorder[idx].cur_cnt = 0; -+ -+ return 0; -+} -+ -+static int32_t inject_packet_reorder_random(struct protocol_stack *stack, struct rte_mbuf **pkts, -+ uint32_t nr_pkts, struct gazelle_fault_inject_data data) -+{ -+ if (rte_mbuf_refcnt_read(*pkts) == 1) { -+ return nr_pkts; -+ } -+ -+ double reorder_rate = data.inject_data.reorder.reorder_rate; -+ int32_t boundary = (int32_t) (reorder_rate * INJECT_MODULO); -+ int32_t count_max = data.inject_data.reorder.reorder_sigle_count; -+ -+ uint32_t rand_num = rte_rand() % INJECT_MODULO; -+ if (rand_num > boundary) { -+ return nr_pkts; -+ } -+ -+ struct rte_mempool *mp = stack->rxtx_mbuf_pool; -+ struct rte_mbuf *mbuf_clone = NULL; -+ int32_t idx = stack->stack_idx; -+ for (int32_t i = 0; i < nr_pkts; ++i) { -+ if (g_reorder[idx].cur_cnt < count_max) { -+ mbuf_clone = rte_pktmbuf_clone(pkts[i], mp); -+ if (mbuf_clone == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "fault inject mbuf_clone fail.\n"); -+ return 0; -+ } -+ *(g_reorder[idx].array + g_reorder[idx].cur_cnt++) = mbuf_clone; -+ /* func rte_pktmbuf_clone will add refcnt of mbuf, so following operation will free mbuf double */ -+ rte_pktmbuf_free(pkts[i]); -+ rte_pktmbuf_free(pkts[i]); -+ } else { -+ send_reorder_array(stack); -+ } -+ } -+ -+ return nr_pkts; -+} -+ -+static int32_t inject_reorder_mem_release() -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ -+ for (uint32_t i = 0; i < stack_group->stack_num; ++i) { -+ struct protocol_stack *stack = stack_group->stacks[i]; -+ if (!g_reorder[i].enable) { -+ return 0; -+ } -+ send_reorder_array(stack); -+ free(g_reorder[i].array); -+ g_reorder[i].enable = 0; -+ } -+ -+ return 0; -+} -+ -+static int32_t inject_reorder_mem_alloc() -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ -+ for (uint32_t i = 0; i < stack_group->stack_num; ++i) { -+ g_reorder[i].enable = 1; -+ -+ g_reorder[i].arr_size = -+ g_inject_tbl[GAZELLE_FAULT_INJECT_PACKET_REORDER].inject_data.inject_data.reorder.reorder_sigle_count; -+ g_reorder[i].cur_cnt = 0; -+ g_reorder[i].array = -+ (struct rte_mbuf**) malloc(sizeof(struct rte_mbuf**) * (g_reorder[i].arr_size)); -+ } -+ return 0; -+} -+ - static int32_t inject_respond_msg(int32_t sockfd) - { - struct gazelle_stack_dfx_data rsp = {0}; -@@ -192,6 +333,10 @@ static int32_t inject_unset_cmd(int32_t sockfd, struct gazelle_fault_inject_data - } - } - -+ if (!g_inject_tbl[GAZELLE_FAULT_INJECT_PACKET_REORDER].inject_data.fault_inject_on) { -+ inject_reorder_mem_release(); -+ } -+ - inject_strategy_update(); - - return inject_respond_msg(sockfd); -@@ -208,8 +353,13 @@ static int32_t inject_set_cmd(int32_t sockfd, struct gazelle_fault_inject_data i - return -1; - } - -+ if (inject.inject_type == GAZELLE_FAULT_INJECT_PACKET_REORDER) { -+ inject_reorder_mem_release(); -+ inject_reorder_mem_alloc(); -+ } -+ - inject_strategy_update(); -- -+ - return inject_respond_msg(sockfd); - } - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 96509e5..2cc3504 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -77,10 +77,10 @@ struct gazelle_fault_inject_type_list { - }; - - static struct gazelle_fault_inject_type_list inject_type_list[] = { -- {"delay", GAZELLE_FAULT_INJECT_PACKET_DELAY, parse_inject_packet_delay_digit}, - {"loss", GAZELLE_FAULT_INJECT_PACKET_LOSS, parse_inject_packet_loss_digit}, -- {"duplicate", GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, parse_inject_packet_duplicate_digit}, - {"reorder", GAZELLE_FAULT_INJECT_PACKET_REORDER, parse_inject_packet_reorder_digit}, -+ {"delay", GAZELLE_FAULT_INJECT_PACKET_DELAY, parse_inject_packet_delay_digit}, -+ {"duplicate", GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE, parse_inject_packet_duplicate_digit}, - }; - - struct gazelle_fault_inject_rule_list { -@@ -1514,7 +1514,7 @@ static void gazelle_print_fault_inject_type_info(struct gazelle_fault_inject_dat - } - - if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_DELAY) { -- printf("\t| inject_type: delay | delay_time: %-7d | delay_range: %-3d | " -+ printf("\t| inject_type: delay | delay_time: %-7d | delay_range: %-3d | " - "inject_rule: random |\n", inject->inject_data.delay.delay_time, - inject->inject_data.delay.delay_range); - } -@@ -1522,10 +1522,22 @@ static void gazelle_print_fault_inject_type_info(struct gazelle_fault_inject_dat - #define INJECT_PERCENT 100 - - if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_LOSS) { -- printf("\t| inject_type: loss | loss_rate: %-3.1f%% | loss_single_count: %-3d | " -+ printf("\t| inject_type: loss | loss_rate: %-4.1f%% | loss_single_count: %-3d | " - "inject_rule: random |\n", inject->inject_data.loss.loss_rate * INJECT_PERCENT, - inject->inject_data.loss.loss_sigle_count); - } -+ -+ if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKAET_DUPLICATE) { -+ printf("\t| inject_type: duplicate | duplicate_rate: %-4.1f%% | duplicate_single_count: %-3d | " -+ "inject_rule: random |\n", inject->inject_data.duplicate.duplicate_rate * INJECT_PERCENT, -+ inject->inject_data.duplicate.duplicate_sigle_count); -+ } -+ -+ if (inject->inject_type == GAZELLE_FAULT_INJECT_PACKET_REORDER) { -+ printf("\t| inject_type: reorder | reorder_rate: %-4.1f%% | reorder_sigle_count: %-3d | " -+ "inject_rule: random |\n", inject->inject_data.reorder.reorder_rate * INJECT_PERCENT, -+ inject->inject_data.reorder.reorder_sigle_count); -+ } - printf("\n"); - } - --- -2.33.0 - diff --git a/0151-select-timeout-arguments-check.patch b/0151-select-timeout-arguments-check.patch deleted file mode 100644 index 61daec9..0000000 --- a/0151-select-timeout-arguments-check.patch +++ /dev/null @@ -1,51 +0,0 @@ -From fbd169eb504f5edc905f07f33785ba3df5812b4c Mon Sep 17 00:00:00 2001 -From: li_yunqing -Date: Thu, 14 Mar 2024 16:37:27 +0800 -Subject: [PATCH] select timeout arguments check - ---- - src/lstack/api/lstack_epoll.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7dbef9d..c9d1f0c 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -927,13 +927,17 @@ static void fds_poll2select(struct pollfd *fds, nfds_t nfds, fd_set *readfds, fd - } - } - --static inline int timeval_to_ms(struct timeval *timeval) -+static inline int timeval_to_ms(struct timeval *timeval, int32_t *timeout) - { -- if (timeval == NULL) { -+ if (!timeval) { -+ *timeout = -1; -+ return 0; -+ } -+ if (unlikely((timeval->tv_sec < 0 || timeval->tv_usec < 0 || timeval->tv_usec >= 1000000))) { - return -1; - } -- -- return (timeval->tv_sec * 1000 + timeval->tv_usec / 1000); -+ *timeout = timeval->tv_sec * 1000 + timeval->tv_usec / 1000; -+ return 0; - } - - static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct pollfd *fds) -@@ -969,7 +973,11 @@ int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfd - /* Convert the select parameter to the poll parameter. */ - struct pollfd fds[FD_SETSIZE] = { 0 }; - nfds_t nfds = fds_select2poll(maxfd, readfds, writefds, exceptfds, fds); -- int timeout = timeval_to_ms(timeval); -+ int timeout = 0; -+ if (timeval_to_ms(timeval, &timeout)) { -+ LSTACK_LOG(ERR, LSTACK, "select input param timeout error.\n"); -+ GAZELLE_RETURN(EINVAL); -+ } - - int event_num = lstack_poll(fds, nfds, timeout); - --- -2.33.0 - diff --git a/0152-recvfrom-support-timeout.patch b/0152-recvfrom-support-timeout.patch deleted file mode 100644 index fa91ff7..0000000 --- a/0152-recvfrom-support-timeout.patch +++ /dev/null @@ -1,213 +0,0 @@ -From e19bb18fad80ed95fb68318fc6ec7f2f892942dd Mon Sep 17 00:00:00 2001 -From: li_yunqing -Date: Tue, 19 Mar 2024 21:06:07 +0800 -Subject: [PATCH] recvfrom support timeout - ---- - src/lstack/api/lstack_epoll.c | 57 ++++++++++++++++--------- - src/lstack/api/lstack_wrap.c | 1 - - src/lstack/core/lstack_lwip.c | 28 +++++------- - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/include/posix/lstack_epoll.h | 10 +---- - 5 files changed, 50 insertions(+), 48 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7dbef9d..1b68c36 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -586,6 +586,41 @@ static void ms_to_timespec(struct timespec *timespec, int32_t timeout) - timespec->tv_nsec = timespec->tv_nsec % SEC_TO_NSEC; - } - -+/** -+ * Block lstack thread -+ * -+ * @param wakeup -+ * The pointer to the wakeup_poll. -+ * @param timeout -+ * The time to wait, if 'timeout <= 0' will block until unlock -+ * -+ * @return -+ * - return '0' on unlock -+ * - return 'ETIMEDOUT' on timeout -+ */ -+int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout) -+{ -+ int ret = 0; -+ if (wakeup == NULL) { -+ return ret; -+ } -+ -+ __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -+ if (timeout > 0) { -+ struct timespec timespec; -+ ms_to_timespec(×pec, timeout); -+ ret = pthread_mutex_timedlock(&wakeup->wait, ×pec); -+ } else { -+ ret = pthread_mutex_lock(&wakeup->wait); -+ } -+ -+ if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -+ __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -+ } -+ -+ return ret; -+} -+ - int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { - struct lwip_sock *sock = get_socket_by_fd(epfd); -@@ -645,7 +680,6 @@ int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - struct wakeup_poll *wakeup = sock->wakeup; - int32_t kernel_num = 0; - int32_t lwip_num = 0; -- int32_t ret = 0; - - if (get_global_cfg_params()->app_bind_numa) { - epoll_bind_statck(sock->wakeup); -@@ -669,15 +703,7 @@ int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - if (timeout == 0) { - break; - } -- -- if (timeout < 0) { -- ret = pthread_mutex_lock(&wakeup->wait); -- } else { -- struct timespec epoll_time; -- ms_to_timespec(&epoll_time, timeout); -- ret = pthread_mutex_timedlock(&wakeup->wait, &epoll_time); -- } -- } while (ret == 0); -+ } while (lstack_block_wait(wakeup, timeout) == 0); - - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - wakeup->stat.app_events += lwip_num; -@@ -857,7 +883,6 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - - int32_t kernel_num = 0; - int32_t lwip_num = 0; -- int32_t ret; - - do { - __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -@@ -881,15 +906,7 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - if (timeout == 0) { - break; - } -- -- if (timeout < 0) { -- ret = pthread_mutex_lock(&wakeup->wait); -- } else { -- struct timespec epoll_time; -- ms_to_timespec(&epoll_time, timeout); -- ret = pthread_mutex_timedlock(&wakeup->wait, &epoll_time); -- } -- } while (ret == 0); -+ } while (lstack_block_wait(wakeup, timeout) == 0); - - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - wakeup->stat.app_events += lwip_num; -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 49bbf91..0dac82e 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -380,7 +380,6 @@ static bool unsupport_socket_optname(int32_t optname) - if ((optname == SO_BROADCAST) || - (optname == SO_PROTOCOL) || - (optname == SO_SNDTIMEO) || -- (optname == SO_RCVTIMEO) || - (optname == SO_SNDBUF) || - (optname == SO_RCVBUF) || - (optname == SO_DONTROUTE)) { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 8aae433..d0dea80 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -859,39 +859,33 @@ static bool recv_break_for_err(struct lwip_sock *sock) - return break_wait; - } - --static void recv_block_wait(struct lwip_sock *sock) --{ -- lstack_block_wait(sock->wakeup); --} -- - /* - * 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) - { -+ int32_t expect = 1; // only get one pbuf -+ - if (sock->recv_lastdata != NULL) { - *pbuf = sock->recv_lastdata; - sock->recv_lastdata = NULL; - return 0; - } - -- if (noblock) { -- if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1) != 1) { -- errno = EAGAIN; -+ while (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) != expect) { -+ if (noblock) { -+ GAZELLE_RETURN(EAGAIN); -+ } -+ if (recv_break_for_err(sock)) { - return -1; -- } else { -- 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); -+ if (lstack_block_wait(sock->wakeup, sock->conn->recv_timeout) == ETIMEDOUT) { -+ noblock = true; - } -- return 0; - } -+ -+ return 0; - } - - /* return true: fin is read to user, false: pend fin */ -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index a545b73..7c4af64 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -1270,7 +1270,7 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - min_sock = get_min_accept_sock(fd); - } else { - while ((min_sock = get_min_accept_sock(fd)) == NULL) { -- lstack_block_wait(sock->wakeup); -+ lstack_block_wait(sock->wakeup, 0); - } - } - -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index 7591f0f..59b5ef7 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -80,15 +80,7 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout); - int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval); - --static inline void lstack_block_wait(struct wakeup_poll *wakeup) --{ -- if (wakeup == NULL) { -- return; -- } -- -- __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -- pthread_mutex_lock(&wakeup->wait); --} -+int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout); - - static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) - { --- -2.33.0 - diff --git a/0153-fix-netperf-setsockopt-fail.patch b/0153-fix-netperf-setsockopt-fail.patch deleted file mode 100644 index 5fcfe82..0000000 --- a/0153-fix-netperf-setsockopt-fail.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 33efdf6e98d223f44a0168ae2e17e95cb7f27402 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 14 Mar 2024 13:16:58 +0800 -Subject: [PATCH] fix netperf setsockopt fail - ---- - src/lstack/api/lstack_wrap.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 49bbf91..1bec08b 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -364,6 +364,14 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - return posix_api->getsockname_fn(s, name, namelen); - } - -+static bool unsupport_ip_optname(int32_t optname) -+{ -+ if (optname == IP_RECVERR) { -+ return true; -+ } -+ return false; -+} -+ - static bool unsupport_tcp_optname(int32_t optname) - { - if ((optname == TCP_QUICKACK) || -@@ -391,6 +399,10 @@ static bool unsupport_socket_optname(int32_t optname) - - static bool unsupport_optname(int32_t level, int32_t optname) - { -+ if (level == SOL_IP) { -+ return unsupport_ip_optname(optname); -+ } -+ - if (level == SOL_TCP) { - return unsupport_tcp_optname(optname); - } --- -2.33.0 - diff --git a/0154-fix-LATENCY_WRITE-increase-in-recv-process.patch b/0154-fix-LATENCY_WRITE-increase-in-recv-process.patch deleted file mode 100644 index 3a0efb6..0000000 --- a/0154-fix-LATENCY_WRITE-increase-in-recv-process.patch +++ /dev/null @@ -1,134 +0,0 @@ -From c3d84d821fcdc15245f7cc9838cf97b4947a48e2 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 13 Mar 2024 13:01:38 +0800 -Subject: [PATCH] fix LATENCY_WRITE increase in recv process - ---- - src/common/dpdk_common.h | 5 +++++ - src/common/gazelle_dfx_msg.h | 2 ++ - src/lstack/core/lstack_lwip.c | 4 ++++ - src/lstack/core/lstack_stack_stat.c | 20 +++++++++++++++++++- - src/lstack/include/lstack_stack_stat.h | 1 + - 5 files changed, 31 insertions(+), 1 deletion(-) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index a79a0f2..cb41747 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -23,6 +23,8 @@ - - #define GAZELLE_KNI_NAME "kni" // will be removed during dpdk update - -+#define GAZELLE_LATENCY_RD 0 -+#define GAZELLE_LATENCY_WR 1 - - /* Layout: - * | rte_mbuf | mbuf_private | payload | -@@ -31,6 +33,7 @@ - struct latency_timestamp { - uint64_t stamp; // time stamp - uint64_t check; // just for later vaild check -+ uint16_t type; // latency type - }; - struct mbuf_private { - /* struct pbuf_custom must at first */ -@@ -92,6 +95,7 @@ static __rte_always_inline void time_stamp_into_mbuf(uint32_t rx_count, struct r - lt = &mbuf_to_private(buf[i])->lt; - lt->stamp = time_stamp; - lt->check = ~(time_stamp); -+ lt->type = GAZELLE_LATENCY_RD; - } - } - -@@ -102,6 +106,7 @@ static __rte_always_inline void time_stamp_into_pbuf(uint32_t tx_count, struct p - lt = &pbuf_to_private(buf[i])->lt; - lt->stamp = time_stamp; - lt->check = ~(time_stamp); -+ lt->type = GAZELLE_LATENCY_WR; - } - } - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 8d528d6..d7ba80f 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -69,6 +69,8 @@ enum GAZELLE_STAT_MODE { - enum GAZELLE_LATENCY_TYPE { - GAZELLE_LATENCY_READ_LWIP, - GAZELLE_LATENCY_READ_LSTACK, -+ GAZELLE_LATENCY_READ_MAX, -+ - GAZELLE_LATENCY_WRITE_LWIP, - GAZELLE_LATENCY_WRITE_LSTACK, - GAZELLE_LATENCY_MAX, -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 8aae433..f9b83c7 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -257,6 +257,10 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - int size = (remain_size + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN - 1; - struct pbuf *pbuf_used[size]; - gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf_used, size); -+ -+ for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < size; i++) { -+ calculate_lstack_latency(&sock->stack->latency, pbuf_used[i], GAZELLE_LATENCY_WRITE_LWIP); -+ } - } - - if (get_protocol_stack_group()->latency_start) { -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 25b5557..3e016b7 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -48,10 +48,27 @@ uint64_t get_current_time(void) - return (rte_rdtsc() / g_cycles_per_us); - } - -+void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) -+{ -+ if (!get_protocol_stack_group()->latency_start) { -+ return; -+ } -+ struct latency_timestamp *lt_old; -+ struct latency_timestamp *lt_new; -+ -+ lt_old = &pbuf_to_private(pbuf_old)->lt; -+ lt_new = &pbuf_to_private(pbuf_new)->lt; -+ -+ lt_new->stamp = lt_old->stamp; -+ lt_new->check = lt_old->check; -+ lt_new->type = lt_old->type; -+} -+ - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, - enum GAZELLE_LATENCY_TYPE type) - { - uint64_t latency; -+ uint16_t lt_type; - const struct latency_timestamp *lt; - struct stack_latency *latency_stat; - -@@ -60,7 +77,8 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - } - - lt = &pbuf_to_private(pbuf)->lt; -- if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time) { -+ lt_type = (type / GAZELLE_LATENCY_READ_MAX) ? GAZELLE_LATENCY_WR : GAZELLE_LATENCY_RD; -+ if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time || lt_type != lt->type) { - return; - } - -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index d5a4ec7..87951aa 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -30,5 +30,6 @@ uint64_t get_current_time(void); - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info); - void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); - void lstack_calculate_aggregate(int type, uint32_t len); -+void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new); - - #endif /* GAZELLE_STACK_STAT_H */ --- -2.33.0 - diff --git a/0155-dpdk-add-vlan-filter.patch b/0155-dpdk-add-vlan-filter.patch deleted file mode 100644 index 05c98d7..0000000 --- a/0155-dpdk-add-vlan-filter.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 3d8a848dde959ef95796e8215cdb1882a3496ce4 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Thu, 21 Mar 2024 11:24:26 +0800 -Subject: [PATCH] dpdk add vlan filter - ---- - src/common/dpdk_common.c | 6 ++++++ - src/lstack/core/lstack_dpdk.c | 19 +++++++++++++------ - 2 files changed, 19 insertions(+), 6 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index c0c4f63..c03b2ec 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -223,6 +223,12 @@ void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev - COMMON_INFO("RTE_ETH_RX_OFFLOAD_VLAN_STRIP\n"); - } - -+ // rx vlan filter -+ if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) { -+ rx_ol |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_VLAN_STRIP\n"); -+ } -+ - // tx ip - if (tx_ol_capa & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) { - tx_ol |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM; -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a774d45..42981f4 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -572,13 +572,13 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - int slave_id = rte_eth_bond_primary_get(port_id); - if (slave_id < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk get bond primary port failed port = %d\n", slave_id); -- free(eth_params); -+ free(eth_params); - return slave_id; - } - ret = rte_eth_dev_info_get(slave_id, &slave_dev_info); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk get bond dev info failed ret = %d\n", ret); -- free(eth_params); -+ free(eth_params); - return ret; - } - dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; -@@ -623,6 +623,13 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - } - -+ /* after rte_eth_dev_configure */ -+ ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); -+ return -1; -+ } -+ - rte_eth_allmulticast_enable(port_id); - - return 0; -@@ -733,7 +740,7 @@ int32_t init_dpdk_ethdev(void) - } - - ret = dpdk_ethdev_init(bond_port_id, 1); -- if (ret != 0) { -+ if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); - return -1; - } -@@ -765,18 +772,18 @@ int32_t init_dpdk_ethdev(void) - - ret = rte_eth_promiscuous_enable(bond_port_id); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable promiscuous failed ret = %d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "dpdk enable promiscuous failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_allmulticast_enable(bond_port_id); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable allmulticast failed ret = %d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "dpdk enable allmulticast failed ret = %d\n", ret); - return -1; - } - - ret = rte_eth_dev_start(bond_port_id); -- if (ret < 0) { -+ if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk start bond port failed ret = %d\n", ret); - return -1; - } --- -2.33.0 - diff --git a/0156-Correcting-spelling-errors.patch b/0156-Correcting-spelling-errors.patch deleted file mode 100644 index ab52f92..0000000 --- a/0156-Correcting-spelling-errors.patch +++ /dev/null @@ -1,25 +0,0 @@ -From b766b84a25e9099e67ebacffed7ff96024af2268 Mon Sep 17 00:00:00 2001 -From: gaojiazhen -Date: Fri, 22 Mar 2024 17:33:59 +0800 -Subject: [PATCH] Correcting spelling errors - ---- - src/ltran/ltran_ethdev.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ltran/ltran_ethdev.c b/src/ltran/ltran_ethdev.c -index 2fb7fab..2f08d4a 100644 ---- a/src/ltran/ltran_ethdev.c -+++ b/src/ltran/ltran_ethdev.c -@@ -378,7 +378,7 @@ static int32_t ltran_bond_port_attr_set(uint16_t port_num, uint16_t bond_port_id - - struct rte_eth_dev_info dev_info; - if (rte_eth_dev_info_get(bond_port_id, &dev_info) != 0) { -- LTRAN_ERR("faile rte_eth_dev_info_get\n"); -+ LTRAN_ERR("rte_eth_dev_info_get failed\n"); - return GAZELLE_ERR; - } - --- -2.33.0 - diff --git a/0157-perftool-add-lhist-statstic-tool.patch b/0157-perftool-add-lhist-statstic-tool.patch deleted file mode 100644 index ed74fd8..0000000 --- a/0157-perftool-add-lhist-statstic-tool.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 34c2f6cc1e1059ffe3e5edd7cebeb758e4ba9f36 Mon Sep 17 00:00:00 2001 -From: wuchangye -Date: Sun, 24 Mar 2024 00:10:08 +0800 -Subject: [PATCH] perftool: add lhist statstic tool - ---- - tools/perf/glhist.bt | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - create mode 100644 tools/perf/glhist.bt - -diff --git a/tools/perf/glhist.bt b/tools/perf/glhist.bt -new file mode 100644 -index 0000000..757f6e9 ---- /dev/null -+++ b/tools/perf/glhist.bt -@@ -0,0 +1,21 @@ -+#!/usr/bin/env bpftrace -+/* -+reference: https://github.com/bpftrace/bpftrace/blob/master/man/adoc/bpftrace.adoc -+prepare: yum install bpftrace -+example: ./glhist.bt rpc_poll_msg -+*/ -+ -+uprobe:/usr/lib64/liblstack.so:$1 -+{ -+ @t_start[tid] = nsecs; -+} -+ -+uretprobe:/usr/lib64/liblstack.so:$1 -+{ -+ @t_dur[tid] = nsecs - @t_start[tid]; -+ @t_count[tid] = count(); -+ if (@t_dur[tid] < 1000000000) { -+ // lhist(int64 n, int64 min, int64 max, int64 step) -+ @t_hist[tid] = lhist(@t_dur[tid], 0, 4000, 100); -+ } -+} -\ No newline at end of file --- -2.33.0 - diff --git a/0158-add-udp-poll.patch b/0158-add-udp-poll.patch deleted file mode 100644 index 4b7380a..0000000 --- a/0158-add-udp-poll.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 776ff89196c1fb5bc0193ea746119e40f80fed46 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Fri, 22 Mar 2024 08:31:28 +0000 -Subject: [PATCH] add udp poll - ---- - src/lstack/core/lstack_lwip.c | 8 ++++++++ - src/lstack/core/lstack_protocol_stack.c | 4 ++++ - 2 files changed, 12 insertions(+) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a604a62..c5161b4 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1307,6 +1307,14 @@ void netif_poll(struct netif *netif) - /* processes on same node handshake packet use this function */ - err_t netif_loop_output(struct netif *netif, struct pbuf *p) - { -+ if (p != NULL) { -+ const struct ip_hdr *iphdr; -+ iphdr = (const struct ip_hdr *)p->payload; -+ if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { -+ return udp_netif_loop_output(netif, p); -+ } -+ } -+ - struct tcp_pcb *pcb = p->pcb; - struct pbuf *head = NULL; - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 7c4af64..138ac2b 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -491,6 +491,10 @@ int stack_polling(uint32_t wakeup_tick) - } - } - -+ if (cfg->udp_enable) { -+ udp_netif_poll(&stack->netif); -+ } -+ - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - /* run to completion mode currently does not support kni */ - /* KNI requests are generally low-rate I/Os, --- -2.33.0 - diff --git a/0159-DFX-adapt-testcase-for-gazellectl-connect-failed.patch b/0159-DFX-adapt-testcase-for-gazellectl-connect-failed.patch deleted file mode 100644 index b9d73f5..0000000 --- a/0159-DFX-adapt-testcase-for-gazellectl-connect-failed.patch +++ /dev/null @@ -1,39 +0,0 @@ -From f082b20ee9bab301fb21f2a40c32ca031f6177af Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Tue, 26 Mar 2024 10:40:00 +0800 -Subject: [PATCH] DFX: adapt testcase for gazellectl connect failed - ---- - src/ltran/ltran_dfx.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 91c6063..073dfa7 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -361,10 +361,10 @@ static int dfx_connect_probe(void) - return 0; - } - -- printf("Connect lstack(path:%s), errno: %d; Connect ltran(path:%s) failed, errno: %d\n", -+ printf("Connect lstack(path:%s) failed, errno: %d; Connect ltran(path:%s) failed, errno: %d\n", - g_lstack_unix_path, -ret2, g_ltran_unix_path, -ret1); -- printf("Please ensure the process is started; If use ltran mode, \ -- set use_ltran=1 in lstack.conf, otherwise set use_ltran=0\n"); -+ printf("Please ensure the process is started; If use ltran mode, " -+ "set use_ltran=1 in lstack.conf, otherwise set use_ltran=0\n"); - return -1; - } - -@@ -1860,7 +1860,7 @@ static int32_t parse_dfx_cmd_args(int32_t argc, char *argv[], struct gazelle_sta - if (strcmp(param, "lstack") == 0) { - ret = dfx_connect_probe(); - if (ret < 0) { -- exit(0); -+ exit(-1); - } - g_use_ltran = ret; - num_cmd = parse_dfx_lstack_args(argc, argv, req_msg); --- -2.33.0 - diff --git a/0160-warp-add-configuration-check-with-host_addr-and-serv.patch b/0160-warp-add-configuration-check-with-host_addr-and-serv.patch deleted file mode 100644 index fdafe9e..0000000 --- a/0160-warp-add-configuration-check-with-host_addr-and-serv.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 7604fb6e3917bd2b745f9dd5591de5a3b244c51e Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 25 Mar 2024 16:07:09 +0800 -Subject: [PATCH] warp: add configuration check with host_addr and server_ip - for ipv6 - ---- - src/lstack/api/lstack_wrap.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 49bbf91..2d5ef83 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -259,6 +259,11 @@ bool is_dst_ip_localhost(const struct sockaddr *addr) - if (get_global_cfg_params()->host_addr.addr == ((struct sockaddr_in *)addr)->sin_addr.s_addr) { - return true; - } -+ } else if (addr->sa_family == AF_INET6) { -+ if (memcmp(get_global_cfg_params()->host_addr6.addr, &((struct sockaddr_in6 *)addr)->sin6_addr, -+ sizeof(struct in6_addr)) == 0) { -+ return true; -+ } - } - - if (getifaddrs(&ifap) == -1) { --- -2.33.0 - diff --git a/0161-add-latency-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch b/0161-add-latency-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch deleted file mode 100644 index b30688e..0000000 --- a/0161-add-latency-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch +++ /dev/null @@ -1,380 +0,0 @@ -From 286e9a267e2d106d05c5fec80a932ed605d4b006 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 1 Apr 2024 09:15:56 +0800 -Subject: [PATCH] add latency nodes: READ_APP_CALL & WRITE_RPC_MSG - ---- - src/common/dpdk_common.h | 2 + - src/common/gazelle_dfx_msg.h | 18 ++++--- - src/lstack/core/lstack_lwip.c | 23 ++++++--- - src/lstack/core/lstack_protocol_stack.c | 4 ++ - src/lstack/core/lstack_stack_stat.c | 68 +++++++++++++++++++++---- - src/lstack/core/lstack_thread_rpc.c | 8 ++- - src/lstack/include/lstack_stack_stat.h | 4 ++ - src/lstack/include/lstack_thread_rpc.h | 2 + - src/lstack/netif/lstack_ethdev.c | 2 +- - src/ltran/ltran_dfx.c | 21 ++++++-- - 10 files changed, 124 insertions(+), 28 deletions(-) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index cb41747..7a05342 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -19,6 +19,7 @@ - #include - #include - -+#include "gazelle_dfx_msg.h" - #include "gazelle_opt.h" - - #define GAZELLE_KNI_NAME "kni" // will be removed during dpdk update -@@ -33,6 +34,7 @@ - struct latency_timestamp { - uint64_t stamp; // time stamp - uint64_t check; // just for later vaild check -+ uint16_t stamp_seg[GAZELLE_LATENCY_MAX]; // time stamp segment - uint16_t type; // latency type - }; - struct mbuf_private { -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index d7ba80f..c2ff760 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -62,17 +62,23 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_FAULT_INJECT_SET, - GAZELLE_STAT_FAULT_INJECT_UNSET, - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ -- -+ - GAZELLE_STAT_MODE_MAX, - }; - - enum GAZELLE_LATENCY_TYPE { -- GAZELLE_LATENCY_READ_LWIP, -- GAZELLE_LATENCY_READ_LSTACK, -- GAZELLE_LATENCY_READ_MAX, -+ GAZELLE_LATENCY_READ_LWIP, // t0 -> t1 -+ GAZELLE_LATENCY_READ_APP_CALL, // t1 -> t2 -+ GAZELLE_LATENCY_READ_LSTACK, // t2 -> t3 -+ GAZELLE_LATENCY_READ_MAX, // t0 -> t3 -+ -+ GAZELLE_LATENCY_WRITE_INTO_RING, // t0 -> t1 -+ GAZELLE_LATENCY_WRITE_LWIP, // t1 -> t2 -+ GAZELLE_LATENCY_WRITE_LSTACK, // t2 -> t3 -+ GAZELLE_LATENCY_WRITE_MAX, // t0 -> t3 -+ -+ GAZELLE_LATENCY_WRITE_RPC_MSG, // rpc_call_send - -- GAZELLE_LATENCY_WRITE_LWIP, -- GAZELLE_LATENCY_WRITE_LSTACK, - GAZELLE_LATENCY_MAX, - }; - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a604a62..1d27938 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -259,12 +259,12 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf_used, size); - - for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < size; i++) { -- calculate_lstack_latency(&sock->stack->latency, pbuf_used[i], GAZELLE_LATENCY_WRITE_LWIP); -+ calculate_lstack_latency(&sock->stack->latency, pbuf_used[i], GAZELLE_LATENCY_WRITE_LWIP, 0); - } - } - - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP); -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP, 0); - } - - sock->send_pre_del = pbuf; -@@ -362,6 +362,12 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - } - } - -+ for (int i = 0; get_protocol_stack_group()->latency_start && i < write_num; i++) { -+ if (pbufs[i] != NULL) { -+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ } -+ } -+ - gazelle_ring_read_over(sock->send_ring); - - sock->remain_len = MBUF_MAX_DATA_LEN - pbufs[write_num - 1]->len; -@@ -611,7 +617,7 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl - - for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) { - if (pbufs[i] != NULL) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP); -+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP, 0); - } - } - -@@ -870,6 +876,7 @@ static bool recv_break_for_err(struct lwip_sock *sock) - static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf **pbuf) - { - int32_t expect = 1; // only get one pbuf -+ uint64_t time_stamp = get_current_time(); - - if (sock->recv_lastdata != NULL) { - *pbuf = sock->recv_lastdata; -@@ -888,7 +895,11 @@ static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf * - noblock = true; - } - } -- -+ -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_lstack_latency(&sock->stack->latency, *pbuf, GAZELLE_LATENCY_READ_APP_CALL, time_stamp); -+ } -+ - return 0; - } - -@@ -954,7 +965,7 @@ static ssize_t recv_ring_tcp_read(struct lwip_sock *sock, void *buf, size_t len, - } - - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK); -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); - } - - gazelle_ring_read_over(sock->recv_ring); -@@ -1001,7 +1012,7 @@ static ssize_t recv_ring_udp_read(struct lwip_sock *sock, void *buf, size_t len, - sock->wakeup->stat.app_read_cnt++; - } - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK); -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); - } - - return copy_len; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 7c4af64..079bba0 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -876,6 +876,10 @@ void stack_send(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack(); - int replenish_again; - -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_rpcmsg_latency(&stack->latency, msg, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ } -+ - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - msg->result = -1; -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 3e016b7..80d4998 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -62,16 +62,53 @@ void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) - lt_new->stamp = lt_old->stamp; - lt_new->check = lt_old->check; - lt_new->type = lt_old->type; -+ for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) { -+ lt_new->stamp_seg[i] = lt_old->stamp_seg[i]; -+ } - } - --void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, -+void time_stamp_into_rpcmsg(struct rpc_msg *msg) -+{ -+ msg->time_stamp = get_current_time(); -+} -+ -+void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, - enum GAZELLE_LATENCY_TYPE type) - { - uint64_t latency; -- uint16_t lt_type; -- const struct latency_timestamp *lt; -+ struct stack_latency *latency_stat; -+ if (msg == NULL || msg->time_stamp < stack_latency->start_time || type >= GAZELLE_LATENCY_MAX) { -+ return; -+ } -+ -+ latency = get_current_time() - msg->time_stamp; -+ latency_stat = &stack_latency->latency[type]; -+ -+ latency_stat->latency_total += latency; -+ latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency; -+ latency_stat->latency_min = (latency_stat->latency_min < latency) ? latency_stat->latency_min : latency; -+ latency_stat->latency_pkts++; -+} -+ -+void calculate_latency_stat(struct gazelle_stack_latency *stack_latency, uint64_t latency, -+ enum GAZELLE_LATENCY_TYPE type) -+{ - struct stack_latency *latency_stat; - -+ latency_stat = &stack_latency->latency[type]; -+ latency_stat->latency_total += latency; -+ latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency; -+ latency_stat->latency_min = (latency_stat->latency_min < latency) ? latency_stat->latency_min : latency; -+ latency_stat->latency_pkts++; -+} -+ -+void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, -+ enum GAZELLE_LATENCY_TYPE type, uint64_t time_record) -+{ -+ uint64_t latency; -+ uint16_t lt_type; -+ struct latency_timestamp *lt; -+ - if (pbuf == NULL || type >= GAZELLE_LATENCY_MAX) { - return; - } -@@ -82,13 +119,26 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - return; - } - -- latency = get_current_time() - lt->stamp; -- latency_stat = &stack_latency->latency[type]; -+ if (time_record == 0) { -+ lt->stamp_seg[type] = get_current_time() - lt->stamp; -+ } else { -+ lt->stamp_seg[type] = time_record > (lt->stamp_seg[type - 1] + lt->stamp) ? -+ (time_record - lt->stamp) : lt->stamp_seg[type - 1]; -+ } - -- latency_stat->latency_total += latency; -- latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency; -- latency_stat->latency_min = (latency_stat->latency_min < latency) ? latency_stat->latency_min : latency; -- latency_stat->latency_pkts++; -+ latency = lt->stamp_seg[type]; -+ if (((lt_type == GAZELLE_LATENCY_RD && type > GAZELLE_LATENCY_READ_LWIP) || -+ (lt_type == GAZELLE_LATENCY_WR && type > GAZELLE_LATENCY_WRITE_INTO_RING)) && -+ latency >= lt->stamp_seg[type - 1]) { -+ latency -= lt->stamp_seg[type - 1]; -+ } -+ -+ /* calculate the time of the entire read/write process */ -+ if (type == GAZELLE_LATENCY_READ_MAX - 1 || type == GAZELLE_LATENCY_WRITE_MAX - 1) { -+ calculate_latency_stat(stack_latency, lt->stamp_seg[type], type + 1); -+ } -+ -+ calculate_latency_stat(stack_latency, latency, type); - } - - void lstack_calculate_aggregate(int type, uint32_t len) -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 20c5a43..30bd827 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -15,6 +15,8 @@ - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_rpc_proc.h" -+#include "lstack_stack_stat.h" -+#include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" - - static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; -@@ -467,11 +469,15 @@ int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int - return -1; - } - -+ if (get_protocol_stack_group()->latency_start) { -+ time_stamp_into_rpcmsg(msg); -+ } -+ - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].size = len; - msg->args[MSG_ARG_2].i = flags; - msg->sync_flag = 0; -- -+ - rpc_call(queue, msg); - - return 0; -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index 87951aa..f901982 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -15,6 +15,7 @@ - - struct gazelle_stack_latency; - struct pbuf; -+struct rpc_msg; - struct gazelle_stat_low_power_info; - struct wakeup_poll; - struct protocol_stack; -@@ -22,6 +23,8 @@ enum GAZELLE_LATENCY_TYPE; - enum GAZELLE_STAT_MODE; - - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, -+ enum GAZELLE_LATENCY_TYPE type, uint64_t time_record); -+void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, - enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); - int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); -@@ -31,5 +34,6 @@ void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_inf - void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); - void lstack_calculate_aggregate(int type, uint32_t len); - void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new); -+void time_stamp_into_rpcmsg(struct rpc_msg *msg); - - #endif /* GAZELLE_STACK_STAT_H */ -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 4d89604..8e97c11 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -60,6 +60,8 @@ struct rpc_msg { - - rpc_msg_func func; /* msg handle func hook */ - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ -+ -+ uint64_t time_stamp; /* rpc_call_* start time */ - }; - - static inline void rpc_queue_init(rpc_queue *queue) -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 8fe11c4..23edc19 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -224,7 +224,7 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - rte_mbuf_refcnt_update(mbuf, 1); - - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LSTACK); -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LSTACK, 0); - } - pbuf = pbuf->next; - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 91c6063..79c172b 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -881,11 +881,22 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st - gazelle_show_latency_result_total(buf, req_msg, res); - - printf("Statistics of lstack latency pkts min(us) max(us) average(us)\n"); -- printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -- printf("range: t0--->t2\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -- printf("range: t3--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LSTACK].latency_stat_result); -- printf("range: t2--->t0\n%s", res[GAZELLE_LATENCY_WRITE_LWIP].latency_stat_result); -- printf("t0:read form/send to nic t1:into/out of lstask queue t2:into/out of app queue t3:app read/send\n"); -+ printf("Recv:\n"); -+ printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -+ printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_READ_APP_CALL].latency_stat_result); -+ printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -+ printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_MAX].latency_stat_result); -+ printf("t0: read from nic t1: into recv ring t2: app read start t3: app read end\n"); -+ -+ printf("Send:\n"); -+ printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_WRITE_INTO_RING].latency_stat_result); -+ printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_WRITE_LWIP].latency_stat_result); -+ printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_WRITE_LSTACK].latency_stat_result); -+ printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_WRITE_MAX].latency_stat_result); -+ printf("t0: app send t1: into send ring t2: out of send ring t3: send to nic\n"); -+ -+ printf("Rpc:\n"); -+ printf("rpc_call_send \n%s", res[GAZELLE_LATENCY_WRITE_RPC_MSG].latency_stat_result); - - free(res); - } --- -2.33.0 - diff --git a/0162-fix-vlan-filter-can-be-added-when-vlan_mode-1.patch b/0162-fix-vlan-filter-can-be-added-when-vlan_mode-1.patch deleted file mode 100644 index 05a5681..0000000 --- a/0162-fix-vlan-filter-can-be-added-when-vlan_mode-1.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c392e263cb5f5392713600174d3b8955f2d26759 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Wed, 3 Apr 2024 14:33:57 +0800 -Subject: [PATCH] fix vlan filter can be added when vlan_mode=-1 - ---- - src/lstack/core/lstack_dpdk.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 42981f4..b972c00 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -624,10 +624,12 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - - /* after rte_eth_dev_configure */ -- ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); -- return -1; -+ if (get_global_cfg_params()->nic.vlan_mode != -1) { -+ ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); -+ return -1; -+ } - } - - rte_eth_allmulticast_enable(port_id); --- -2.33.0 - diff --git a/0163-Add-support-for-arch-ppc64le.patch b/0163-Add-support-for-arch-ppc64le.patch deleted file mode 100644 index 7d42df3..0000000 --- a/0163-Add-support-for-arch-ppc64le.patch +++ /dev/null @@ -1,36 +0,0 @@ -From e89442aa3aebae9896a5d5dac0e397e5da16f8de Mon Sep 17 00:00:00 2001 -From: Ren Zhijie -Date: Mon, 25 Mar 2024 16:46:08 +0800 -Subject: [PATCH] Add support for arch ppc64le - -Signed-off-by: Ren Zhijie ---- - src/ltran/CMakeLists.txt | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index a484ae3..2eb7d70 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -63,6 +63,9 @@ if (DPDK_VERSION GREATER_EQUAL 23.11) - set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_log -larchive -Wl,-lrte_eal") - else() - set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_kni -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic") -+ if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "ppc64le") -+ set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-larchive") -+ endif() - endif() - - add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_stat.c ltran_errno.c -@@ -79,7 +82,7 @@ target_compile_options(ltran PRIVATE -fno-strict-aliasing -D__ARM_FEATURE_CRC32= - -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2 -Wno-error=deprecated-declarations) - - # gcc coredump in openEuler-20.03-LTS-XX aarch64 when add -march=native --if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64" ) -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64|ppc64le" ) - target_compile_options(ltran PRIVATE -march=native -Wcast-align) - endif() - --- -2.33.0 - diff --git a/0164-dfx-support-get-nic-bond-status.patch b/0164-dfx-support-get-nic-bond-status.patch deleted file mode 100644 index af4f21a..0000000 --- a/0164-dfx-support-get-nic-bond-status.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 819f74f014592b8af93eb45fd13681caa2cb662a Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Thu, 28 Mar 2024 21:24:05 +0800 -Subject: [PATCH] dfx: support get nic bond status - ---- - src/common/gazelle_dfx_msg.h | 9 +++++++++ - src/lstack/core/lstack_dpdk.c | 27 +++++++++++++++++++++++++++ - src/ltran/ltran_dfx.c | 14 ++++++++++++++ - 3 files changed, 50 insertions(+) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index d7ba80f..4929ae7 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -256,15 +256,24 @@ struct gazelle_stat_low_power_info { - - #define RTE_ETH_XSTATS_NAME_SIZE 64 - #define RTE_ETH_XSTATS_MAX_LEN 256 -+#define RTE_MAX_ETHPORTS 32 - struct nic_eth_xstats_name { - char name[RTE_ETH_XSTATS_NAME_SIZE]; - }; - -+struct bonding { -+ int8_t mode; -+ int32_t miimon; -+ uint16_t primary_port_id; -+ uint16_t slaves[RTE_MAX_ETHPORTS]; -+}; -+ - struct nic_eth_xstats { - struct nic_eth_xstats_name xstats_name[RTE_ETH_XSTATS_MAX_LEN]; - uint64_t values[RTE_ETH_XSTATS_MAX_LEN]; - uint32_t len; - uint16_t port_id; -+ struct bonding bonding; - }; - - struct nic_eth_features { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a774d45..cd87026 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -870,6 +870,31 @@ static int dpdk_nic_xstats_name_get(struct nic_eth_xstats_name *names, uint16_t - return len; - } - -+void dpdk_nic_bond_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id, uint16_t *slaves, int count) -+{ -+ dfx->data.nic_xstats.bonding.mode = rte_eth_bond_mode_get(port_id); -+ if (dfx->data.nic_xstats.bonding.mode < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_mode_get failed.\n"); -+ return; -+ } -+ -+ dfx->data.nic_xstats.bonding.primary_port_id = rte_eth_bond_primary_get(port_id); -+ if (dfx->data.nic_xstats.bonding.primary_port_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_primary_get failed.\n"); -+ return; -+ } -+ -+ dfx->data.nic_xstats.bonding.miimon = rte_eth_bond_link_monitoring_get(port_id); -+ if (dfx->data.nic_xstats.bonding.miimon <= 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_bond_link_monitoring_get failed.\n"); -+ return; -+ } -+ -+ for (int i = 0; i < count; i++) { -+ dfx->data.nic_xstats.bonding.slaves[i] = slaves[i]; -+ } -+} -+ - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - { - struct rte_eth_dev_info dev_info; -@@ -878,6 +903,7 @@ void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - - dfx->data.nic_xstats.len = -1; - dfx->data.nic_xstats.port_id = port_id; -+ dfx->data.nic_xstats.bonding.mode = -1; - ret = rte_eth_dev_info_get(port_id, &dev_info); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_info_get failed.\n"); -@@ -904,6 +930,7 @@ void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - if (dpdk_nic_xstats_value_get(dfx->data.nic_xstats.values, len, slaves, slave_count) != 0) { - return; - } -+ dpdk_nic_bond_xstats_get(dfx, port_id, slaves, slave_count); - } else { - len = dpdk_nic_xstats_name_get(dfx->data.nic_xstats.xstats_name, port_id); - if (len <= 0) { -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 073dfa7..88d11bd 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -200,6 +200,20 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - struct nic_eth_xstats *xstats = &stat->data.nic_xstats; - static const char *nic_stats_border = "########################"; - -+ if (xstats->bonding.mode >= 0) { -+ printf("############# NIC bonding mode display #############\n"); -+ printf("%s############################\n", nic_stats_border); -+ printf("Bonding mode: [%d]\n", xstats->bonding.mode); -+ printf("Bonding miimon: [%d]\n", xstats->bonding.miimon); -+ printf("Slaves(%d): [", xstats->port_id); -+ for (int i = 0; i < xstats->port_id - 1; i++) { -+ printf("%d ", xstats->bonding.slaves[i]); -+ } -+ printf("%d]\n", xstats->bonding.slaves[xstats->port_id - 1]); -+ printf("Primary: [%d]\n", xstats->bonding.primary_port_id); -+ printf("%s############################\n", nic_stats_border); -+ } -+ - printf("###### NIC extended statistics for port %-2d #########\n", xstats->port_id); - printf("%s############################\n", nic_stats_border); - if (xstats->len <= 0 || xstats->len > RTE_ETH_XSTATS_MAX_LEN) { --- -2.33.0 - diff --git a/0165-remove-dpdk_skip_nic_init-for-dpdk-23.11.patch b/0165-remove-dpdk_skip_nic_init-for-dpdk-23.11.patch deleted file mode 100644 index c97b59f..0000000 --- a/0165-remove-dpdk_skip_nic_init-for-dpdk-23.11.patch +++ /dev/null @@ -1,54 +0,0 @@ -From aae704235da3299fb2d6920aef46afd560ab2c01 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 9 Apr 2024 17:50:46 +0800 -Subject: [PATCH] remove dpdk_skip_nic_init for dpdk-23.11 - ---- - src/lstack/core/lstack_init.c | 4 ++++ - src/lstack/include/lstack_dpdk.h | 4 +++- - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index f1ef134..79b4060 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -144,7 +144,9 @@ static void create_control_thread(void) - pthread_t tid; - if (use_ltran()) { - /* The function call here should be in strict order. */ -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_skip_nic_init(); -+#endif - if (control_init_client(false) != 0) { - LSTACK_EXIT(1, "control_init_client failed\n"); - } -@@ -279,7 +281,9 @@ __attribute__((constructor)) void gazelle_network_init(void) - - /* Init control plane and dpdk init */ - create_control_thread(); -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_restore_pci(); -+#endif - - /* cancel the core binding from DPDK initialization */ - if (!get_global_cfg_params()->main_thread_affinity) { -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index c7cfbdf..fe3d07b 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -48,9 +48,11 @@ int32_t create_shared_ring(struct protocol_stack *stack); - void lstack_log_level_init(void); - int dpdk_ethdev_init(int port_id, bool bond_port); - int dpdk_ethdev_start(void); -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void); --int32_t dpdk_init_lstack_kni(void); - void dpdk_restore_pci(void); -+#endif -+int32_t dpdk_init_lstack_kni(void); - bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port, uint16_t dst_port); - struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); --- -2.33.0 - diff --git a/0166-gazellectl-add-lwip-stats_proto-print.patch b/0166-gazellectl-add-lwip-stats_proto-print.patch deleted file mode 100644 index bb4c27f..0000000 --- a/0166-gazellectl-add-lwip-stats_proto-print.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 3beb273528f360c7d6863990a5d0cdcb5ebcb407 Mon Sep 17 00:00:00 2001 -From: ningjin -Date: Thu, 28 Mar 2024 16:05:01 +0800 -Subject: [PATCH] gazellectl add lwip stats_proto print - ---- - src/common/gazelle_dfx_msg.h | 23 ++++++++++ - src/lstack/core/lstack_control_plane.c | 2 +- - src/lstack/core/lstack_stack_stat.c | 41 +++++++++++++++-- - src/lstack/include/lstack_stack_stat.h | 3 +- - src/ltran/ltran_dfx.c | 61 +++++++++++++++++++++++++- - src/ltran/ltran_monitor.c | 1 + - 6 files changed, 124 insertions(+), 7 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index d7ba80f..6cd90b1 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -24,6 +24,7 @@ - - #define GAZELLE_CLIENT_NUM_MIN 1 - #define GAZELLE_LOG_LEVEL_MAX 10 -+#define MAX_PROTOCOL_LENGTH 20 - #define GAZELLECTL_TIMEOUT 5000 // millisecond - /* maybe it should be consistent with MEMP_NUM_TCP_PCB */ - #define GAZELLE_LSTACK_MAX_CONN (20000 + 2000) // same as MAX_CLIENTS + RESERVED_CLIENTS in lwipopts.h -@@ -46,6 +47,7 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LTRAN_SHOW_SOCKTABLE, - GAZELLE_STAT_LTRAN_SHOW_CONNTABLE, - GAZELLE_STAT_LTRAN_SHOW_LSTACK, -+ GAZELLE_STAT_LSTACK_SHOW_PROTOCOL, - - GAZELLE_STAT_LSTACK_SHOW, - GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, -@@ -193,6 +195,24 @@ struct gazelle_stat_lstack_snmp { - uint32_t icmp_out_echo_reps; - }; - -+/* same as define in lwip/stats.h - struct stats_proto */ -+struct gazelle_stat_lstack_proto { -+ /* data */ -+ uint16_t xmit; /* Transmitted packets. */ -+ uint16_t recv; /* Received packets. */ -+ uint16_t fw; /* Forwarded packets. */ -+ uint16_t drop; /* Dropped packets. */ -+ uint16_t chkerr; /* Checksum error. */ -+ uint16_t lenerr; /* Invalid length error. */ -+ uint16_t memerr; /* Out of memory error. */ -+ uint16_t rterr; /* Routing error. */ -+ uint16_t proterr; /* Protocol error. */ -+ uint16_t opterr; /* Error in options. */ -+ uint16_t err; /* Misc error. */ -+ uint16_t cachehit; -+}; -+ -+ - /* same as define in lwip/tcp.h - struct tcp_pcb_dp */ - struct gazelle_stat_lstack_conn_info { - uint32_t state; -@@ -288,6 +308,8 @@ struct gazelle_stack_dfx_data { - struct gazelle_stat_lstack_snmp snmp; - struct nic_eth_xstats nic_xstats; - struct nic_eth_features nic_features; -+ struct gazelle_stat_lstack_proto proto_data; -+ - #ifdef GAZELLE_FAULT_INJECT_ENABLE - struct gazelle_fault_inject_data inject; - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ -@@ -321,6 +343,7 @@ struct gazelle_stat_msg_request { - union stat_param { - char log_level[GAZELLE_LOG_LEVEL_MAX]; - uint16_t low_power_mod; -+ char protocol[MAX_PROTOCOL_LENGTH]; - #ifdef GAZELLE_FAULT_INJECT_ENABLE - struct gazelle_fault_inject_data inject; - #endif /* GAZELLE_FAULT_INJECT_ENABLE */ -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 9f0c313..04858c7 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -601,7 +601,7 @@ static int32_t handle_stat_request(int32_t sockfd) - msg.stat_mode == GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES) { - return handle_dpdk_cmd(sockfd, msg.stat_mode); - } else { -- ret = handle_stack_cmd(sockfd, msg.stat_mode); -+ ret = handle_stack_cmd(sockfd, &msg); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "get_stats failed ret=%d\n", ret); - } -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 3e016b7..d439357 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -210,11 +210,42 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - dfx->data.pkts.conn_num = stack->conn_num; - } - -+static void get_stack_dfx_data_proto(struct gazelle_stack_dfx_data *dfx, struct protocol_stack *stack, -+ struct gazelle_stat_msg_request *msg) -+{ -+ int32_t ret = 0; -+ msg->data.protocol[MAX_PROTOCOL_LENGTH - 1] = '\0'; -+ const char* proto_mode = msg->data.protocol; -+ -+ if (strcmp(proto_mode, "UDP") == 0) { -+ ret = memcpy_s(&dfx->data.proto_data, sizeof(dfx->data.proto_data), -+ &stack->lwip_stats->udp, sizeof(stack->lwip_stats->udp)); -+ } else if (strcmp(proto_mode, "TCP") == 0) { -+ ret = memcpy_s(&dfx->data.proto_data, sizeof(dfx->data.proto_data), -+ &stack->lwip_stats->tcp, sizeof(stack->lwip_stats->tcp)); -+ } else if (strcmp(proto_mode, "IP") == 0) { -+ ret = memcpy_s(&dfx->data.proto_data, sizeof(dfx->data.proto_data), -+ &stack->lwip_stats->ip, sizeof(stack->lwip_stats->ip)); -+ } else if (strcmp(proto_mode, "ICMP") == 0) { -+ ret = memcpy_s(&dfx->data.proto_data, sizeof(dfx->data.proto_data), -+ &stack->lwip_stats->icmp, sizeof(stack->lwip_stats->icmp)); -+ } else if (strcmp(proto_mode, "ETHARP") == 0) { -+ ret = memcpy_s(&dfx->data.proto_data, sizeof(dfx->data.proto_data), -+ &stack->lwip_stats->etharp, sizeof(stack->lwip_stats->etharp)); -+ } else { -+ printf("Error: Invalid protocol\n"); -+ } -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); -+ } -+} -+ - static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protocol_stack *stack, -- enum GAZELLE_STAT_MODE stat_mode) -+ struct gazelle_stat_msg_request *msg) - { - int32_t rpc_call_result; - int32_t ret; -+ enum GAZELLE_STAT_MODE stat_mode = msg->stat_mode; - - switch (stat_mode) { - case GAZELLE_STAT_LSTACK_SHOW: -@@ -255,6 +286,9 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - case GAZELLE_STAT_LTRAN_STOP_LATENCY: - set_latency_start_flag(false); - break; -+ case GAZELLE_STAT_LSTACK_SHOW_PROTOCOL: -+ get_stack_dfx_data_proto(dfx, stack, msg); -+ break; - default: - break; - } -@@ -298,16 +332,17 @@ int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) - return 0; - } - --int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode) -+int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg) - { - struct gazelle_stack_dfx_data dfx; - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ enum GAZELLE_STAT_MODE stat_mode = msg->stat_mode; - - for (uint32_t i = 0; i < stack_group->stack_num; i++) { - struct protocol_stack *stack = stack_group->stacks[i]; - - memset_s(&dfx, sizeof(dfx), 0, sizeof(dfx)); -- get_stack_dfx_data(&dfx, stack, stat_mode); -+ get_stack_dfx_data(&dfx, stack, msg); - - if (!use_ltran() && - (stat_mode == GAZELLE_STAT_LTRAN_START_LATENCY || stat_mode == GAZELLE_STAT_LTRAN_STOP_LATENCY)) { -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index 87951aa..867f35b 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.handle -@@ -21,13 +21,14 @@ struct wakeup_poll; - struct protocol_stack; - enum GAZELLE_LATENCY_TYPE; - enum GAZELLE_STAT_MODE; -+struct gazelle_stat_msg_request; - - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, - enum GAZELLE_LATENCY_TYPE type, uint64_t time_record); - void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, - enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); --int handle_stack_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); -+int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg); - int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); - uint64_t get_current_time(void); - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info); -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 073dfa7..717744a 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -136,6 +136,7 @@ static void gazelle_print_ltran_conn(void *buf, const struct gazelle_stat_msg_re - static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg); - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -@@ -168,7 +169,8 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LSTACK_SHOW_XSTATS, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_xstats}, - {GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_aggregate}, - {GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_nic_features}, -- -+ {GAZELLE_STAT_LSTACK_SHOW_PROTOCOL, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_proto}, -+ - #ifdef GAZELLE_FAULT_INJECT_ENABLE - {GAZELLE_STAT_FAULT_INJECT_SET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_set_status}, - {GAZELLE_STAT_FAULT_INJECT_UNSET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_unset_status}, -@@ -1083,6 +1085,20 @@ static void gazelle_print_lstack_stat_snmp_core(const struct gazelle_stack_dfx_d - printf("icmp_out_echo_reps: %u\n", snmp->icmp_out_echo_reps); - } - -+static void gazelle_print_lstack_stat_proto_core(const struct gazelle_stack_dfx_data *stat, -+ const struct gazelle_stat_lstack_proto *proto) -+{ -+ printf("\n------ stack tid: %6u ------\n", stat->tid); -+ printf("xmit: %u\n", proto->xmit); -+ printf("recv: %u\n", proto->recv); -+ printf("fw: %u\n", proto->fw); -+ printf("drop: %u\n", proto->drop); -+ printf("chkerr: %u\n", proto->chkerr); -+ printf("lenerr: %u\n", proto->lenerr); -+ printf("memerr: %u\n", proto->memerr); -+ printf("rterr: %u\n", proto->rterr); -+} -+ - static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - int32_t ret; -@@ -1102,6 +1118,26 @@ static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_ - } while (true); - } - -+static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t ret; -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct gazelle_stat_lstack_proto *proto = NULL; -+ -+ proto = &stat->data.proto_data; -+ printf("Statistics of lstack proto:\n"); -+ do { -+ gazelle_print_lstack_stat_proto_core(stat, proto); -+ if (stat->eof != 0) { -+ break; -+ } -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); -+ if (ret != GAZELLE_OK) { -+ return; -+ } -+ } while (true); -+} -+ - static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_stat_lstack_conn_info *conn_info) - { - if (conn_info->keepalive == 0) { -@@ -1240,6 +1276,7 @@ static void show_usage(void) - " loglevel {error | info | debug} set lstack loglevel \n" - " lowpower {0 | 1} set lowpower enable \n" - " [time] measure latency time default 1S, maximum 30mins \n\n" -+ " -p, protocol {UDP | TCP | ICMP | IP | ETHARP | IP_FRAG} show lstack protocol statistics \n" - #ifdef GAZELLE_FAULT_INJECT_ENABLE - " *inject params*\n" - " |inject_type | digit_param_1 | digit_param_2 | inject_rule |\n" -@@ -1444,6 +1481,25 @@ static int parse_delay_arg(int32_t argc, char *argv[], long int delay) - return 0; - } - -+static int32_t parse_dfx_lstack_show_proto_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t cmd_index = 0; -+ int32_t ret; -+ -+ char *param = argv[GAZELLE_OPTIONS2_ARG_IDX]; -+ if (strcmp(param, "UDP") != 0 && strcmp(param, "TCP") != 0 && strcmp(param, "IP") && -+ strcmp(param, "ICMP") && strcmp(param, "ETHARP") != 0) { -+ return cmd_index; -+ } -+ ret = strncpy_s(req_msg[cmd_index].data.protocol, MAX_PROTOCOL_LENGTH, argv[GAZELLE_OPTIONS2_ARG_IDX], -+ MAX_PROTOCOL_LENGTH - 1); -+ if (ret != EOK) { -+ return -1; -+ } -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_PROTOCOL; -+ return cmd_index; -+} -+ - static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gazelle_stat_msg_request *req_msg) - { - int32_t cmd_index = 0; -@@ -1490,8 +1546,9 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - } - } else if (strcmp(param, "-k") == 0 || strcmp(param, "nic-features") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES; -+ } else if (strcmp(param, "protocol") == 0 || strcmp(param, "-p") == 0) { -+ cmd_index = parse_dfx_lstack_show_proto_args(argc, argv, req_msg); - } -- - return cmd_index; - } - -diff --git a/src/ltran/ltran_monitor.c b/src/ltran/ltran_monitor.c -index ea31e84..457e8c8 100644 ---- a/src/ltran/ltran_monitor.c -+++ b/src/ltran/ltran_monitor.c -@@ -347,6 +347,7 @@ static int32_t lstack_req_mode_process(int32_t fd, const struct gazelle_stat_msg - case GAZELLE_STAT_LSTACK_SHOW_CONN: - case GAZELLE_STAT_LSTACK_SHOW_LATENCY: - case GAZELLE_STAT_LSTACK_LOW_POWER_MDF: -+ case GAZELLE_STAT_LSTACK_SHOW_PROTOCOL: - handle_resp_lstack_transfer(req_msg, fd); - break; - default: --- -2.33.0 - diff --git a/0167-fix-port-not-support-vlan-filter.patch b/0167-fix-port-not-support-vlan-filter.patch deleted file mode 100644 index 3083078..0000000 --- a/0167-fix-port-not-support-vlan-filter.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 3171100d06146791ab9d22523805b8ed580daf3f Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Fri, 12 Apr 2024 15:09:12 +0800 -Subject: [PATCH] fix port not support vlan filter - ---- - src/lstack/core/lstack_dpdk.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a6a8a01..5d90408 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -624,7 +624,8 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - } - - /* after rte_eth_dev_configure */ -- if (get_global_cfg_params()->nic.vlan_mode != -1) { -+ if ((get_global_cfg_params()->nic.vlan_mode != -1) && -+ ((stack_group->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) == RTE_ETH_RX_OFFLOAD_VLAN_FILTER)) { - ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); --- -2.33.0 - diff --git a/0168-fix-tcp-recv-does-not-return-pkg-when-ring-buffer-is.patch b/0168-fix-tcp-recv-does-not-return-pkg-when-ring-buffer-is.patch deleted file mode 100644 index 01ded10..0000000 --- a/0168-fix-tcp-recv-does-not-return-pkg-when-ring-buffer-is.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 5fff605ff68741482d7fff992343eaccb383115f Mon Sep 17 00:00:00 2001 -From: li_yunqing -Date: Fri, 22 Mar 2024 15:47:19 +0800 -Subject: [PATCH] fix tcp recv does not return pkg when ring buffer is empty - ---- - src/lstack/core/lstack_lwip.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a604a62..51238ba 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -925,7 +925,9 @@ static ssize_t recv_ring_tcp_read(struct lwip_sock *sock, void *buf, size_t len, - } - - while (recv_left > 0) { -- if (recv_ring_get_one(sock, noblock, &pbuf) != 0) { -+ if (recv_ring_get_one(sock, noblock | recvd, &pbuf) != 0) { -+ /* When the buffer is empty, it will be returned directly -+ if in non-blocking mode or if data has already been received */ - break; - } - --- -2.33.0 - diff --git a/0169-add-tuple_fileter-error-info.patch b/0169-add-tuple_fileter-error-info.patch deleted file mode 100644 index e15770e..0000000 --- a/0169-add-tuple_fileter-error-info.patch +++ /dev/null @@ -1,24 +0,0 @@ -From e4d3f17fbb3efce9e29c86838a09fa1f9e224fd3 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Tue, 16 Apr 2024 03:46:12 +0000 -Subject: [PATCH] add tuple_fileter error info - ---- - src/lstack/core/lstack_cfg.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index b533a33..533eb6c 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1159,6 +1159,7 @@ static int parse_tuple_filter(void) - return 0; - } - if (g_config_params.use_ltran || g_config_params.listen_shadow) { -+ LSTACK_LOG(ERR, LSTACK, "tuple filter and (ltran or listen_shadow) cannot be enabled at the same time\n"); - return -EINVAL; - } - --- -2.33.0 - diff --git a/0170-adapt-dpdk-23.11-remove-kni.patch b/0170-adapt-dpdk-23.11-remove-kni.patch deleted file mode 100644 index f264f5d..0000000 --- a/0170-adapt-dpdk-23.11-remove-kni.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 201e8d1e2fad0d83ea1544fd14b35492d8dd72bc Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 17 Apr 2024 15:43:07 +0800 -Subject: [PATCH] adapt dpdk-23.11 remove kni - ---- - src/lstack/core/lstack_dpdk.c | 4 +++- - src/lstack/core/lstack_init.c | 4 ++++ - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 5d90408..016276a 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -694,6 +694,7 @@ int32_t dpdk_ethdev_start(void) - return 0; - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - int32_t dpdk_init_lstack_kni(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -@@ -712,7 +713,6 @@ int32_t dpdk_init_lstack_kni(void) - return 0; - } - --#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void) - { - /* when lstack init nic again, ltran can't read pkts from nic. unregister pci_bus to avoid init nic in lstack */ -@@ -799,12 +799,14 @@ int32_t init_dpdk_ethdev(void) - } - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_global_cfg_params()->kni_switch && get_global_cfg_params()->is_primary) { - ret = dpdk_init_lstack_kni(); - if (ret < 0) { - return -1; - } - } -+#endif - - return 0; - } -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 79b4060..c2499d7 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -183,6 +183,7 @@ static void gazelle_signal_init(void) - lstack_signal_init(); - } - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - static void set_kni_ip_mac() - { - struct cfg_params *cfg = get_global_cfg_params(); -@@ -230,6 +231,7 @@ static void set_kni_ip_mac() - - posix_api->close_fn(fd); - } -+#endif - - __attribute__((constructor)) void gazelle_network_init(void) - { -@@ -315,9 +317,11 @@ __attribute__((constructor)) void gazelle_network_init(void) - /* lwip initialization */ - lwip_sock_init(); - -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_global_cfg_params()->kni_switch) { - set_kni_ip_mac(); - } -+#endif - - if (set_process_start_flag() != 0) { - gazelle_exit(); --- -2.33.0 - diff --git a/0171-fix-ioctl-set-failed.patch b/0171-fix-ioctl-set-failed.patch deleted file mode 100644 index e1cfefc..0000000 --- a/0171-fix-ioctl-set-failed.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 5924fd2879acbb52b12a61380b939cce30a133a9 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 28 Apr 2024 10:44:15 +0800 -Subject: [PATCH] fix ioctl set failed - ---- - src/lstack/api/lstack_wrap.c | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index c90aa04..7101d98 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -690,13 +690,27 @@ static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set - if (select_posix_path() == PATH_KERNEL || \ - select_fd_posix_path(_fd, &sock) == PATH_KERNEL) \ - return _fcntl_fn(_fd, _cmd, val); \ -- int32_t ret = _fcntl_fn(_fd, _cmd, val); \ -- if (ret == -1) \ -- return ret; \ -- return _lwip_fcntl(_fd, _cmd, val); \ -+ int32_t ret1 = _fcntl_fn(_fd, _cmd, val); \ -+ if (ret1 == -1) { \ -+ LSTACK_LOG(ERR, LSTACK, "fd(%d) kernel path call failed, errno is %d, maybe not error\n", \ -+ _fd, errno); \ -+ return ret1; \ -+ } \ -+ int32_t ret2 = _lwip_fcntl(_fd, _cmd, val); \ -+ /* -+ * if function not implemented, fcntl get/set context will not be modifyed by user path, -+ * return kernel path result -+ */ \ -+ if (ret2 == -1) { \ -+ if (errno == ENOSYS) { \ -+ return ret1; \ -+ } \ -+ LSTACK_LOG(ERR, LSTACK, "fd(%d) user path call failed, errno is %d, maybe not error\n", \ -+ _fd, errno); \ -+ } \ -+ return ret2; \ - } while (0) - -- - /* -------------------------------------------------------- - * ------- LD_PRELOAD mode replacement interface -------- - * -------------------------------------------------------- --- -2.33.0 - diff --git a/0172-ltran-memset-quintuple.patch b/0172-ltran-memset-quintuple.patch deleted file mode 100644 index 94a2d36..0000000 --- a/0172-ltran-memset-quintuple.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 3e10c7661d412082990d88d479c02d77c14fbd8c Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Tue, 30 Apr 2024 09:56:59 +0800 -Subject: [PATCH] ltran: memset quintuple - ---- - src/ltran/ltran_forward.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index a5756d7..0658b11 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -251,7 +251,7 @@ static __rte_always_inline int32_t tcp_handle(struct rte_mbuf *m, const struct r - { - struct gazelle_tcp_conn *tcp_conn = NULL; - struct gazelle_tcp_sock *tcp_sock = NULL; -- struct gazelle_quintuple quintuple; -+ struct gazelle_quintuple quintuple = {0}; - - quintuple.dst_ip.u_addr.ip4.addr = ipv4_hdr->dst_addr; - quintuple.src_ip.u_addr.ip4.addr = ipv4_hdr->src_addr; --- -2.33.0 - diff --git a/0173-gazellectl-add-lwip-stats_proto-print.patch b/0173-gazellectl-add-lwip-stats_proto-print.patch deleted file mode 100644 index 82ec1dd..0000000 --- a/0173-gazellectl-add-lwip-stats_proto-print.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 62297e7fb9299a75bc582b1abb4343e88e5c7c05 Mon Sep 17 00:00:00 2001 -From: ningjin -Date: Thu, 28 Mar 2024 16:05:01 +0800 -Subject: [PATCH] gazellectl add lwip stats_proto print - ---- - src/common/gazelle_dfx_msg.h | 4 ++++ - src/ltran/ltran_dfx.c | 12 +++++++----- - 2 files changed, 11 insertions(+), 5 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 5d626a2..17e1662 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -206,6 +206,10 @@ struct gazelle_stat_lstack_proto { - /* data */ - uint16_t xmit; /* Transmitted packets. */ - uint16_t recv; /* Received packets. */ -+ uint16_t tx_in; /* Transmitted in packets. */ -+ uint16_t tx_out; /* Transmitted out packets. */ -+ uint16_t rx_in; /* Received in packets. */ -+ uint16_t rx_out; /* Received out packets. */ - uint16_t fw; /* Forwarded packets. */ - uint16_t drop; /* Dropped packets. */ - uint16_t chkerr; /* Checksum error. */ -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index c81cce2..f4e55e3 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1114,8 +1114,10 @@ static void gazelle_print_lstack_stat_proto_core(const struct gazelle_stack_dfx_ - const struct gazelle_stat_lstack_proto *proto) - { - printf("\n------ stack tid: %6u ------\n", stat->tid); -- printf("xmit: %u\n", proto->xmit); -- printf("recv: %u\n", proto->recv); -+ printf("tx_in: %u\n", proto->tx_in); -+ printf("tx_out: %u\n", proto->tx_out); -+ printf("rx_in: %u\n", proto->rx_in); -+ printf("rx_out: %u\n", proto->rx_out); - printf("fw: %u\n", proto->fw); - printf("drop: %u\n", proto->drop); - printf("chkerr: %u\n", proto->chkerr); -@@ -1297,11 +1299,11 @@ static void show_usage(void) - " -x, xstats show lstack xstats \n" - " -k, nic-features show state of protocol offload and other features \n" - " -a, aggregatin [time] show lstack send/recv aggregation \n" -+ " -p, protocol {UDP | TCP | ICMP | IP | ETHARP} show lstack protocol statistics \n" - " set: \n" - " loglevel {error | info | debug} set lstack loglevel \n" - " lowpower {0 | 1} set lowpower enable \n" - " [time] measure latency time default 1S, maximum 30mins \n\n" -- " -p, protocol {UDP | TCP | ICMP | IP | ETHARP | IP_FRAG} show lstack protocol statistics \n" - #ifdef GAZELLE_FAULT_INJECT_ENABLE - " *inject params*\n" - " |inject_type | digit_param_1 | digit_param_2 | inject_rule |\n" -@@ -1512,8 +1514,8 @@ static int32_t parse_dfx_lstack_show_proto_args(int32_t argc, char *argv[], stru - int32_t ret; - - char *param = argv[GAZELLE_OPTIONS2_ARG_IDX]; -- if (strcmp(param, "UDP") != 0 && strcmp(param, "TCP") != 0 && strcmp(param, "IP") && -- strcmp(param, "ICMP") && strcmp(param, "ETHARP") != 0) { -+ if ((param == NULL) || (strcmp(param, "UDP") != 0 && strcmp(param, "TCP") != 0 && strcmp(param, "IP") && -+ strcmp(param, "ICMP") && strcmp(param, "ETHARP") != 0)) { - return cmd_index; - } - ret = strncpy_s(req_msg[cmd_index].data.protocol, MAX_PROTOCOL_LENGTH, argv[GAZELLE_OPTIONS2_ARG_IDX], --- -2.33.0 - diff --git a/0174-CFG-set-multicast-IP-assert.patch b/0174-CFG-set-multicast-IP-assert.patch deleted file mode 100644 index 0bdb20e..0000000 --- a/0174-CFG-set-multicast-IP-assert.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 38f5dbd34dfede9fc4a22c89903132fafc01fc6d Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 29 Apr 2024 17:07:15 +0800 -Subject: [PATCH] CFG:set multicast IP assert - ---- - src/lstack/core/lstack_cfg.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 533eb6c..319a720 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -244,6 +244,11 @@ static int32_t parse_host_addr(void) - if (g_config_params.host_addr.addr == INADDR_NONE) { - return -EINVAL; - } -+ -+ if (IN_MULTICAST(g_config_params.host_addr.addr)) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr:%s should not be a multicast IP.", value); -+ return -EINVAL; -+ } - return 0; - } - --- -2.33.0 - diff --git a/0175-cfg-devices-must-be-in-bond_slave_mac-for-BONDING_MO.patch b/0175-cfg-devices-must-be-in-bond_slave_mac-for-BONDING_MO.patch deleted file mode 100644 index fef0c39..0000000 --- a/0175-cfg-devices-must-be-in-bond_slave_mac-for-BONDING_MO.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 82ad5f93a2bd11411fec78ec7bcb26d6055fdfda Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Mon, 29 Apr 2024 10:43:37 +0800 -Subject: [PATCH] cfg: devices must be in bond_slave_mac for - BONDING_MODE_ACTIVE - ---- - src/lstack/core/lstack_cfg.c | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 533eb6c..8073dd4 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1210,6 +1210,16 @@ static int32_t parse_bond_miimon(void) - return ret; - } - -+static bool validate_bond_mac(uint8_t *mac_addr, struct rte_ether_addr *bond_slave_mac, int num_slaves) -+{ -+ for (int i = 0; i < num_slaves; i++) { -+ if (memcmp(mac_addr, bond_slave_mac[i].addr_bytes, ETHER_ADDR_LEN) == 0) { -+ return true; -+ } -+ } -+ return false; -+} -+ - static int32_t parse_bond_slave_mac(void) - { - if (g_config_params.bond_mode == -1) { -@@ -1252,6 +1262,12 @@ static int32_t parse_bond_slave_mac(void) - k = k + 1; - } - free(bond_slave_mac_tmp); -+ if (g_config_params.bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -+ if (!validate_bond_mac(g_config_params.mac_addr, g_config_params.bond_slave_mac_addr, GAZELLE_MAX_BOND_NUM)) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: devices must be in bond_slave_mac for BONDING_MODE_ACTIVE_BACKUP.\n"); -+ return -EINVAL; -+ } -+ } - return ret; - } - --- -2.33.0 - diff --git a/0176-CFG-fix-multicast-IP-assert-error.patch b/0176-CFG-fix-multicast-IP-assert-error.patch deleted file mode 100644 index ec26a4b..0000000 --- a/0176-CFG-fix-multicast-IP-assert-error.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f9407c8871223cef6dfbc66afb89a3b1b13b811a Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Wed, 8 May 2024 16:32:44 +0800 -Subject: [PATCH] CFG:fix multicast IP assert error - ---- - src/lstack/core/lstack_cfg.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 7967bb7..9efdbaa 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -245,7 +245,7 @@ static int32_t parse_host_addr(void) - return -EINVAL; - } - -- if (IN_MULTICAST(g_config_params.host_addr.addr)) { -+ if (IN_MULTICAST(ntohl(g_config_params.host_addr.addr))) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr:%s should not be a multicast IP.", value); - return -EINVAL; - } --- -2.33.0 - diff --git a/0177-fix-mbuf-leak-in-dpdk-23.11-due-to-kni-removed.patch b/0177-fix-mbuf-leak-in-dpdk-23.11-due-to-kni-removed.patch deleted file mode 100644 index 042fd04..0000000 --- a/0177-fix-mbuf-leak-in-dpdk-23.11-due-to-kni-removed.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 27af442164cce5ccb7df65435f76262ebb2d810e Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 9 May 2024 15:27:48 +0800 -Subject: [PATCH] fix mbuf leak in dpdk-23.11 due to kni removed - ---- - src/lstack/core/lstack_dpdk.c | 3 +++ - src/lstack/core/lstack_protocol_stack.c | 3 ++- - src/lstack/netif/lstack_ethdev.c | 2 ++ - src/ltran/ltran_forward.c | 5 ++++- - 4 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 016276a..ec35f9c 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -321,6 +321,9 @@ int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, ui - ret = gazelle_ring_sp_enqueue(ring, (void **)free_buf, batch); - if (ret == 0) { - LSTACK_LOG(ERR, LSTACK, "cannot enqueue to ring, count: %u\n", batch); -+ for (int i = 0; i < batch; i++) { -+ rte_pktmbuf_free(free_buf[i]); -+ } - return -1; - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 04d54c5..892c16d 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -937,16 +937,17 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - - ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); - if (ret != 0) { -+ rte_pktmbuf_free(mbuf_copy); - return; - } - } -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); - if (ret != 0) { - cur_stack->stats.rx_allocmbuf_fail++; - return; - } - copy_mbuf(mbuf_copy, mbuf); --#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - kni_handle_tx(mbuf_copy); - #endif - return; -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 23edc19..048ea92 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -173,6 +173,8 @@ int32_t eth_dev_poll(void) - } else if (transfer_type == TRANSFER_KERNEL) { - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - kni_handle_tx(stack->pkts[i]); -+#else -+ rte_pktmbuf_free(stack->pkts[i]); - #endif - } else { - /* transfer to other thread */ -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index a5756d7..d27f073 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -424,8 +424,11 @@ forward_to_kni: - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_ltran_config()->dpdk.kni_switch == GAZELLE_ON) { - enqueue_rx_packet(get_kni_stack(), m); -- } -+ } else - #endif -+ { -+ rte_pktmbuf_free(m); -+ } - return; - } - --- -2.33.0 - diff --git a/0178-add-riscv64-support.patch b/0178-add-riscv64-support.patch deleted file mode 100644 index a1cbcb7..0000000 --- a/0178-add-riscv64-support.patch +++ /dev/null @@ -1,48 +0,0 @@ -From c17a61a4e7872af8eabdf213f71ff8aad84687ad Mon Sep 17 00:00:00 2001 -From: laokz -Date: Thu, 9 May 2024 18:44:28 +0800 -Subject: [PATCH] add riscv64 support - ---- - src/lstack/Makefile | 2 +- - src/ltran/CMakeLists.txt | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index d2c039d..ace33bd 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -109,7 +109,7 @@ else - $(LIB_PATH)/librte_net_virtio.so \ - $(LIB_PATH)/librte_telemetry.so \ - $(LIB_PATH)/librte_pcapng.so -- ifneq ($(ARCH), loongarch64) -+ ifeq ($(filter loongarch64 riscv64, $(ARCH)),) - LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so - endif - endif -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index 2eb7d70..fee3a94 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -54,7 +54,7 @@ if (DPDK_VERSION STREQUAL "19.11") - else() - set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ - -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry") -- if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") -+ if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64|riscv64") - set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_net_i40e") - endif() - endif() -@@ -82,7 +82,7 @@ target_compile_options(ltran PRIVATE -fno-strict-aliasing -D__ARM_FEATURE_CRC32= - -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2 -Wno-error=deprecated-declarations) - - # gcc coredump in openEuler-20.03-LTS-XX aarch64 when add -march=native --if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64|ppc64le" ) -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64|ppc64le|riscv64" ) - target_compile_options(ltran PRIVATE -march=native -Wcast-align) - endif() - --- -2.33.0 - diff --git a/0179-dfx-fix-gazellectl-x-for-bond.patch b/0179-dfx-fix-gazellectl-x-for-bond.patch deleted file mode 100644 index f9c46fe..0000000 --- a/0179-dfx-fix-gazellectl-x-for-bond.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 3c3f69c0ca77b3d05df27aeda2fb7daa9757f50c Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Mon, 13 May 2024 14:51:18 +0800 -Subject: [PATCH] dfx: fix gazellectl -x for bond - ---- - src/common/gazelle_dfx_msg.h | 1 + - src/lstack/core/lstack_dpdk.c | 2 ++ - src/ltran/ltran_dfx.c | 7 ++++--- - 3 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 17e1662..9f88203 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -296,6 +296,7 @@ struct bonding { - int32_t miimon; - uint16_t primary_port_id; - uint16_t slaves[RTE_MAX_ETHPORTS]; -+ uint16_t slave_count; - }; - - struct nic_eth_xstats { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index ec35f9c..f1a22ea 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -905,6 +905,8 @@ void dpdk_nic_bond_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_ - return; - } - -+ dfx->data.nic_xstats.bonding.slave_count = count; -+ - for (int i = 0; i < count; i++) { - dfx->data.nic_xstats.bonding.slaves[i] = slaves[i]; - } -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index f4e55e3..aa08f25 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -207,11 +207,12 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - printf("%s############################\n", nic_stats_border); - printf("Bonding mode: [%d]\n", xstats->bonding.mode); - printf("Bonding miimon: [%d]\n", xstats->bonding.miimon); -- printf("Slaves(%d): [", xstats->port_id); -- for (int i = 0; i < xstats->port_id - 1; i++) { -+ printf("Port range: 0->%d; Bonding port is %d\n", xstats->port_id, xstats->port_id); -+ printf("Slaves(%d): [", xstats->bonding.slave_count); -+ for (int i = 0; i < xstats->bonding.slave_count - 1; i++) { - printf("%d ", xstats->bonding.slaves[i]); - } -- printf("%d]\n", xstats->bonding.slaves[xstats->port_id - 1]); -+ printf("%d]\n", xstats->bonding.slaves[xstats->bonding.slave_count - 1]); - printf("Primary: [%d]\n", xstats->bonding.primary_port_id); - printf("%s############################\n", nic_stats_border); - } --- -2.33.0 - diff --git a/0180-change-gazelle_stat_lstack_proto-from-u16-to-u64.patch b/0180-change-gazelle_stat_lstack_proto-from-u16-to-u64.patch deleted file mode 100644 index bac10b5..0000000 --- a/0180-change-gazelle_stat_lstack_proto-from-u16-to-u64.patch +++ /dev/null @@ -1,87 +0,0 @@ -From f9872991239cc4ddcd9b3c706cf135cdbea28a48 Mon Sep 17 00:00:00 2001 -From: ningjin -Date: Tue, 21 May 2024 10:23:49 +0800 -Subject: [PATCH] change gazelle_stat_lstack_proto from u16 to u64 - ---- - src/common/gazelle_dfx_msg.h | 32 ++++++++++++++++---------------- - src/ltran/ltran_dfx.c | 20 ++++++++++---------- - 2 files changed, 26 insertions(+), 26 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 9f88203..cad7978 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -204,22 +204,22 @@ struct gazelle_stat_lstack_snmp { - /* same as define in lwip/stats.h - struct stats_proto */ - struct gazelle_stat_lstack_proto { - /* data */ -- uint16_t xmit; /* Transmitted packets. */ -- uint16_t recv; /* Received packets. */ -- uint16_t tx_in; /* Transmitted in packets. */ -- uint16_t tx_out; /* Transmitted out packets. */ -- uint16_t rx_in; /* Received in packets. */ -- uint16_t rx_out; /* Received out packets. */ -- uint16_t fw; /* Forwarded packets. */ -- uint16_t drop; /* Dropped packets. */ -- uint16_t chkerr; /* Checksum error. */ -- uint16_t lenerr; /* Invalid length error. */ -- uint16_t memerr; /* Out of memory error. */ -- uint16_t rterr; /* Routing error. */ -- uint16_t proterr; /* Protocol error. */ -- uint16_t opterr; /* Error in options. */ -- uint16_t err; /* Misc error. */ -- uint16_t cachehit; -+ uint64_t xmit; /* Transmitted packets. */ -+ uint64_t recv; /* Received packets. */ -+ uint64_t tx_in; /* Transmitted in packets. */ -+ uint64_t tx_out; /* Transmitted out packets. */ -+ uint64_t rx_in; /* Received in packets. */ -+ uint64_t rx_out; /* Received out packets. */ -+ uint64_t fw; /* Forwarded packets. */ -+ uint64_t drop; /* Dropped packets. */ -+ uint64_t chkerr; /* Checksum error. */ -+ uint64_t lenerr; /* Invalid length error. */ -+ uint64_t memerr; /* Out of memory error. */ -+ uint64_t rterr; /* Routing error. */ -+ uint64_t proterr; /* Protocol error. */ -+ uint64_t opterr; /* Error in options. */ -+ uint64_t err; /* Misc error. */ -+ uint64_t cachehit; - }; - - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index aa08f25..319f7cd 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1115,16 +1115,16 @@ static void gazelle_print_lstack_stat_proto_core(const struct gazelle_stack_dfx_ - const struct gazelle_stat_lstack_proto *proto) - { - printf("\n------ stack tid: %6u ------\n", stat->tid); -- printf("tx_in: %u\n", proto->tx_in); -- printf("tx_out: %u\n", proto->tx_out); -- printf("rx_in: %u\n", proto->rx_in); -- printf("rx_out: %u\n", proto->rx_out); -- printf("fw: %u\n", proto->fw); -- printf("drop: %u\n", proto->drop); -- printf("chkerr: %u\n", proto->chkerr); -- printf("lenerr: %u\n", proto->lenerr); -- printf("memerr: %u\n", proto->memerr); -- printf("rterr: %u\n", proto->rterr); -+ printf("tx_in: %lu\n", proto->tx_in); -+ printf("tx_out: %lu\n", proto->tx_out); -+ printf("rx_in: %lu\n", proto->rx_in); -+ printf("rx_out: %lu\n", proto->rx_out); -+ printf("fw: %lu\n", proto->fw); -+ printf("drop: %lu\n", proto->drop); -+ printf("chkerr: %lu\n", proto->chkerr); -+ printf("lenerr: %lu\n", proto->lenerr); -+ printf("memerr: %lu\n", proto->memerr); -+ printf("rterr: %lu\n", proto->rterr); - } - - static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_msg_request *req_msg) --- -2.33.0 - diff --git a/0181-memary-error-fix-some-memary-error.patch b/0181-memary-error-fix-some-memary-error.patch deleted file mode 100644 index 8c602ff..0000000 --- a/0181-memary-error-fix-some-memary-error.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 7b859a1e3dbb8ed719035942040a581982d71508 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Sat, 18 May 2024 17:27:35 +0800 -Subject: [PATCH] memary error: fix some memary error - ---- - src/lstack/core/lstack_protocol_stack.c | 3 ++- - src/lstack/netif/lstack_flow.c | 4 ++++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 892c16d..c5a265e 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -626,10 +626,11 @@ int32_t stack_setup_app_thread(void) - - if (stack_thread_init(t_params) == NULL) { - LSTACK_LOG(INFO, LSTACK, "stack setup failed in app thread\n"); -+ free(t_params); - return -1; - } - atomic_fetch_add(&g_stack_group.stack_num, 1); -- -+ free(t_params); - return 0; - } - -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index 4e04209..9e8792c 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -84,6 +84,10 @@ static void add_rule(char* rule_key, struct rte_flow *flow) - HASH_FIND_STR(g_flow_rules, rule_key, rule); - if (rule == NULL) { - rule = (struct flow_rule*)malloc(sizeof(struct flow_rule)); -+ if (rule == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "flow rule add failed. \n"); -+ return; -+ } - strcpy_s(rule->rule_key, RULE_KEY_LEN, rule_key); - HASH_ADD_STR(g_flow_rules, rule_key, rule); - } --- -2.33.0 - diff --git a/0182-bond-remove-bond-initialization-code-in-dpdk_ethdev_.patch b/0182-bond-remove-bond-initialization-code-in-dpdk_ethdev_.patch deleted file mode 100644 index c672328..0000000 --- a/0182-bond-remove-bond-initialization-code-in-dpdk_ethdev_.patch +++ /dev/null @@ -1,545 +0,0 @@ -From 369b298752a84df677300792174f1957fa52cd52 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 21 May 2024 22:24:39 +0800 -Subject: [PATCH] bond:remove bond initialization code in dpdk_ethdev_init - ---- - src/common/dpdk_common.c | 2 +- - src/lstack/core/lstack_dpdk.c | 364 ++++++++++----------- - src/lstack/include/lstack_dpdk.h | 2 +- - src/lstack/include/lstack_protocol_stack.h | 2 - - 4 files changed, 173 insertions(+), 197 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index c03b2ec..66ad529 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -226,7 +226,7 @@ void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev - // rx vlan filter - if (rx_ol_capa & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) { - rx_ol |= RTE_ETH_RX_OFFLOAD_VLAN_FILTER; -- COMMON_INFO("RTE_ETH_RX_OFFLOAD_VLAN_STRIP\n"); -+ COMMON_INFO("RTE_ETH_RX_OFFLOAD_VLAN_FILTER\n"); - } - - // tx ip -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index f1a22ea..07fffe9 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -58,10 +58,14 @@ struct eth_params { - uint16_t nb_rx_desc; - uint16_t nb_tx_desc; - -+ uint32_t reta_mask; -+ - struct rte_eth_conf conf; - struct rte_eth_rxconf rx_conf; - struct rte_eth_txconf tx_conf; - }; -+ -+static struct eth_params g_eth_params; - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - struct rte_kni; - static struct rte_bus *g_pci_bus = NULL; -@@ -368,34 +372,6 @@ static int32_t ethdev_port_id(uint8_t *mac) - return port_id; - } - --static struct eth_params *alloc_eth_params(uint16_t port_id, uint16_t nb_queues) --{ -- struct eth_params *eth_params = calloc(1, sizeof(struct eth_params)); -- if (eth_params == NULL) { -- return NULL; -- } -- -- eth_params->port_id = port_id; -- eth_params->nb_queues = nb_queues; -- eth_params->nb_rx_desc = get_global_cfg_params()->nic.rxqueue_size; -- eth_params->nb_tx_desc = get_global_cfg_params()->nic.txqueue_size; -- eth_params->conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; -- eth_params->conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; -- eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; -- -- return eth_params; --} -- --uint64_t get_eth_params_rx_ol(void) --{ -- return get_protocol_stack_group()->rx_offload; --} -- --uint64_t get_eth_params_tx_ol(void) --{ -- return get_protocol_stack_group()->tx_offload; --} -- - static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info) - { - int rss_enable = 0; -@@ -423,6 +399,54 @@ static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *de - return rss_enable; - } - -+static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint16_t nb_queues, int *rss_enable) -+{ -+ struct rte_eth_dev_info dev_info; -+ int ret = rte_eth_dev_info_get(port_id, &dev_info); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "get dev info ret=%d\n", ret); -+ return ret; -+ } -+ -+ int32_t max_queues = LWIP_MIN(dev_info.max_rx_queues, dev_info.max_tx_queues); -+ if (max_queues < nb_queues) { -+ LSTACK_LOG(ERR, LSTACK, "port_id %d max_queues=%d\n", port_id, max_queues); -+ return -EINVAL; -+ } -+ -+ memset_s(eth_params, sizeof(struct eth_params), 0, sizeof(struct eth_params)); -+ -+ eth_params->port_id = port_id; -+ eth_params->nb_queues = nb_queues; -+ eth_params->nb_rx_desc = get_global_cfg_params()->nic.rxqueue_size; -+ eth_params->nb_tx_desc = get_global_cfg_params()->nic.txqueue_size; -+ eth_params->conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; -+ eth_params->conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; -+ eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; -+ /* used for tcp port alloc */ -+ eth_params->reta_mask = dev_info.reta_size - 1; -+ -+ eth_params_checksum(ð_params->conf, &dev_info); -+ -+ if (!get_global_cfg_params()->tuple_filter) { -+ *rss_enable = eth_params_rss(ð_params->conf, &dev_info); -+ } else { -+ *rss_enable = 0; -+ } -+ -+ return 0; -+} -+ -+uint64_t get_eth_params_rx_ol(void) -+{ -+ return get_protocol_stack_group()->rx_offload; -+} -+ -+uint64_t get_eth_params_tx_ol(void) -+{ -+ return get_protocol_stack_group()->tx_offload; -+} -+ - static void rss_setup(const int port_id, const uint16_t nb_queues) - { - int ret; -@@ -481,8 +505,10 @@ int32_t dpdk_bond_primary_set(int port_id, int slave_port_id) - return 0; - } - --int32_t dpdk_ethdev_init(int port_id, bool bond_port) -+int32_t dpdk_ethdev_init(int port_id) - { -+ int ret; -+ int32_t rss_enable = 0; - uint16_t nb_queues = get_global_cfg_params()->num_cpu; - if (get_global_cfg_params()->seperate_send_recv) { - nb_queues = get_global_cfg_params()->num_cpu * 2; -@@ -494,145 +520,55 @@ int32_t dpdk_ethdev_init(int port_id, bool bond_port) - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - -- if (get_global_cfg_params()->bond_mode < 0) { -- port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); -- if (port_id < 0) { -- LSTACK_LOG(ERR, LSTACK, "ethdev_port_id FAIL port_id=%d\n", port_id); -- return port_id; -- } -- } -- -- struct rte_eth_dev_info dev_info; -- int32_t ret = rte_eth_dev_info_get(port_id, &dev_info); -+ ret = eth_params_init(&g_eth_params, port_id, nb_queues, &rss_enable); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "get dev info ret=%d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "eth_params_init failed ret=%d\n", ret); - return ret; - } - -- int32_t max_queues = LWIP_MIN(dev_info.max_rx_queues, dev_info.max_tx_queues); -- if (max_queues < nb_queues) { -- LSTACK_LOG(ERR, LSTACK, "port_id %d max_queues=%d\n", port_id, max_queues); -- return -EINVAL; -- } -- -- if (bond_port) { -- int32_t slave_port_id[GAZELLE_MAX_BOND_NUM]; -- for (int i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -- if (rte_is_zero_ether_addr(&get_global_cfg_params()->bond_slave_mac_addr[i])) { -- break; -- } -- slave_port_id[i] = ethdev_port_id(get_global_cfg_params()->bond_slave_mac_addr[i].addr_bytes); -- if (slave_port_id[i] < 0) { -- LSTACK_LOG(ERR, LSTACK, "get slave port id failed port = %d\n", slave_port_id[1]); -- return slave_port_id[i]; -- } -- ret = dpdk_ethdev_init(slave_port_id[i], 0); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); -- return -1; -- } -- ret = rte_eth_promiscuous_enable(slave_port_id[i]); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk slave enable promiscuous failed ret = %d\n", ret); -- return -1; -- } -- -- ret = rte_eth_allmulticast_enable(slave_port_id[i]); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk slave enable allmulticast failed ret = %d\n", ret); -- return -1; -- } -- --#if RTE_VERSION >= RTE_VERSION_NUM(23, 11, 0, 0) -- ret = rte_eth_bond_member_add(port_id, slave_port_id[i]); --#else -- ret = rte_eth_bond_slave_add(port_id, slave_port_id[i]); --#endif -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk add slave port failed ret = %d\n", ret); -- return -1; -- } -- -- if (get_global_cfg_params()->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -- dpdk_bond_primary_set(port_id, slave_port_id[i]); -- } -- -- ret = rte_eth_dev_start(slave_port_id[i]); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk start slave port failed ret = %d\n", ret); -- return -1; -- } -- } -- } -- -- struct eth_params *eth_params = alloc_eth_params(port_id, nb_queues); -- if (eth_params == NULL) { -- return -ENOMEM; -- } -- -- if (bond_port) { -- struct rte_eth_dev_info slave_dev_info; -- int slave_id = rte_eth_bond_primary_get(port_id); -- if (slave_id < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk get bond primary port failed port = %d\n", slave_id); -- free(eth_params); -- return slave_id; -- } -- ret = rte_eth_dev_info_get(slave_id, &slave_dev_info); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk get bond dev info failed ret = %d\n", ret); -- free(eth_params); -- return ret; -- } -- dev_info.rx_offload_capa = slave_dev_info.rx_offload_capa; -- dev_info.tx_offload_capa = slave_dev_info.tx_offload_capa; -- dev_info.reta_size = slave_dev_info.reta_size; -- dev_info.flow_type_rss_offloads = slave_dev_info.flow_type_rss_offloads; -- } -- -- eth_params_checksum(ð_params->conf, &dev_info); -- int32_t rss_enable = 0; -- if (!get_global_cfg_params()->tuple_filter) { -- rss_enable = eth_params_rss(ð_params->conf, &dev_info); -- } -- stack_group->eth_params = eth_params; -- stack_group->port_id = eth_params->port_id; -- stack_group->rx_offload = eth_params->conf.rxmode.offloads; -- stack_group->tx_offload = eth_params->conf.txmode.offloads; -- /* used for tcp port alloc */ -- stack_group->reta_mask = dev_info.reta_size - 1; -- stack_group->nb_queues = nb_queues; -+ stack_group->eth_params = &g_eth_params; -+ stack_group->rx_offload = g_eth_params.conf.rxmode.offloads; -+ stack_group->tx_offload = g_eth_params.conf.txmode.offloads; -+ stack_group->port_id = port_id; - - if (get_global_cfg_params()->is_primary) { -- ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, ð_params->conf); -+ ret = rte_eth_dev_configure(port_id, nb_queues, nb_queues, &stack_group->eth_params->conf); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot config eth dev at port %d: %s\n", port_id, rte_strerror(-ret)); -- stack_group->eth_params = NULL; -- free(eth_params); - return ret; - } - - ret = dpdk_ethdev_start(); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_start failed ret=%d\n", ret); -- stack_group->eth_params = NULL; -- free(eth_params); - return ret; - } - - if (rss_enable && !get_global_cfg_params()->tuple_filter) { - rss_setup(port_id, nb_queues); -- stack_group->reta_mask = dev_info.reta_size - 1; - } - } - - /* after rte_eth_dev_configure */ - if ((get_global_cfg_params()->nic.vlan_mode != -1) && - ((stack_group->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) == RTE_ETH_RX_OFFLOAD_VLAN_FILTER)) { -- ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); -- return -1; -+ /* -+ * vlan filter can be configured for switch,nic and software. -+ * bond4/6 mode need enable promiscuous mode, it conflicts with nic vlan filter. -+ * therefore, we can't use nic vlan filter in bond4/6 mode. -+ * 1. use software: need disable vlan strip in nic, the corresponding GRO becomes invalid -+ * GRO does not support vlan pakckets, which affects performance. -+ * 2. use switch: it's a good config -+ */ -+ if ((get_global_cfg_params()->bond_mode != BONDING_MODE_8023AD) && -+ (get_global_cfg_params()->bond_mode != BONDING_MODE_ALB)) { -+ ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); -+ return -1; -+ } -+ } else { -+ LSTACK_LOG(ERR, LSTACK, "bond4 and bond6 not support set vlan filter in nic\n"); - } - } - -@@ -684,10 +620,6 @@ int32_t dpdk_ethdev_start(void) - } - } - -- if (get_global_cfg_params()->bond_mode >= 0) { -- return 0; -- } -- - ret = rte_eth_dev_start(stack_group->eth_params->port_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot start ethdev: %d\n", (-ret)); -@@ -733,77 +665,117 @@ void dpdk_restore_pci(void) - } - #endif - --int32_t init_dpdk_ethdev(void) -+static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - { -- int32_t ret; -+ int port_id = rte_eth_bond_create("net_bonding0", mode, rte_socket_id()); -+ struct cfg_params *cfg = get_global_cfg_params(); -+ int ret; - -- if (get_global_cfg_params()->bond_mode >= 0) { -- uint8_t socket_id = rte_socket_id(); -- int bond_port_id = rte_eth_bond_create("net_bonding0", get_global_cfg_params()->bond_mode, socket_id); -- if (bond_port_id < 0) { -- LSTACK_LOG(ERR, LSTACK, "get bond port id failed ret=%d\n", bond_port_id); -- return bond_port_id; -- } -+ if (port_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "get bond port id failed ret=%d\n", port_id); -+ return -1; -+ } - -- ret = dpdk_ethdev_init(bond_port_id, 1); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed ret = %d\n", ret); -+ for (int i = 0; i < count; i++) { -+ /* rte_dev_info_get can get correct devinfo after call bond_member_add */ -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -+ ret = rte_eth_bond_slave_add(port_id, slave_port_id[i]); -+#else -+ ret = rte_eth_bond_member_add(port_id, slave_port_id[i]); -+#endif -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "bond add slave devices failed, ret=%d\n", ret); - return -1; - } -+ if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -+ dpdk_bond_primary_set(port_id, slave_port_id[i]); -+ } -+ } - -- ret = rte_eth_bond_xmit_policy_set(bond_port_id, BALANCE_XMIT_POLICY_LAYER34); -+ if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { -+ ret = rte_eth_bond_8023ad_dedicated_queues_enable(port_id); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk set bond xmit policy failed ret = %d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); - return -1; - } -+ } - -- if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { -- ret = rte_eth_bond_8023ad_dedicated_queues_enable(bond_port_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); -+ if (dpdk_ethdev_init(port_id) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed for bond port\n"); -+ return -1; -+ } -+ -+ ret = rte_eth_bond_xmit_policy_set(port_id, BALANCE_XMIT_POLICY_LAYER34); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond xmit policy failed ret = %d\n", ret); -+ return -1; -+ } -+ -+ ret = rte_eth_bond_link_monitoring_set(port_id, get_global_cfg_params()->bond_miimon); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond link monitoring failed ret = %d\n", ret); -+ return -1; -+ } -+ -+ if ((get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) || -+ (get_global_cfg_params()->bond_mode == BONDING_MODE_ALB)) { -+ for (int i = 0; i < count; i++) { -+ /* bond port promiscuous only enable primary port */ -+ /* we enable all ports */ -+ ret = rte_eth_promiscuous_enable(slave_port_id[i]); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk slave enable promiscuous failed ret = %d\n", ret); - return -1; - } -- } else { -- ret = rte_eth_bond_mode_set(bond_port_id, get_global_cfg_params()->bond_mode); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable mode set failed ret = %d\n", ret); -- } - } -+ } - -- ret = rte_eth_bond_link_monitoring_set(bond_port_id, get_global_cfg_params()->bond_miimon); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk set bond link monitoring failed ret = %d\n", ret); -- return -1; -- } -+ ret = rte_eth_dev_start(port_id); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk start bond port failed ret = %d\n", ret); -+ return -1; -+ } - -- ret = rte_eth_promiscuous_enable(bond_port_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable promiscuous failed ret = %d\n", ret); -- return -1; -- } -+ return 0; -+} - -- ret = rte_eth_allmulticast_enable(bond_port_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk enable allmulticast failed ret = %d\n", ret); -- return -1; -+int32_t init_dpdk_ethdev(void) -+{ -+ int32_t ret; -+ int slave_port_id[GAZELLE_MAX_BOND_NUM]; -+ int port_id; -+ struct cfg_params *cfg = get_global_cfg_params(); -+ int i; -+ -+ if (cfg->bond_mode >= 0) { -+ for (i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -+ if (rte_is_zero_ether_addr(&cfg->bond_slave_mac_addr[i])) { -+ break; -+ } -+ slave_port_id[i] = ethdev_port_id(cfg->bond_slave_mac_addr[i].addr_bytes); -+ ret = dpdk_ethdev_init(slave_port_id[i]); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "slave port(%d) init failed, ret=%d\n", slave_port_id[i], ret); -+ return -1; -+ } - } - -- ret = rte_eth_dev_start(bond_port_id); -+ ret = dpdk_bond_create(cfg->bond_mode, slave_port_id, i); - if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk start bond port failed ret = %d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "bond device create failed, ret=%d\n", ret); - return -1; - } -- - } else { -- ret = dpdk_ethdev_init(0, 0); -+ port_id = ethdev_port_id(cfg->mac_addr); -+ ret = dpdk_ethdev_init(port_id); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed\n"); -+ LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed, port id=%d\n", port_id); - return -1; - } - } - - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -- if (get_global_cfg_params()->kni_switch && get_global_cfg_params()->is_primary) { -+ if (cfg->kni_switch && cfg->is_primary) { - ret = dpdk_init_lstack_kni(); - if (ret < 0) { - return -1; -@@ -817,7 +789,13 @@ int32_t init_dpdk_ethdev(void) - bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port, uint16_t dst_port) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- if (stack_group->reta_mask == 0 || stack_group->nb_queues <= 1) { -+ -+ /* ltran mode */ -+ if (stack_group->eth_params == NULL) { -+ return true; -+ } -+ -+ if (stack_group->eth_params->reta_mask == 0 || stack_group->eth_params->nb_queues <= 1) { - return true; - } - -@@ -840,10 +818,10 @@ bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port - hash = rte_softrss((uint32_t *)&tuple, RTE_THASH_V6_L4_LEN, g_default_rss_key); - } - -- uint32_t reta_index = hash & stack_group->reta_mask; -+ uint32_t reta_index = hash & stack_group->eth_params->reta_mask; - - struct protocol_stack *stack = get_protocol_stack(); -- return (reta_index % stack_group->nb_queues) == stack->queue_id; -+ return (reta_index % stack_group->eth_params->nb_queues) == stack->queue_id; - } - - static int dpdk_nic_xstats_value_get(uint64_t *values, unsigned int len, uint16_t *ports, unsigned int count) -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index fe3d07b..dff1e44 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -46,7 +46,7 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si - uint32_t flags, int32_t idx); - int32_t create_shared_ring(struct protocol_stack *stack); - void lstack_log_level_init(void); --int dpdk_ethdev_init(int port_id, bool bond_port); -+int dpdk_ethdev_init(int port_id); - int dpdk_ethdev_start(void); - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index df0902d..93fa40c 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -92,8 +92,6 @@ struct protocol_stack_group { - uint16_t port_id; - uint64_t rx_offload; - uint64_t tx_offload; -- uint32_t reta_mask; -- uint16_t nb_queues; - struct rte_mempool *kni_pktmbuf_pool; - struct eth_params *eth_params; - struct protocol_stack *stacks[PROTOCOL_STACK_MAX]; --- -2.33.0 - diff --git a/0183-make-rpc_msg_max-recv_ring_size-configurable.patch b/0183-make-rpc_msg_max-recv_ring_size-configurable.patch deleted file mode 100644 index ae786ca..0000000 --- a/0183-make-rpc_msg_max-recv_ring_size-configurable.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 55ed3c6aaccf320a7d3240753a5aabe400ac4bd3 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Fri, 7 Jun 2024 17:06:50 +0800 -Subject: [PATCH] make rpc_msg_max recv_ring_size-configurable - - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 9efdbaa..0e5fbf3 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -68,6 +68,7 @@ static int32_t parse_nic_read_number(void); - static int32_t parse_tcp_conn_count(void); - static int32_t parse_mbuf_count_per_conn(void); - static int32_t parse_send_ring_size(void); -+static int32_t parse_recv_ring_size(void); - static int32_t parse_num_process(void); - static int32_t parse_process_numa(void); - static int32_t parse_process_index(void); -@@ -83,6 +84,7 @@ static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); - static int32_t parse_defaule_nonblock_mode(void); -+static int32_t parse_rpc_msg_max(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -132,6 +134,7 @@ static struct config_vector_t g_config_tbl[] = { - { "rpc_number", parse_rpc_number }, - { "nic_read_number", parse_nic_read_number }, - { "send_ring_size", parse_send_ring_size }, -+ { "recv_ring_size", parse_recv_ring_size }, - { "num_process", parse_num_process }, - { "process_numa", parse_process_numa }, - { "process_idx", parse_process_index }, -@@ -146,6 +149,7 @@ static struct config_vector_t g_config_tbl[] = { - { "stack_thread_mode", parse_stack_thread_mode }, - { "nic_vlan_mode", parse_nic_vlan_mode }, - { "nonblock_mode", parse_defaule_nonblock_mode }, -+ { "rpc_msg_max", parse_rpc_msg_max }, - { NULL, NULL } - }; - -@@ -908,6 +912,14 @@ static int32_t parse_send_ring_size(void) - return ret; - } - -+static int32_t parse_recv_ring_size(void) -+{ -+ int32_t ret; -+ /* recv ring size default value is 128 */ -+ PARSE_ARG(g_config_params.recv_ring_size, "recv_ring_size", 128, 1, SOCK_RECV_RING_SIZE_MAX, ret); -+ return ret; -+} -+ - static int32_t parse_mbuf_count_per_conn(void) - { - int32_t ret; -@@ -1356,3 +1368,15 @@ static int32_t parse_defaule_nonblock_mode(void) - } - return ret; - } -+ -+static int32_t parse_rpc_msg_max(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.rpc_msg_max, "rpc_msg_max", 4096, 1, 8192, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid rpc msg max value %d ret=%d. only support 1~8192\n", -+ g_config_params.rpc_msg_max, ret); -+ } -+ return ret; -+} -+ -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 30bd827..b98ba84 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -13,6 +13,7 @@ - #include - - #include "lstack_log.h" -+#include "lstack_cfg.h" - #include "lstack_dpdk.h" - #include "lstack_rpc_proc.h" - #include "lstack_stack_stat.h" -@@ -71,7 +72,7 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - exit(-1); - } - -- g_rpc_pool->mempool = create_mempool("rpc_pool", RPC_MSG_MAX, sizeof(struct rpc_msg), -+ g_rpc_pool->mempool = create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), - 0, rte_gettid()); - if (g_rpc_pool->mempool == NULL) { - LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index a00e47a..94878de 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -110,6 +110,7 @@ struct cfg_params { - struct secondary_attach_arg sec_attach_arg; - char unix_socket_filename[NAME_MAX]; - uint16_t send_ring_size; -+ uint16_t recv_ring_size; - bool tuple_filter; - int8_t bond_mode; - int32_t bond_miimon; -@@ -119,6 +120,7 @@ struct cfg_params { - struct cfg_nic_params nic; - bool stack_mode_rtc; - bool nonblock_mode; -+ uint32_t rpc_msg_max; - }; - - struct cfg_params *get_global_cfg_params(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 93fa40c..c210ab9 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -25,8 +25,9 @@ - #include "lstack_ethdev.h" - #include "gazelle_opt.h" - --#define SOCK_RECV_RING_SIZE (128) -+#define SOCK_RECV_RING_SIZE (get_global_cfg_params()->recv_ring_size) - #define SOCK_RECV_FREE_THRES (32) -+#define SOCK_RECV_RING_SIZE_MAX (2048) - #define SOCK_SEND_RING_SIZE_MAX (2048) - #define SOCK_SEND_REPLENISH_THRES (16) - #define WAKEUP_MAX_NUM (32) -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 8e97c11..0c51848 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -26,8 +26,6 @@ - #define MSG_ARG_4 (4) - #define RPM_MSG_ARG_SIZE (5) - --#define RPC_MSG_MAX 4096 --#define RPC_MSG_MASK (RPC_MSG_MAX - 1) - typedef struct lockless_queue rpc_queue; - - struct rpc_stats { -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index a7f4e75..4c3784f 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -22,8 +22,12 @@ tcp_conn_count = 1500 - mbuf_count_per_conn = 170 - - # send ring size, default is 32, max is 2048 -+# if udp pktlen exceeds 45952(32 * 1436)B, send_ring_size must be at least 64. - send_ring_size = 32 - -+#recv ring size, default is 128, max is 2048 -+recv_ring_size = 128 -+ - #protocol stack thread per loop params - #read data form protocol stack into recv_ring - read_connect_number = 4 -@@ -67,3 +71,6 @@ nic_vlan_mode=-1 - bond_mode=-1 - #bond slave mac, separated by ; , only support 2 slave mac - #bond_slave_mac="aa:bb:cc:dd:ee:ff;gg:hh:ii:jj:kk:ll" -+ -+#maximum number of rpc memory pools -+rpc_msg_max=4096 --- -2.33.0 - diff --git a/0184-EPOLL-fix-coredump-while-event-count-exceed-maxevent.patch b/0184-EPOLL-fix-coredump-while-event-count-exceed-maxevent.patch deleted file mode 100644 index b80b273..0000000 --- a/0184-EPOLL-fix-coredump-while-event-count-exceed-maxevent.patch +++ /dev/null @@ -1,46 +0,0 @@ -From e3c12e9d73678b3c5445f770c929e035ef1c4997 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Fri, 7 Jun 2024 11:13:08 +0800 -Subject: [PATCH] EPOLL: fix coredump while event count exceed maxevents - ---- - src/lstack/api/lstack_epoll.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index c8a2e43..28a3dd9 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -488,7 +488,14 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - list_del_node_null(node); - continue; - } -- -+ -+ if (event_num >= maxevents) { -+ /* move list head after the current node, and start traversing from this node next time */ -+ list_del_node_null(&wakeup->event_list); -+ list_add_node(node, &wakeup->event_list); -+ break; -+ } -+ - events[event_num].events = sock->events & sock->epoll_events; - events[event_num].data = sock->ep_data; - event_num++; -@@ -504,13 +511,6 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - list_del_node_null(node); - sock->epoll_events = 0; - } -- -- if (event_num >= maxevents) { -- /* move list head after the current node, and start traversing from this node next time */ -- list_del_node_null(&wakeup->event_list); -- list_add_node(node, &wakeup->event_list); -- break; -- } - } - - return event_num; --- -2.33.0 - diff --git a/0185-fix-fin-pack-free-coredump.patch b/0185-fix-fin-pack-free-coredump.patch deleted file mode 100644 index 22aa7d1..0000000 --- a/0185-fix-fin-pack-free-coredump.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 8bcbc7ef61b9193da5d3deb519211a2406564298 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Fri, 7 Jun 2024 01:51:34 +0000 -Subject: [PATCH] fix fin pack free coredump - ---- - src/lstack/core/lstack_lwip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 667ffd7..628319c 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -88,7 +88,7 @@ static void reset_sock_data(struct lwip_sock *sock) - sock->remain_len = 0; - sock->already_bind_numa = 0; - -- if (sock->recv_lastdata) { -+ if (sock->recv_lastdata && sock->recv_lastdata != (void *)&fin_packet) { - pbuf_free(sock->recv_lastdata); - } - sock->recv_lastdata = NULL; --- -2.33.0 - diff --git a/0186-fix-MySQL-shutdown-cmd.patch b/0186-fix-MySQL-shutdown-cmd.patch deleted file mode 100644 index fa2d7ee..0000000 --- a/0186-fix-MySQL-shutdown-cmd.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 1431fd828005acb2aa7df1844cdec62e21f50769 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 5 Jun 2024 12:56:52 +0800 -Subject: [PATCH] fix MySQL shutdown cmd - ---- - src/lstack/api/lstack_epoll.c | 14 ++++++-------- - src/lstack/include/posix/lstack_epoll.h | 4 ++-- - 2 files changed, 8 insertions(+), 10 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index c8a2e43..1d6ae52 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -144,7 +144,7 @@ void wakeup_stack_epoll(struct protocol_stack *stack) - if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - rte_mb(); -- pthread_mutex_unlock(&wakeup->wait); -+ sem_post(&wakeup->wait); - stack->stats.wakeup_events++; - } - -@@ -258,12 +258,11 @@ int32_t lstack_do_epoll_create(int32_t fd) - init_list_node_null(&wakeup->wakeup_list[i]); - } - -- if (pthread_mutex_init(&wakeup->wait, NULL) != 0) { -+ if (sem_init(&wakeup->wait, 0, 0) != 0) { - posix_api->close_fn(fd); - free(wakeup); - GAZELLE_RETURN(EINVAL); - } -- pthread_mutex_trylock(&wakeup->wait); - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -@@ -337,7 +336,7 @@ int32_t lstack_epoll_close(int32_t fd) - list_del_node_null(&wakeup->poll_list); - pthread_spin_unlock(&stack_group->poll_list_lock); - -- pthread_mutex_destroy(&wakeup->wait); -+ sem_destroy(&wakeup->wait); - - free(wakeup); - sock->wakeup = NULL; -@@ -609,9 +608,9 @@ int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout) - if (timeout > 0) { - struct timespec timespec; - ms_to_timespec(×pec, timeout); -- ret = pthread_mutex_timedlock(&wakeup->wait, ×pec); -+ ret = sem_timedwait(&wakeup->wait, ×pec); - } else { -- ret = pthread_mutex_lock(&wakeup->wait); -+ ret = sem_wait(&wakeup->wait); - } - - if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -@@ -714,10 +713,9 @@ int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - - static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) - { -- if (pthread_mutex_init(&wakeup->wait, NULL) != 0) { -+ if (sem_init(&wakeup->wait, 0, 0) != 0) { - GAZELLE_RETURN(EINVAL); - } -- pthread_mutex_trylock(&wakeup->wait); - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - - for (uint32_t i = 0; i < PROTOCOL_STACK_MAX; i++) { -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index 59b5ef7..a7164f4 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -37,7 +37,7 @@ struct protocol_stack; - struct wakeup_poll { - /* stack thread read frequently */ - enum wakeup_type type; -- pthread_mutex_t wait __rte_cache_aligned; -+ sem_t wait; - bool in_wait; - struct list_node wakeup_list[PROTOCOL_STACK_MAX]; - bool have_kernel_event; -@@ -87,7 +87,7 @@ static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) - if (wakeup && __atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - rte_mb(); -- pthread_mutex_unlock(&wakeup->wait); -+ sem_post(&wakeup->wait); - } - } - --- -2.33.0 - diff --git a/0187-cfg-remove-map-perfect-flag-in-lstack.conf.patch b/0187-cfg-remove-map-perfect-flag-in-lstack.conf.patch deleted file mode 100644 index 40d63be..0000000 --- a/0187-cfg-remove-map-perfect-flag-in-lstack.conf.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 9cd0a7ebb73b882ef3ac968795fb22ca78fb33cc Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 29 May 2024 16:20:59 +0800 -Subject: [PATCH] cfg: remove map-perfect flag in lstack.conf - -This parameter is used in ltran mode. -By defualt, ltran mode is not used, so remove it. ---- - src/lstack/lstack.conf | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 07a6092..0b7dbc9 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -8,10 +8,11 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] -+dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem"] - - stack_thread_mode="run-to-wakeup" - -+#ltran mode need add "--map-perfect" in dpdk_args - use_ltran=0 - kni_switch=0 - --- -2.33.0 - diff --git a/0188-redis-perf-add-tx-driver-cache.patch b/0188-redis-perf-add-tx-driver-cache.patch deleted file mode 100644 index af3dfff..0000000 --- a/0188-redis-perf-add-tx-driver-cache.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 9e6197b3d39a244ed7900bfc2df9d0f2290fcfb2 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 17 Jun 2024 10:41:54 +0800 -Subject: [PATCH] redis perf: add tx driver cache - ---- - src/lstack/api/dir.mk | 2 +- - src/lstack/api/lstack_tx_cache.c | 47 ++++++++++++++++++++++ - src/lstack/core/lstack_cfg.c | 13 ++++++ - src/lstack/core/lstack_protocol_stack.c | 1 + - src/lstack/include/lstack_cfg.h | 1 + - src/lstack/include/lstack_protocol_stack.h | 2 + - src/lstack/include/lstack_tx_cache.h | 28 +++++++++++++ - src/lstack/netif/lstack_ethdev.c | 30 +++++++++++--- - 8 files changed, 117 insertions(+), 7 deletions(-) - create mode 100644 src/lstack/api/lstack_tx_cache.c - create mode 100644 src/lstack/include/lstack_tx_cache.h - -diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk -index 729690d..70bc59d 100644 ---- a/src/lstack/api/dir.mk -+++ b/src/lstack/api/dir.mk -@@ -8,7 +8,7 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c -+SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c lstack_tx_cache.c - - $(eval $(call register_dir, api, $(SRC))) - -diff --git a/src/lstack/api/lstack_tx_cache.c b/src/lstack/api/lstack_tx_cache.c -new file mode 100644 -index 0000000..42aef57 ---- /dev/null -+++ b/src/lstack/api/lstack_tx_cache.c -@@ -0,0 +1,47 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include "lwip/sockets.h" -+#include "lstack_cfg.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_tx_cache.h" -+ -+void stack_send_pkts(struct protocol_stack *stack) -+{ -+ if (!get_global_cfg_params()->send_cache_mode) { -+ return; -+ } -+ -+ uint32_t send_num = stack->tx_cache.send_end - stack->tx_cache.send_start; -+ -+ if (send_num == 0) { -+ return; -+ } -+ -+ uint32_t start = stack->tx_cache.send_start & STACK_SEND_MASK; -+ uint32_t end = stack->tx_cache.send_end & STACK_SEND_MASK; -+ uint32_t sent_pkts = 0; -+ -+ if (start < end) { -+ sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num); -+ } else { -+ send_num = STACK_SEND_MAX - start; -+ sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num); -+ if (sent_pkts == send_num) { -+ sent_pkts += stack->dev_ops.tx_xmit(stack, stack->tx_cache.send_pkts, end); -+ } -+ } -+ -+ stack->tx_cache.send_start += sent_pkts; -+ stack->stats.tx += sent_pkts; -+} -+ -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0e5fbf3..56f290e 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -85,6 +85,7 @@ static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); - static int32_t parse_defaule_nonblock_mode(void); - static int32_t parse_rpc_msg_max(void); -+static int32_t parse_send_cache_mode(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -150,6 +151,7 @@ static struct config_vector_t g_config_tbl[] = { - { "nic_vlan_mode", parse_nic_vlan_mode }, - { "nonblock_mode", parse_defaule_nonblock_mode }, - { "rpc_msg_max", parse_rpc_msg_max }, -+ { "send_cache_mode", parse_send_cache_mode }, - { NULL, NULL } - }; - -@@ -1380,3 +1382,14 @@ static int32_t parse_rpc_msg_max(void) - return ret; - } - -+static int32_t parse_send_cache_mode(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.send_cache_mode, "send_cache_mode", 0, 0, 1, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid send cache mode value %d. only support 0 or 1\n", -+ g_config_params.send_cache_mode); -+ } -+ return ret; -+} -+ -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index c5a265e..98d6549 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -480,6 +480,7 @@ int stack_polling(uint32_t wakeup_tick) - do_lwip_read_recvlist(stack, read_connect_number); - if ((wakeup_tick & 0xf) == 0) { - wakeup_stack_epoll(stack); -+ stack_send_pkts(stack); - } - - /* run to completion mode currently does not support sockmap */ -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 94878de..b9721ff 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -121,6 +121,7 @@ struct cfg_params { - bool stack_mode_rtc; - bool nonblock_mode; - uint32_t rpc_msg_max; -+ bool send_cache_mode; - }; - - struct cfg_params *get_global_cfg_params(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index c210ab9..ab27dfa 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -23,6 +23,7 @@ - #include "gazelle_dfx_msg.h" - #include "lstack_thread_rpc.h" - #include "lstack_ethdev.h" -+#include "lstack_tx_cache.h" - #include "gazelle_opt.h" - - #define SOCK_RECV_RING_SIZE (get_global_cfg_params()->recv_ring_size) -@@ -76,6 +77,7 @@ struct protocol_stack { - uint32_t tx_ring_used; - - struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX]; -+ struct lstack_tx_cache tx_cache; - struct list_node recv_list; - struct list_node same_node_recv_list; /* used for same node processes communication */ - struct list_node wakeup_list; -diff --git a/src/lstack/include/lstack_tx_cache.h b/src/lstack/include/lstack_tx_cache.h -new file mode 100644 -index 0000000..3991b16 ---- /dev/null -+++ b/src/lstack/include/lstack_tx_cache.h -@@ -0,0 +1,28 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_TX_CACHE_H_ -+#define _LSTACK_TX_CACHE_H_ -+ -+#define STACK_SEND_MAX (2048) -+#define STACK_SEND_MASK (STACK_SEND_MAX - 1) -+#define STACK_SEND_INDEX(index) ((index) & STACK_SEND_MASK) -+ -+struct lstack_tx_cache { -+ uint32_t send_start; -+ uint32_t send_end; -+ struct rte_mbuf *send_pkts[STACK_SEND_MAX]; -+}; -+ -+void stack_send_pkts(struct protocol_stack *stack); -+ -+#endif /* _LSTACK_TX_CACHE_H_ */ -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 048ea92..77172f8 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -34,6 +34,7 @@ - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" - #include "lstack_flow.h" -+#include "lstack_tx_cache.h" - #include "lstack_ethdev.h" - - /* FRAME_MTU + 14byte header */ -@@ -186,6 +187,19 @@ int32_t eth_dev_poll(void) - return nr_pkts; - } - -+static void eth_dev_send_pkt(struct protocol_stack *stack, struct rte_mbuf *mbuf) -+{ -+ do { -+ if (STACK_SEND_INDEX(stack->tx_cache.send_end + 1) != STACK_SEND_INDEX(stack->tx_cache.send_start)) { -+ stack->tx_cache.send_pkts[STACK_SEND_INDEX(stack->tx_cache.send_end)] = mbuf; -+ stack->tx_cache.send_end++; -+ return; -+ } -+ stack_send_pkts(stack); -+ stack->stats.send_pkts_fail++; -+ } while (1); -+} -+ - static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - { - struct protocol_stack *stack = get_protocol_stack(); -@@ -231,12 +245,16 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - pbuf = pbuf->next; - } - -- uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1); -- stack->stats.tx += sent_pkts; -- if (sent_pkts < 1) { -- stack->stats.tx_drop++; -- rte_pktmbuf_free(first_mbuf); -- return ERR_MEM; -+ if (!get_global_cfg_params()->send_cache_mode) { -+ uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1); -+ stack->stats.tx += sent_pkts; -+ if (sent_pkts < 1) { -+ stack->stats.tx_drop++; -+ rte_pktmbuf_free(first_mbuf); -+ return ERR_MEM; -+ } -+ } else { -+ eth_dev_send_pkt(stack, first_mbuf); - } - - return ERR_OK; --- -2.33.0 - diff --git a/0189-optimized-latency-distribution-dotting.patch b/0189-optimized-latency-distribution-dotting.patch deleted file mode 100644 index fee0346..0000000 --- a/0189-optimized-latency-distribution-dotting.patch +++ /dev/null @@ -1,250 +0,0 @@ -From 8fd1a2bfacf928d86fe1b76fc1cd80b3a21cb2cc Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 13 Jun 2024 18:31:42 +0800 -Subject: [PATCH] optimized latency distribution dotting - ---- - src/common/gazelle_dfx_msg.h | 10 ++++--- - src/lstack/core/lstack_lwip.c | 4 +++ - src/lstack/core/lstack_protocol_stack.c | 8 +++--- - src/lstack/core/lstack_stack_stat.c | 36 +++++++++++++++++++++---- - src/lstack/core/lstack_thread_rpc.c | 3 ++- - src/lstack/include/lstack_stack_stat.h | 7 ++++- - src/lstack/include/lstack_thread_rpc.h | 2 -- - src/ltran/ltran_dfx.c | 17 +++++++----- - 8 files changed, 63 insertions(+), 24 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index cad7978..696daf2 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -69,10 +69,11 @@ enum GAZELLE_STAT_MODE { - }; - - enum GAZELLE_LATENCY_TYPE { -- GAZELLE_LATENCY_READ_LWIP, // t0 -> t1 -- GAZELLE_LATENCY_READ_APP_CALL, // t1 -> t2 -- GAZELLE_LATENCY_READ_LSTACK, // t2 -> t3 -- GAZELLE_LATENCY_READ_MAX, // t0 -> t3 -+ GAZELLE_LATENCY_INTO_MBOX, // t0 -> t1 -+ GAZELLE_LATENCY_READ_LWIP, // t1 -> t2 -+ GAZELLE_LATENCY_READ_APP_CALL, // t2 -> t3 -+ GAZELLE_LATENCY_READ_LSTACK, // t3 -> t4 -+ GAZELLE_LATENCY_READ_MAX, // t0 -> t4 - - GAZELLE_LATENCY_WRITE_INTO_RING, // t0 -> t1 - GAZELLE_LATENCY_WRITE_LWIP, // t1 -> t2 -@@ -80,6 +81,7 @@ enum GAZELLE_LATENCY_TYPE { - GAZELLE_LATENCY_WRITE_MAX, // t0 -> t3 - - GAZELLE_LATENCY_WRITE_RPC_MSG, // rpc_call_send -+ GAZELLE_LATENCY_RECVMBOX_READY, // ready to read from recvmbox - - GAZELLE_LATENCY_MAX, - }; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 628319c..153c5cc 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1104,6 +1104,10 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - continue; - } - -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_sock_latency(&sock->stack->latency, sock, GAZELLE_LATENCY_RECVMBOX_READY); -+ } -+ - ssize_t len = 0; - if (NETCONN_IS_UDP(sock)) { - len = lwip_recv(sock->conn->callback_arg.socket, NULL, SSIZE_MAX, 0); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 98d6549..74e543d 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -882,10 +882,6 @@ void stack_send(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack(); - int replenish_again; - -- if (get_protocol_stack_group()->latency_start) { -- calculate_rpcmsg_latency(&stack->latency, msg, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -- - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - msg->result = -1; -@@ -893,6 +889,10 @@ void stack_send(struct rpc_msg *msg) - return; - } - -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ } -+ - replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); - if (replenish_again < 0) { - __sync_fetch_and_sub(&sock->call_num, 1); -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index e430195..a1bd44d 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #include "lstack_cfg.h" - #include "lstack_ethdev.h" -@@ -67,21 +68,46 @@ void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) - } - } - --void time_stamp_into_rpcmsg(struct rpc_msg *msg) -+void time_stamp_into_rpcmsg(struct lwip_sock *sock) - { -- msg->time_stamp = get_current_time(); -+ sock->stamp.rpc_time_stamp = get_current_time(); - } - --void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, -+void time_stamp_into_recvmbox(struct lwip_sock *sock) -+{ -+ sock->stamp.mbox_time_stamp = get_current_time(); -+} -+ -+void time_stamp_record(int fd, struct pbuf *pbuf) -+{ -+ struct lwip_sock *sock = get_socket_by_fd(fd); -+ -+ if (get_protocol_stack_group()->latency_start && pbuf != NULL) { -+ calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); -+ time_stamp_into_recvmbox(sock); -+ } -+} -+ -+void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct lwip_sock *sock, - enum GAZELLE_LATENCY_TYPE type) - { - uint64_t latency; -+ uint64_t stamp; - struct stack_latency *latency_stat; -- if (msg == NULL || msg->time_stamp < stack_latency->start_time || type >= GAZELLE_LATENCY_MAX) { -+ -+ if (type == GAZELLE_LATENCY_WRITE_RPC_MSG) { -+ stamp = sock->stamp.rpc_time_stamp; -+ } else if (type == GAZELLE_LATENCY_RECVMBOX_READY) { -+ stamp = sock->stamp.mbox_time_stamp; -+ } else { -+ return; -+ } -+ -+ if (stamp < stack_latency->start_time) { - return; - } - -- latency = get_current_time() - msg->time_stamp; -+ latency = get_current_time() - stamp; - latency_stat = &stack_latency->latency[type]; - - latency_stat->latency_total += latency; -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index b98ba84..04bdc3a 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -10,6 +10,7 @@ - * See the Mulan PSL v2 for more details. - */ - #include -+#include - #include - - #include "lstack_log.h" -@@ -471,7 +472,7 @@ int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int - } - - if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(msg); -+ time_stamp_into_rpcmsg(get_socket_by_fd(fd)); - } - - msg->args[MSG_ARG_0].i = fd; -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index 939189e..f0d3d5d 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -22,11 +22,14 @@ struct protocol_stack; - enum GAZELLE_LATENCY_TYPE; - enum GAZELLE_STAT_MODE; - struct gazelle_stat_msg_request; -+struct lwip_sock; - - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, - enum GAZELLE_LATENCY_TYPE type, uint64_t time_record); - void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, - enum GAZELLE_LATENCY_TYPE type); -+void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct lwip_sock *sock, -+ enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); - int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg); - int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); -@@ -35,6 +38,8 @@ void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_inf - void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); - void lstack_calculate_aggregate(int type, uint32_t len); - void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new); --void time_stamp_into_rpcmsg(struct rpc_msg *msg); -+void time_stamp_into_rpcmsg(struct lwip_sock *sock); -+void time_stamp_into_recvmbox(struct lwip_sock *sock); -+void time_stamp_record(int fd, struct pbuf *pbuf); - - #endif /* GAZELLE_STACK_STAT_H */ -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 0c51848..276ebb2 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -58,8 +58,6 @@ struct rpc_msg { - - rpc_msg_func func; /* msg handle func hook */ - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ -- -- uint64_t time_stamp; /* rpc_call_* start time */ - }; - - static inline void rpc_queue_init(rpc_queue *queue) -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 319f7cd..4351891 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -899,11 +899,13 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st - - printf("Statistics of lstack latency pkts min(us) max(us) average(us)\n"); - printf("Recv:\n"); -- printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -- printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_READ_APP_CALL].latency_stat_result); -- printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -- printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_MAX].latency_stat_result); -- printf("t0: read from nic t1: into recv ring t2: app read start t3: app read end\n"); -+ -+ printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_INTO_MBOX].latency_stat_result); -+ printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -+ printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_READ_APP_CALL].latency_stat_result); -+ printf("range: t3--->t4\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -+ printf("range: t0--->t4\n%s", res[GAZELLE_LATENCY_READ_MAX].latency_stat_result); -+ printf("t0: read from nic t1: into recvmbox t2: into recvring t3: app read start t4: app read end\n"); - - printf("Send:\n"); - printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_WRITE_INTO_RING].latency_stat_result); -@@ -912,8 +914,9 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st - printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_WRITE_MAX].latency_stat_result); - printf("t0: app send t1: into send ring t2: out of send ring t3: send to nic\n"); - -- printf("Rpc:\n"); -- printf("rpc_call_send \n%s", res[GAZELLE_LATENCY_WRITE_RPC_MSG].latency_stat_result); -+ printf("Others:\n"); -+ printf("rpc_call_send\n%s", res[GAZELLE_LATENCY_WRITE_RPC_MSG].latency_stat_result); -+ printf("ready to read from recvmbox\n%s", res[GAZELLE_LATENCY_RECVMBOX_READY].latency_stat_result); - - free(res); - } --- -2.33.0 - diff --git a/0190-rtc-adapt-rtc_close.patch b/0190-rtc-adapt-rtc_close.patch deleted file mode 100644 index 11f66dd..0000000 --- a/0190-rtc-adapt-rtc_close.patch +++ /dev/null @@ -1,51 +0,0 @@ -From cba42b0ca25bed62c946a4d902deb82ce0ca74e9 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 2 Mar 2024 13:44:20 +0800 -Subject: [PATCH] rtc: adapt rtc_close - ---- - src/lstack/api/lstack_epoll.c | 4 +++- - src/lstack/api/lstack_rtc_api.c | 12 +++++++++++- - 2 files changed, 14 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7dbef9d..6ae0eec 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -322,7 +322,9 @@ int32_t lstack_epoll_close(int32_t fd) - - wakeup->type = WAKEUP_CLOSE; - -- stack_broadcast_clean_epoll(wakeup); -+ if (!get_global_cfg_params()->stack_mode_rtc) { -+ stack_broadcast_clean_epoll(wakeup); -+ } - - struct list_node *node, *temp; - pthread_spin_lock(&wakeup->event_list_lock); -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 2e10e30..18664ca 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -63,7 +63,17 @@ int rtc_socket(int domain, int type, int protocol) - - int rtc_close(int s) - { -- return lwip_close(s); -+ struct lwip_sock *sock = get_socket(s); -+ if (sock != NULL && sock->wakeup != NULL && sock->wakeup->epollfd == s) { -+ return lstack_epoll_close(s); -+ } -+ -+ lwip_close(s); -+ if (sock != NULL) { -+ list_del_node_null(&sock->event_list); -+ } -+ -+ return posix_api->close_fn(s); - } - - int rtc_shutdown(int fd, int how) --- -2.33.0 - diff --git a/0191-virtio-flow_bifurcation-switch.patch b/0191-virtio-flow_bifurcation-switch.patch deleted file mode 100644 index a6c6241..0000000 --- a/0191-virtio-flow_bifurcation-switch.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 259092f39041968a07b395c43ed9cd26250215d9 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Tue, 18 Jun 2024 11:29:58 +0800 -Subject: [PATCH] [virtio]: flow_bifurcation switch - ---- - src/lstack/core/lstack_cfg.c | 12 ++++++++++++ - src/lstack/include/lstack_cfg.h | 1 + - 2 files changed, 13 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 56f290e..f0c5f4f 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -86,6 +86,7 @@ static int32_t parse_nic_vlan_mode(void); - static int32_t parse_defaule_nonblock_mode(void); - static int32_t parse_rpc_msg_max(void); - static int32_t parse_send_cache_mode(void); -+static int32_t parse_flow_bifurcation(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -152,6 +153,7 @@ static struct config_vector_t g_config_tbl[] = { - { "nonblock_mode", parse_defaule_nonblock_mode }, - { "rpc_msg_max", parse_rpc_msg_max }, - { "send_cache_mode", parse_send_cache_mode }, -+ { "flow_bifurcation", parse_flow_bifurcation}, - { NULL, NULL } - }; - -@@ -1393,3 +1395,13 @@ static int32_t parse_send_cache_mode(void) - return ret; - } - -+static int32_t parse_flow_bifurcation(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.flow_bifurcation, "flow_bifurcation", 0, 0, 1, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid flow_bifurcation value %d. only support 0 or 1\n", -+ g_config_params.flow_bifurcation); -+ } -+ return ret; -+} -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index b9721ff..9649d73 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -122,6 +122,7 @@ struct cfg_params { - bool nonblock_mode; - uint32_t rpc_msg_max; - bool send_cache_mode; -+ bool flow_bifurcation; - }; - - struct cfg_params *get_global_cfg_params(void); --- -2.33.0 - diff --git a/0192-remove-legacy-mem.patch b/0192-remove-legacy-mem.patch deleted file mode 100644 index 411da6a..0000000 --- a/0192-remove-legacy-mem.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 9fc2f5d7e298c3f549ad7abccc01ee1b971068e2 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 16 Jun 2024 14:29:43 +0800 -Subject: [PATCH] remove legacy-mem - ---- - src/lstack/lstack.conf | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 9cf967a..c65a25d 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -8,11 +8,11 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem"] -+dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary"] - - stack_thread_mode="run-to-wakeup" - --#ltran mode need add "--map-perfect" in dpdk_args -+#ltran mode need add "--map-perfect" and "--legacy-mem" in dpdk_args - use_ltran=0 - kni_switch=0 - --- -2.33.0 - diff --git a/0193-cfg-bond_slave_mac-support-pci-addr.patch b/0193-cfg-bond_slave_mac-support-pci-addr.patch deleted file mode 100644 index 4721ce6..0000000 --- a/0193-cfg-bond_slave_mac-support-pci-addr.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 61366e0a54935684ca3e17477c6367907285a5ff Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 17 Jun 2024 18:35:12 +0800 -Subject: [PATCH] cfg: bond_slave_mac support pci addr - ---- - src/lstack/core/lstack_cfg.c | 35 +++++++++--------- - src/lstack/core/lstack_dpdk.c | 63 ++++++++++++++++++++++++--------- - src/lstack/include/lstack_cfg.h | 16 ++++++++- - 3 files changed, 80 insertions(+), 34 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0e5fbf3..6ce862b 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -39,6 +39,7 @@ - #define LSTACK_CONF_ENV "LSTACK_CONF_PATH" - #define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist" - #define DEV_MAC_LEN 17 -+#define DEV_PCI_ADDR_LEN 12 - #define CPUS_MAX_NUM 256 - #define BOND_MIIMON_MIN 1 - #define BOND_MIIMON_MAX INT_MAX -@@ -188,6 +189,21 @@ static int32_t str_to_eth_addr(const char *src, unsigned char *dst) - return 0; - } - -+static int32_t str_to_dev_addr(const char *src, struct dev_addr *dst) -+{ -+ int32_t ret = 0; -+ if (strlen(src) == DEV_PCI_ADDR_LEN) { -+ /* str to pci addr */ -+ ret = rte_pci_addr_parse(src, &dst->addr.pci_addr); -+ dst->addr_type = DEV_ADDR_TYPE_PCI; -+ } else { -+ /* str to mac addr */ -+ ret = str_to_eth_addr(src, dst->addr.mac_addr.addr_bytes); -+ dst->addr_type = DEV_ADDR_TYPE_MAC; -+ } -+ return ret; -+} -+ - static int32_t parse_gateway_addr(void) - { - char *value; -@@ -1227,16 +1243,6 @@ static int32_t parse_bond_miimon(void) - return ret; - } - --static bool validate_bond_mac(uint8_t *mac_addr, struct rte_ether_addr *bond_slave_mac, int num_slaves) --{ -- for (int i = 0; i < num_slaves; i++) { -- if (memcmp(mac_addr, bond_slave_mac[i].addr_bytes, ETHER_ADDR_LEN) == 0) { -- return true; -- } -- } -- return false; --} -- - static int32_t parse_bond_slave_mac(void) - { - if (g_config_params.bond_mode == -1) { -@@ -1269,7 +1275,8 @@ static int32_t parse_bond_slave_mac(void) - free(bond_slave_mac_tmp); - return -EINVAL; - } -- ret = str_to_eth_addr(mac_addr, g_config_params.bond_slave_mac_addr[k].addr_bytes); -+ -+ ret = str_to_dev_addr(mac_addr, &g_config_params.bond_slave_addr[k]); - if (ret != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", mac_addr, ret); - free(bond_slave_mac_tmp); -@@ -1279,12 +1286,6 @@ static int32_t parse_bond_slave_mac(void) - k = k + 1; - } - free(bond_slave_mac_tmp); -- if (g_config_params.bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -- if (!validate_bond_mac(g_config_params.mac_addr, g_config_params.bond_slave_mac_addr, GAZELLE_MAX_BOND_NUM)) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: devices must be in bond_slave_mac for BONDING_MODE_ACTIVE_BACKUP.\n"); -- return -EINVAL; -- } -- } - return ret; - } - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 07fffe9..785431f 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -372,6 +372,23 @@ static int32_t ethdev_port_id(uint8_t *mac) - return port_id; - } - -+static int32_t pci_to_port_id(struct rte_pci_addr *pci_addr) -+{ -+ uint16_t port_id; -+ char device_name[RTE_DEV_NAME_MAX_LEN] = ""; -+ -+ rte_pci_device_name(pci_addr, device_name, RTE_DEV_NAME_MAX_LEN); -+ -+ int ret = rte_eth_dev_get_port_by_name(device_name, &port_id); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "match failed: no NIC matches cfg:%04x:%02x:%02x.%x\n", -+ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function); -+ return -EINVAL; -+ } -+ -+ return port_id; -+} -+ - static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info) - { - int rss_enable = 0; -@@ -491,18 +508,25 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - free(reta_conf); - } - --int32_t dpdk_bond_primary_set(int port_id, int slave_port_id) -+int32_t dpdk_bond_primary_set(int port_id, int *slave_port_id) - { - int32_t primary_port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); -- if (slave_port_id == primary_port_id) { -- int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret); -- return -1; -+ if (primary_port_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "cannot get the port id of the cfg\n"); -+ return -1; -+ } -+ for (int i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -+ if (slave_port_id[i] == primary_port_id) { -+ int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret); -+ return -1; -+ } -+ return ret; - } -- return ret; - } -- return 0; -+ LSTACK_LOG(ERR, LSTACK, "cfg: devices must be in bond_slave_mac for BONDING_MODE_ACTIVE_BACKUP.\n"); -+ return -1; - } - - int32_t dpdk_ethdev_init(int port_id) -@@ -687,12 +711,17 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - LSTACK_LOG(ERR, LSTACK, "bond add slave devices failed, ret=%d\n", ret); - return -1; - } -- if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -- dpdk_bond_primary_set(port_id, slave_port_id[i]); -+ } -+ -+ if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -+ ret = dpdk_bond_primary_set(port_id, slave_port_id); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret); -+ return -1; - } - } - -- if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) { -+ if (cfg->bond_mode == BONDING_MODE_8023AD) { - ret = rte_eth_bond_8023ad_dedicated_queues_enable(port_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret); -@@ -717,8 +746,7 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - return -1; - } - -- if ((get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) || -- (get_global_cfg_params()->bond_mode == BONDING_MODE_ALB)) { -+ if ((cfg->bond_mode == BONDING_MODE_8023AD) || (cfg->bond_mode == BONDING_MODE_ALB)) { - for (int i = 0; i < count; i++) { - /* bond port promiscuous only enable primary port */ - /* we enable all ports */ -@@ -742,17 +770,20 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - int32_t init_dpdk_ethdev(void) - { - int32_t ret; -- int slave_port_id[GAZELLE_MAX_BOND_NUM]; -+ int slave_port_id[GAZELLE_MAX_BOND_NUM] = {-1}; - int port_id; - struct cfg_params *cfg = get_global_cfg_params(); - int i; - - if (cfg->bond_mode >= 0) { - for (i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -- if (rte_is_zero_ether_addr(&cfg->bond_slave_mac_addr[i])) { -+ if (cfg->bond_slave_addr[i].addr_type == DEV_ADDR_TYPE_EMPTY) { - break; -+ } else if (cfg->bond_slave_addr[i].addr_type == DEV_ADDR_TYPE_MAC) { -+ slave_port_id[i] = ethdev_port_id(cfg->bond_slave_addr[i].addr.mac_addr.addr_bytes); -+ } else { -+ slave_port_id[i] = pci_to_port_id(&cfg->bond_slave_addr[i].addr.pci_addr); - } -- slave_port_id[i] = ethdev_port_id(cfg->bond_slave_mac_addr[i].addr_bytes); - ret = dpdk_ethdev_init(slave_port_id[i]); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "slave port(%d) init failed, ret=%d\n", slave_port_id[i], ret); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 94878de..21d9d83 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -16,6 +16,8 @@ - - #include - #include -+#include -+#include - - #include "lstack_protocol_stack.h" - #include "gazelle_opt.h" -@@ -52,6 +54,18 @@ - #define LSTACK_LPM_PKTS_IN_DETECT_MIN 5 - #define LSTACK_LPM_PKTS_IN_DETECT_MAX 65535 - -+#define DEV_ADDR_TYPE_EMPTY 0 -+#define DEV_ADDR_TYPE_MAC 1 -+#define DEV_ADDR_TYPE_PCI 2 -+ -+struct dev_addr { -+ uint8_t addr_type; // 0:empty, 1:mac, 2:pci -+ union addr_union { -+ struct rte_ether_addr mac_addr; -+ struct rte_pci_addr pci_addr; -+ } addr; -+}; -+ - struct secondary_attach_arg { - uint8_t socket_num; - uint64_t socket_size; -@@ -114,7 +128,7 @@ struct cfg_params { - bool tuple_filter; - int8_t bond_mode; - int32_t bond_miimon; -- struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM]; -+ struct dev_addr bond_slave_addr[GAZELLE_MAX_BOND_NUM]; - bool use_sockmap; - bool udp_enable; - struct cfg_nic_params nic; --- -2.33.0 - diff --git a/0194-refactor-tx-cache-module.patch b/0194-refactor-tx-cache-module.patch deleted file mode 100644 index 3516aaa..0000000 --- a/0194-refactor-tx-cache-module.patch +++ /dev/null @@ -1,340 +0,0 @@ -From dae1c41eea8dba45344f49c2fc00eeb31a24f925 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 17 Jun 2024 19:09:13 +0800 -Subject: [PATCH] refactor tx cache module - ---- - src/lstack/api/dir.mk | 2 +- - src/lstack/api/lstack_tx_cache.c | 47 --------- - src/lstack/core/lstack_cfg.c | 1 - - src/lstack/core/lstack_protocol_stack.c | 4 +- - src/lstack/include/lstack_protocol_stack.h | 1 - - src/lstack/include/lstack_tx_cache.h | 13 +-- - src/lstack/netif/dir.mk | 2 +- - src/lstack/netif/lstack_ethdev.c | 32 ++---- - src/lstack/netif/lstack_tx_cache.c | 114 +++++++++++++++++++++ - 9 files changed, 130 insertions(+), 86 deletions(-) - delete mode 100644 src/lstack/api/lstack_tx_cache.c - create mode 100644 src/lstack/netif/lstack_tx_cache.c - -diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk -index 70bc59d..729690d 100644 ---- a/src/lstack/api/dir.mk -+++ b/src/lstack/api/dir.mk -@@ -8,7 +8,7 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c lstack_tx_cache.c -+SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c - - $(eval $(call register_dir, api, $(SRC))) - -diff --git a/src/lstack/api/lstack_tx_cache.c b/src/lstack/api/lstack_tx_cache.c -deleted file mode 100644 -index 42aef57..0000000 ---- a/src/lstack/api/lstack_tx_cache.c -+++ /dev/null -@@ -1,47 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#include "lwip/sockets.h" --#include "lstack_cfg.h" --#include "lstack_protocol_stack.h" --#include "lstack_tx_cache.h" -- --void stack_send_pkts(struct protocol_stack *stack) --{ -- if (!get_global_cfg_params()->send_cache_mode) { -- return; -- } -- -- uint32_t send_num = stack->tx_cache.send_end - stack->tx_cache.send_start; -- -- if (send_num == 0) { -- return; -- } -- -- uint32_t start = stack->tx_cache.send_start & STACK_SEND_MASK; -- uint32_t end = stack->tx_cache.send_end & STACK_SEND_MASK; -- uint32_t sent_pkts = 0; -- -- if (start < end) { -- sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num); -- } else { -- send_num = STACK_SEND_MAX - start; -- sent_pkts = stack->dev_ops.tx_xmit(stack, &stack->tx_cache.send_pkts[start], send_num); -- if (sent_pkts == send_num) { -- sent_pkts += stack->dev_ops.tx_xmit(stack, stack->tx_cache.send_pkts, end); -- } -- } -- -- stack->tx_cache.send_start += sent_pkts; -- stack->stats.tx += sent_pkts; --} -- -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index f0c5f4f..5521898 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -32,7 +32,6 @@ - #include "gazelle_reg_msg.h" - #include "lstack_log.h" - #include "gazelle_base_func.h" --#include "lstack_protocol_stack.h" - #include "lstack_cfg.h" - - #define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 74e543d..f6d381e 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -480,7 +480,9 @@ int stack_polling(uint32_t wakeup_tick) - do_lwip_read_recvlist(stack, read_connect_number); - if ((wakeup_tick & 0xf) == 0) { - wakeup_stack_epoll(stack); -- stack_send_pkts(stack); -+ if (get_global_cfg_params()->send_cache_mode) { -+ tx_cache_send(stack->queue_id); -+ } - } - - /* run to completion mode currently does not support sockmap */ -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index ab27dfa..6ca4f14 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -77,7 +77,6 @@ struct protocol_stack { - uint32_t tx_ring_used; - - struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX]; -- struct lstack_tx_cache tx_cache; - struct list_node recv_list; - struct list_node same_node_recv_list; /* used for same node processes communication */ - struct list_node wakeup_list; -diff --git a/src/lstack/include/lstack_tx_cache.h b/src/lstack/include/lstack_tx_cache.h -index 3991b16..04e9e35 100644 ---- a/src/lstack/include/lstack_tx_cache.h -+++ b/src/lstack/include/lstack_tx_cache.h -@@ -13,16 +13,7 @@ - #ifndef _LSTACK_TX_CACHE_H_ - #define _LSTACK_TX_CACHE_H_ - --#define STACK_SEND_MAX (2048) --#define STACK_SEND_MASK (STACK_SEND_MAX - 1) --#define STACK_SEND_INDEX(index) ((index) & STACK_SEND_MASK) -- --struct lstack_tx_cache { -- uint32_t send_start; -- uint32_t send_end; -- struct rte_mbuf *send_pkts[STACK_SEND_MAX]; --}; -- --void stack_send_pkts(struct protocol_stack *stack); -+int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops); -+int tx_cache_send(uint16_t queue_id); - - #endif /* _LSTACK_TX_CACHE_H_ */ -diff --git a/src/lstack/netif/dir.mk b/src/lstack/netif/dir.mk -index 1e67734..b551041 100644 ---- a/src/lstack/netif/dir.mk -+++ b/src/lstack/netif/dir.mk -@@ -8,7 +8,7 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c -+SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c lstack_tx_cache.c - ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1) - SRC += lstack_fault_inject.c - endif -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 77172f8..45c5f9e 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -187,19 +187,6 @@ int32_t eth_dev_poll(void) - return nr_pkts; - } - --static void eth_dev_send_pkt(struct protocol_stack *stack, struct rte_mbuf *mbuf) --{ -- do { -- if (STACK_SEND_INDEX(stack->tx_cache.send_end + 1) != STACK_SEND_INDEX(stack->tx_cache.send_start)) { -- stack->tx_cache.send_pkts[STACK_SEND_INDEX(stack->tx_cache.send_end)] = mbuf; -- stack->tx_cache.send_end++; -- return; -- } -- stack_send_pkts(stack); -- stack->stats.send_pkts_fail++; -- } while (1); --} -- - static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - { - struct protocol_stack *stack = get_protocol_stack(); -@@ -245,16 +232,12 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - pbuf = pbuf->next; - } - -- if (!get_global_cfg_params()->send_cache_mode) { -- uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1); -- stack->stats.tx += sent_pkts; -- if (sent_pkts < 1) { -- stack->stats.tx_drop++; -- rte_pktmbuf_free(first_mbuf); -- return ERR_MEM; -- } -- } else { -- eth_dev_send_pkt(stack, first_mbuf); -+ uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1); -+ stack->stats.tx += sent_pkts; -+ if (sent_pkts < 1) { -+ stack->stats.tx_drop++; -+ rte_pktmbuf_free(first_mbuf); -+ return ERR_MEM; - } - - return ERR_OK; -@@ -295,6 +278,9 @@ int32_t ethdev_init(struct protocol_stack *stack) - struct cfg_params *cfg = get_global_cfg_params(); - - vdev_dev_ops_init(&stack->dev_ops); -+ if (cfg->send_cache_mode) { -+ tx_cache_init(stack->queue_id, stack, &stack->dev_ops); -+ } - - if (use_ltran()) { - stack->rx_ring_used = 0; -diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c -new file mode 100644 -index 0000000..ac5a9db ---- /dev/null -+++ b/src/lstack/netif/lstack_tx_cache.c -@@ -0,0 +1,114 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+ -+#include "lwip/sockets.h" -+#include "lstack_ethdev.h" -+#include "lstack_log.h" -+#include "gazelle_opt.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_tx_cache.h" -+ -+#define TX_CACHE_MAX 128 -+#define TX_CACHE_MASK (TX_CACHE_MAX - 1) -+#define TX_CACHE_INDEX(index) ((index) & TX_CACHE_MASK) -+ -+struct tx_cache { -+ uint16_t port_id; -+ uint16_t queue_id; -+ -+ uint32_t send_start; -+ uint32_t send_end; -+ struct rte_mbuf *send_pkts[TX_CACHE_MAX]; -+ -+ uint64_t send_pkts_fail; -+ void *priv; -+}; -+struct lstack_dev_ops g_tx_cache_dev_ops; -+ -+static uint32_t tx_cache_recv(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts); -+ -+struct tx_cache *g_tx_cache[PROTOCOL_STACK_MAX]; -+ -+int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops) -+{ -+ struct tx_cache *tx_cache = calloc(1, sizeof(struct tx_cache)); -+ if (tx_cache == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache init failed\n", queue_id); -+ } -+ -+ tx_cache->queue_id = queue_id; -+ tx_cache->priv = priv; -+ g_tx_cache[queue_id] = tx_cache; -+ -+ g_tx_cache_dev_ops.tx_xmit = dev_ops->tx_xmit; -+ dev_ops->tx_xmit = tx_cache_recv; -+ -+ return 0; -+} -+ -+int tx_cache_send(uint16_t queue_id) -+{ -+ struct tx_cache *tx_cache = g_tx_cache[queue_id]; -+ if (tx_cache == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache get failed\n", queue_id); -+ return 0; -+ } -+ -+ uint32_t send_num = tx_cache->send_end - tx_cache->send_start; -+ if (send_num == 0) { -+ return 0; -+ } -+ -+ uint32_t start = tx_cache->send_start & TX_CACHE_MASK; -+ uint32_t end = tx_cache->send_end & TX_CACHE_MASK; -+ uint32_t sent_pkts = 0; -+ if (start < end) { -+ sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, &tx_cache->send_pkts[start], send_num); -+ } else { -+ send_num = TX_CACHE_MAX - start; -+ sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, &tx_cache->send_pkts[start], send_num); -+ if (sent_pkts == send_num) { -+ sent_pkts += g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, tx_cache->send_pkts, end); -+ } -+ } -+ -+ tx_cache->send_start += sent_pkts; -+ return sent_pkts; -+} -+ -+static uint32_t tx_cache_recv(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) -+{ -+ if (nr_pkts != 1) { -+ LSTACK_LOG(ERR, LSTACK, "arg not support, nr_pkts is %d\n", nr_pkts); -+ return 0; -+ } -+ uint16_t queue_id = stack->queue_id; -+ struct tx_cache *tx_cache = g_tx_cache[queue_id]; -+ if (tx_cache == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache get failed\n", queue_id); -+ return 0; -+ } -+ -+ do { -+ if (TX_CACHE_INDEX(tx_cache->send_end + 1) != TX_CACHE_INDEX(tx_cache->send_start)) { -+ tx_cache->send_pkts[TX_CACHE_INDEX(tx_cache->send_end)] = pkts[0]; -+ tx_cache->send_end++; -+ return nr_pkts; -+ } -+ -+ tx_cache_send(queue_id); -+ } while (1); -+ -+ return 0; -+} --- -2.33.0 - diff --git a/0195-virtio-create-and-init-virtio_port.patch b/0195-virtio-create-and-init-virtio_port.patch deleted file mode 100644 index 0c7706a..0000000 --- a/0195-virtio-create-and-init-virtio_port.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 696cd69752032e55ef301f3eb4f7ad42693137ab Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 17 Jun 2024 14:33:50 +0800 -Subject: [PATCH] [virtio]: create and init virtio_port - ---- - src/lstack/core/dir.mk | 2 +- - src/lstack/core/lstack_dpdk.c | 6 +- - src/lstack/core/lstack_port_map.c | 43 ++++++ - src/lstack/core/lstack_virtio.c | 201 +++++++++++++++++++++++++++ - src/lstack/include/lstack_port_map.h | 20 +++ - src/lstack/include/lstack_virtio.h | 36 +++++ - 6 files changed, 306 insertions(+), 2 deletions(-) - create mode 100644 src/lstack/core/lstack_port_map.c - create mode 100644 src/lstack/core/lstack_virtio.c - create mode 100644 src/lstack/include/lstack_port_map.h - create mode 100644 src/lstack/include/lstack_virtio.h - -diff --git a/src/lstack/core/dir.mk b/src/lstack/core/dir.mk -index e2d10a5..21b0d22 100644 ---- a/src/lstack/core/dir.mk -+++ b/src/lstack/core/dir.mk -@@ -8,6 +8,6 @@ - # PURPOSE. - # See the Mulan PSL v2 for more details. - --SRC = lstack_preload.c lstack_init.c lstack_cfg.c lstack_dpdk.c lstack_control_plane.c lstack_stack_stat.c lstack_lwip.c lstack_protocol_stack.c lstack_thread_rpc.c -+SRC = lstack_preload.c lstack_init.c lstack_cfg.c lstack_dpdk.c lstack_control_plane.c lstack_stack_stat.c lstack_lwip.c lstack_protocol_stack.c lstack_thread_rpc.c lstack_virtio.c lstack_port_map.c - $(eval $(call register_dir, core, $(SRC))) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 785431f..b0d76bf 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -49,6 +49,7 @@ - #include "lstack_thread_rpc.h" - #include "lstack_lwip.h" - #include "lstack_cfg.h" -+#include "lstack_virtio.h" - #include "lstack_dpdk.h" - - struct eth_params { -@@ -771,7 +772,7 @@ int32_t init_dpdk_ethdev(void) - { - int32_t ret; - int slave_port_id[GAZELLE_MAX_BOND_NUM] = {-1}; -- int port_id; -+ int port_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); - int i; - -@@ -813,6 +814,9 @@ int32_t init_dpdk_ethdev(void) - } - } - #endif -+ if (get_global_cfg_params()->flow_bifurcation && virtio_port_create(port_id) != 0) { -+ return -1; -+ } - - return 0; - } -diff --git a/src/lstack/core/lstack_port_map.c b/src/lstack/core/lstack_port_map.c -new file mode 100644 -index 0000000..e5008b3 ---- /dev/null -+++ b/src/lstack/core/lstack_port_map.c -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+ * gazelle is licensed under the Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+ * PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ */ -+ -+#include -+#include -+#include "lstack_port_map.h" -+ -+#define PORT_MAP_UNIX_TCP_PORT_MAX 65535 -+#define PORT_MAP_EIGHT_BIT 8 -+ -+static uint8_t g_rule_port[(PORT_MAP_UNIX_TCP_PORT_MAX + 1) / PORT_MAP_EIGHT_BIT]; // 8k byte -+static pthread_mutex_t g_rule_map_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+void port_map_set(uint32_t modBit, int setVal) -+{ -+ pthread_mutex_lock(&g_rule_map_mutex); -+ g_rule_port[modBit / PORT_MAP_EIGHT_BIT] &= ~(1 << (modBit % PORT_MAP_EIGHT_BIT)); -+ g_rule_port[modBit / PORT_MAP_EIGHT_BIT] |= (setVal << (modBit % PORT_MAP_EIGHT_BIT)); -+ pthread_mutex_unlock(&g_rule_map_mutex); -+} -+ -+int port_map_get(int bit_index) -+{ -+ int bit_val = 0; -+ int byte_index = bit_index / PORT_MAP_EIGHT_BIT; -+ int bit_offset = bit_index % PORT_MAP_EIGHT_BIT; -+ uint8_t mask = 1 << bit_offset; -+ pthread_mutex_lock(&g_rule_map_mutex); -+ if ((g_rule_port[byte_index] & mask) != 0) { -+ bit_val = 1; -+ } -+ pthread_mutex_unlock(&g_rule_map_mutex); -+ return bit_val; -+} -\ No newline at end of file -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -new file mode 100644 -index 0000000..810e343 ---- /dev/null -+++ b/src/lstack/core/lstack_virtio.c -@@ -0,0 +1,201 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+ * gazelle is licensed under the Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+ * PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ */ -+#include -+#include "lstack_cfg.h" -+#include "lstack_log.h" -+#include "lstack_port_map.h" -+#include "lstack_virtio.h" -+ -+#define VIRTIO_USER_NAME "virtio_user0" -+#define VIRTIO_DPDK_PARA_LEN 256 -+#define VIRTIO_TX_RX_RING_SIZE 1024 -+ -+static struct virtio_instance g_virtio_instance = {0}; -+ -+struct virtio_instance* virtio_instance_get(void) -+{ -+ return &g_virtio_instance; -+} -+ -+static int virtio_set_ipv6_addr(void) -+{ -+ return 0; -+} -+ -+static int virtio_cfg_ip(void) -+{ -+ // set ipv4 adr() -+ -+ // set ipv6 addr -+ virtio_set_ipv6_addr(); -+ return 0; -+} -+ -+void virtio_tap_process_rx(uint16_t port, uint32_t queue_id) -+{ -+ struct rte_mbuf *pkts_burst[VIRTIO_TX_RX_RING_SIZE]; -+ uint16_t lstack_net_port = port; -+ 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); -+ 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); -+ for (uint16_t i = nb_rx; i < pkg_num; ++i) { -+ rte_pktmbuf_free(pkts_burst[i]); -+ g_virtio_instance.rx_drop[queue_id]++; -+ } -+ } -+} -+ -+void virtio_tap_process_tx(uint16_t queue_id, struct rte_mbuf *mbuf_copy) -+{ -+ int tx_num = rte_eth_tx_burst(g_virtio_instance.virtio_port_id, queue_id, &(mbuf_copy), 1); -+ if (tx_num < 0) { -+ rte_pktmbuf_free(mbuf_copy); -+ g_virtio_instance.tx_drop[queue_id]++; -+ LSTACK_LOG(ERR, LSTACK, "virtio_tap_process_tx failed %d, %d\n", queue_id, tx_num); -+ } -+ g_virtio_instance.tx_pkg[queue_id]++; -+} -+ -+static int virtio_port_init(uint16_t port) -+{ -+ int retval; -+ uint16_t rx_queue_num = g_virtio_instance.rx_queue_num; -+ uint16_t tx_queue_num = g_virtio_instance.tx_queue_num; -+ -+ LSTACK_LOG(INFO, LSTACK, "virtio_port_init port= %u rx_queue_num=%u tx_queue_num=%u \n", -+ port, rx_queue_num, tx_queue_num); -+ -+ struct rte_eth_conf port_conf; -+ memset(&port_conf, 0, sizeof(struct rte_eth_conf)); -+ -+ struct rte_eth_dev_info dev_info; -+ retval = rte_eth_dev_info_get(port, &dev_info); -+ if (retval != 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_info_get failed(port %u) info: %d\n", port, retval); -+ return retval; -+ } -+ -+ retval = rte_eth_dev_configure(port, rx_queue_num, tx_queue_num, &port_conf); -+ if (retval != 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_configure failed retval=%d\n", retval); -+ return retval; -+ } -+ -+ for (uint16_t q = 0; q < tx_queue_num; q++) { -+ retval = rte_eth_tx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); -+ if (retval < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_tx_queue_setup failed (queue %u) retval=%d \n", q, retval); -+ return retval; -+ } -+ } -+ -+ for (uint16_t q = 0; q < rx_queue_num; q++) { -+ struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[q]; -+ retval = rte_eth_rx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, rte_eth_dev_socket_id(port), -+ NULL, rxtx_mbuf_pool); -+ if (retval < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_rx_queue_setup failed (queue %u) retval=%d \n", q, retval); -+ return retval; -+ } -+ } -+ return 0; -+} -+ -+static int32_t virtio_port_start(uint16_t virtio_port) -+{ -+ int retval = 0; -+ if (virtio_port_init(virtio_port) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_port_init failed \n"); -+ return -1; -+ } -+ -+ retval = rte_eth_dev_start(virtio_port); -+ if (retval < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_start failed retval=%d\n", retval); -+ return retval; -+ } -+ -+ if (virtio_cfg_ip() != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_cfg_ip_mac failed\n"); -+ return -1; -+ } -+ LSTACK_LOG(INFO, LSTACK, "virtio_user lstack_net_port=%u virtio_port=%u rx_queue_num = %u tx_queue_num = %u\n", -+ g_virtio_instance.lstack_port_id, g_virtio_instance.virtio_port_id, -+ g_virtio_instance.rx_queue_num, g_virtio_instance.tx_queue_num); -+ return 0; -+} -+int virtio_port_create(int lstack_net_port) -+{ -+ char portargs[VIRTIO_DPDK_PARA_LEN] = {0}; -+ -+ struct rte_ether_addr addr; -+ uint16_t virtio_port_id = 0xffff; // invalid val -+ -+ struct rte_eth_dev_info dev_info; -+ int ret = rte_eth_dev_info_get(lstack_net_port, &dev_info); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "get dev info ret=%d\n", ret); -+ return ret; -+ } -+ -+ g_virtio_instance.rx_queue_num = dev_info.nb_rx_queues; -+ g_virtio_instance.tx_queue_num = dev_info.nb_tx_queues; -+ -+ if (g_virtio_instance.rx_queue_num > VIRTIO_MAX_QUEUE_NUM || -+ g_virtio_instance.tx_queue_num > VIRTIO_MAX_QUEUE_NUM) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_port_create failed queue_num (%u %u) is bigger than %u\n", -+ g_virtio_instance.rx_queue_num, g_virtio_instance.tx_queue_num, VIRTIO_MAX_QUEUE_NUM); -+ return -1; -+ } -+ -+ int retval = rte_eth_macaddr_get(lstack_net_port, &addr); // virtio_user0'mac is same with lstack.conf MAC addr -+ if (retval != 0) { -+ LSTACK_LOG(ERR, LSTACK, " rte_eth_macaddr_get failed ret = %d\n", retval); -+ return retval; -+ } -+ -+ retval = snprintf(portargs, sizeof(portargs), -+ "path=/dev/vhost-net,queues=%u,queue_size=%u,iface=%s,mac=" RTE_ETHER_ADDR_PRT_FMT, -+ VIRTIO_MAX_QUEUE_NUM, VIRTIO_TX_RX_RING_SIZE, VIRTIO_USER_NAME, RTE_ETHER_ADDR_BYTES(&addr)); -+ if (retval < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio portargs snprintf failed ret=%d \n", retval); -+ return retval; -+ } -+ LSTACK_LOG(INFO, LSTACK, "virtio portargs=%s \n", portargs); -+ -+ retval = rte_eal_hotplug_add("vdev", VIRTIO_USER_NAME, portargs); -+ if (retval < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eal_hotplug_add failed retval=%d : %s\n", retval, strerror(-retval)); -+ return retval; -+ } -+ -+ retval = rte_eth_dev_get_port_by_name(VIRTIO_USER_NAME, &virtio_port_id); -+ if (retval != 0) { -+ rte_eal_hotplug_remove("vdev", VIRTIO_USER_NAME); -+ LSTACK_LOG(ERR, LSTACK, "virtio_user0 not found\n"); -+ return -1; -+ } -+ -+ g_virtio_instance.virtio_port_id = virtio_port_id; -+ g_virtio_instance.lstack_port_id = lstack_net_port; -+ -+ retval = virtio_port_start(virtio_port_id); -+ if (retval != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_port_start failed ret=%d\n", retval); -+ rte_eal_hotplug_remove("vdev", VIRTIO_USER_NAME); -+ return retval; -+ } -+ return 0; -+} -\ No newline at end of file -diff --git a/src/lstack/include/lstack_port_map.h b/src/lstack/include/lstack_port_map.h -new file mode 100644 -index 0000000..24ef53a ---- /dev/null -+++ b/src/lstack/include/lstack_port_map.h -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+ * gazelle is licensed under the Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+ * PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ */ -+#ifndef __LSTACK_PORT_MAP_H__ -+#define __LSTACK_PORT_MAP_H__ -+ -+#include -+ -+void port_map_set(uint32_t modBit, int setVal); -+int port_map_get(int bit_index); -+ -+#endif -\ No newline at end of file -diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h -new file mode 100644 -index 0000000..5e001ca ---- /dev/null -+++ b/src/lstack/include/lstack_virtio.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+ * gazelle is licensed under the Mulan PSL v2. -+ * You can use this software according to the terms and conditions of the Mulan PSL v2. -+ * You may obtain a copy of Mulan PSL v2 at: -+ * http://license.coscl.org.cn/MulanPSL2 -+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+ * PURPOSE. -+ * See the Mulan PSL v2 for more details. -+ */ -+#ifndef __LSTACK_VIRTIO_H__ -+#define __LSTACK_VIRTIO_H__ -+ -+#include -+ -+#define VIRTIO_MAX_QUEUE_NUM 8 -+struct virtio_instance { -+ uint16_t lstack_port_id; -+ uint16_t virtio_port_id; -+ uint16_t rx_queue_num; -+ uint16_t tx_queue_num; -+ -+ uint64_t rx_pkg[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t rx_drop[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t tx_pkg[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t tx_drop[VIRTIO_MAX_QUEUE_NUM]; -+}; -+ -+void virtio_tap_process_rx(uint16_t port, uint32_t queue_id); -+void virtio_tap_process_tx(uint16_t queue_id, struct rte_mbuf *mbuf_copy); -+ -+int virtio_port_create(int lstack_net_port); -+ -+struct virtio_instance* virtio_instance_get(void); -+#endif -\ No newline at end of file --- -2.33.0 - diff --git a/0196-refactor-udp-send.patch b/0196-refactor-udp-send.patch deleted file mode 100644 index a622143..0000000 --- a/0196-refactor-udp-send.patch +++ /dev/null @@ -1,341 +0,0 @@ -From c109336bcf860c9dd16ba8becd9de72ecdce4d8f Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 11 Jun 2024 14:15:49 +0800 -Subject: [PATCH] refactor udp send distinguish tcp/udp get_from_sendring - cancel the restrictioin that maximum of 2 rpc msg can be send over the same - udp sock - ---- - src/lstack/core/lstack_lwip.c | 107 ++++++++++++++++-------- - src/lstack/core/lstack_protocol_stack.c | 39 ++++++++- - src/lstack/core/lstack_thread_rpc.c | 29 ++++++- - src/lstack/include/lstack_lwip.h | 3 +- - src/lstack/include/lstack_rpc_proc.h | 3 +- - src/lstack/include/lstack_thread_rpc.h | 3 +- - 6 files changed, 141 insertions(+), 43 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 153c5cc..db948b0 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -101,7 +101,7 @@ static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, u - void *data = rte_pktmbuf_mtod(mbuf, void *); - struct pbuf *pbuf = pbuf_alloced_custom(layer, length, type, pbuf_custom, data, MAX_PACKET_SZ); - if (pbuf) { -- pbuf->allow_in = 1; -+ pbuf->allow_append = 1; - pbuf->addr = *IP_ANY_TYPE; - pbuf->port = 0; - pthread_spin_init(&pbuf->pbuf_lock, PTHREAD_PROCESS_SHARED); -@@ -227,24 +227,61 @@ struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type typ - return init_mbuf_to_pbuf(mbuf, layer, length, type); - } - --struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags) -+static inline bool pbuf_allow_append(struct pbuf *pbuf, uint16_t remain_size) -+{ -+ pthread_spin_lock(&pbuf->pbuf_lock); -+ if (pbuf->tot_len > remain_size) { -+ pthread_spin_unlock(&pbuf->pbuf_lock); -+ return false; -+ } -+ if (pbuf->allow_append == 1) { -+ __sync_fetch_and_sub(&pbuf->allow_append, 1); -+ } -+ -+ pthread_spin_unlock(&pbuf->pbuf_lock); -+ return true; -+} -+ -+struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size) -+{ -+ int count; -+ /* when remain_size is 0, fill_sendring write one pbuf to sendring */ -+ if (remain_size == 0) { -+ count = 1; -+ } else { -+ count = (remain_size + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN; -+ } -+ -+ struct pbuf *pbufs[count]; -+ -+ int actual_count = gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbufs, count); -+ if (unlikely(actual_count != count)) { -+ LSTACK_LOG(ERR, LSTACK, "udp get pbuf from sendring error, expected: %d, actual: %d\n", -+ count, actual_count); -+ } -+ -+ if (unlikely(pbufs[0]->tot_len != remain_size)) { -+ LSTACK_LOG(ERR, LSTACK, "udp get pbuf size error, expected: %d, actual: %d\n", -+ remain_size, pbufs[0]->tot_len); -+ } -+ -+ for (int i = 0; get_protocol_stack_group()->latency_start && i < count; i++) { -+ calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_LWIP, 0); -+ } -+ -+ return pbufs[0]; -+} -+ -+struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size) - { - struct pbuf *pbuf = NULL; - - if (unlikely(sock->send_pre_del)) { -- pbuf = sock->send_pre_del; -- pthread_spin_lock(&pbuf->pbuf_lock); -- if (pbuf->tot_len > remain_size) { -- pthread_spin_unlock(&pbuf->pbuf_lock); -- *apiflags &= ~TCP_WRITE_FLAG_MORE; -+ if (pbuf_allow_append(sock->send_pre_del, remain_size)) { -+ return sock->send_pre_del; -+ } else { - return NULL; - } -- if (pbuf->allow_in == 1) { -- __sync_fetch_and_sub(&pbuf->allow_in, 1); -- } -- pthread_spin_unlock(&pbuf->pbuf_lock); -- -- return pbuf; - } - - gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf, 1); -@@ -252,17 +289,6 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - return NULL; - } - -- /* udp send a pbuf chain, dequeue all pbufs except head pbuf */ -- if (NETCONN_IS_UDP(sock) && remain_size > MBUF_MAX_DATA_LEN) { -- int size = (remain_size + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN - 1; -- struct pbuf *pbuf_used[size]; -- gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf_used, size); -- -- for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < size; i++) { -- calculate_lstack_latency(&sock->stack->latency, pbuf_used[i], GAZELLE_LATENCY_WRITE_LWIP, 0); -- } -- } -- - if (get_protocol_stack_group()->latency_start) { - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP, 0); - } -@@ -270,19 +296,11 @@ struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_s - sock->send_pre_del = pbuf; - - if (!gazelle_ring_readover_count(sock->send_ring)) { -- pthread_spin_lock(&pbuf->pbuf_lock); -- if (pbuf->tot_len > remain_size) { -- pthread_spin_unlock(&pbuf->pbuf_lock); -- *apiflags &= ~TCP_WRITE_FLAG_MORE; -+ if (!pbuf_allow_append(pbuf, remain_size)) { - return NULL; - } -- if (pbuf->allow_in == 1) { -- __sync_fetch_and_sub(&pbuf->allow_in, 1); -- } -- pthread_spin_unlock(&pbuf->pbuf_lock); - } else { - if (pbuf->tot_len > remain_size) { -- *apiflags &= ~TCP_WRITE_FLAG_MORE; - return NULL; - } - } -@@ -388,7 +406,7 @@ static inline struct pbuf *gazelle_ring_readlast(struct rte_ring *r) - if (pthread_spin_trylock(&last_pbuf->pbuf_lock) != 0) { - return NULL; - } -- if (last_pbuf->allow_in != 1) { -+ if (last_pbuf->allow_append != 1) { - pthread_spin_unlock(&last_pbuf->pbuf_lock); - return NULL; - } -@@ -675,17 +693,34 @@ ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int3 - return buflen; - } - --static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) -+static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) - { - // 2: call_num >= 2, don't need add new rpc send - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) < 2) { -- while (rpc_call_send(&sock->stack->rpc_queue, fd, NULL, len, flags) < 0) { -+ while (rpc_call_tcp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { - usleep(1000); // 1000: wait 1ms to exec again - } - __sync_fetch_and_add(&sock->call_num, 1); - } - } - -+static inline void notice_stack_udp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) -+{ -+ __sync_fetch_and_add(&sock->call_num, 1); -+ while (rpc_call_udp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { -+ usleep(1000); // 1000: wait 1ms to exec again -+ } -+} -+ -+static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) -+{ -+ if (NETCONN_IS_UDP(sock)) { -+ notice_stack_udp_send(sock, fd, len, flags); -+ } else { -+ notice_stack_tcp_send(sock, fd, len, flags); -+ } -+} -+ - /* process on same node use ring to recv data */ - ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) - { -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f6d381e..d130c91 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -877,7 +877,7 @@ void stack_recv(struct rpc_msg *msg) - msg->args[MSG_ARG_3].i); - } - --void stack_send(struct rpc_msg *msg) -+void stack_tcp_send(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; - size_t len = msg->args[MSG_ARG_1].size; -@@ -913,6 +913,39 @@ void stack_send(struct rpc_msg *msg) - return; - } - -+void stack_udp_send(struct rpc_msg *msg) -+{ -+ int32_t fd = msg->args[MSG_ARG_0].i; -+ size_t len = msg->args[MSG_ARG_1].size; -+ struct protocol_stack *stack = get_protocol_stack(); -+ int replenish_again; -+ uint32_t call_num; -+ -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_rpcmsg_latency(&stack->latency, msg, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ } -+ -+ struct lwip_sock *sock = get_socket(fd); -+ if (sock == NULL) { -+ msg->result = -1; -+ LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); -+ return; -+ } -+ -+ 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)) { -+ rpc_call_replenish(&stack->rpc_queue, sock); -+ return; -+ } -+ -+ return; -+} -+ - /* any protocol stack thread receives arp packet and sync it to other threads so that it can have the arp table */ - void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack) - { -@@ -1040,6 +1073,10 @@ void stack_replenish_sendring(struct rpc_msg *msg) - struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p; - - msg->result = do_lwip_replenish_sendring(stack, sock); -+ if (msg->result == true) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); -+ } - } - - void stack_get_conntable(struct rpc_msg *msg) -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 04bdc3a..e438c37 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -460,13 +460,36 @@ int32_t rpc_call_replenish(rpc_queue *queue, void *sock) - } - - msg->args[MSG_ARG_0].p = sock; -+ msg->sync_flag = 0; - -- return rpc_sync_call(queue, msg); -+ rpc_call(queue, msg); -+ return 0; -+} -+ -+int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(stack_tcp_send); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ if (get_protocol_stack_group()->latency_start) { -+ time_stamp_into_rpcmsg(get_socket_by_fd(fd)); -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].size = len; -+ msg->args[MSG_ARG_2].i = flags; -+ msg->sync_flag = 0; -+ -+ rpc_call(queue, msg); -+ -+ return 0; - } - --int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int flags) -+int32_t rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_send); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_udp_send); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index fa10e3f..85c9c20 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -33,7 +33,8 @@ int do_lwip_close(int32_t fd); - void do_lwip_init_sock(int32_t fd); - void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); - --struct pbuf *do_lwip_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size, uint8_t *apiflags); -+struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); -+struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); - void do_lwip_get_from_sendring_over(struct lwip_sock *sock); - bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock); - ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, uint8_t apiflags); -diff --git a/src/lstack/include/lstack_rpc_proc.h b/src/lstack/include/lstack_rpc_proc.h -index 71f0c58..77b18bd 100644 ---- a/src/lstack/include/lstack_rpc_proc.h -+++ b/src/lstack/include/lstack_rpc_proc.h -@@ -30,7 +30,8 @@ void stack_getsockopt(struct rpc_msg *msg); - void stack_setsockopt(struct rpc_msg *msg); - void stack_fcntl(struct rpc_msg *msg); - void stack_ioctl(struct rpc_msg *msg); --void stack_send(struct rpc_msg *msg); -+void stack_tcp_send(struct rpc_msg *msg); -+void stack_udp_send(struct rpc_msg *msg); - void stack_mempool_size(struct rpc_msg *msg); - void stack_rpcpool_size(struct rpc_msg *msg); - void stack_create_shadow_fd(struct rpc_msg *msg); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 276ebb2..fa98b0c 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -83,7 +83,8 @@ int32_t rpc_call_bind(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, - int32_t rpc_call_listen(rpc_queue *queue, int s, int backlog); - int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); - int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_send(rpc_queue *queue, int fd, const void *buf, size_t len, int flags); -+int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags); -+int32_t rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); - int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); - int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); - int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen); --- -2.33.0 - diff --git a/0197-solve-compile-err-in-20.03.patch b/0197-solve-compile-err-in-20.03.patch deleted file mode 100644 index 1f5ccef..0000000 --- a/0197-solve-compile-err-in-20.03.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 7755b72b475fdb5fbd75f51cfb8dfd4a49b70852 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Mon, 24 Jun 2024 15:26:31 +0800 -Subject: [PATCH] solve complie err in 20.03 RTE_ETHER_ADDR_PRT_FMT - RTE_ETHER_ADDR_BYTES are defined in dpdk 21.11 - ---- - src/lstack/include/lstack_virtio.h | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h -index 5e001ca..d40c754 100644 ---- a/src/lstack/include/lstack_virtio.h -+++ b/src/lstack/include/lstack_virtio.h -@@ -15,6 +15,21 @@ - #include - - #define VIRTIO_MAX_QUEUE_NUM 8 -+ -+// RTE_ETHER_ADDR_PRT_FMT RTE_ETHER_ADDR_BYTES are defined in dpdk 21.11 -+#ifndef RTE_ETHER_ADDR_PRT_FMT -+#define RTE_ETHER_ADDR_PRT_FMT "%02X:%02X:%02X:%02X:%02X:%02X" -+#endif -+ -+#ifndef RTE_ETHER_ADDR_BYTES -+#define RTE_ETHER_ADDR_BYTES(mac_addrs) ((mac_addrs)->addr_bytes[0]), \ -+ ((mac_addrs)->addr_bytes[1]), \ -+ ((mac_addrs)->addr_bytes[2]), \ -+ ((mac_addrs)->addr_bytes[3]), \ -+ ((mac_addrs)->addr_bytes[4]), \ -+ ((mac_addrs)->addr_bytes[5]) -+#endif -+ - struct virtio_instance { - uint16_t lstack_port_id; - uint16_t virtio_port_id; --- -2.33.0 - diff --git a/0198-fix-function-call-error.patch b/0198-fix-function-call-error.patch deleted file mode 100644 index b6353af..0000000 --- a/0198-fix-function-call-error.patch +++ /dev/null @@ -1,66 +0,0 @@ -From bcf0dff302a8416cb7528ee44c2f0fb3138ff13e Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Tue, 25 Jun 2024 17:53:36 +0800 -Subject: [PATCH] fix function call error - ---- - src/lstack/core/lstack_protocol_stack.c | 8 ++++---- - src/lstack/core/lstack_stack_stat.c | 2 +- - src/lstack/include/lstack_stack_stat.h | 2 -- - 3 files changed, 5 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d130c91..d6e3c86 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -921,10 +921,6 @@ void stack_udp_send(struct rpc_msg *msg) - int replenish_again; - uint32_t call_num; - -- if (get_protocol_stack_group()->latency_start) { -- calculate_rpcmsg_latency(&stack->latency, msg, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -- - struct lwip_sock *sock = get_socket(fd); - if (sock == NULL) { - msg->result = -1; -@@ -932,6 +928,10 @@ void stack_udp_send(struct rpc_msg *msg) - return; - } - -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_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) { -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index a1bd44d..0f1f693 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -82,7 +82,7 @@ void time_stamp_record(int fd, struct pbuf *pbuf) - { - struct lwip_sock *sock = get_socket_by_fd(fd); - -- if (get_protocol_stack_group()->latency_start && pbuf != NULL) { -+ if (get_protocol_stack_group()->latency_start && sock && pbuf) { - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); - time_stamp_into_recvmbox(sock); - } -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index f0d3d5d..9fca04a 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -26,8 +26,6 @@ struct lwip_sock; - - void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, - enum GAZELLE_LATENCY_TYPE type, uint64_t time_record); --void calculate_rpcmsg_latency(struct gazelle_stack_latency *stack_latency, struct rpc_msg *msg, -- enum GAZELLE_LATENCY_TYPE type); - void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct lwip_sock *sock, - enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); --- -2.33.0 - diff --git a/0199-perftool-add-latency-tool.patch b/0199-perftool-add-latency-tool.patch deleted file mode 100644 index 7bf1e21..0000000 --- a/0199-perftool-add-latency-tool.patch +++ /dev/null @@ -1,57 +0,0 @@ -From a037f2d9d92ea4a5e659297c5c9839557040f1ce Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Fri, 21 Jun 2024 16:48:20 +0800 -Subject: [PATCH] perftool: add latency tool - ---- - tools/perf/latency.bt | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) - create mode 100755 tools/perf/latency.bt - -diff --git a/tools/perf/latency.bt b/tools/perf/latency.bt -new file mode 100755 -index 0000000..bfe18ae ---- /dev/null -+++ b/tools/perf/latency.bt -@@ -0,0 +1,38 @@ -+#!/usr/bin/env bpftrace -+/* -+reference: https://github.com/bpftrace/bpftrace/blob/master/man/adoc/bpftrace.adoc -+prepare: yum install bpftrace -+example: ./latency.bt xxx.so func1 func2 -+supported functions: bpftrace -l 'uprobe:xxx.so' -+*/ -+ -+BEGIN -+{ -+} -+ -+uprobe:$1:$2 -+{ -+ @t_start[tid] = nsecs; -+} -+ -+uretprobe:$1:$3 -+/@t_start[tid]/ -+{ -+ $t_dur = nsecs - @t_start[tid]; -+ @t_avg = avg($t_dur); -+ -+ //@t_hist = lhist($t_dur, 0, 4000, 100); -+ @t_hist = hist($t_dur); -+ -+ delete(@t_start[tid]); -+} -+ -+END -+{ -+ printf("\n\n%s -> %s \n", str($2), str($3)); -+ printf("average time(nsec):"); -+ print(@t_avg); -+ -+ clear(@t_avg); -+ clear(@t_start); -+} --- -2.33.0 - diff --git a/0200-cfg-del-unnecessary-logs.patch b/0200-cfg-del-unnecessary-logs.patch deleted file mode 100644 index b1f8f23..0000000 --- a/0200-cfg-del-unnecessary-logs.patch +++ /dev/null @@ -1,88 +0,0 @@ -From b83a8ba5bb2f7f689cbdb404d3352bd039def160 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 20 Jun 2024 16:58:38 +0800 -Subject: [PATCH] cfg: del unnecessary logs - ---- - src/lstack/core/lstack_cfg.c | 24 ++---------------------- - 1 file changed, 2 insertions(+), 22 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index a1afe70..a5918f1 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -100,7 +100,7 @@ static int32_t parse_flow_bifurcation(void); - } \ - int32_t _val = config_setting_get_int(_config_arg); \ - if (_val < (_min_val) || _val > (_max_val)) { \ -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg %s %d invaild, range is [%d, %d].\n", \ -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg %s %d invalid, range is [%d, %d].\n", \ - (_arg_string), _val, (_min_val), (_max_val)); \ - (_ret) = -EINVAL; \ - break; \ -@@ -1196,7 +1196,7 @@ static int parse_tuple_filter(void) - return 0; - } - if (g_config_params.use_ltran || g_config_params.listen_shadow) { -- LSTACK_LOG(ERR, LSTACK, "tuple filter and (ltran or listen_shadow) cannot be enabled at the same time\n"); -+ LSTACK_LOG(ERR, LSTACK, "tuple filter and (ltran or listen_shadow) cannot be enabled at the same time\n"); - return -EINVAL; - } - -@@ -1356,10 +1356,6 @@ static int32_t parse_nic_vlan_mode(void) - { - int32_t ret; - PARSE_ARG(g_config_params.nic.vlan_mode, "nic_vlan_mode", -1, -1, 4094, ret); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid vlan mode value %d ret=%d. only support -1~4094\n", \ -- g_config_params.nic.vlan_mode, ret); -- } - return ret; - } - -@@ -1367,10 +1363,6 @@ static int32_t parse_defaule_nonblock_mode(void) - { - int32_t ret; - PARSE_ARG(g_config_params.nonblock_mode, "nonblock_mode", 1, 0, 1, ret); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid nonblock mode value %d. only support 0 or 1\n", \ -- g_config_params.nonblock_mode); -- } - return ret; - } - -@@ -1378,10 +1370,6 @@ static int32_t parse_rpc_msg_max(void) - { - int32_t ret; - PARSE_ARG(g_config_params.rpc_msg_max, "rpc_msg_max", 4096, 1, 8192, ret); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid rpc msg max value %d ret=%d. only support 1~8192\n", -- g_config_params.rpc_msg_max, ret); -- } - return ret; - } - -@@ -1389,10 +1377,6 @@ static int32_t parse_send_cache_mode(void) - { - int32_t ret; - PARSE_ARG(g_config_params.send_cache_mode, "send_cache_mode", 0, 0, 1, ret); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid send cache mode value %d. only support 0 or 1\n", -- g_config_params.send_cache_mode); -- } - return ret; - } - -@@ -1400,9 +1384,5 @@ static int32_t parse_flow_bifurcation(void) - { - int32_t ret; - PARSE_ARG(g_config_params.flow_bifurcation, "flow_bifurcation", 0, 0, 1, ret); -- if (ret != 0) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid flow_bifurcation value %d. only support 0 or 1\n", -- g_config_params.flow_bifurcation); -- } - return ret; - } --- -2.33.0 - diff --git a/0201-fix-dpdk_bond_primary_set-bug.patch b/0201-fix-dpdk_bond_primary_set-bug.patch deleted file mode 100644 index 9a7f813..0000000 --- a/0201-fix-dpdk_bond_primary_set-bug.patch +++ /dev/null @@ -1,72 +0,0 @@ -From c65b58b68bf51cc09d1c2438e55d1dcb92ffd4ca Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 24 Jun 2024 10:43:50 +0800 -Subject: [PATCH] fix dpdk_bond_primary_set bug - ---- - src/lstack/core/lstack_dpdk.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index b0d76bf..6e52187 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -509,14 +509,14 @@ static void rss_setup(const int port_id, const uint16_t nb_queues) - free(reta_conf); - } - --int32_t dpdk_bond_primary_set(int port_id, int *slave_port_id) -+int32_t dpdk_bond_primary_set(int port_id, int *slave_port_id, int count) - { - int32_t primary_port_id = ethdev_port_id(get_global_cfg_params()->mac_addr); - if (primary_port_id < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot get the port id of the cfg\n"); - return -1; - } -- for (int i = 0; i < GAZELLE_MAX_BOND_NUM; i++) { -+ for (int i = 0; i < count; i++) { - if (slave_port_id[i] == primary_port_id) { - int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id); - if (ret != 0) { -@@ -715,7 +715,7 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - } - - if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) { -- ret = dpdk_bond_primary_set(port_id, slave_port_id); -+ ret = dpdk_bond_primary_set(port_id, slave_port_id, count); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret); - return -1; -@@ -771,7 +771,7 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - int32_t init_dpdk_ethdev(void) - { - int32_t ret; -- int slave_port_id[GAZELLE_MAX_BOND_NUM] = {-1}; -+ int slave_port_id[GAZELLE_MAX_BOND_NUM]; - int port_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); - int i; -@@ -785,6 +785,10 @@ int32_t init_dpdk_ethdev(void) - } else { - slave_port_id[i] = pci_to_port_id(&cfg->bond_slave_addr[i].addr.pci_addr); - } -+ if (slave_port_id[i] < 0) { -+ LSTACK_LOG(ERR, LSTACK, "cfg->bond_slave_addr[%d] parsing failed, ret=%d\n", i, ret); -+ return -1; -+ } - ret = dpdk_ethdev_init(slave_port_id[i]); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "slave port(%d) init failed, ret=%d\n", slave_port_id[i], ret); -@@ -799,6 +803,9 @@ int32_t init_dpdk_ethdev(void) - } - } else { - port_id = ethdev_port_id(cfg->mac_addr); -+ if (port_id < 0) { -+ return -1; -+ } - ret = dpdk_ethdev_init(port_id); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed, port id=%d\n", port_id); --- -2.33.0 - diff --git a/0202-fix-build-failed-in-2003sp4.patch b/0202-fix-build-failed-in-2003sp4.patch deleted file mode 100644 index d0e38cf..0000000 --- a/0202-fix-build-failed-in-2003sp4.patch +++ /dev/null @@ -1,25 +0,0 @@ -From a287036099c050f91bceaeb7bd1a3b5c1b0b6af6 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Mon, 24 Jun 2024 20:01:58 +0800 -Subject: [PATCH] fix build failed in 2003sp4 - ---- - src/lstack/core/lstack_dpdk.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 6e52187..2de41e3 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -786,7 +786,7 @@ int32_t init_dpdk_ethdev(void) - slave_port_id[i] = pci_to_port_id(&cfg->bond_slave_addr[i].addr.pci_addr); - } - if (slave_port_id[i] < 0) { -- LSTACK_LOG(ERR, LSTACK, "cfg->bond_slave_addr[%d] parsing failed, ret=%d\n", i, ret); -+ LSTACK_LOG(ERR, LSTACK, "cfg->bond_slave_addr[%d] parsing failed.\n", i); - return -1; - } - ret = dpdk_ethdev_init(slave_port_id[i]); --- -2.33.0 - diff --git a/0203-virtio-cfg-ipv4-and-ipv6-addr.patch b/0203-virtio-cfg-ipv4-and-ipv6-addr.patch deleted file mode 100644 index a2df27c..0000000 --- a/0203-virtio-cfg-ipv4-and-ipv6-addr.patch +++ /dev/null @@ -1,190 +0,0 @@ -From e2bdddb748e891312aa6e2c67a44ba265ca16edf Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Fri, 21 Jun 2024 09:20:03 +0800 -Subject: [PATCH] [virtio]: cfg ipv4 and ipv6 addr - ---- - src/lstack/core/lstack_virtio.c | 140 +++++++++++++++++++++++++++++++- - 1 file changed, 136 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 810e343..c3b3511 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -10,15 +10,23 @@ - * See the Mulan PSL v2 for more details. - */ - #include -+#include -+#include -+#include -+#include -+#include - #include "lstack_cfg.h" - #include "lstack_log.h" - #include "lstack_port_map.h" - #include "lstack_virtio.h" -+#include "securec.h" - - #define VIRTIO_USER_NAME "virtio_user0" - #define VIRTIO_DPDK_PARA_LEN 256 - #define VIRTIO_TX_RX_RING_SIZE 1024 - -+#define VIRTIO_MASK_BITS(mask) (32 - __builtin_clz(mask)) -+ - static struct virtio_instance g_virtio_instance = {0}; - - struct virtio_instance* virtio_instance_get(void) -@@ -28,15 +36,139 @@ struct virtio_instance* virtio_instance_get(void) - - static int virtio_set_ipv6_addr(void) - { -+ struct cfg_params *cfg = get_global_cfg_params(); -+ struct ifreq ifr; -+ memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); -+ -+ int sockfd = posix_api->socket_fn(AF_INET6, SOCK_DGRAM, 0); -+ if (sockfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr failed ret =%d errno=%d \n", sockfd, errno); -+ return -1; -+ } -+ -+ int ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME, sizeof(VIRTIO_USER_NAME)); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr strncpy failed ret =%d errno=%d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ ret = posix_api->ioctl_fn(sockfd, SIOGIFINDEX, &ifr); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr failed ret =%d errno=%d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ struct in6_ifreq ifr6; -+ memset_s(&ifr6, sizeof(ifr6), 0, sizeof(ifr6)); -+ ret = memcpy_s(&ifr6.ifr6_addr, sizeof(ifr6.ifr6_addr), &(cfg->host_addr6), sizeof((cfg->host_addr6.addr))); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr memcpy_s failed ret =%d errno=%d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ ifr6.ifr6_ifindex = ifr.ifr_ifindex; -+ ifr6.ifr6_prefixlen = VIRTIO_MASK_BITS(cfg->netmask.addr); -+ -+ ret = posix_api->ioctl_fn(sockfd, SIOCSIFADDR, &ifr6); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr failed err= %d errno %d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ posix_api->close_fn(sockfd); -+ return 0; -+} -+ -+static int virtio_set_ipv4_addr(void) -+{ -+ int ret = 0; -+ int sockfd = posix_api->socket_fn(AF_INET, SOCK_DGRAM, 0); -+ if (sockfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr failed ret= %d errno %d \n", sockfd, errno); -+ return -1; -+ } -+ -+ struct cfg_params *cfg = get_global_cfg_params(); -+ struct ifreq ifr; -+ memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); -+ -+ ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv4_addr strcpy_s failed ret=%d errno %d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr; -+ addr->sin_family = AF_INET; -+ addr->sin_addr.s_addr = cfg->host_addr.addr; -+ -+ if (posix_api->ioctl_fn(sockfd, SIOCSIFADDR, &ifr) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_cfg_ip failed errno %d \n", errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ addr->sin_addr.s_addr = cfg->netmask.addr; -+ if (posix_api->ioctl_fn(sockfd, SIOCSIFNETMASK, &ifr) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_cfg_ip netmask=%u fail\n", cfg->netmask.addr); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ posix_api->close_fn(sockfd); -+ return 0; -+} -+ -+static int virtio_netif_up(void) -+{ -+ int sockfd = posix_api->socket_fn(AF_INET, SOCK_DGRAM, 0); -+ if (sockfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_netif_up socket_fn failed ret= %d errno %d \n", sockfd, errno); -+ return -1; -+ } -+ -+ struct ifreq ifr; -+ memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); -+ int ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_netif_up strcpy_s failed ret=%d errno %d \n", ret, errno); -+ posix_api->close_fn(sockfd); -+ return -1; -+ } -+ -+ ifr.ifr_flags |= IFF_UP; -+ if (posix_api->ioctl_fn(sockfd, SIOCSIFFLAGS, &ifr) < 0) { -+ posix_api->close_fn(sockfd); -+ LSTACK_LOG(ERR, LSTACK, " virtio_netif_up ioctl_fn failed errno= %d \n", errno); -+ return -1; -+ } -+ -+ posix_api->close_fn(sockfd); - return 0; - } - - static int virtio_cfg_ip(void) - { -- // set ipv4 adr() -+ struct cfg_params *cfg = get_global_cfg_params(); - -- // set ipv6 addr -- virtio_set_ipv6_addr(); -+ if (virtio_set_ipv4_addr() < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv4_addr failed \n"); -+ return -1; -+ } -+ -+ if (!ip6_addr_isany(&cfg->host_addr6) && virtio_set_ipv6_addr() < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr failed \n"); -+ return -1; -+ } -+ -+ // start virtio_user -+ if (virtio_netif_up() < 0) { -+ LSTACK_LOG(ERR, LSTACK, "virtio_netif_up failed \n"); -+ return -1; -+ } - return 0; - } - -@@ -198,4 +330,4 @@ int virtio_port_create(int lstack_net_port) - return retval; - } - return 0; --} -\ No newline at end of file -+} --- -2.33.0 - diff --git a/0204-parse-packages-type-in-rx_poll.patch b/0204-parse-packages-type-in-rx_poll.patch deleted file mode 100644 index 35a7d0f..0000000 --- a/0204-parse-packages-type-in-rx_poll.patch +++ /dev/null @@ -1,168 +0,0 @@ -From c7fff9e6eb2ba6f9d71389dc43c606b55f9379ce Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 18 Jun 2024 15:33:14 +0800 -Subject: [PATCH] parse packages type in rx_poll - ---- - src/lstack/netif/lstack_ethdev.c | 28 ++++++++--- - src/lstack/netif/lstack_vdev.c | 84 ++++++++++++++++++++------------ - 2 files changed, 73 insertions(+), 39 deletions(-) - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 45c5f9e..3bfa8af 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -130,6 +130,25 @@ void kni_handle_tx(struct rte_mbuf *mbuf) - } - #endif - -+#define IS_ARP_PKT(ptype) ((ptype & RTE_PTYPE_L2_ETHER_ARP) == RTE_PTYPE_L2_ETHER_ARP) -+#define IS_IPV4_TCP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ -+ ((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP) && \ -+ ((ptype & RTE_PTYPE_L4_FRAG) != RTE_PTYPE_L4_FRAG) && \ -+ (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) -+ -+#define IS_IPV6_TCP_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \ -+ ((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP) && \ -+ ((ptype & RTE_PTYPE_L4_FRAG) != RTE_PTYPE_L4_FRAG) && \ -+ (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) -+ -+#define IS_IPV4_UDP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \ -+ ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \ -+ (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) -+ -+#define IS_IPV6_UDP_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \ -+ ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \ -+ (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) -+ - int32_t eth_dev_poll(void) - { - uint32_t nr_pkts; -@@ -151,14 +170,7 @@ int32_t eth_dev_poll(void) - int transfer_type = TRANSFER_CURRENT_THREAD; - /* copy arp into other stack */ - if (!use_ltran()) { -- struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(stack->pkts[i], struct rte_ether_hdr *); -- u16_t type; -- type = ethh->ether_type; -- if (type == PP_HTONS(ETHTYPE_VLAN)) { -- struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr *)(((char *)ethh) + SIZEOF_ETH_HDR); -- type = vlan->tpid; -- } -- if (unlikely(RTE_BE16(RTE_ETHER_TYPE_ARP) == type)) { -+ if (unlikely(IS_ARP_PKT(stack->pkts[i]->packet_type))) { - stack_broadcast_arp(stack->pkts[i], stack); - /* copy arp into other process */ - transfer_arp_to_other_process(stack->pkts[i]); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 107ee8c..5ce69a9 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -72,6 +72,58 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - return rcvd_pkts; - } - -+static inline void vdev_pkts_parse(struct rte_mbuf **pkts, int pkt_num) -+{ -+ for (int i = 0; i < pkt_num; i++) { -+ struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); -+ u16_t type = ethh->ether_type; -+ if (type == RTE_BE16(RTE_ETHER_TYPE_VLAN)) { -+ struct rte_vlan_hdr *vlan = (struct rte_vlan_hdr *)(ethh + 1); -+ type = vlan->eth_proto; -+ pkts[i]->l2_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_vlan_hdr); -+ } else { -+ pkts[i]->l2_len = sizeof(struct rte_ether_hdr); -+ } -+ -+ 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); -+ if (unlikely((iph->version_ihl & IPV4_MASK) != IPV4_VERION)) { -+ continue; -+ } -+ pkts[i]->l3_len = sizeof(struct rte_ipv4_hdr); -+ if (iph->next_proto_id == IPPROTO_TCP) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -+ pkts[i]->l2_len + pkts[i]->l3_len); -+ pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -+ -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; -+ } else if (iph->next_proto_id == IPPROTO_UDP) { -+ pkts[i]->l4_len = sizeof(struct rte_udp_hdr); -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_UDP; -+ } -+ -+ } else if (type == RTE_BE16(RTE_ETHER_TYPE_IPV6)) { -+ struct rte_ipv6_hdr *iph6 = rte_pktmbuf_mtod_offset(pkts[i], struct rte_ipv6_hdr *, -+ pkts[i]->l2_len); -+ pkts[i]->l3_len = sizeof(struct rte_ipv6_hdr); -+ if (iph6->proto == IPPROTO_TCP) { -+ struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -+ pkts[i]->l2_len + pkts[i]->l3_len); -+ pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; -+ } else if (iph6->proto == IPPROTO_UDP) { -+ pkts[i]->l4_len = sizeof(struct rte_udp_hdr); -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; -+ } -+ } else if (type == RTE_BE16(RTE_ETHER_TYPE_ARP)) { -+ pkts[i]->packet_type = RTE_PTYPE_L2_ETHER_ARP; -+ } else { -+ continue; -+ } -+ } -+} -+ - static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t max_mbuf) - { - struct rte_gro_param gro_param = { -@@ -82,6 +134,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - }; - - uint32_t pkt_num = rte_eth_rx_burst(stack->port_id, stack->queue_id, pkts, max_mbuf); -+ vdev_pkts_parse(pkts, pkt_num); - if (pkt_num <= 1) { - return pkt_num; - } -@@ -92,37 +145,6 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - return pkt_num; - } - -- for (uint32_t i = 0; i < pkt_num; i++) { -- struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *); -- u16_t type = ethh->ether_type; -- -- pkts[i]->l2_len = sizeof(struct rte_ether_hdr); -- -- if (type == RTE_BE16(RTE_ETHER_TYPE_IPV4)) { -- struct rte_ipv4_hdr *iph = rte_pktmbuf_mtod_offset(pkts[i], struct rte_ipv4_hdr *, -- sizeof(struct rte_ether_hdr)); -- if (unlikely((iph->version_ihl & IPV4_MASK) != IPV4_VERION)) { -- continue; -- } -- pkts[i]->l3_len = sizeof(struct rte_ipv4_hdr); -- -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr)); -- pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -- -- pkts[i]->packet_type = RTE_PTYPE_L3_IPV4 | RTE_PTYPE_L4_TCP; -- } else if (type == RTE_BE16(RTE_ETHER_TYPE_IPV6)) { -- pkts[i]->l3_len = sizeof(struct rte_ipv6_hdr); -- -- struct rte_tcp_hdr *tcp_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct rte_tcp_hdr *, -- sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv6_hdr)); -- pkts[i]->l4_len = TCP_HDR_LEN(tcp_hdr); -- -- pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_TCP; -- } else { -- continue; -- } -- } - pkt_num = rte_gro_reassemble_burst(pkts, pkt_num, &gro_param); - - return pkt_num; --- -2.33.0 - diff --git a/0205-virtio-distribute-pkg-by-dst_port.patch b/0205-virtio-distribute-pkg-by-dst_port.patch deleted file mode 100644 index 77e8204..0000000 --- a/0205-virtio-distribute-pkg-by-dst_port.patch +++ /dev/null @@ -1,198 +0,0 @@ -From a86ef865f47b99b41e426e621cb3b5e3416a70ff Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Thu, 27 Jun 2024 19:53:07 +0800 -Subject: [PATCH] [virtio]: distribute pkg by dst_port - ---- - src/lstack/core/lstack_protocol_stack.c | 27 ++++++++++++++---- - src/lstack/core/lstack_virtio.c | 9 ++++++ - src/lstack/include/lstack_virtio.h | 2 ++ - src/lstack/netif/lstack_ethdev.c | 37 +++++++++++++++++++++++-- - src/lstack/netif/lstack_vdev.c | 2 ++ - 5 files changed, 68 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d6e3c86..e272a04 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -34,6 +34,7 @@ - #include "lstack_control_plane.h" - #include "posix/lstack_epoll.h" - #include "lstack_stack_stat.h" -+#include "lstack_virtio.h" - #include "lstack_protocol_stack.h" - - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -@@ -509,6 +510,9 @@ int stack_polling(uint32_t wakeup_tick) - } - } - #endif -+ if (get_global_cfg_params()->flow_bifurcation) { -+ virtio_tap_process_rx(stack->port_id, stack->queue_id); -+ } - return force_quit; - } - -@@ -979,14 +983,25 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - } - } - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -- cur_stack->stats.rx_allocmbuf_fail++; -- return; -+ if (get_global_cfg_params()->kni_switch) { -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -+ if (ret != 0) { -+ cur_stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ kni_handle_tx(mbuf_copy); - } -- copy_mbuf(mbuf_copy, mbuf); -- kni_handle_tx(mbuf_copy); - #endif -+ if (get_global_cfg_params()->flow_bifurcation) { -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -+ if (ret != 0) { -+ cur_stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ virtio_tap_process_tx(stack->queue_id, mbuf_copy); -+ } - return; - } - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index c3b3511..ad3088d 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -331,3 +331,12 @@ int virtio_port_create(int lstack_net_port) - } - return 0; - } -+ -+bool virtio_distribute_pkg_to_kernel(uint16_t dst_port) -+{ -+ if (dst_port == VIRTIO_PORT_INVALID) { -+ return false; -+ } -+ -+ return (port_map_get(dst_port) == 0); -+} -\ No newline at end of file -diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h -index d40c754..615d9c9 100644 ---- a/src/lstack/include/lstack_virtio.h -+++ b/src/lstack/include/lstack_virtio.h -@@ -14,6 +14,7 @@ - - #include - -+#define VIRTIO_PORT_INVALID 0xffff - #define VIRTIO_MAX_QUEUE_NUM 8 - - // RTE_ETHER_ADDR_PRT_FMT RTE_ETHER_ADDR_BYTES are defined in dpdk 21.11 -@@ -48,4 +49,5 @@ void virtio_tap_process_tx(uint16_t queue_id, struct rte_mbuf *mbuf_copy); - int virtio_port_create(int lstack_net_port); - - struct virtio_instance* virtio_instance_get(void); -+bool virtio_distribute_pkg_to_kernel(uint16_t dst_port); - #endif -\ No newline at end of file -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 3bfa8af..933c3e8 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -35,6 +35,7 @@ - #include "lstack_thread_rpc.h" - #include "lstack_flow.h" - #include "lstack_tx_cache.h" -+#include "lstack_virtio.h" - #include "lstack_ethdev.h" - - /* FRAME_MTU + 14byte header */ -@@ -149,6 +150,25 @@ void kni_handle_tx(struct rte_mbuf *mbuf) - ((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \ - (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) - -+#define IS_ICMPV6_PKT(ptype) (RTE_ETH_IS_IPV6_HDR(ptype) && \ -+ ((ptype & RTE_PTYPE_L4_ICMP) == RTE_PTYPE_L4_ICMP) && \ -+ (RTE_ETH_IS_TUNNEL_PKT(ptype) == 0)) -+ -+static uint16_t eth_dev_get_dst_port(struct rte_mbuf *pkt) -+{ -+ uint16_t dst_port = VIRTIO_PORT_INVALID; -+ uint32_t packet_type = pkt->packet_type; -+ -+ void *l4_hdr = rte_pktmbuf_mtod_offset(pkt, void *, pkt->l2_len + pkt->l3_len); -+ -+ if (IS_IPV4_TCP_PKT(packet_type) || IS_IPV6_TCP_PKT(packet_type)) { -+ dst_port = rte_be_to_cpu_16(((struct rte_tcp_hdr *)l4_hdr)->dst_port); -+ } else if (IS_IPV4_UDP_PKT(packet_type) || IS_IPV6_UDP_PKT(packet_type)) { -+ dst_port = rte_be_to_cpu_16(((struct rte_udp_hdr *)l4_hdr)->dst_port); -+ } -+ return dst_port; -+} -+ - int32_t eth_dev_poll(void) - { - uint32_t nr_pkts; -@@ -170,7 +190,8 @@ int32_t eth_dev_poll(void) - int transfer_type = TRANSFER_CURRENT_THREAD; - /* copy arp into other stack */ - if (!use_ltran()) { -- if (unlikely(IS_ARP_PKT(stack->pkts[i]->packet_type))) { -+ if (unlikely(IS_ARP_PKT(stack->pkts[i]->packet_type)) || -+ unlikely(IS_ICMPV6_PKT(stack->pkts[i]->packet_type))) { - stack_broadcast_arp(stack->pkts[i], stack); - /* copy arp into other process */ - transfer_arp_to_other_process(stack->pkts[i]); -@@ -178,17 +199,27 @@ int32_t eth_dev_poll(void) - if (get_global_cfg_params()->tuple_filter && stack->queue_id == 0) { - transfer_type = distribute_pakages(stack->pkts[i]); - } -+ if (get_global_cfg_params()->flow_bifurcation) { -+ uint16_t dst_port = eth_dev_get_dst_port(stack->pkts[i]); -+ if (virtio_distribute_pkg_to_kernel(dst_port)) { -+ transfer_type = TRANSFER_KERNEL; -+ } -+ } - } - } - - if (likely(transfer_type == TRANSFER_CURRENT_THREAD)) { - eth_dev_recv(stack->pkts[i], stack); - } else if (transfer_type == TRANSFER_KERNEL) { -+ if (get_global_cfg_params()->flow_bifurcation) { -+ virtio_tap_process_tx(stack->queue_id, stack->pkts[i]); -+ } else { - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -- kni_handle_tx(stack->pkts[i]); -+ kni_handle_tx(stack->pkts[i]); - #else -- rte_pktmbuf_free(stack->pkts[i]); -+ rte_pktmbuf_free(stack->pkts[i]); - #endif -+ } - } else { - /* transfer to other thread */ - } -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 5ce69a9..cb3953e 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -115,6 +115,8 @@ static inline void vdev_pkts_parse(struct rte_mbuf **pkts, int pkt_num) - } else if (iph6->proto == IPPROTO_UDP) { - pkts[i]->l4_len = sizeof(struct rte_udp_hdr); - pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_UDP; -+ } else if (iph6->proto == IPPROTO_ICMPV6) { -+ pkts[i]->packet_type = RTE_PTYPE_L3_IPV6 | RTE_PTYPE_L4_ICMP; - } - } else if (type == RTE_BE16(RTE_ETHER_TYPE_ARP)) { - pkts[i]->packet_type = RTE_PTYPE_L2_ETHER_ARP; --- -2.33.0 - diff --git a/0206-fix-coredump-when-get-empty-from-udp-sendring.patch b/0206-fix-coredump-when-get-empty-from-udp-sendring.patch deleted file mode 100644 index c4bb923..0000000 --- a/0206-fix-coredump-when-get-empty-from-udp-sendring.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 8cd5427107511b6daed9905590c2812346a3a57d Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 27 Jun 2024 19:52:02 +0800 -Subject: [PATCH] fix coredump when get empty from udp sendring - ---- - src/lstack/core/lstack_lwip.c | 13 ++++++------- - 1 file changed, 6 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index db948b0..3728100 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -255,17 +255,16 @@ struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t rema - struct pbuf *pbufs[count]; - - int actual_count = gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbufs, count); -- if (unlikely(actual_count != count)) { -+ /* it's impossible to enter this branch theoretically */ -+ if (unlikely((actual_count != count) || -+ ((actual_count != 0) && pbufs[0]->tot_len != remain_size))) { - LSTACK_LOG(ERR, LSTACK, "udp get pbuf from sendring error, expected: %d, actual: %d\n", - count, actual_count); -+ LSTACK_LOG(ERR, LSTACK, "udp get pbuf size error, expected: %d, actual: %d\n", -+ remain_size, actual_count == 0 ? 0 : pbufs[0]->tot_len); - } - -- if (unlikely(pbufs[0]->tot_len != remain_size)) { -- LSTACK_LOG(ERR, LSTACK, "udp get pbuf size error, expected: %d, actual: %d\n", -- remain_size, pbufs[0]->tot_len); -- } -- -- for (int i = 0; get_protocol_stack_group()->latency_start && i < count; i++) { -+ for (int i = 0; get_protocol_stack_group()->latency_start && i < actual_count; i++) { - calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_LWIP, 0); - } - --- -2.33.0 - diff --git a/0207-fix-poll-init-not-clear-old-fd.patch b/0207-fix-poll-init-not-clear-old-fd.patch deleted file mode 100644 index f2b4d3f..0000000 --- a/0207-fix-poll-init-not-clear-old-fd.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 5dbdb572406e168205cb9e54b2c247e97a57c22c Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Sat, 29 Jun 2024 07:17:27 +0000 -Subject: [PATCH] fix poll init not clear old fd - ---- - src/lstack/api/lstack_epoll.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 2791dd7..2ac7150 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -837,14 +837,15 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - continue; - } - } -- wakeup->last_fds[i].fd = fd; -- wakeup->last_fds[i].events = fds[i].events; -- poll_change = 1; - - if (sock == NULL || sock->conn == NULL || CONN_TYPE_HAS_HOST(sock->conn)) { - update_kernel_poll(wakeup, i, fds + i); - } - -+ wakeup->last_fds[i].fd = fd; -+ wakeup->last_fds[i].events = fds[i].events; -+ poll_change = 1; -+ - while (sock && sock->conn) { - sock->epoll_events = fds[i].events | POLLERR; - sock->wakeup = wakeup; --- -2.33.0 - diff --git a/0208-virtio-mode-actual_queue_num.patch b/0208-virtio-mode-actual_queue_num.patch deleted file mode 100644 index fd53200..0000000 --- a/0208-virtio-mode-actual_queue_num.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0613a7275ed2ed0aefc2f8419adeaadd8fd87de9 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sat, 29 Jun 2024 17:35:37 +0800 -Subject: [PATCH] virtio: mode actual_queue_num - ---- - src/lstack/core/lstack_virtio.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index ad3088d..bc42bb9 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -298,9 +298,11 @@ int virtio_port_create(int lstack_net_port) - return retval; - } - -+ uint16_t actual_queue_num = (g_virtio_instance.rx_queue_num < g_virtio_instance.tx_queue_num) ? -+ g_virtio_instance.rx_queue_num : g_virtio_instance.tx_queue_num; - retval = snprintf(portargs, sizeof(portargs), - "path=/dev/vhost-net,queues=%u,queue_size=%u,iface=%s,mac=" RTE_ETHER_ADDR_PRT_FMT, -- VIRTIO_MAX_QUEUE_NUM, VIRTIO_TX_RX_RING_SIZE, VIRTIO_USER_NAME, RTE_ETHER_ADDR_BYTES(&addr)); -+ actual_queue_num, VIRTIO_TX_RX_RING_SIZE, VIRTIO_USER_NAME, RTE_ETHER_ADDR_BYTES(&addr)); - if (retval < 0) { - LSTACK_LOG(ERR, LSTACK, "virtio portargs snprintf failed ret=%d \n", retval); - return retval; --- -2.33.0 - diff --git a/0209-virtio-update-g_rule_port-by-reg_ring_type-enum.patch b/0209-virtio-update-g_rule_port-by-reg_ring_type-enum.patch deleted file mode 100644 index 9833f1e..0000000 --- a/0209-virtio-update-g_rule_port-by-reg_ring_type-enum.patch +++ /dev/null @@ -1,109 +0,0 @@ -From cb0c86801bc4c221ae79a284619879dc98a5464d Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sat, 29 Jun 2024 14:46:32 +0800 -Subject: [PATCH] virtio: update g_rule_port by reg_ring_type enum - ---- - src/lstack/core/lstack_port_map.c | 25 ++++++++++++------------- - src/lstack/include/lstack_port_map.h | 4 ++-- - src/lstack/netif/lstack_vdev.c | 15 +++++++++++++++ - 3 files changed, 29 insertions(+), 15 deletions(-) - -diff --git a/src/lstack/core/lstack_port_map.c b/src/lstack/core/lstack_port_map.c -index e5008b3..5439394 100644 ---- a/src/lstack/core/lstack_port_map.c -+++ b/src/lstack/core/lstack_port_map.c -@@ -15,29 +15,28 @@ - #include "lstack_port_map.h" - - #define PORT_MAP_UNIX_TCP_PORT_MAX 65535 --#define PORT_MAP_EIGHT_BIT 8 - --static uint8_t g_rule_port[(PORT_MAP_UNIX_TCP_PORT_MAX + 1) / PORT_MAP_EIGHT_BIT]; // 8k byte -+static uint32_t g_rule_port[PORT_MAP_UNIX_TCP_PORT_MAX] = {0}; - static pthread_mutex_t g_rule_map_mutex = PTHREAD_MUTEX_INITIALIZER; - --void port_map_set(uint32_t modBit, int setVal) -+void port_map_mod(uint16_t port, uint16_t flag) - { - pthread_mutex_lock(&g_rule_map_mutex); -- g_rule_port[modBit / PORT_MAP_EIGHT_BIT] &= ~(1 << (modBit % PORT_MAP_EIGHT_BIT)); -- g_rule_port[modBit / PORT_MAP_EIGHT_BIT] |= (setVal << (modBit % PORT_MAP_EIGHT_BIT)); -+ if (flag == 0) { -+ g_rule_port[port]--; -+ } else { -+ g_rule_port[port]++; -+ } - pthread_mutex_unlock(&g_rule_map_mutex); - } - --int port_map_get(int bit_index) -+uint16_t port_map_get(uint16_t port) - { -- int bit_val = 0; -- int byte_index = bit_index / PORT_MAP_EIGHT_BIT; -- int bit_offset = bit_index % PORT_MAP_EIGHT_BIT; -- uint8_t mask = 1 << bit_offset; -+ uint16_t val = 0; - pthread_mutex_lock(&g_rule_map_mutex); -- if ((g_rule_port[byte_index] & mask) != 0) { -- bit_val = 1; -+ if (g_rule_port[port] > 0) { -+ val = 1; - } - pthread_mutex_unlock(&g_rule_map_mutex); -- return bit_val; -+ return val; - } -\ No newline at end of file -diff --git a/src/lstack/include/lstack_port_map.h b/src/lstack/include/lstack_port_map.h -index 24ef53a..80955dc 100644 ---- a/src/lstack/include/lstack_port_map.h -+++ b/src/lstack/include/lstack_port_map.h -@@ -14,7 +14,7 @@ - - #include - --void port_map_set(uint32_t modBit, int setVal); --int port_map_get(int bit_index); -+void port_map_mod(uint16_t port, uint16_t flag); -+uint16_t port_map_get(uint16_t port); - - #endif -\ No newline at end of file -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index cb3953e..75e4acc 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -35,6 +35,8 @@ - #include "lstack_lwip.h" - #include "lstack_flow.h" - #include "lstack_vdev.h" -+#include "lstack_port_map.h" -+#include "lstack_virtio.h" - - /* INUSE_TX_PKTS_WATERMARK < VDEV_RX_QUEUE_SZ; - * USE_RX_PKTS_WATERMARK < FREE_RX_QUEUE_SZ. -@@ -197,6 +199,19 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - return -1; - } - -+ uint16_t local_port = ntohs(qtuple->src_port); -+ if (get_global_cfg_params()->flow_bifurcation && get_global_cfg_params()->is_primary) { -+ if (type == REG_RING_TCP_LISTEN_CLOSE || type == REG_RING_UDP_BIND_CLOSE) { // add enum type in reg_sock.h -+ port_map_mod(local_port, 0); -+ } else if (type == REG_RING_TCP_LISTEN || type == REG_RING_UDP_BIND) { -+ port_map_mod(local_port, 1); -+ } else if (type == REG_RING_TCP_CONNECT_CLOSE) { -+ port_map_mod(local_port, 0); -+ } else if (type == REG_RING_TCP_CONNECT) { -+ port_map_mod(local_port, 1); -+ } -+ } -+ - if (!use_ltran() && get_global_cfg_params()->tuple_filter) { - if (type == REG_RING_TCP_LISTEN_CLOSE) { - if (get_global_cfg_params()->is_primary) { --- -2.33.0 - diff --git a/0210-virtio-dfx-data-of-virtio.patch b/0210-virtio-dfx-data-of-virtio.patch deleted file mode 100644 index 2769715..0000000 --- a/0210-virtio-dfx-data-of-virtio.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 0c6cf045fb0eea38cc7e53ee1984459ae90792bf Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Sat, 29 Jun 2024 15:16:54 +0800 -Subject: [PATCH] virtio: dfx data of virtio - ---- - src/common/gazelle_dfx_msg.h | 16 ++++++++++++++++ - src/lstack/core/lstack_stack_stat.c | 8 ++++++++ - src/lstack/include/lstack_virtio.h | 2 +- - src/ltran/ltran_dfx.c | 23 +++++++++++++++++++++++ - 4 files changed, 48 insertions(+), 1 deletion(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 696daf2..57bf631 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -53,6 +53,7 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, - GAZELLE_STAT_LSTACK_SHOW_RATE, - GAZELLE_STAT_LSTACK_SHOW_SNMP, -+ GAZELLE_STAT_LSTACK_SHOW_VIRTIO, - GAZELLE_STAT_LSTACK_SHOW_CONN, - GAZELLE_STAT_LSTACK_SHOW_LATENCY, - GAZELLE_STAT_LSTACK_LOW_POWER_MDF, -@@ -137,6 +138,20 @@ struct gazelle_stat_pkts { - struct gazelle_stack_aggregate_stats aggregate_stats; - }; - -+// same with lstack_virtio.h struct virtio_instance -+struct gazelle_stat_lstack_virtio { -+#define VIRTIO_MAX_QUEUE_NUM 8 -+ uint16_t lstack_port_id; -+ uint16_t virtio_port_id; -+ uint16_t rx_queue_num; -+ uint16_t tx_queue_num; -+ -+ uint64_t rx_pkg[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t rx_drop[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t tx_pkg[VIRTIO_MAX_QUEUE_NUM]; -+ uint64_t tx_drop[VIRTIO_MAX_QUEUE_NUM]; -+}; -+ - /* same as define in lwip/stats.h - struct stats_mib2 */ - struct gazelle_stat_lstack_snmp { - /* IP */ -@@ -328,6 +343,7 @@ struct gazelle_stack_dfx_data { - struct gazelle_stack_latency latency; - struct gazelle_stat_lstack_conn conn; - struct gazelle_stat_lstack_snmp snmp; -+ struct gazelle_stat_lstack_virtio virtio; - struct nic_eth_xstats nic_xstats; - struct nic_eth_features nic_features; - struct gazelle_stat_lstack_proto proto_data; -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 0f1f693..1e32c45 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -29,6 +29,7 @@ - #include "posix/lstack_epoll.h" - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" -+#include "lstack_virtio.h" - - #define US_PER_SEC 1000000 - -@@ -343,6 +344,13 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); - } - break; -+ case GAZELLE_STAT_LSTACK_SHOW_VIRTIO: -+ ret = memcpy_s(&dfx->data.virtio, sizeof(dfx->data.virtio), virtio_instance_get(), -+ sizeof(*(virtio_instance_get()))); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); -+ } -+ break; - case GAZELLE_STAT_LSTACK_SHOW_CONN: - rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, - GAZELLE_LSTACK_MAX_CONN); -diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h -index 615d9c9..5298dbe 100644 ---- a/src/lstack/include/lstack_virtio.h -+++ b/src/lstack/include/lstack_virtio.h -@@ -30,7 +30,7 @@ - ((mac_addrs)->addr_bytes[4]), \ - ((mac_addrs)->addr_bytes[5]) - #endif -- -+// When modifying virtio_instance, gazelle_stat_lstack_virtio also needs to be modified together. - struct virtio_instance { - uint16_t lstack_port_id; - uint16_t virtio_port_id; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 4351891..cdcd7b3 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -128,6 +128,7 @@ static void gazelle_print_ltran_start_latency(void *buf, const struct gazelle_st - static void gazelle_print_lstack_stat_total(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_rate(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_lstack_stat_virtio(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_lpm(void *buf, const struct gazelle_stat_msg_request *req_msg); -@@ -163,6 +164,7 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LSTACK_LOG_LEVEL_SET, 0, gazelle_print_ltran_wait}, - {GAZELLE_STAT_LSTACK_SHOW_RATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_rate}, - {GAZELLE_STAT_LSTACK_SHOW_SNMP, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_snmp}, -+ {GAZELLE_STAT_LSTACK_SHOW_VIRTIO, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_virtio}, - {GAZELLE_STAT_LSTACK_SHOW_CONN, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_conn}, - {GAZELLE_STAT_LSTACK_SHOW_LATENCY, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_latency}, - {GAZELLE_STAT_LSTACK_LOW_POWER_MDF, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_lpm}, -@@ -1169,6 +1171,24 @@ static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat - } while (true); - } - -+static void gazelle_print_lstack_stat_virtio(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct gazelle_stat_lstack_virtio *virtio = &stat->data.virtio; -+ printf("\nStatistics of lstack virtio:\n"); -+ -+ printf("\nlstack_port_id =%u virtio_port_id =%u rx_queue_num =%u tx_queue_num =%u \n", -+ virtio->lstack_port_id, virtio->virtio_port_id, virtio->rx_queue_num, -+ virtio->tx_queue_num); -+ -+ printf("\n%-8s %-8s %-8s %-8s %-8s\n", "queue_id", "rx_pkg", "rx_drop", "tx_pkg", "tx_drop"); -+ for (int i = 0; i < virtio->rx_queue_num; i++) { -+ printf("%-8d %-8lu %-8lu %-8lu %-8lu\n", i, -+ virtio->rx_pkg[i], virtio->rx_drop[i], virtio->tx_pkg[i], virtio->tx_drop[i]); -+ } -+ printf("\n"); -+} -+ - static void gazelle_keepalive_string(char* str, int buff_len, struct gazelle_stat_lstack_conn_info *conn_info) - { - if (conn_info->keepalive == 0) { -@@ -1298,6 +1318,7 @@ static void show_usage(void) - " show lstack all statistics \n" - " -r, rate show lstack statistics per second \n" - " -s, snmp show lstack snmp \n" -+ " -v, virtio show rx_pkg/rx_drop/tx_pkg/tx_drop num of virtio \n" - " -c, connect show lstack connect \n" - " -l, latency [time] show lstack latency \n" - " -x, xstats show lstack xstats \n" -@@ -1553,6 +1574,8 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; - } else if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_SNMP; -+ } else if (strcmp(param, "virtio") == 0 || strcmp(param, "-v") == 0) { -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_VIRTIO; - } else if (strcmp(param, "connect") == 0 || strcmp(param, "-c") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_CONN; - } else if (strcmp(param, "xstats") == 0 || strcmp(param, "-x") == 0) { --- -2.33.0 - diff --git a/0211-add-flow_bifurcation-switch-in-lstack_cfg-file.patch b/0211-add-flow_bifurcation-switch-in-lstack_cfg-file.patch deleted file mode 100644 index ecd2031..0000000 --- a/0211-add-flow_bifurcation-switch-in-lstack_cfg-file.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 4af8c587a4f5b861012cb2d1ca954af8e6872162 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Tue, 2 Jul 2024 15:26:48 +0800 -Subject: [PATCH] add flow_bifurcation switch in lstack_cfg file - ---- - src/lstack/lstack.conf | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index c65a25d..490bdfc 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -15,6 +15,7 @@ stack_thread_mode="run-to-wakeup" - #ltran mode need add "--map-perfect" and "--legacy-mem" in dpdk_args - use_ltran=0 - kni_switch=0 -+flow_bifurcation=0 - - low_power_mode=0 - --- -2.33.0 - diff --git a/0212-example-sync-example-update.patch b/0212-example-sync-example-update.patch deleted file mode 100644 index 28e4028..0000000 --- a/0212-example-sync-example-update.patch +++ /dev/null @@ -1,3751 +0,0 @@ -From f599cc99be29c47a7765e3fae602f3474b30926a Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Thu, 11 Jul 2024 10:30:31 +0800 -Subject: [PATCH] example: sync example update - ---- - build/build.sh | 8 + - examples/FAULT_INJECT.md | 33 ++ - examples/README.md | 79 +++- - examples/inc/bussiness.h | 16 +- - examples/inc/client.h | 44 +- - examples/inc/parameter.h | 80 +++- - examples/inc/server.h | 25 +- - examples/inc/utilities.h | 88 +++- - examples/main.c | 7 +- - examples/src/bussiness.c | 212 ++++++--- - examples/src/client.c | 562 ++++++++++++++++++------ - examples/src/parameter.c | 484 +++++++++++++++++--- - examples/src/server.c | 512 ++++++++++++++++----- - examples/src/utilities.c | 386 +++++++++++----- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 15 files changed, 2006 insertions(+), 532 deletions(-) - create mode 100644 examples/FAULT_INJECT.md - -diff --git a/build/build.sh b/build/build.sh -index 4464f8c..622e1cc 100755 ---- a/build/build.sh -+++ b/build/build.sh -@@ -31,3 +31,11 @@ if [ $? -ne 0 ]; then - fi - - cd - -+cd ../examples -+cmake . -+make -+if [ $? -ne 0 ]; then -+ echo "build examples failed" -+ exit 1 -+fi -+cd - -diff --git a/examples/FAULT_INJECT.md b/examples/FAULT_INJECT.md -new file mode 100644 -index 0000000..ff551a9 ---- /dev/null -+++ b/examples/FAULT_INJECT.md -@@ -0,0 +1,33 @@ -+# Gazelle 故障注入 说明 -+ -+## 需求 -+1. example:构造黑盒故障 -+ * 延迟类:accept|read: -+ * accept: 构造tcp_acceptmbox_full的情景. -+ * read: 构造tcp_refuse_count、recvmbox满 -+ * 跳过类:跳过 read/write并close: -+ * read: 构造链接关闭时时4次挥手的情景,验证TCP状态机。 -+2. gazelle/lwip: 构造白盒故障,支持注入故障报文、协议栈状态、事件设置、资源异常等 -+ * 编译宏支持 -+ * 提供接口:配置文件、env -+ * 故障报文注入: -+ * 类似内核tc工具: -+ * 内核TC工具qdisc指令原理:报文分组被添加到网卡队列(qdisc),该队列决定发包顺序。
-+ qdisc指令可以在队列层面实现延时、丢包、重复等故障。 -+ * dpdk性能检测工具testpmd可以模拟实现类似的故障模拟,testpmd与gazelle不兼容,需要参考其中调用的dpdk接口来改gazelle代码。
-+ * 延时故障 -+ * 丢包故障 -+ - 思路:调整网卡队列,随机丢弃百分比的包,然后发送。 -+ - 函数调用:rte_rand(),rte_eth_tx_burst()。 -+ * 包重复故障 -+ * 随机故障 -+ * 乱序故障 -+ * 协议栈状态故障 -+ * ... -+ * 事件设置 -+ * ... -+ * 资源异常 -+ * 资源耗尽,无法申请。 -+ * ... -+ -+ -diff --git a/examples/README.md b/examples/README.md -index 5a73ce0..77a0f85 100644 ---- a/examples/README.md -+++ b/examples/README.md -@@ -7,6 +7,7 @@ - * 支持多线程网络非对称模型,一个 listen 线程,若干个读写线程。listen 线程和读写线程使用 `poll` / `epoll` 监听事件。 - * 支持 `recvmsg` 、`sendmsg` 、`recv` 、`send` 、`recvfrom`、`sendto`、`getpeername` 、`getsockopt` 、`epoll_ctl` 等 posix 接口。 - * 网络通讯报文采用问答方式,丢包或者内容错误则报错并停止通讯。报文内容有变化,长度可配。 -+* 支持网络故障注入,延迟进行(delay)、跳过(skip)read、write、accept等逻辑。 - - ## 网络模型 - -@@ -103,15 +104,15 @@ - * `-a, --as [server | client]`:作为服务端还是客户端。 - * `server`:作为服务端。 - * `client`:作为客户端。 --* `-i, --ip [xxx.xxx.xxx.xxx]`:IP地址。 --* `-g, --groupip [xxx.xxx.xxx.xxx]`:UDP组播地址。 -+* `-i, --ip [xxx.xxx.xxx.xxx]`:server端IP地址。当v4与v6地址同时存在时,以","分隔。例如:`-i 192.168.1.88,aa22:bb11:1122:cdef:1234:aa99:7654:7410` -+* `-g, --groupip [xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx]`:配置UDP组播地址与interface地址,以','分隔,其中interface地址为可选项。例如:`-g 224.0.0.24,192.168.1.202`或`-g 224.0.0.24` - * `-p, --port [xxxx]`:端口。 - * `-m, --model [mum | mud]`:采用的网络模型类型。 - * `mum (multi thread, unblock, multiplexing IO)`:多线程非阻塞IO复用。 - * `mud (multi thread, unblock, dissymmetric)`:多线程非阻塞非对称。 - * `-t, --threadnum`:线程数设置。 - * `-c, --connectnum`:连接数设置。当 `domain` 设置为 `udp` 时,`connectnum` 会被设置为1。 --* `-D, --domain [unix | tcp | udp]`:通信协议。 -+* `-D, --domain [unix | tcp | udp]`:通信协议。当支持多个通信协议时以","分隔。例如:`-D tcp,udp` - * `unix`:基于 unix 协议实现。 - * `tcp`:基于 tcp 协议实现。 - * `udp`:基于 udp 协议实现。 -@@ -132,6 +133,19 @@ - * `-C, --accept`:accept的方式。 - * `ac`:使用accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)通过套接口接受连接。 - * `ac4`:使用accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags)通过套接口接受连接,flags=SOCK_CLOEXEC。 -+* `-k, --keep_alive`:配置TCP keep_alive idle , keep_alive interval时间(second)。 -+* `-I, --inject`: 配置故障注入类型。 -+ * `delay`: -+ * `"delay 20 before_accept"`: 延迟20秒进行accept,时间可自定义,需大于0。可用于构造tcp_acceptmbox_full的情景 -+ * `"delay 20 before_read"`: 延迟20秒进行read,时间可自定义,需大于0。 -+ * `"delay 20 before_write"`: 延迟20秒进行write,时间可自定义,需大于0。 -+ * `"delay 20 before_read_and_write"`: 延迟20秒进行read和write,时间可自定义,需大于0。 -+ * `skip`: -+ * `"skip write"`: 跳过写过程,并关闭链接。 -+ * `"skip read"`: 跳过读过程,并关闭链接。 -+ * `"skip read_and_write"`: 跳过读写写过程,并关闭链接。 -+ -+ - ## 使用 - - * **环境配置** -@@ -235,12 +249,12 @@ make - * 创建udp组播服务端 - - ``` --./example -A server -D udp -i 192.168.0.1 -g 225.0.0.1 -A recvfromsendto -+./example -A server -D udp -g 225.0.0.1,192.168.0.1 -A recvfromsendto - - [program parameters]: - --> [as]: server ----> [server ip]: 192.168.0.1 - --> [server group ip]: 225.0.0.1 -+--> [server groupip_interface]: 192.168.0.1 - --> [server port]: 5050 - --> [model]: mum - --> [thread number]: 1 -@@ -260,12 +274,12 @@ make - * 创建udp组播客户端 - - ``` --./example -A client -D udp -i 192.168.0.1 -g 225.0.0.1 -A recvfromsendto -+./example -A client -D udp -g 225.0.0.1,192.168.0.1 -A recvfromsendto - - [program parameters]: ----> [as]: server ----> [server ip]: 225.0.0.1 ----> [client send ip]: 192.168.0.1 -+--> [as]: client -+--> [client group ip]: 225.0.0.1 -+--> [client groupip_interface]: 192.168.0.1 - --> [server port]: 5050 - --> [thread number]: 1 - --> [connection number]: 1 -@@ -280,3 +294,50 @@ make - [program informations]: - --> : [connect num]: 0, [send]: 0.000 B/s - ``` -+ -+* 混杂模式下server 与 client 配置 -+``` -+./example -a server -D tcp,udp -i 192.168.1.88 -p 33333 -g 224.0.0.24,192.168.1.188 -+[program parameters]: -+--> [as]: server -+--> [server group ip]: 224.0.0.24 -+--> [server groupip_interface]: 192.168.1.188 -+--> [server ip]: 192.168.1.888 -+--> [server port]: 33333 -+--> [model]: mum -+--> [thread number]: 1 -+--> [domain]: tcp,udp -+--> [api]: read & write -+--> [packet length]: 1024 -+--> [verify]: off -+--> [ringpmd]: off -+--> [debug]: off -+--> [epoll create]: ec -+--> [accept]: ac -+--> [inject]: none -+ -+[program informations]: -+``` -+``` -+./example -a client -D tcp,udp -i 192.168.1.188 -p 33333 -g 192.168.1.202,224.0.0.24 -+[program parameters]: -+--> [as]: client -+--> [client group ip]: 224.0.0.24 -+--> [client groupip_interface]: 192.168.1.202 -+--> [server ip]: 192.168.1.188 -+--> [server port]: 33333 -+--> [thread number]: 1 -+--> [connection number]: 1 -+--> [domain]: tcp,udp -+--> [api]: read & write -+--> [packet length]: 1024 -+--> [verify]: off -+--> [ringpmd]: off -+--> [debug]: off -+--> [epoll create]: ec -+--> [accept]: ac -+--> [inject]: none -+ -+[program informations]: -+ -+``` -\ No newline at end of file -diff --git a/examples/inc/bussiness.h b/examples/inc/bussiness.h -index 83645ef..3a78b1f 100644 ---- a/examples/inc/bussiness.h -+++ b/examples/inc/bussiness.h -@@ -28,7 +28,9 @@ - */ - struct ServerHandler - { -+ int32_t listen_fd_array[PROTOCOL_MODE_MAX]; - int32_t fd; ///< socket file descriptor -+ int32_t is_v6; - }; - - /** -@@ -39,6 +41,7 @@ struct ClientHandler - { - int32_t fd; ///< socket file descriptor - uint32_t msg_idx; ///< the start charactors index of message -+ int32_t sendtime_interverl; ///< udp send packet interverl - }; - - -@@ -90,24 +93,21 @@ int32_t client_bussiness(char *out, const char *in, uint32_t size, bool verify, - /** - * @brief server checks the information and answers - * This function checks the information and answers. -- * @param server_handler server handler -+ * @param fd socket_fd - * @param pktlen the length of package - * @param api the api - * @return the result - */ --int32_t server_ans(struct ServerHandler *server_handler, uint32_t pktlen, const char* api, const char* domain); -+int32_t server_ans(int32_t fd, uint32_t pktlen, const char* api, const char* domain); - - /** - * @brief client asks server - * This function asks server. - * @param client_handler client handler -- * @param pktlen the length of package -- * @param api the api -- * @param domain the domain -+ * @param client_unit ClientUnit - * @return the result - */ --int32_t client_ask(struct ClientHandler *client_handler, uint32_t pktlen, const char* api, const char* domain, in_addr_t ip, uint16_t port); -- -+int32_t client_ask(struct ClientHandler *client_handler, struct ClientUnit *client_unit); - /** - * @brief client checks the information and answers - * This function checks the information and answers. -@@ -119,7 +119,7 @@ int32_t client_ask(struct ClientHandler *client_handler, uint32_t pktlen, const - * @param ip the ip address of peer, maybe group ip - * @return the result - */ --int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, bool verify, const char* api, const char* domain, in_addr_t ip); -+int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, bool verify, const char* api, const char* domain, ip_addr_t* ip); - - - #endif // __EXAMPLES_BUSSINESS_H__ -diff --git a/examples/inc/client.h b/examples/inc/client.h -index 97af33f..0fe07aa 100644 ---- a/examples/inc/client.h -+++ b/examples/inc/client.h -@@ -19,31 +19,8 @@ - #include "parameter.h" - #include "bussiness.h" - -- --/** -- * @brief client unit -- * The information of each thread of client. -- */ --struct ClientUnit --{ -- struct ClientHandler *handlers; ///< the handlers -- int32_t epfd; ///< the connect epoll file descriptor -- struct epoll_event *epevs; ///< the epoll events -- uint32_t curr_connect; ///< current connection number -- uint64_t send_bytes; ///< total send bytes -- in_addr_t ip; ///< server ip -- in_addr_t groupip; ///< server groupip -- uint16_t port; ///< server port -- uint16_t sport; ///< client sport -- uint32_t connect_num; ///< total connection number -- uint32_t pktlen; ///< the length of peckage -- bool verify; ///< if we verify or not -- char* domain; ///< the communication domain -- char* api; ///< the type of api -- bool debug; ///< if we print the debug information -- char* epollcreate; ///< epoll_create method -- struct ClientUnit *next; ///< next pointer --}; -+#define TIME_SCAN_INTERVAL 1 -+#define TIME_SEND_INTERVAL 1 - - /** - * @brief client -@@ -53,8 +30,14 @@ struct Client - { - struct ClientUnit *uints; ///< the server mum unit - bool debug; ///< if we print the debug information -+ uint32_t threadNum; -+ bool loop; ///< judge client info print while loop is open - }; - -+struct Client_domain_ip { -+ char *domain; -+ uint8_t ip_family; -+}; - - /** - * @brief the single thread, client prints informations -@@ -66,7 +49,7 @@ struct Client - * @param debug if debug or not - * @return the result pointer - */ --void client_debug_print(const char *ch_str, const char *act_str, in_addr_t ip, uint16_t port, bool debug); -+void client_debug_print(const char *ch_str, const char *act_str, ip_addr_t *ip, uint16_t port, bool debug); - - /** - * @brief the client prints informations -@@ -86,7 +69,7 @@ void client_info_print(struct Client *client); - * @param domain domain - * @return the result pointer - */ --int32_t client_thread_try_connect(struct ClientHandler *client_handler, int32_t epoll_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, uint16_t sport, const char *domain, const char *api); -+int32_t client_thread_try_connect(struct ClientHandler *client_handler, struct ClientUnit *client_unit); - - /** - * @brief the single thread, client retry to connect to server, register to epoll -@@ -122,4 +105,11 @@ void *client_s_create_and_run(void *arg); - int32_t client_create_and_run(struct ProgramParams *params); - - -+/** -+ * @brief loop server info -+ * This function print loop mode server info. -+ */ -+void loop_info_print(); -+ -+ - #endif // __EXAMPLES_CLIENT_H__ -diff --git a/examples/inc/parameter.h b/examples/inc/parameter.h -index 93e3672..ff2f114 100644 ---- a/examples/inc/parameter.h -+++ b/examples/inc/parameter.h -@@ -20,6 +20,8 @@ - - #define PARAM_DEFAULT_AS ("server") ///< default type - #define PARAM_DEFAULT_IP ("127.0.0.1") ///< default IP -+#define PARAM_DEFAULT_IP_V6 ("0.0.0.0.0.0.0.0") ///< default IP -+#define PARAM_DEFAULT_ADDR_FAMILY (AF_INET) ///< default address family - #define PARAM_DEFAULT_PORT (5050) ///< default port - #define PARAM_DEFAULT_SPORT (0) ///< default sport - #define PARAM_DEFAULT_MODEL ("mum") ///< default model type -@@ -34,6 +36,9 @@ - #define PARAM_DEFAULT_EPOLLCREATE ("ec") ///< default method of epoll_create - #define PARAM_DEFAULT_ACCEPT ("ac") ///< default method of accept method - #define PARAM_DEFAULT_GROUPIP ("0.0.0.0") ///< default group IP> -+#define PARAM_DEFAULT_KEEPALIVEIDLE (0) ///< default TCP_KEEPALIVE_IDLE_TIME> -+ -+#define TCP_KEEPALIVE_IDLE_MAX (3600) // time: second - - - enum { -@@ -43,7 +48,7 @@ enum { - PARAM_NUM_IP = 'i', - #define PARAM_NAME_PORT ("port") ///< name of parameter port - PARAM_NUM_PORT = 'p', --#define PARAM_NAME_SPORT ("sport") ///< name of parameter sport -+#define PARAM_NAME_SPORT ("sport") ///< name of parameter sport - PARAM_NUM_SPORT = 's', - #define PARAM_NAME_MODEL ("model") ///< name of parameter model type - PARAM_NUM_MODEL = 'm', -@@ -71,12 +76,27 @@ enum { - PARAM_NUM_ACCEPT = 'C', - #define PARAM_NAME_GROUPIP ("groupip") ///< name of parameter group ip - PARAM_NUM_GROUPIP = 'g', -+#define PARAM_NAME_KEEPALIVE ("keep_alive") ///< name of parameter keep_alive -+ PARAM_NUM_KEEPALIVE = 'k', -+#define PARAM_NAME_INJECT ("inject") ///< name of parameter fault inject -+ PARAM_NUM_INJECT = 'I', - }; - - #define NO_ARGUMENT 0 ///< options takes no arguments - #define REQUIRED_ARGUMETN 1 ///< options requires arguments - #define OPTIONAL_ARGUMETN 2 ///< options arguments are optional - -+uint8_t getbit_num(uint8_t mode, uint8_t index); -+uint8_t setbitnum_on(uint8_t mode, uint8_t index); -+uint8_t setbitnum_off(uint8_t mode, uint8_t index); -+ -+uint8_t program_get_protocol_mode_by_domain_ip(char* domain, char* ipv4, char* ipv6, char* group_ip); -+ -+struct ServerBaseCfgInfo { -+ const char *domain; -+ const char *api; -+ uint32_t pktlen; -+}; - - /** - * @brief program option description -@@ -96,12 +116,13 @@ struct ProgramOption { - struct ProgramParams { - char* as; ///< as server or client - char* ip; ///< IP address -- uint32_t port; ///< port -- uint32_t sport; ///< sport -+ char* ipv6; -+ bool port[UNIX_TCP_PORT_MAX]; ///< index:port list; value:port is set or not -+ bool sport[UNIX_TCP_PORT_MAX]; ///< index:sport list; value:sport is set or not - char* model; ///< model type - uint32_t thread_num; ///< the number of threads - uint32_t connect_num; ///< the connection number -- char* domain; ///< the communication dimain -+ char* domain; ///< the communication domain - char* api; ///< the type of api - uint32_t pktlen; ///< the packet length - bool verify; ///< if we verify the message or not -@@ -110,8 +131,58 @@ struct ProgramParams { - char* accept; ///< accept connections method - bool ringpmd; ///< if we use ring PMD or not - char* groupip; ///< group IP address> -+ char* groupip_interface; ///< udp multicast interface address> -+ uint32_t addr_family; ///< IP address family -+ int32_t tcp_keepalive_idle; ///< tcp keepalive idle time -+ int32_t tcp_keepalive_interval; ///< tcp keepalive interval time -+#define INJECT_TYPE_IDX (0) ///< the index of inject type -+#define INJECT_TIME_IDX (1) ///< the index of delay time -+#define INJECT_SKIP_IDX (1) ///< the index of skip location -+#define INJECT_LOCATION_IDX (2) ///< the index of delay location -+#define FAULT_INJECT_PARA_COUNT (3) ///< the count of fault injection parameters -+ char* inject[FAULT_INJECT_PARA_COUNT]; /// < fault inject - }; - -+typedef enum { -+ INJECT_DELAY_ACCEPT = 0, -+ INJECT_DELAY_READ, -+ INJECT_DELAY_WRITE, -+ INJECT_DELAY_MAX, -+}delay_type; -+ -+typedef enum { -+ INJECT_SKIP_READ = 0, -+ INJECT_SKIP_WRITE, -+ INJECT_SKIP_MAX, -+} skip_type; -+ -+typedef enum { -+ V4_TCP, -+ V6_TCP, -+ V4_UDP, -+ V6_UDP, -+ UDP_MULTICAST, -+ UNIX, -+ PROTOCOL_MODE_MAX -+} PROTOCOL_MODE_ENUM_TYPE; -+ -+#define FAULT_INJECT_SKIP_BEGIN(skip_type) \ -+ if (get_g_inject_skip((skip_type))) {} \ -+ else { -+#define FAULT_INJECT_SKIP_END } -+ -+/** -+ * @brief return g_inject_skip value -+ * This function return g_inject_skip value to deside if excute skip -+ */ -+int32_t get_g_inject_skip(skip_type type); -+ -+/** -+ * @brief function execute delay inject -+ * This function delay execute following program. -+ */ -+void fault_inject_delay(delay_type type); -+ - /** - * @brief initialize the parameters - * This function initializes the parameters of main function. -@@ -142,5 +213,6 @@ int32_t program_params_parse(struct ProgramParams *params, uint32_t argc, char * - */ - void program_params_print(struct ProgramParams *params); - -+bool ip_is_v6(const char *ip); - - #endif // __EXAMPLES_PARAMETER_H__ -diff --git a/examples/inc/server.h b/examples/inc/server.h -index a3affef..4631a28 100644 ---- a/examples/inc/server.h -+++ b/examples/inc/server.h -@@ -31,8 +31,7 @@ struct ServerMumUnit - struct epoll_event *epevs; ///< the epoll events - uint32_t curr_connect; ///< current connection number - uint64_t recv_bytes; ///< total receive bytes -- in_addr_t ip; ///< server ip -- in_addr_t groupip; ///< server group ip -+ struct ServerIpInfo server_ip_info; - uint16_t port; ///< server port - uint32_t pktlen; ///< the length of peckage - char* domain; ///< communication domain -@@ -40,6 +39,9 @@ struct ServerMumUnit - bool debug; ///< if we print the debug information - char* epollcreate; ///< epoll_create method - char* accept; ///< accept connections method -+ int32_t tcp_keepalive_idle; ///< tcp keepalive idle time -+ int32_t tcp_keepalive_interval; ///< tcp keepalive interval time -+ uint8_t protocol_type_mode; ///< tcp/udp ipv4/ipv6 protocol mode - struct ServerMumUnit *next; ///< next pointer - }; - -@@ -64,11 +66,13 @@ struct ServerMudWorker - struct epoll_event *epevs; ///< the epoll events - uint64_t recv_bytes; ///< total receive bytes - uint32_t pktlen; ///< the length of peckage -- in_addr_t ip; ///< client ip -+ ip_addr_t ip; ///< client ip - uint16_t port; ///< client port - char* api; ///< the type of api - bool debug; ///< if we print the debug information - char* epollcreate; ///< epoll_create method -+ char* domain; -+ uint32_t curr_connect; - struct ServerMudWorker *next; ///< next pointer - }; - -@@ -82,16 +86,17 @@ struct ServerMud - struct ServerMudWorker *workers; ///< the workers - int32_t epfd; ///< the listen epoll file descriptor - struct epoll_event *epevs; ///< the epoll events -- uint32_t curr_connect; ///< current connection number -- in_addr_t ip; ///< server ip -- in_addr_t groupip; ///< server group ip -- uint16_t port; ///< server port -+ struct ServerIpInfo server_ip_info; -+ bool* port; ///< server port point to parameter's port - uint32_t pktlen; ///< the length of peckage - char* domain; ///< communication domain - char* api; ///< the type of api - bool debug; ///< if we print the debug information - char* accept; ///< accept connections method - char* epollcreate; ///< epoll_create method -+ int32_t tcp_keepalive_idle; ///< tcp keepalive idle time -+ int32_t tcp_keepalive_interval; ///< tcp keepalive interval time -+ uint8_t protocol_type_mode; ///< tcp/udp ipv4/ipv6 protocol mode - }; - - -@@ -105,7 +110,7 @@ struct ServerMud - * @param debug if debug or not - * @return the result pointer - */ --void server_debug_print(const char *ch_str, const char *act_str, in_addr_t ip, uint16_t port, bool debug); -+void server_debug_print(const char *ch_str, const char *act_str, ip_addr_t *ip, uint16_t port, bool debug); - - /** - * @brief the multi thread, unblock, dissymmetric server prints informations -@@ -136,7 +141,7 @@ int32_t sermud_listener_create_epfd_and_reg(struct ServerMud *server_mud); - * @param server_mud the server unit - * @return the result pointer - */ --int32_t sermud_listener_accept_connects(struct ServerMud *server_mud); -+int32_t sermud_listener_accept_connects(struct epoll_event *curr_epev, struct ServerMud *server_mud); - - /** - * @brief the worker thread, unblock, dissymmetric server processes the events -@@ -200,7 +205,7 @@ int32_t sersum_create_epfd_and_reg(struct ServerMumUnit *server_unit); - * @param server_handler the server handler - * @return the result pointer - */ --int32_t sersum_accept_connects(struct ServerMumUnit *server_unit, struct ServerHandler *server_handler); -+int32_t sersum_accept_connects(struct epoll_event *cur_epev, struct ServerMumUnit *server_unit); - - /** - * @brief the single thread, unblock, mutliplexing IO server processes the events -diff --git a/examples/inc/utilities.h b/examples/inc/utilities.h -index 0f9db4e..262481a 100644 ---- a/examples/inc/utilities.h -+++ b/examples/inc/utilities.h -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -36,6 +37,7 @@ - #include - - #include -+#include - #include - - #include "securec.h" -@@ -47,7 +49,7 @@ - { \ - printf("\n[error]: "); \ - printf(format, ##__VA_ARGS__); \ -- printf("\n"); \ -+ printf("\n\n"); \ - } while (0) - #define PRINT_WARNNING(format, ...) do \ - { \ -@@ -76,7 +78,7 @@ - } while(0) - #define PRINT_CLIENT_DATAFLOW(format, ...) do \ - { \ -- printf("\033[?25l\033[A\033[K"); \ -+ printf(" "); \ - printf("--> : "); \ - printf(format, ##__VA_ARGS__); \ - printf("\033[?25h\n"); \ -@@ -90,24 +92,94 @@ - #define PROGRAM_INPROGRESS (-2) ///< program in progress flag - - #define UNIX_TCP_PORT_MIN (1024) ///< TCP minimum port number in unix --#define UNIX_TCP_PORT_MAX (65535) ///< TCP minimum port number in unix -+#define UNIX_TCP_PORT_MAX (65535) ///< TCP maximum port number in unix - #define THREAD_NUM_MIN (1) ///< minimum number of thead - #define THREAD_NUM_MAX (1000) ///< maximum number of thead - #define MESSAGE_PKTLEN_MIN (2) ///< minimum length of message (1 byte) - #define MESSAGE_PKTLEN_MAX (1024 * 1024 * 10) ///< maximum length of message (10 Mb) -+#define UDP_PKTLEN_MAX (65507) ///< maximum length of udp message - --#define SERVER_SOCKET_LISTEN_BACKLOG (128) ///< the queue of socket -+#define SERVER_SOCKET_LISTEN_BACKLOG (4096) ///< the queue of socket - #define SERVER_EPOLL_SIZE_MAX (10000) ///< the max wait event of epoll - #define SERVER_EPOLL_WAIT_TIMEOUT (-1) ///< the timeout value of epoll - - #define CLIENT_EPOLL_SIZE_MAX (10000) ///< the max wait event of epoll - #define CLIENT_EPOLL_WAIT_TIMEOUT (-1) ///< the timeout value of epoll - --#define TERMINAL_REFRESH_MS (100) ///< the time cut off between of terminal refresh -+#define TERMINAL_REFRESH_MS (500) ///< the time cut off between of terminal refresh - - #define SOCKET_UNIX_DOMAIN_FILE "unix_domain_file" ///< socket unix domain file - -+#define IPV4_STR "V4" -+#define IPV6_STR "V6" -+#define IPV4_MULTICAST "Multicast" -+#define INVAILD_STR "STR_NULL" -+ -+#define TIMES_CONVERSION_RATE (1000) -+#define KB (1024) -+#define MB (KB * KB) -+#define GB (MB * MB) -+ -+struct ThreadUintInfo { -+ uint64_t send_bytes; ///< total send bytes -+ uint32_t cur_connect_num; ///< total connection number -+ char* domain; -+ char* ip_type_info; -+ pthread_t thread_id; -+}; -+ -+typedef struct ip_addr { -+ struct { -+ struct in_addr ip4; -+ struct in6_addr ip6; -+ } u_addr; -+ uint32_t addr_family; -+} ip_addr_t; -+ -+typedef union sockaddr_union { -+ struct sockaddr sa; -+ struct sockaddr_in in; -+ struct sockaddr_in6 in6; -+} sockaddr_t; - -+/** -+ * @brief client unit -+ * The information of each thread of client. -+ */ -+struct ClientUnit { -+ struct ClientHandler *handlers; ///< the handlers -+ int32_t epfd; ///< the connect epoll file descriptor -+ struct epoll_event *epevs; ///< the epoll events -+ uint32_t curr_connect; ///< current connection number -+ ip_addr_t ip; ///< server ip -+ ip_addr_t groupip; ///< server groupip -+ uint32_t port; ///< server port -+ ip_addr_t groupip_interface; ///< udp multicast interface address> -+ uint32_t sport; ///< client sport -+ uint32_t connect_num; ///< total connection number -+ uint32_t pktlen; ///< the length of peckage -+ uint32_t loop; ///< the packet send to loop -+ bool verify; ///< if we verify or not -+ char* domain; ///< the communication domain -+ char* api; ///< the type of api -+ bool debug; ///< if we print the debug information -+ char* epollcreate; ///< epoll_create method -+ uint8_t protocol_type_mode; ///< tcp/udp ipv4/ipv6 protocol mode -+ struct ThreadUintInfo threadVolume; -+ struct ClientUnit *next; ///< next pointer -+}; -+struct ServerIpInfo { -+ ip_addr_t ip; ///< server ip -+ ip_addr_t groupip; ///< server group ip -+ ip_addr_t groupip_interface; ///< server group interface ip -+}; -+ -+struct LoopInfo { -+ char* model; -+ struct ServerMud *server_mud_info; -+ struct ServerMum *server_mum_info; -+}; -+extern struct LoopInfo loopmod; - /** - * @brief create the socket and listen - * Thi function creates the socket and listen. -@@ -118,7 +190,8 @@ - * @param domain domain - * @return the result - */ --int32_t create_socket_and_listen(int32_t *socket_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, const char *domain); -+int32_t create_socket_and_listen(int32_t *listen_fd_array, struct ServerIpInfo *server_ip_info, uint16_t port, -+ uint8_t protocol_mode); - - /** - * @brief create the socket and connect -@@ -131,7 +204,7 @@ int32_t create_socket_and_listen(int32_t *socket_fd, in_addr_t ip, in_addr_t gro - * @param api api - * @return the result - */ --int32_t create_socket_and_connect(int32_t *socket_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, uint16_t sport, const char *domain, const char *api); -+int32_t create_socket_and_connect(int32_t *socket_fd, struct ClientUnit *client_unit); - - /** - * @brief set the socket to unblock -@@ -140,6 +213,7 @@ int32_t create_socket_and_connect(int32_t *socket_fd, in_addr_t ip, in_addr_t gr - * @return the result - */ - int32_t set_socket_unblock(int32_t socket_fd); -+int32_t set_tcp_keep_alive_info(int32_t sockfd, int32_t tcp_keepalive_idle, int32_t tcp_keepalive_interval); - - - #endif // __EXAMPLES_UTILITIES_H__ -diff --git a/examples/main.c b/examples/main.c -index 5338572..dfee2db 100644 ---- a/examples/main.c -+++ b/examples/main.c -@@ -31,7 +31,12 @@ int32_t main(int argc, char *argv[]) - - if (strcmp(prog_params.as, "server") == 0) { - server_create_and_run(&prog_params); -- } else { -+ } else if (strcmp(prog_params.as, "client") == 0) { -+ client_create_and_run(&prog_params); -+ } else if (strcmp(prog_params.as, "loop") == 0) { -+ server_create_and_run(&prog_params); -+ /* sleep to wait server creating */ -+ sleep(1); - client_create_and_run(&prog_params); - } - -diff --git a/examples/src/bussiness.c b/examples/src/bussiness.c -index 7263371..46c99fe 100644 ---- a/examples/src/bussiness.c -+++ b/examples/src/bussiness.c -@@ -11,8 +11,9 @@ - */ - - --#include "bussiness.h" -+#include "parameter.h" - #include "client.h" -+#include "bussiness.h" - - - static const char bussiness_messages_low[] = "abcdefghijklmnopqrstuvwxyz"; // the lower charactors of business message -@@ -135,41 +136,41 @@ int32_t client_bussiness(char *out, const char *in, uint32_t size, bool verify, - return PROGRAM_OK; - } - --// server answers --int32_t server_ans(struct ServerHandler *server_handler, uint32_t pktlen, const char* api, const char* domain) -+static void server_ans_free_buff(char *buff_in, char *buff_out) - { -- const uint32_t length = pktlen; -- char *buffer_in = (char *)malloc(length * sizeof(char)); -- char *buffer_out = (char *)malloc(length * sizeof(char)); -+ if (buff_in) { -+ free(buff_in); -+ } -+ if (buff_out) { -+ free(buff_out); -+ } -+} -+ -+// server_ans_read -+static int32_t server_ans_read(int32_t socket_fd, struct ServerBaseCfgInfo *server_base_info, char *buffer_in, -+ struct sockaddr *client_addr) -+{ -+ const uint32_t length = server_base_info->pktlen; -+ const char *api = server_base_info->api; -+ const char *domain = server_base_info->domain; - - int32_t cread = 0; - int32_t sread = length; - int32_t nread = 0; -- struct sockaddr_in client_addr; -- socklen_t len = sizeof(client_addr); - -- if (strcmp(domain, "udp") == 0 && strncmp(api, "recvfrom", strlen("recvfrom")) != 0) { -- if (getpeername(server_handler->fd, (struct sockaddr *)&client_addr, &len) < 0) { -- if (recvfrom(server_handler->fd, buffer_in, length, MSG_PEEK, (struct sockaddr *)&client_addr, &len) < 0) { -- return PROGRAM_FAULT; -- } -- if (connect(server_handler->fd, (struct sockaddr *)&client_addr, sizeof(struct sockaddr_in)) < 0) { -- return PROGRAM_FAULT; -- } -- } -- } -+ socklen_t len = sizeof(sockaddr_t); - - while (cread < sread) { - if (strcmp(domain, "udp") == 0 && strcmp(api, "recvfromsendto") == 0) { -- nread = recvfrom(server_handler->fd, buffer_in, length, 0, (struct sockaddr *)&client_addr, &len); -+ nread = recvfrom(socket_fd, buffer_in, length, 0, client_addr, &len); - } else { -- nread = read_api(server_handler->fd, buffer_in, length, api); -+ nread = read_api(socket_fd, buffer_in, length, api); - } -- - if (nread == 0) { - return PROGRAM_ABORT; - } else if (nread < 0) { - if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) { -+ PRINT_ERROR("nread =%d, errno=%d", nread, errno); - return PROGRAM_FAULT; - } - } else { -@@ -177,66 +178,152 @@ int32_t server_ans(struct ServerHandler *server_handler, uint32_t pktlen, const - continue; - } - } -+ return PROGRAM_OK; -+} - -- if (strcmp(api, "recvfrom") == 0) { -- free(buffer_in); -- free(buffer_out); -- return PROGRAM_OK; -- } -- -- server_bussiness(buffer_out, buffer_in, length); -+static int32_t server_ans_write(int32_t socket_fd, struct ServerBaseCfgInfo *server_base_info, char *buffer_out, -+ struct sockaddr *client_addr) -+{ -+ const uint32_t length = server_base_info->pktlen; -+ const char *api = server_base_info->api; -+ const char *domain = server_base_info->domain; - - int32_t cwrite = 0; - int32_t swrite = length; - int32_t nwrite = 0; -+ socklen_t len = sizeof(sockaddr_t); -+ - while (cwrite < swrite) { - if (strcmp(domain, "udp") == 0 && strcmp(api, "recvfromsendto") == 0) { -- nwrite = sendto(server_handler->fd, buffer_out, length, 0, (struct sockaddr *)&client_addr, len); -+ nwrite = sendto(socket_fd, buffer_out, swrite - cwrite, 0, client_addr, len); - } else { -- nwrite = write_api(server_handler->fd, buffer_out, length, api); -+ nwrite = write_api(socket_fd, buffer_out, swrite - cwrite, api); - } - - if (nwrite == 0) { - return PROGRAM_ABORT; - } else if (nwrite < 0) { -- if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) { -+ if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN) { -+ PRINT_ERROR("nwrite =%d, errno=%d", nwrite, errno); - return PROGRAM_FAULT; -- } -+ } - } else { - cwrite += nwrite; - continue; - } - } -+ return PROGRAM_OK; -+} - -- free(buffer_in); -- free(buffer_out); -+// server answers -+int32_t server_ans(int32_t fd, uint32_t pktlen, const char* api, const char* domain) -+{ -+ const uint32_t length = pktlen; -+ char *buffer_in = (char *)calloc(length, sizeof(char)); -+ char *buffer_out = (char *)calloc(length, sizeof(char)); -+ if (buffer_in == NULL || buffer_out == NULL) { -+ return PROGRAM_FAULT; -+ } -+ -+ struct ServerBaseCfgInfo server_base_info; -+ server_base_info.domain = domain; -+ server_base_info.api = api; -+ server_base_info.pktlen = pktlen; -+ -+ sockaddr_t client_addr; -+ socklen_t len = sizeof(sockaddr_t); -+ -+ if (strcmp(domain, "udp") == 0 && strncmp(api, "recvfrom", strlen("recvfrom")) != 0) { -+ if (getpeername(fd, (struct sockaddr *)&client_addr, &len) < 0) { -+ if (recvfrom(fd, buffer_in, length, MSG_PEEK, (struct sockaddr *)&client_addr, &len) < 0) { -+ server_ans_free_buff(buffer_in, buffer_out); -+ return PROGRAM_FAULT; -+ } -+ if (connect(fd, (struct sockaddr *)&client_addr, len) < 0) { -+ server_ans_free_buff(buffer_in, buffer_out); -+ return PROGRAM_FAULT; -+ } -+ } -+ } -+ -+ fault_inject_delay(INJECT_DELAY_READ); -+ FAULT_INJECT_SKIP_BEGIN(INJECT_SKIP_READ) -+ -+ if (server_ans_read(fd, &server_base_info, buffer_in, (struct sockaddr *)&client_addr) != PROGRAM_OK) { -+ server_ans_free_buff(buffer_in, buffer_out); -+ return PROGRAM_FAULT; -+ } -+ -+ FAULT_INJECT_SKIP_END -+ -+ if (strcmp(api, "recvfrom") == 0) { -+ server_ans_free_buff(buffer_in, buffer_out); -+ return PROGRAM_OK; -+ } -+ -+ server_bussiness(buffer_out, buffer_in, length); -+ -+ fault_inject_delay(INJECT_DELAY_WRITE); -+ FAULT_INJECT_SKIP_BEGIN(INJECT_SKIP_WRITE) -+ -+ if (server_ans_write(fd, &server_base_info, buffer_out, (struct sockaddr *)&client_addr) != PROGRAM_OK) { -+ server_ans_free_buff(buffer_in, buffer_out); -+ return PROGRAM_FAULT; -+ } -+ -+ FAULT_INJECT_SKIP_END -+ -+ server_ans_free_buff(buffer_in, buffer_out); - - return PROGRAM_OK; - } - - // client asks --int32_t client_ask(struct ClientHandler *client_handler, uint32_t pktlen, const char* api, const char* domain, in_addr_t ip, uint16_t port) -+int32_t client_ask(struct ClientHandler *client_handler, struct ClientUnit *client_unit) - { -- const uint32_t length = pktlen; -- char *buffer_in = (char *)malloc(length * sizeof(char)); -- char *buffer_out = (char *)malloc(length * sizeof(char)); -- struct sockaddr_in server_addr; -- socklen_t len = sizeof(server_addr); -- memset_s(&server_addr, sizeof(server_addr), 0, sizeof(server_addr)); -- server_addr.sin_family = AF_INET; -- server_addr.sin_addr.s_addr = ip; -- server_addr.sin_port = port; -+ const char *api = client_unit->api; -+ const char *domain = client_unit->domain; -+ -+ ip_addr_t *ip = client_unit->protocol_type_mode == UDP_MULTICAST ? &client_unit->groupip : &client_unit->ip; -+ uint16_t port = client_unit->port; -+ -+ const uint32_t length = client_unit->pktlen; -+ char *buffer_in = (char *)calloc(length, sizeof(char)); -+ char *buffer_out = (char *)calloc(length, sizeof(char)); -+ if (buffer_in == NULL || buffer_out == NULL) { -+ return PROGRAM_FAULT; -+ } -+ sockaddr_t server_addr; -+ socklen_t len = 0; -+ -+ if (ip->addr_family == AF_INET6) { -+ memset_s(&server_addr, sizeof(struct sockaddr_in6), 0, sizeof(struct sockaddr_in6)); -+ ((struct sockaddr_in6 *)&server_addr)->sin6_family = AF_INET6; -+ ((struct sockaddr_in6 *)&server_addr)->sin6_addr = ip->u_addr.ip6; -+ ((struct sockaddr_in6 *)&server_addr)->sin6_port = port; -+ len = sizeof(struct sockaddr_in6); -+ } else if (ip->addr_family == AF_INET) { -+ memset_s(&server_addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)); -+ ((struct sockaddr_in *)&server_addr)->sin_family = AF_INET; -+ ((struct sockaddr_in *)&server_addr)->sin_addr = ip->u_addr.ip4; -+ ((struct sockaddr_in *)&server_addr)->sin_port = port; -+ len = sizeof(struct sockaddr_in); -+ } - - client_bussiness(buffer_out, buffer_in, length, false, &(client_handler->msg_idx)); - - int32_t cwrite = 0; - int32_t swrite = length; - int32_t nwrite = 0; -+ -+ fault_inject_delay(INJECT_DELAY_WRITE); -+ FAULT_INJECT_SKIP_BEGIN(INJECT_SKIP_WRITE) -+ - while (cwrite < swrite) { - if (strcmp(domain, "udp") == 0 && strcmp(api, "recvfromsendto") == 0) { -- nwrite = sendto(client_handler->fd, buffer_out, length, 0, (struct sockaddr *)&server_addr, len); -+ nwrite = sendto(client_handler->fd, buffer_out, swrite - cwrite, 0, (struct sockaddr *)&server_addr, len); - } else { -- nwrite = write_api(client_handler->fd, buffer_out, length, api); -+ nwrite = write_api(client_handler->fd, buffer_out, swrite - cwrite, api); - } - if (nwrite == 0) { - return PROGRAM_ABORT; -@@ -250,6 +337,8 @@ int32_t client_ask(struct ClientHandler *client_handler, uint32_t pktlen, const - } - } - -+ FAULT_INJECT_SKIP_END -+ - free(buffer_in); - free(buffer_out); - -@@ -257,18 +346,24 @@ int32_t client_ask(struct ClientHandler *client_handler, uint32_t pktlen, const - } - - // client checks --int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, bool verify, const char* api, const char* domain, in_addr_t ip) -+int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, bool verify, const char* api, const char* domain, ip_addr_t* ip) - { - const uint32_t length = pktlen; -- char *buffer_in = (char *)malloc(length * sizeof(char)); -- char *buffer_out = (char *)malloc(length * sizeof(char)); -+ char *buffer_in = (char *)calloc(length, sizeof(char)); -+ char *buffer_out = (char *)calloc(length, sizeof(char)); -+ if (buffer_in == NULL || buffer_out == NULL) { -+ return PROGRAM_FAULT; -+ } - - int32_t cread = 0; - int32_t sread = length; - int32_t nread = 0; -- struct sockaddr_in server_addr; -- socklen_t len = sizeof(server_addr); -+ sockaddr_t server_addr; -+ socklen_t len = ip->addr_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - -+ fault_inject_delay(INJECT_DELAY_READ); -+ FAULT_INJECT_SKIP_BEGIN(INJECT_SKIP_READ) -+ - while (cread < sread) { - if (strcmp(domain, "udp") == 0 && strcmp(api, "recvfromsendto") == 0) { - nread = recvfrom(client_handler->fd, buffer_in, length, 0, (struct sockaddr *)&server_addr, &len); -@@ -287,6 +382,8 @@ int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, boo - } - } - -+ FAULT_INJECT_SKIP_END -+ - if (client_bussiness(buffer_out, buffer_in, length, verify, &(client_handler->msg_idx)) < 0) { - PRINT_ERROR("message verify fault! "); - getchar(); -@@ -295,15 +392,18 @@ int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, boo - int32_t cwrite = 0; - int32_t swrite = length; - int32_t nwrite = 0; -- if (ip >= inet_addr("224.0.0.0") && ip <= inet_addr("239.255.255.255")) { -- server_addr.sin_addr.s_addr = ip; -+ if (ip->addr_family == AF_INET && ip->u_addr.ip4.s_addr >= inet_addr("224.0.0.0") && ip->u_addr.ip4.s_addr <= inet_addr("239.255.255.255")) { -+ ((struct sockaddr_in*)&server_addr)->sin_addr = ip->u_addr.ip4; - } - -+ fault_inject_delay(INJECT_DELAY_WRITE); -+ FAULT_INJECT_SKIP_BEGIN(INJECT_SKIP_WRITE) -+ - while (cwrite < swrite) { - if (strcmp(domain, "udp") == 0 && strcmp(api, "recvfromsendto") == 0) { -- nwrite = sendto(client_handler->fd, buffer_out, length, 0, (struct sockaddr *)&server_addr, len); -+ nwrite = sendto(client_handler->fd, buffer_out, swrite - cwrite, 0, (struct sockaddr *)&server_addr, len); - } else { -- nwrite = write_api(client_handler->fd, buffer_out, length, api); -+ nwrite = write_api(client_handler->fd, buffer_out, swrite - cwrite, api); - } - if (nwrite == 0) { - return PROGRAM_ABORT; -@@ -317,6 +417,8 @@ int32_t client_chkans(struct ClientHandler *client_handler, uint32_t pktlen, boo - } - } - -+ FAULT_INJECT_SKIP_END -+ - free(buffer_in); - free(buffer_out); - -diff --git a/examples/src/client.c b/examples/src/client.c -index 1366924..43fbd0e 100644 ---- a/examples/src/client.c -+++ b/examples/src/client.c -@@ -12,24 +12,61 @@ - - - #include "client.h" -- -+#include "server.h" - - static pthread_mutex_t client_debug_mutex; // the client mutex for printf -+struct Client *g_client_begin = NULL; -+ -+static int32_t client_process_ask(struct ClientHandler *client_handler, struct ClientUnit *client_unit); -+static void client_get_domain_ipversion(uint8_t protocol_type, struct ClientUnit *client_unit); - -+static void timer_handle(int signum) -+{ -+ if (g_client_begin == NULL) { -+ return; -+ } -+ -+ struct ClientUnit *begin_client_unit = g_client_begin->uints; -+ while (begin_client_unit != NULL) { -+ if (begin_client_unit->domain != NULL && strcmp(begin_client_unit->domain, "udp") != 0) { -+ begin_client_unit = begin_client_unit->next; -+ continue; -+ } -+ for (int32_t i = 0; i < begin_client_unit->connect_num; i++) { -+ struct ClientHandler *handle = begin_client_unit->handlers + i; -+ if (handle->sendtime_interverl == TIME_SEND_INTERVAL) { -+ client_process_ask(handle, begin_client_unit); -+ } else { -+ handle->sendtime_interverl++; -+ } -+ } -+ -+ begin_client_unit = begin_client_unit->next; -+ } -+ alarm(TIME_SCAN_INTERVAL); -+} -+ -+static struct Client_domain_ip g_cfgmode_map[PROTOCOL_MODE_MAX] = { -+ [V4_TCP] = {"tcp", AF_INET}, -+ [V6_TCP] = {"tcp", AF_INET6}, -+ [V4_UDP] = {"udp", AF_INET}, -+ [V6_UDP] = {"udp", AF_INET6}, -+ [UDP_MULTICAST] = {"udp", AF_INET}}; - - // the single thread, client prints informations --void client_debug_print(const char *ch_str, const char *act_str, in_addr_t ip, uint16_t port, bool debug) -+void client_debug_print(const char *ch_str, const char *act_str, ip_addr_t *ip, uint16_t port, bool debug) - { - if (debug == true) { - pthread_mutex_lock(&client_debug_mutex); -- struct in_addr sin_addr; -- sin_addr.s_addr = ip; -+ uint8_t str_len = ip->addr_family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; -+ char str_ip[str_len]; -+ inet_ntop(ip->addr_family, &ip->u_addr, str_ip, str_len); - PRINT_CLIENT("[%s] [pid: %d] [tid: %ld] [%s <- %s:%d]. ", \ - ch_str, \ - getpid(), \ - pthread_self(), \ - act_str, \ -- inet_ntoa(sin_addr), \ -+ str_ip, \ - ntohs(port)); - pthread_mutex_unlock(&client_debug_mutex); - } -@@ -41,7 +78,8 @@ void client_info_print(struct Client *client) - if (client->debug == false) { - struct timeval begin; - gettimeofday(&begin, NULL); -- uint64_t begin_time = (uint64_t)begin.tv_sec * 1000 + (uint64_t)begin.tv_usec / 1000; -+ uint64_t begin_time = (uint64_t)begin.tv_sec * TIMES_CONVERSION_RATE + -+ (uint64_t)begin.tv_usec / TIMES_CONVERSION_RATE; - - uint32_t curr_connect = 0; - double bytes_ps = 0; -@@ -49,45 +87,164 @@ void client_info_print(struct Client *client) - struct ClientUnit *begin_uint = client->uints; - while (begin_uint != NULL) { - curr_connect += begin_uint->curr_connect; -- begin_send_bytes += begin_uint->send_bytes; -+ begin_send_bytes += begin_uint->threadVolume.send_bytes; - begin_uint = begin_uint->next; - } - - struct timeval delay; - delay.tv_sec = 0; -- delay.tv_usec = TERMINAL_REFRESH_MS * 1000; -+ delay.tv_usec = TERMINAL_REFRESH_MS * TIMES_CONVERSION_RATE; - select(0, NULL, NULL, NULL, &delay); - - uint64_t end_send_bytes = 0; - struct ClientUnit *end_uint = client->uints; - while (end_uint != NULL) { -- end_send_bytes += end_uint->send_bytes; -+ end_send_bytes += end_uint->threadVolume.send_bytes; - end_uint = end_uint->next; - } - - struct timeval end; - gettimeofday(&end, NULL); -- uint64_t end_time = (uint64_t)end.tv_sec * 1000 + (uint64_t)end.tv_usec / 1000; -- -+ uint64_t end_time = (uint64_t)end.tv_sec * TIMES_CONVERSION_RATE + -+ (uint64_t)end.tv_usec / TIMES_CONVERSION_RATE; -+ - double bytes_sub = end_send_bytes > begin_send_bytes ? (double)(end_send_bytes - begin_send_bytes) : 0; -- double time_sub = end_time > begin_time ? (double)(end_time - begin_time) / 1000 : 0; -+ double time_sub = end_time > begin_time ? (double)(end_time - begin_time) / TIMES_CONVERSION_RATE : 0; - - bytes_ps = bytes_sub / time_sub; - -- if (bytes_ps < 1024) { -+ if (bytes_ps < KB) { - PRINT_CLIENT_DATAFLOW("[connect num]: %d, [send]: %.3f B/s", curr_connect, bytes_ps); -- } else if (bytes_ps < (1024 * 1024)) { -- PRINT_CLIENT_DATAFLOW("[connect num]: %d, [send]: %.3f KB/s", curr_connect, bytes_ps / 1024); -+ } else if (bytes_ps < MB) { -+ PRINT_CLIENT_DATAFLOW("[connect num]: %d, [send]: %.3f KB/s", curr_connect, bytes_ps / KB); - } else { -- PRINT_CLIENT_DATAFLOW("[connect num]: %d, [send]: %.3f MB/s", curr_connect, bytes_ps / (1024 * 1024)); -+ PRINT_CLIENT_DATAFLOW("[connect num]: %d, [send]: %.3f MB/s", curr_connect, bytes_ps / MB); -+ } -+ -+ if (client->loop) { -+ printf("\033[2A\033[120C\033[K\n"); -+ return; -+ } -+ printf("\033[A\033[K"); -+ } -+} -+ -+static int32_t client_process_ask(struct ClientHandler *client_handler, struct ClientUnit *client_unit) -+{ -+ // not support udp+v6 currently -+ if (strcmp(client_unit->domain, "udp") == 0 && client_unit->ip.addr_family == AF_INET6) { -+ return PROGRAM_OK; -+ } -+ -+ int32_t client_ask_ret = client_ask(client_handler, client_unit); -+ if (client_ask_ret == PROGRAM_FAULT) { -+ --client_unit->curr_connect; -+ struct epoll_event ep_ev; -+ if (client_handler->fd > 0 && epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, (client_handler)->fd, &ep_ev) < 0) { -+ PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", (client_handler)->fd, errno); -+ return PROGRAM_FAULT; - } -+ } else if (client_ask_ret == PROGRAM_ABORT) { -+ --client_unit->curr_connect; -+ if (close((client_handler)->fd) < 0) { -+ PRINT_ERROR("client can't close the socket! "); -+ return PROGRAM_FAULT; -+ } -+ client_debug_print("client unit", "close", &client_unit->ip, client_unit->port, client_unit->debug); -+ } else { -+ client_unit->threadVolume.send_bytes += client_unit->pktlen; -+ client_handler->sendtime_interverl = 0; -+ client_debug_print("client unit", "send", &client_unit->ip, client_unit->port, client_unit->debug); -+ } -+ return PROGRAM_OK; -+} -+ -+static void client_get_thread_volume(struct Client *client, struct ThreadUintInfo *threadVolume) -+{ -+ int index = 0; -+ struct ClientUnit *curUint = client->uints; -+ while (curUint != NULL && index < client->threadNum) { -+ threadVolume[index].send_bytes = curUint->threadVolume.send_bytes; -+ -+ threadVolume[index].cur_connect_num = curUint->curr_connect; -+ threadVolume[index].thread_id = curUint->threadVolume.thread_id; -+ threadVolume[index].domain = curUint->threadVolume.domain; -+ threadVolume[index].ip_type_info = curUint->threadVolume.ip_type_info; -+ curUint = curUint->next; -+ index++; -+ } -+} -+ -+void client_info_print_mixed(struct Client *client, struct ThreadUintInfo *threadVolume, -+ struct ThreadUintInfo *endThreadVolume) -+{ -+ if (client->debug == true) { -+ return; -+ } -+ int32_t pthread_num = client->threadNum; -+ int32_t not_support_thread = 0; -+ struct timeval cur = {0}; -+ -+ gettimeofday(&cur, NULL); -+ uint64_t begin_time = (uint64_t)cur.tv_sec * TIMES_CONVERSION_RATE + (uint64_t)cur.tv_usec / TIMES_CONVERSION_RATE; -+ -+ client_get_thread_volume(client, threadVolume); -+ -+ struct timeval delay; -+ delay.tv_sec = 0; -+ delay.tv_usec = TERMINAL_REFRESH_MS * TIMES_CONVERSION_RATE; -+ select(0, NULL, NULL, NULL, &delay); -+ -+ client_get_thread_volume(client, endThreadVolume); -+ -+ gettimeofday(&cur, NULL); -+ uint64_t end_time = (uint64_t)cur.tv_sec * TIMES_CONVERSION_RATE + (uint64_t)cur.tv_usec / TIMES_CONVERSION_RATE; -+ -+ for (int i = 0; i < pthread_num; i++) { -+ uint64_t begin_send_bytes = threadVolume[i].send_bytes; -+ uint64_t end_send_bytes = endThreadVolume[i].send_bytes; -+ pthread_t thread_id = endThreadVolume[i].thread_id; -+ uint32_t connect_num = endThreadVolume[i].cur_connect_num; -+ char *domain = endThreadVolume[i].domain; -+ char *ip_ver = endThreadVolume[i].ip_type_info; -+ -+ if (thread_id == 0) { -+ not_support_thread++; -+ continue; -+ } -+ -+ double bytes_sub = end_send_bytes > begin_send_bytes ? (double)(end_send_bytes - begin_send_bytes) : 0; -+ double time_sub = end_time > begin_time ? (double)(end_time - begin_time) / TIMES_CONVERSION_RATE : 0; -+ double bytes_ps = bytes_sub / time_sub; -+ -+ if (bytes_ps < KB) { -+ PRINT_CLIENT_DATAFLOW("threadID=%-15lu, %s_%-9s [connect num]: %u, [send]: %.3f B/s", -+ thread_id, domain, ip_ver, connect_num, bytes_ps); -+ } else if (bytes_ps < MB) { -+ PRINT_CLIENT_DATAFLOW("threadID=%-15lu, %s_%-9s [connect num]: %u, [send]: %.3f kB/s", -+ thread_id, domain, ip_ver, connect_num, bytes_ps / KB); -+ } else { -+ PRINT_CLIENT_DATAFLOW("threadID=%-15lu, %s_%-9s [connect num]: %u, [send]: %.3f MB/s", -+ thread_id, domain, ip_ver, connect_num, bytes_ps / MB); -+ } -+ } -+ printf("\033[%dA\033[K", pthread_num - not_support_thread); -+} -+ -+void loop_info_print() -+{ -+ printf(" "); -+ if (strcmp(loopmod.model, "mum") == 0) { -+ sermum_info_print(loopmod.server_mum_info); -+ } else { -+ sermud_info_print(loopmod.server_mud_info); - } - } - - // the single thread, client try to connect to server, register to epoll --int32_t client_thread_try_connect(struct ClientHandler *client_handler, int32_t epoll_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, uint16_t sport, const char *domain, const char *api) -+int32_t client_thread_try_connect(struct ClientHandler *client_handler, struct ClientUnit *client_unit) - { -- int32_t create_socket_and_connect_ret = create_socket_and_connect(&(client_handler->fd), ip, groupip, port, sport, domain, api); -+ int32_t create_socket_and_connect_ret = create_socket_and_connect(&(client_handler->fd), client_unit); - if (create_socket_and_connect_ret == PROGRAM_INPROGRESS) { - return PROGRAM_OK; - } -@@ -97,7 +254,7 @@ int32_t client_thread_try_connect(struct ClientHandler *client_handler, int32_t - // the single thread, client retry to connect to server, register to epoll - int32_t client_thread_retry_connect(struct ClientUnit *client_unit, struct ClientHandler *client_handler) - { -- int32_t clithd_try_cnntask_ret = client_thread_try_connect(client_handler, client_unit->epfd, client_unit->ip, client_unit->groupip, client_unit->port, client_unit->sport, client_unit->domain, client_unit->api); -+ int32_t clithd_try_cnntask_ret = client_thread_try_connect(client_handler, client_unit); - if (clithd_try_cnntask_ret < 0) { - if (clithd_try_cnntask_ret == PROGRAM_INPROGRESS) { - return PROGRAM_OK; -@@ -114,35 +271,27 @@ int32_t client_thread_retry_connect(struct ClientUnit *client_unit, struct Clien - - ++(client_unit->curr_connect); - -- struct sockaddr_in server_addr; -- socklen_t server_addr_len = sizeof(server_addr); -+ sockaddr_t server_addr; -+ socklen_t server_addr_len = client_unit->ip.addr_family ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - if (getpeername(client_handler->fd, (struct sockaddr *)&server_addr, &server_addr_len) < 0) { - PRINT_ERROR("client can't socket peername %d! ", errno); - return PROGRAM_FAULT; - } -- client_debug_print("client unit", "connect", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); - -- int32_t client_ask_ret = client_ask(client_handler, client_unit->pktlen, client_unit->api, client_unit->domain, client_unit->groupip ? client_unit->groupip:client_unit->ip, client_unit->port); -- if (client_ask_ret == PROGRAM_FAULT) { -- --client_unit->curr_connect; -- struct epoll_event ep_ev; -- if (epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, client_handler->fd, &ep_ev) < 0) { -- PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", client_handler->fd, errno); -- return PROGRAM_FAULT; -- } -- } else if (client_ask_ret == PROGRAM_ABORT) { -- --client_unit->curr_connect; -- if (close(client_handler->fd) < 0) { -- PRINT_ERROR("client can't close the socket %d! ", errno); -- return PROGRAM_FAULT; -- } -- client_debug_print("client unit", "close", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); -- } else { -- client_unit->send_bytes += client_unit->pktlen; -- client_debug_print("client unit", "send", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); -+ // sockaddr to ip, port -+ ip_addr_t remote_ip; -+ uint16_t remote_port = ((struct sockaddr_in*)&server_addr)->sin_port; -+ if (((struct sockaddr *)&server_addr)->sa_family == AF_INET) { -+ remote_ip.addr_family = AF_INET; -+ remote_ip.u_addr.ip4 = ((struct sockaddr_in *)&server_addr)->sin_addr; -+ } else if (((struct sockaddr *)&server_addr)->sa_family == AF_INET6) { -+ remote_ip.addr_family = AF_INET6; -+ remote_ip.u_addr.ip6 = ((struct sockaddr_in6 *)&server_addr)->sin6_addr; - } - -- return PROGRAM_OK; -+ client_debug_print("client unit", "connect", &remote_ip, remote_port, client_unit->debug); -+ -+ return client_process_ask(client_handler, client_unit); - } - - // the single thread, client connects and gets epoll feature descriptors -@@ -162,7 +311,7 @@ int32_t client_thread_create_epfd_and_reg(struct ClientUnit *client_unit) - } - - for (uint32_t i = 0; i < connect_num; ++i) { -- int32_t clithd_try_cnntask_ret = client_thread_try_connect(client_unit->handlers + i, client_unit->epfd, client_unit->ip, client_unit->groupip, client_unit->port, client_unit->sport, client_unit->domain, client_unit->api); -+ int32_t clithd_try_cnntask_ret = client_thread_try_connect(client_unit->handlers + i, client_unit); - if (clithd_try_cnntask_ret < 0) { - if (clithd_try_cnntask_ret == PROGRAM_INPROGRESS) { - continue; -@@ -179,26 +328,11 @@ int32_t client_thread_create_epfd_and_reg(struct ClientUnit *client_unit) - - ++(client_unit->curr_connect); - -- client_debug_print("client unit", "connect", client_unit->ip, client_unit->port, client_unit->debug); -- -- int32_t client_ask_ret = client_ask(client_unit->handlers + i, client_unit->pktlen, client_unit->api, client_unit->domain, client_unit->groupip ? client_unit->groupip:client_unit->ip, client_unit->port); -- if (client_ask_ret == PROGRAM_FAULT) { -- --client_unit->curr_connect; -- struct epoll_event ep_ev; -- if (epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, (client_unit->handlers + i)->fd, &ep_ev) < 0) { -- PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", client_unit->epevs[i].data.fd, errno); -- return PROGRAM_FAULT; -- } -- } else if (client_ask_ret == PROGRAM_ABORT) { -- --client_unit->curr_connect; -- if (close((client_unit->handlers + i)->fd) < 0) { -- PRINT_ERROR("client can't close the socket! "); -- return PROGRAM_FAULT; -- } -- client_debug_print("client unit", "close", client_unit->ip, client_unit->port, client_unit->debug); -- } else { -- client_unit->send_bytes += client_unit->pktlen; -- client_debug_print("client unit", "send", client_unit->ip, client_unit->port, client_unit->debug); -+ client_debug_print("client unit", "connect", &client_unit->ip, client_unit->port, client_unit->debug); -+ -+ int32_t client_ask_ret = client_process_ask(client_unit->handlers + i, client_unit); -+ if (client_ask_ret != PROGRAM_OK) { -+ return client_ask_ret; - } - } - } -@@ -206,15 +340,97 @@ int32_t client_thread_create_epfd_and_reg(struct ClientUnit *client_unit) - return PROGRAM_OK; - } - -+ -+static int32_t clithd_proc_epevs_epollout(struct epoll_event *curr_epev, struct ClientUnit *client_unit) -+{ -+ int32_t connect_error = 0; -+ socklen_t connect_error_len = sizeof(connect_error); -+ struct ClientHandler *client_handler = (struct ClientHandler *)curr_epev->data.ptr; -+ if (getsockopt(client_handler->fd, SOL_SOCKET, SO_ERROR, (void *)(&connect_error), &connect_error_len) < 0) { -+ PRINT_ERROR("client can't get socket option %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ if (connect_error < 0) { -+ if (connect_error == ETIMEDOUT) { -+ if (client_thread_retry_connect(client_unit, client_handler) < 0) { -+ return PROGRAM_FAULT; -+ } -+ return PROGRAM_OK; -+ } -+ PRINT_ERROR("client connect error %d! ", connect_error); -+ return PROGRAM_FAULT; -+ } else { -+ ++(client_unit->curr_connect); -+ -+ sockaddr_t server_addr; -+ socklen_t server_addr_len = -+ client_unit->ip.addr_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); -+ if (getpeername(client_handler->fd, (struct sockaddr *)&server_addr, &server_addr_len) < 0) { -+ PRINT_ERROR("client can't socket peername %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ -+ // sockaddr to ip, port -+ ip_addr_t remote_ip; -+ uint16_t remote_port = ((struct sockaddr_in *)&server_addr)->sin_port; -+ if (((struct sockaddr *)&server_addr)->sa_family == AF_INET) { -+ remote_ip.addr_family = AF_INET; -+ remote_ip.u_addr.ip4 = ((struct sockaddr_in *)&server_addr)->sin_addr; -+ } else if (((struct sockaddr *)&server_addr)->sa_family == AF_INET6) { -+ remote_ip.addr_family = AF_INET6; -+ remote_ip.u_addr.ip6 = ((struct sockaddr_in6 *)&server_addr)->sin6_addr; -+ } -+ -+ client_debug_print("client unit", "connect", &remote_ip, remote_port, client_unit->debug); -+ -+ int32_t client_ask_ret = client_process_ask(client_handler, client_unit); -+ if (client_ask_ret != PROGRAM_OK) { -+ return client_ask_ret; -+ } -+ } -+ return PROGRAM_OK; -+} -+ -+static int32_t clithd_proc_epevs_epollin(struct epoll_event *curr_epev, struct ClientUnit *client_unit) -+{ -+ ip_addr_t *chkans_ip = client_unit->protocol_type_mode == UDP_MULTICAST ? &client_unit->groupip : &client_unit->ip; -+ int32_t client_chkans_ret = client_chkans((struct ClientHandler *)curr_epev->data.ptr, client_unit->pktlen, -+ client_unit->verify, client_unit->api, client_unit->domain, chkans_ip); -+ struct ClientHandler *client_handler = (struct ClientHandler *)curr_epev->data.ptr; -+ int32_t fd = client_handler->fd; -+ if (client_chkans_ret == PROGRAM_FAULT) { -+ --client_unit->curr_connect; -+ struct epoll_event ep_ev; -+ if (epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, fd, &ep_ev) < 0) { -+ PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", fd, errno); -+ return PROGRAM_FAULT; -+ } -+ } else if (client_chkans_ret == PROGRAM_ABORT) { -+ --client_unit->curr_connect; -+ if (close(fd) < 0) { -+ PRINT_ERROR("client can't close the socket %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ client_debug_print("client unit", "close", &client_unit->ip, client_unit->port, client_unit->debug); -+ } else { -+ client_unit->threadVolume.send_bytes += client_unit->pktlen; -+ client_handler->sendtime_interverl = 0; -+ client_debug_print("client unit", "receive", &client_unit->ip, client_unit->port, client_unit->debug); -+ } -+ return PROGRAM_OK; -+} -+ - // the single thread, client processes epoll events - int32_t clithd_proc_epevs(struct ClientUnit *client_unit) - { - int32_t epoll_nfds = epoll_wait(client_unit->epfd, client_unit->epevs, CLIENT_EPOLL_SIZE_MAX, CLIENT_EPOLL_WAIT_TIMEOUT); -+ int ret = 0; - if (epoll_nfds < 0) { - PRINT_ERROR("client epoll wait error %d! ", errno); - return PROGRAM_FAULT; - } - -+ - for (int32_t i = 0; i < epoll_nfds; ++i) { - struct epoll_event *curr_epev = client_unit->epevs + i; - -@@ -222,76 +438,17 @@ int32_t clithd_proc_epevs(struct ClientUnit *client_unit) - PRINT_ERROR("client epoll wait error! %d", curr_epev->events); - return PROGRAM_FAULT; - } else if (curr_epev->events == EPOLLOUT) { -- int32_t connect_error = 0; -- socklen_t connect_error_len = sizeof(connect_error); -- struct ClientHandler *client_handler = (struct ClientHandler *)curr_epev->data.ptr; -- if (getsockopt(client_handler->fd, SOL_SOCKET, SO_ERROR, (void *)(&connect_error), &connect_error_len) < 0) { -- PRINT_ERROR("client can't get socket option %d! ", errno); -- return PROGRAM_FAULT; -- } -- if (connect_error < 0) { -- if (connect_error == ETIMEDOUT) { -- if (client_thread_retry_connect(client_unit, client_handler) < 0) { -- return PROGRAM_FAULT; -- } -- continue; -- } -- PRINT_ERROR("client connect error %d! ", connect_error); -- return PROGRAM_FAULT; -- } else { -- ++(client_unit->curr_connect); -- -- struct sockaddr_in server_addr; -- socklen_t server_addr_len = sizeof(server_addr); -- if (getpeername(client_handler->fd, (struct sockaddr *)&server_addr, &server_addr_len) < 0) { -- PRINT_ERROR("client can't socket peername %d! ", errno); -- return PROGRAM_FAULT; -- } -- client_debug_print("client unit", "connect", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); -- -- int32_t client_ask_ret = client_ask(client_handler, client_unit->pktlen, client_unit->api, client_unit->domain, client_unit->groupip ? client_unit->groupip:client_unit->ip, client_unit->port); -- if (client_ask_ret == PROGRAM_FAULT) { -- --client_unit->curr_connect; -- struct epoll_event ep_ev; -- if (epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, curr_epev->data.fd, &ep_ev) < 0) { -- PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", curr_epev->data.fd, errno); -- return PROGRAM_FAULT; -- } -- } else if (client_ask_ret == PROGRAM_ABORT) { -- --client_unit->curr_connect; -- if (close(curr_epev->data.fd) < 0) { -- PRINT_ERROR("client can't close the socket! "); -- return PROGRAM_FAULT; -- } -- client_debug_print("client unit", "close", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); -- } else { -- client_unit->send_bytes += client_unit->pktlen; -- client_debug_print("client unit", "send", server_addr.sin_addr.s_addr, server_addr.sin_port, client_unit->debug); -- } -+ ret = clithd_proc_epevs_epollout(curr_epev, client_unit); -+ if (ret != PROGRAM_OK) { -+ return ret; - } - } else if (curr_epev->events == EPOLLIN) { -- int32_t client_chkans_ret = client_chkans((struct ClientHandler *)curr_epev->data.ptr, client_unit->pktlen, client_unit->verify, client_unit->api, client_unit->domain, client_unit->groupip ? client_unit->groupip:client_unit->ip); -- if (client_chkans_ret == PROGRAM_FAULT) { -- --client_unit->curr_connect; -- struct epoll_event ep_ev; -- if (epoll_ctl(client_unit->epfd, EPOLL_CTL_DEL, curr_epev->data.fd, &ep_ev) < 0) { -- PRINT_ERROR("client can't delete socket '%d' to control epoll %d! ", curr_epev->data.fd, errno); -- return PROGRAM_FAULT; -- } -- } else if (client_chkans_ret == PROGRAM_ABORT) { -- --client_unit->curr_connect; -- if (close(curr_epev->data.fd) < 0) { -- PRINT_ERROR("client can't close the socket %d! ", errno); -- return PROGRAM_FAULT; -- } -- client_debug_print("client unit", "close", client_unit->ip, client_unit->port, client_unit->debug); -- } else { -- client_unit->send_bytes += client_unit->pktlen; -- client_debug_print("client unit", "receive", client_unit->ip, client_unit->port, client_unit->debug); -+ ret = clithd_proc_epevs_epollin(curr_epev, client_unit); -+ if (ret != PROGRAM_OK) { -+ return ret; - } - } - } -- - return PROGRAM_OK; - } - -@@ -299,6 +456,17 @@ int32_t clithd_proc_epevs(struct ClientUnit *client_unit) - void *client_s_create_and_run(void *arg) - { - struct ClientUnit *client_unit = (struct ClientUnit *)arg; -+ // update domain ip info. -+ client_get_domain_ipversion(client_unit->protocol_type_mode, client_unit); -+ -+ if (client_unit->protocol_type_mode == UDP_MULTICAST) { -+ client_unit->threadVolume.ip_type_info = IPV4_MULTICAST; -+ } else { -+ client_unit->threadVolume.ip_type_info = (client_unit->ip.addr_family == AF_INET ? IPV4_STR : IPV6_STR); -+ } -+ client_unit->threadVolume.thread_id = pthread_self(); -+ -+ client_unit->threadVolume.domain = client_unit->domain; - - if (client_thread_create_epfd_and_reg(client_unit) < 0) { - exit(PROGRAM_FAULT); -@@ -316,6 +484,42 @@ void *client_s_create_and_run(void *arg) - return (void *)PROGRAM_OK; - } - -+// prase the specific supported TCP IP types by cfg_mode. -+static void client_get_protocol_type_by_cfgmode(uint8_t mode, int32_t *support_type_array, int32_t buff_len, -+ int32_t *actual_len) -+{ -+ int32_t index = 0; -+ for (uint8_t i = V4_TCP; i < PROTOCOL_MODE_MAX; i++) { -+ if (i == V6_UDP) { -+ continue; -+ } -+ if (getbit_num(mode, i) == 1) { -+ if (index >= buff_len) { -+ PRINT_ERROR("index is over, index =%d", index); -+ return; -+ } -+ support_type_array[index] = i; -+ index++; -+ } -+ } -+ *actual_len = index; -+} -+ -+static void client_get_domain_ipversion(uint8_t protocol_type, struct ClientUnit *client_unit) -+{ -+ client_unit->domain = g_cfgmode_map[protocol_type].domain; -+ client_unit->ip.addr_family = g_cfgmode_map[protocol_type].ip_family; -+} -+ -+static void alarm_init() -+{ -+ struct sigaction sa; -+ memset(&sa, 0, sizeof(sa)); -+ sa.sa_handler = &timer_handle; -+ sigaction(SIGALRM, &sa, NULL); -+ alarm(TIME_SCAN_INTERVAL); -+} -+ - // create client and run - int32_t client_create_and_run(struct ProgramParams *params) - { -@@ -323,16 +527,44 @@ int32_t client_create_and_run(struct ProgramParams *params) - const uint32_t thread_num = params->thread_num; - pthread_t *tids = (pthread_t *)malloc(thread_num * sizeof(pthread_t)); - struct Client *client = (struct Client *)malloc(sizeof(struct Client)); -+ g_client_begin = client; -+ client->threadNum = thread_num; -+ - struct ClientUnit *client_unit = (struct ClientUnit *)malloc(sizeof(struct ClientUnit)); -+ memset_s(client_unit, sizeof(struct ClientUnit), 0, sizeof(struct ClientUnit)); -+ int32_t protocol_support_array[PROTOCOL_MODE_MAX] = {0}; -+ int32_t number_of_support_type = 1; - - if (pthread_mutex_init(&client_debug_mutex, NULL) < 0) { - PRINT_ERROR("client can't init posix mutex %d! ", errno); - return PROGRAM_FAULT; - } - -+ bool v4_cfg_flag = (strcmp(params->ip, PARAM_DEFAULT_IP) != 0); -+ bool v6_cfg_flag = (strcmp(params->ipv6, PARAM_DEFAULT_IP_V6) != 0); -+ bool multcact_cfg_flag = (strcmp(params->groupip, PARAM_DEFAULT_GROUPIP) != 0); -+ -+ bool mixed_mode_flag = false; -+ if ((strchr(params->domain, ',') != NULL) || (v4_cfg_flag && v6_cfg_flag) || -+ (multcact_cfg_flag && (v4_cfg_flag || v6_cfg_flag))) { -+ mixed_mode_flag = true; -+ } -+ - client->uints = client_unit; - client->debug = params->debug; - -+ uint8_t protocol_type_mode = program_get_protocol_mode_by_domain_ip(params->domain, params->ip, params->ipv6, -+ params->groupip); -+ -+ client_get_protocol_type_by_cfgmode(protocol_type_mode, protocol_support_array, PROTOCOL_MODE_MAX, -+ &number_of_support_type); -+ -+ uint32_t port = UNIX_TCP_PORT_MIN; -+ uint32_t sport = 0; -+ uint32_t sp = 0; -+ -+ alarm_init(); -+ - for (uint32_t i = 0; i < thread_num; ++i) { - client_unit->handlers = (struct ClientHandler *)malloc(connect_num * sizeof(struct ClientHandler)); - for (uint32_t j = 0; j < connect_num; ++j) { -@@ -342,13 +574,42 @@ int32_t client_create_and_run(struct ProgramParams *params) - client_unit->epfd = -1; - client_unit->epevs = (struct epoll_event *)malloc(CLIENT_EPOLL_SIZE_MAX * sizeof(struct epoll_event)); - client_unit->curr_connect = 0; -- client_unit->send_bytes = 0; -- client_unit->ip = inet_addr(params->ip); -- client_unit->groupip = inet_addr(params->groupip); -- client_unit->port = htons(params->port); -- client_unit->sport = htons(params->sport); -+ -+ client_unit->threadVolume.cur_connect_num = 0; -+ client_unit->threadVolume.thread_id = 0; -+ client_unit->threadVolume.send_bytes = 0; -+ client_unit->threadVolume.ip_type_info = INVAILD_STR; -+ client_unit->threadVolume.domain = INVAILD_STR; -+ -+ client_unit->ip.addr_family = params->addr_family; -+ inet_pton(AF_INET, params->ip, &client_unit->ip.u_addr.ip4); -+ inet_pton(AF_INET6, params->ipv6, &client_unit->ip.u_addr.ip6); -+ client_unit->groupip.addr_family = AF_INET; -+ inet_pton(AF_INET, params->groupip, &client_unit->groupip.u_addr); -+ client_unit->groupip_interface.addr_family = params->addr_family; -+ inet_pton(AF_INET, params->groupip_interface, &client_unit->groupip_interface.u_addr); -+ -+ /* loop to set ports to each client_units */ -+ while (!((params->port)[port])) { -+ port = (port + 1) % UNIX_TCP_PORT_MAX; -+ } -+ client_unit->port = htons(port++); -+ -+ sp = sport; -+ sport++; -+ while (!((params->sport)[sport]) && (sport != sp)) { -+ sport = (sport + 1) % UNIX_TCP_PORT_MAX; -+ } -+ -+ client_unit->sport = htons(sport); - client_unit->connect_num = params->connect_num; - client_unit->pktlen = params->pktlen; -+ if (strcmp(params->as, "loop") == 0) { -+ client_unit->loop = 1; -+ } else { -+ client_unit->loop = 0; -+ } -+ - client_unit->verify = params->verify; - client_unit->domain = params->domain; - client_unit->api = params->api; -@@ -357,6 +618,16 @@ int32_t client_create_and_run(struct ProgramParams *params) - client_unit->next = (struct ClientUnit *)malloc(sizeof(struct ClientUnit)); - memset_s(client_unit->next, sizeof(struct ClientUnit), 0, sizeof(struct ClientUnit)); - -+ if (number_of_support_type > 0) { -+ int32_t index = i % number_of_support_type; -+ client_unit->protocol_type_mode = protocol_support_array[index]; -+ } -+ if (client_unit->protocol_type_mode == V4_UDP || client_unit->protocol_type_mode == V6_UDP || -+ client_unit->protocol_type_mode == UDP_MULTICAST) { -+ client_unit->pktlen = params->pktlen > UDP_PKTLEN_MAX ? UDP_PKTLEN_MAX : params->pktlen; -+ } else { -+ client_unit->pktlen = params->pktlen; -+ } - if (pthread_create((tids + i), NULL, client_s_create_and_run, client_unit) < 0) { - PRINT_ERROR("client can't create thread of poisx %d! ", errno); - return PROGRAM_FAULT; -@@ -367,9 +638,34 @@ int32_t client_create_and_run(struct ProgramParams *params) - if (client->debug == false) { - printf("[program informations]: \n\n"); - } -+ -+ struct ThreadUintInfo *beginVolume = (struct ThreadUintInfo *)malloc(thread_num * sizeof(struct ThreadUintInfo)); -+ if (beginVolume == NULL) { -+ return PROGRAM_FAULT; -+ } -+ memset_s(beginVolume, thread_num * sizeof(struct ThreadUintInfo), 0, thread_num * sizeof(struct ThreadUintInfo)); -+ struct ThreadUintInfo *endVolume = (struct ThreadUintInfo *)malloc(thread_num * sizeof(struct ThreadUintInfo)); -+ if (endVolume == NULL) { -+ return PROGRAM_FAULT; -+ } -+ memset_s(endVolume, thread_num * sizeof(struct ThreadUintInfo), 0, thread_num * sizeof(struct ThreadUintInfo)); -+ -+ if (strcmp(params->as, "loop") == 0) { -+ client->loop = true; -+ } -+ - while (true) { -- client_info_print(client); -+ if (strcmp(params->as, "loop") == 0) { -+ loop_info_print(); -+ } -+ if (mixed_mode_flag == true) { -+ client_info_print_mixed(client, beginVolume, endVolume); -+ } else { -+ client_info_print(client); -+ } - } -+ free(beginVolume); -+ free(endVolume); - - pthread_mutex_destroy(&client_debug_mutex); - -diff --git a/examples/src/parameter.c b/examples/src/parameter.c -index 1bb6858..7f519e7 100644 ---- a/examples/src/parameter.c -+++ b/examples/src/parameter.c -@@ -13,6 +13,8 @@ - - #include "parameter.h" - -+static int32_t g_inject_delay[INJECT_DELAY_MAX] = {0}; -+static int32_t g_inject_skip[INJECT_SKIP_MAX]; - - // program short options - const char prog_short_opts[] = \ -@@ -30,9 +32,11 @@ const char prog_short_opts[] = \ - "r" // ringpmd - "d" // debug - "h" // help -- "E" // epollcreate -- "C" // accept -+ "E:" // epollcreate -+ "C:" // accept - "g:" // group address -+ "k:" // tcp keep_alive -+ "I:" // fault inject - ; - - // program long options -@@ -55,17 +59,72 @@ const struct ProgramOption prog_long_opts[] = \ - {PARAM_NAME_EPOLLCREATE, REQUIRED_ARGUMETN, NULL, PARAM_NUM_EPOLLCREATE}, - {PARAM_NAME_ACCEPT, REQUIRED_ARGUMETN, NULL, PARAM_NUM_ACCEPT}, - {PARAM_NAME_GROUPIP, REQUIRED_ARGUMETN, NULL, PARAM_NUM_GROUPIP}, -+ {PARAM_NAME_KEEPALIVE, REQUIRED_ARGUMETN, NULL, PARAM_NUM_KEEPALIVE}, -+ {PARAM_NAME_INJECT, REQUIRED_ARGUMETN, NULL, PARAM_NUM_INJECT}, - }; - - - // get long options - int getopt_long(int argc, char * const argv[], const char *optstring, const struct ProgramOption *long_opts, int *long_idx); -+// index [0,7) -+uint8_t getbit_num(uint8_t mode, uint8_t index) -+{ -+ return (mode & ((uint8_t)1 << index)) != 0; -+} -+ -+uint8_t setbitnum_on(uint8_t mode, uint8_t index) -+{ -+ mode |= ((uint8_t)1 << index); -+ return mode; -+} -+ -+uint8_t setbitnum_off(uint8_t mode, uint8_t index) -+{ -+ mode &= ~((uint8_t)1 << index); -+ return mode; -+} -+ -+static uint8_t program_set_protocol_mode(uint8_t protocol_mode, char *ipv4, char *ipv6, uint8_t index_v4, -+ uint8_t index_v6) -+{ -+ uint8_t protocol_mode_temp = protocol_mode; -+ if (strcmp(ipv4, PARAM_DEFAULT_IP) != 0) { -+ protocol_mode_temp = setbitnum_on(protocol_mode_temp, index_v4); -+ } -+ if (strcmp(ipv6, PARAM_DEFAULT_IP_V6) != 0) { -+ protocol_mode_temp = setbitnum_on(protocol_mode_temp, index_v6); -+ } -+ return protocol_mode_temp; -+} -+ -+uint8_t program_get_protocol_mode_by_domain_ip(char* domain, char* ipv4, char* ipv6, char* groupip) -+{ -+ uint8_t protocol_mode = 0; -+ char *cur_ptr = NULL; -+ char *next_Ptr = NULL; -+ cur_ptr = strtok_s(domain, ",", &next_Ptr); -+ while (cur_ptr) { -+ if (strcmp(cur_ptr, "tcp") == 0) { -+ protocol_mode = program_set_protocol_mode(protocol_mode, ipv4, ipv6, V4_TCP, V6_TCP); -+ } else if (strcmp(cur_ptr, "udp") == 0) { -+ protocol_mode = program_set_protocol_mode(protocol_mode, ipv4, ipv6, V4_UDP, V6_UDP); -+ } else if (strcmp(cur_ptr, "unix") == 0) { -+ protocol_mode = setbitnum_on(protocol_mode, UNIX); -+ } -+ cur_ptr = strtok_s(NULL, ",", &next_Ptr); -+ } -+ -+ if (strcmp(groupip, PARAM_DEFAULT_GROUPIP) != 0) { -+ protocol_mode = setbitnum_on(protocol_mode, UDP_MULTICAST); -+ } - -+ return protocol_mode; -+} - - // set `as` parameter - void program_param_parse_as(struct ProgramParams *params) - { -- if (strcmp(optarg, "server") == 0 || strcmp(optarg, "client") == 0) { -+ if (strcmp(optarg, "server") == 0 || strcmp(optarg, "client") == 0 || strcmp(optarg, "loop") == 0) { - params->as = optarg; - } else { - PRINT_ERROR("illigal argument -- %s \n", optarg); -@@ -73,40 +132,113 @@ void program_param_parse_as(struct ProgramParams *params) - } - } - --// set `ip` parameter --void program_param_parse_ip(struct ProgramParams *params) -+bool ip_is_v6(const char *cp) -+{ -+ if (cp != NULL) { -+ const char *c; -+ for (c = cp; *c != 0; c++) { -+ if (*c == ':') { -+ return 1; -+ } -+ } -+ } -+ return 0; -+} -+ -+ -+static bool program_ipv4_check(char *ipv4) - { -- if (inet_addr(optarg) != INADDR_NONE) { -- params->ip = optarg; -+ in_addr_t ip = ntohl(inet_addr(ipv4)); -+ if (ip == INADDR_NONE) { -+ PRINT_ERROR("illigal argument -- %s \n", ipv4); -+ return false; -+ } -+ if ((ip >= ntohl(inet_addr("1.0.0.1")) && ip <= ntohl(inet_addr("126.255.255.254"))) || -+ (ip >= ntohl(inet_addr("127.0.0.1")) && ip <= ntohl(inet_addr("127.255.255.254"))) || -+ (ip >= ntohl(inet_addr("128.0.0.1")) && ip <= ntohl(inet_addr("191.255.255.254"))) || -+ (ip >= ntohl(inet_addr("192.0.0.1")) && ip <= ntohl(inet_addr("223.255.255.254"))) || -+ (ip >= ntohl(inet_addr("224.0.0.1")) && ip <= ntohl(inet_addr("224.255.255.255"))) ) { // Broadcast IP -+ return true; -+ } -+ -+ PRINT_ERROR("illigal argument -- %s \n", ipv4); -+ return false; -+} -+ -+static void program_param_parse_ipv4_addr(char* v4ip_addr, struct ProgramParams *params) -+{ -+ struct in6_addr ip_tmp; -+ params->addr_family = AF_INET; -+ if (inet_pton(params->addr_family, v4ip_addr, &ip_tmp) > 0 && program_ipv4_check(v4ip_addr) == true) { -+ params->ip = v4ip_addr; - } else { -- PRINT_ERROR("illigal argument -- %s \n", optarg); -+ PRINT_ERROR("illegal ipv4 addr -- %s \n", v4ip_addr); - exit(PROGRAM_ABORT); - } - } - --// set `port` parameter --void program_param_parse_port(struct ProgramParams *params) -+static void program_param_parse_ipv6_addr(char* v6ip_add, struct ProgramParams *params) - { -- int32_t port_arg = strtol(optarg, NULL, 0); -- printf("%d\n", port_arg); -- if (CHECK_VAL_RANGE(port_arg, UNIX_TCP_PORT_MIN, UNIX_TCP_PORT_MAX) == true) { -- params->port = (uint32_t)port_arg; -+ struct in6_addr ip_tmp; -+ params->addr_family = AF_INET6; -+ if (inet_pton(AF_INET6, v6ip_add, &ip_tmp) > 0) { -+ params->ipv6 = v6ip_add; - } else { -- PRINT_ERROR("illigal argument -- %s \n", optarg); -+ PRINT_ERROR("illegal ipv6 addr -- %s \n", v6ip_add); - exit(PROGRAM_ABORT); - } - } -+// set `ip` parameter,支持同时配置 ipv4 和 ipv6 地址,格式为 ipv4,ipv6 -+void program_param_parse_ip(struct ProgramParams *params) -+{ -+ char *cur_ptr = NULL; -+ char *next_ptr = NULL; -+ -+ cur_ptr = strtok_s(optarg, ",", &next_ptr); -+ while (cur_ptr) { -+ if (ip_is_v6(cur_ptr)) { -+ program_param_parse_ipv6_addr(cur_ptr, params); -+ } else { -+ program_param_parse_ipv4_addr(cur_ptr, params); -+ } -+ cur_ptr = strtok_s(NULL, ",", &next_ptr); -+ } -+} -+ -+// set `port` parameter -+void program_param_parse_port(struct ProgramParams *params) -+{ -+ char* port_list = optarg; -+ char* token = NULL; -+ int32_t port_arg = 0; -+ params->port[PARAM_DEFAULT_PORT] = 0; -+ -+ while ((token = strtok_r(port_list, ",", &port_list))) { -+ port_arg = strtol(token, NULL, 0); -+ if (CHECK_VAL_RANGE(port_arg, UNIX_TCP_PORT_MIN, UNIX_TCP_PORT_MAX) == true) { -+ params->port[port_arg] = 1; -+ } else { -+ PRINT_ERROR("illigal argument -- %s \n", optarg); -+ exit(PROGRAM_ABORT); -+ } -+ } -+} - - // set `sport` parameter - void program_param_parse_sport(struct ProgramParams *params) - { -- int32_t sport_arg = strtol(optarg, NULL, 0); -- printf("%d\n", sport_arg); -- if (CHECK_VAL_RANGE(sport_arg, UNIX_TCP_PORT_MIN, UNIX_TCP_PORT_MAX) == true) { -- params->sport = (uint32_t)sport_arg; -- } else { -- PRINT_ERROR("illigal argument -- %s \n", optarg); -- exit(PROGRAM_ABORT); -+ char* port_list = optarg; -+ char* token = NULL; -+ int32_t port_arg = 0; -+ -+ while ((token = strtok_r(port_list, ",", &port_list))) { -+ port_arg = strtol(token, NULL, 0); -+ if (CHECK_VAL_RANGE(port_arg, UNIX_TCP_PORT_MIN, UNIX_TCP_PORT_MAX) == true) { -+ params->sport[port_arg] = 1; -+ } else { -+ PRINT_ERROR("illigal argument -- %s \n", optarg); -+ exit(PROGRAM_ABORT); -+ } - } - } - -@@ -148,12 +280,23 @@ void program_param_parse_threadnum(struct ProgramParams *params) - // set `domain` parameter - void program_param_parse_domain(struct ProgramParams *params) - { -- if (strcmp(optarg, "unix") == 0 || strcmp(optarg, "tcp") == 0 || strcmp(optarg, "udp") == 0) { -- params->domain = optarg; -- } else { -- PRINT_ERROR("illigal argument -- %s \n", optarg); -+ char temp[100] = {0}; -+ int32_t ret = strcpy_s(temp, sizeof(temp) / sizeof(char), optarg); -+ if (ret != 0) { -+ PRINT_ERROR("strcpy_s fail ret=%d \n", ret); - exit(PROGRAM_ABORT); - } -+ char *cur_ptr = temp; -+ char *next_ptr = NULL; -+ cur_ptr = strtok_s(cur_ptr, ",", &next_ptr); -+ while (cur_ptr) { -+ if (strcmp(cur_ptr, "tcp") != 0 && strcmp(cur_ptr, "udp") != 0 && strcmp(cur_ptr, "unix") != 0) { -+ PRINT_ERROR("illigal argument -- %s \n", cur_ptr); -+ exit(PROGRAM_ABORT); -+ } -+ cur_ptr = strtok_s(NULL, ",", &next_ptr); -+ } -+ params->domain = optarg; - } - - // set `api` parameter -@@ -174,6 +317,9 @@ void program_param_parse_pktlen(struct ProgramParams *params) - int32_t pktlen_arg = strtol(optarg, NULL, 0); - if (CHECK_VAL_RANGE(pktlen_arg, MESSAGE_PKTLEN_MIN, MESSAGE_PKTLEN_MAX) == true) { - params->pktlen = (uint32_t)pktlen_arg; -+ if (strstr(params->domain, "udp") && params->pktlen > UDP_PKTLEN_MAX) { -+ PRINT_WARNNING("udp message too long, change it to %d \n", UDP_PKTLEN_MAX); -+ } - } else { - PRINT_ERROR("illigal argument -- %s \n", optarg); - exit(PROGRAM_ABORT); -@@ -202,16 +348,196 @@ void program_param_parse_accept(struct ProgramParams *params) - } - } - -+// set `tcp_keepalive_idle` parameter -+void program_param_parse_keepalive(struct ProgramParams *params) -+{ -+ char *token = NULL; -+ char *next_token = NULL; -+ token = strtok_s(optarg, ",", &next_token); -+ if (token == NULL) { -+ PRINT_ERROR("parse keep_alive idle null, illigal argument(%s) \n", optarg); -+ exit(PROGRAM_ABORT); -+ } -+ -+ int32_t keep_alive_idle = strtol(optarg, NULL, 0); -+ if (keep_alive_idle > 0 && keep_alive_idle <= TCP_KEEPALIVE_IDLE_MAX) { -+ params->tcp_keepalive_idle = keep_alive_idle; -+ } else { -+ PRINT_ERROR("keep_alive_idle=%d,illigal argument -- %s \n", keep_alive_idle, optarg); -+ exit(PROGRAM_ABORT); -+ } -+ -+ token = strtok_s(NULL, ",", &next_token); -+ if (token == NULL) { -+ PRINT_ERROR("parse keep_alive interval null, illigal argument(%s) \n", optarg); -+ exit(PROGRAM_ABORT); -+ } -+ int32_t keep_alive_interval = strtol(token, NULL, 0); -+ if (keep_alive_interval > 0 && keep_alive_interval <= TCP_KEEPALIVE_IDLE_MAX) { -+ params->tcp_keepalive_interval = keep_alive_interval; -+ } else { -+ PRINT_ERROR("keep_alive_interval=%d,illigal argument -- %s \n", keep_alive_interval, optarg); -+ exit(PROGRAM_ABORT); -+ } -+} -+ - // set `group ip` parameter - void program_param_parse_groupip(struct ProgramParams *params) - { -- in_addr_t ip = inet_addr(optarg); -- if (ip != INADDR_NONE && ip >= inet_addr("224.0.0.0") && ip <= inet_addr("239.255.255.255")) { -- params->groupip = optarg; -+ char *cur_ptr = NULL; -+ char *next_ptr = NULL; -+ -+ cur_ptr = strtok_s(optarg, ",", &next_ptr); -+ if (program_ipv4_check(cur_ptr) == false) { -+ PRINT_ERROR("illigal argument -- %s \n", cur_ptr); -+ exit(PROGRAM_ABORT); -+ } -+ -+ in_addr_t ip = ntohl(inet_addr(cur_ptr)); -+ if (ip != INADDR_NONE && ip >= ntohl(inet_addr("224.0.0.0")) && ip <= ntohl(inet_addr("239.255.255.255"))) { -+ params->groupip = cur_ptr; - } else { -- PRINT_ERROR("illigal argument -- %s \n", optarg); -+ PRINT_ERROR("illigal argument -- %s \n", cur_ptr); -+ exit(PROGRAM_ABORT); -+ } -+ -+ if (*next_ptr) { -+ if (program_ipv4_check(next_ptr)) { -+ params->groupip_interface = next_ptr; -+ } else { -+ PRINT_ERROR("illigal argument -- %s \n", next_ptr); -+ exit(PROGRAM_ABORT); -+ } -+ } -+} -+ -+void fault_inject_delay(delay_type type) -+{ -+ if (g_inject_delay[type]) { -+ printf("FAULT INJECT: Delay begin, sleep %d seconds.\n", g_inject_delay[type]); -+ sleep(g_inject_delay[type]); -+ g_inject_delay[type] = 0; -+ printf("FAULT INJECT: Delay finished.\n"); -+ } -+} -+ -+ -+// apply fault inject type of delay -+static void delay_param_parse(struct ProgramParams *params) -+{ -+ int32_t time = 0; -+ if (params->inject[INJECT_TIME_IDX] != NULL) { -+ time = atoi(params->inject[INJECT_TIME_IDX]); -+ } -+ if (time <= 0) { -+ PRINT_ERROR("FAULT INJECT: delay time input error! receive: \"%s\"\n", params->inject[INJECT_TIME_IDX]); -+ exit(PROGRAM_ABORT); -+ } -+ -+ char *location = params->inject[INJECT_LOCATION_IDX]; -+ if (location == NULL) { -+ PRINT_ERROR("FAULT INJECT: Lack param for delay fault inject, The location is not appointed.\n"); - exit(PROGRAM_ABORT); - } -+ -+ if (strcmp("before_accept", location) == 0) { -+ g_inject_delay[INJECT_DELAY_ACCEPT] = time; -+ return; -+ } -+ if (strcmp("before_read", location) == 0) { -+ g_inject_delay[INJECT_DELAY_READ] = time; -+ return; -+ } -+ if (strcmp("before_write", location) == 0) { -+ g_inject_delay[INJECT_DELAY_WRITE] = time; -+ return; -+ } -+ if (strcmp("before_read_and_write", location) == 0) { -+ g_inject_delay[INJECT_DELAY_READ] = time; -+ g_inject_delay[INJECT_DELAY_WRITE] = time; -+ return; -+ } -+ -+ PRINT_ERROR("FAULT INJECT: Unidentified fault inject location -- %s \n", location); -+ exit(PROGRAM_ABORT); -+} -+ -+// apply fault inject type of skip -+static void skip_param_parse(struct ProgramParams *params) -+{ -+ char* location = params->inject[INJECT_SKIP_IDX]; -+ if (location == NULL) { -+ PRINT_ERROR("FAULT INJECT: Lack param for skip fault inject, location is not appointed.\n"); -+ exit(PROGRAM_ABORT); -+ } -+ -+ if (strcmp("read", location) == 0) { -+ g_inject_skip[INJECT_SKIP_READ] = 1; -+ return; -+ } -+ if (strcmp("write", location) == 0) { -+ g_inject_skip[INJECT_SKIP_WRITE] = 1; -+ return; -+ } -+ if (strcmp("read_and_write", location) == 0) { -+ g_inject_skip[INJECT_SKIP_READ] = 1; -+ g_inject_skip[INJECT_SKIP_WRITE] = 1; -+ return; -+ } -+ -+ PRINT_ERROR("FAULT INJECT: Unidentified fault inject location -- %s \n", location); -+ exit(PROGRAM_ABORT); -+} -+ -+// judge if need skip fault inject -+int32_t get_g_inject_skip(skip_type type) -+{ -+ return g_inject_skip[type]; -+} -+ -+// check legitimacy of fault injection and apply it. -+static void apply_fault_inject(struct ProgramParams *params) -+{ -+ char *inject_type = params->inject[INJECT_TYPE_IDX]; -+ if (strcmp("delay", inject_type) == 0) { -+ delay_param_parse(params); -+ return; -+ } -+ if (strcmp("skip", inject_type) == 0) { -+ skip_param_parse(params); -+ return; -+ } -+ -+ PRINT_ERROR("FAULT INJCET: Unidentified fault inject -- %s \n", inject_type); -+ exit(PROGRAM_ABORT); -+} -+ -+// set `fault injection` parameter -+static void program_param_parse_inject(struct ProgramParams *params) -+{ -+ int32_t inject_idx = 0; -+ char *inject_input = strdup(optarg); -+ if (inject_input == NULL) { -+ PRINT_ERROR("FAULT INJCET: Insufficient memory, strdup failed.\n"); -+ exit(PROGRAM_ABORT); -+ } -+ -+ char *context = NULL; -+ char *elem = strtok_s(inject_input, " ", &context); -+ if (elem == NULL) { -+ PRINT_ERROR("FAULT INJECT: Input error. -- %s \n", inject_input); -+ exit(PROGRAM_ABORT); -+ } -+ while (elem != NULL) { -+ if (inject_idx == FAULT_INJECT_PARA_COUNT) { -+ PRINT_ERROR("FAULT INJECT: Exceed the max count (3) of fault inject params. -- %s\n", optarg); -+ exit(PROGRAM_ABORT); -+ } -+ params->inject[inject_idx++] = elem; -+ elem = strtok_s(NULL, " ", &context); -+ } -+ -+ apply_fault_inject(params); - } - - // initialize the parameters -@@ -219,8 +545,11 @@ void program_params_init(struct ProgramParams *params) - { - params->as = PARAM_DEFAULT_AS; - params->ip = PARAM_DEFAULT_IP; -- params->port = PARAM_DEFAULT_PORT; -- params->sport = PARAM_DEFAULT_SPORT; -+ params->ipv6 = PARAM_DEFAULT_IP_V6; -+ params->addr_family = PARAM_DEFAULT_ADDR_FAMILY; -+ memset_s(params->port, sizeof(bool)*UNIX_TCP_PORT_MAX, 0, sizeof(bool)*UNIX_TCP_PORT_MAX); -+ memset_s(params->sport, sizeof(bool)*UNIX_TCP_PORT_MAX, 0, sizeof(bool)*UNIX_TCP_PORT_MAX); -+ (params->port)[PARAM_DEFAULT_PORT] = 1; - params->model = PARAM_DEFAULT_MODEL; - params->thread_num = PARAM_DEFAULT_THREAD_NUM; - params->connect_num = PARAM_DEFAULT_CONNECT_NUM; -@@ -233,15 +562,19 @@ void program_params_init(struct ProgramParams *params) - params->epollcreate = PARAM_DEFAULT_EPOLLCREATE; - params->accept = PARAM_DEFAULT_ACCEPT; - params->groupip = PARAM_DEFAULT_GROUPIP; -+ params->groupip_interface = PARAM_DEFAULT_GROUPIP; -+ params->tcp_keepalive_idle = PARAM_DEFAULT_KEEPALIVEIDLE; -+ params->tcp_keepalive_interval = PARAM_DEFAULT_KEEPALIVEIDLE; - } - - // print program helps - void program_params_help(void) - { - printf("\n"); -- printf("-a, --as [server | client]: set programas server or client. \n"); -+ printf("-a, --as [server | client | loop]: set programas server, client or loop. \n"); - printf(" server: as server. \n"); - printf(" client: as client. \n"); -+ printf(" loop: as server and client. \n"); - printf("-i, --ip [???.???.???.???]: set ip address. \n"); - printf("-g, --groupip [???.???.???.???]: set group ip address. \n"); - printf("-p, --port [????]: set port number in range of %d - %d. \n", UNIX_TCP_PORT_MIN, UNIX_TCP_PORT_MAX); -@@ -268,6 +601,16 @@ void program_params_help(void) - printf("-h, --help: see helps. \n"); - printf("-E, --epollcreate [ec | ec1]: epoll_create method. \n"); - printf("-C, --accept [ac | ac4]: accept method. \n"); -+ printf("-k, --keep_alive [keep_alive_idle:keep_alive_interval]: set tcp-alive info in range of %d-%d. \n", -+ PARAM_DEFAULT_KEEPALIVEIDLE, TCP_KEEPALIVE_IDLE_MAX); -+ printf("-I, --inject [\"fault_inject_param0 fault_inject_param1 fault_inject_param2\"]: fault inject\n"); -+ printf(" for example: \"delay 20 before_accept\"\n"); -+ printf(" \"delay 20 before_read\"\n"); -+ printf(" \"delay 20 before_write\"\n"); -+ printf(" \"delay 20 before_read_and_write\"\n"); -+ printf(" \"skip read\"\n"); -+ printf(" \"skip write\"\n"); -+ printf(" \"skip read_and_write\"\n"); - printf("\n"); - } - -@@ -295,7 +638,7 @@ int32_t program_params_parse(struct ProgramParams *params, uint32_t argc, char * - case (PARAM_NUM_PORT): - program_param_parse_port(params); - break; -- case (PARAM_NUM_SPORT): -+ case (PARAM_NUM_SPORT): - program_param_parse_sport(params); - break; - case (PARAM_NUM_MODEL): -@@ -331,9 +674,15 @@ int32_t program_params_parse(struct ProgramParams *params, uint32_t argc, char * - case (PARAM_NUM_ACCEPT): - program_param_parse_accept(params); - break; -- case (PARAM_NUM_GROUPIP): -- program_param_parse_groupip(params); -- break; -+ case (PARAM_NUM_GROUPIP): -+ program_param_parse_groupip(params); -+ break; -+ case (PARAM_NUM_KEEPALIVE): -+ program_param_parse_keepalive(params); -+ break; -+ case (PARAM_NUM_INJECT): -+ program_param_parse_inject(params); -+ break; - case (PARAM_NUM_HELP): - program_params_help(); - return PROGRAM_ABORT; -@@ -345,11 +694,6 @@ int32_t program_params_parse(struct ProgramParams *params, uint32_t argc, char * - } - } - -- if (strcmp(params->domain, "tcp") != 0) { -- params->thread_num = 1; -- params->connect_num = 1; -- } -- - return PROGRAM_OK; - } - -@@ -361,22 +705,47 @@ void program_params_print(struct ProgramParams *params) - printf("--> [as]: %s \n", params->as); - if (strcmp(params->groupip, PARAM_DEFAULT_GROUPIP) != 0) { - if (strcmp(params->as, "server") == 0) { -- printf("--> [server ip]: %s \n", params->ip); - printf("--> [server group ip]: %s \n", params->groupip); -+ printf("--> [server groupip_interface]: %s \n", params->groupip_interface); - } else { -- printf("--> [server ip]: %s \n", params->groupip); -- printf("--> [client send ip]: %s \n", params->ip); -+ printf("--> [client group ip]: %s \n", params->groupip); -+ printf("--> [client groupip_interface]: %s \n", params->groupip_interface); - } -- } else { -- printf("--> [server ip]: %s \n", params->ip); - } -- if ((strcmp(params->as, "server") == 0 && strcmp(params->groupip, PARAM_DEFAULT_GROUPIP)) != 0) { -- printf("--> [server group ip]: %s \n", params->groupip); -+ printf("--> [server ip]: %s \n", params->ip); -+ if (strcmp(params->ipv6, PARAM_DEFAULT_IP_V6) != 0) { -+ printf("--> [server ipv6]: %s \n", params->ipv6); -+ } -+ -+ printf("--> [server port]: "); -+ uint32_t comma = 0; -+ uint32_t sport = 0; -+ -+ /* use comma to print port list */ -+ for (uint32_t i = UNIX_TCP_PORT_MIN; i < UNIX_TCP_PORT_MAX; i++) { -+ if ((params->port)[i]) { -+ printf("%s%u", comma?",":"", i); -+ comma = 1; -+ } -+ if ((params->sport)[i]) { -+ sport = i; -+ } - } -- printf("--> [server port]: %u \n", params->port); -- if (params->sport && strcmp(params->as, "client") == 0) { -- printf("--> [client sport]: %u \n", params->sport); -+ printf(" \n"); -+ -+ /* use comma to print sport list */ -+ if (sport && strcmp(params->as, "client") == 0) { -+ printf("--> [client sport]: "); -+ comma = 0; -+ for (uint32_t i = UNIX_TCP_PORT_MIN; i < sport + 1; i++) { -+ if ((params->sport)[i]) { -+ printf("%s%u", comma?",":"", i); -+ comma = 1; -+ } -+ } -+ printf(" \n"); - } -+ - if (strcmp(params->as, "server") == 0) { - printf("--> [model]: %s \n", params->model); - } -@@ -404,5 +773,16 @@ void program_params_print(struct ProgramParams *params) - printf("--> [debug]: %s \n", (params->debug == true) ? "on" : "off"); - printf("--> [epoll create]: %s \n", params->epollcreate); - printf("--> [accept]: %s \n", params->accept); -+ printf("--> [inject]: "); -+ if (params->inject[INJECT_TYPE_IDX] == NULL) { -+ printf("none \n"); -+ } else { -+ for (int32_t i = 0; i < FAULT_INJECT_PARA_COUNT; ++i) { -+ if (params->inject[i] != NULL) { -+ printf("%s ", params->inject[i]); -+ } -+ } -+ printf("\n"); -+ } - printf("\n"); - } -diff --git a/examples/src/server.c b/examples/src/server.c -index 8634dde..7bc7d9e 100644 ---- a/examples/src/server.c -+++ b/examples/src/server.c -@@ -14,20 +14,22 @@ - #include "server.h" - - static pthread_mutex_t server_debug_mutex; // the server mutex for debug -+struct LoopInfo loopmod; - - // server debug information print --void server_debug_print(const char *ch_str, const char *act_str, in_addr_t ip, uint16_t port, bool debug) -+void server_debug_print(const char *ch_str, const char *act_str, ip_addr_t *ip, uint16_t port, bool debug) - { - if (debug == true) { - pthread_mutex_lock(&server_debug_mutex); -- struct in_addr sin_addr; -- sin_addr.s_addr = ip; -+ uint8_t str_len = ip->addr_family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; -+ char str_ip[str_len]; -+ inet_ntop(ip->addr_family, &ip->u_addr, str_ip, str_len); - PRINT_SERVER("[%s] [pid: %d] [tid: %ld] [%s <- %s:%d]. ", \ - ch_str, \ - getpid(), \ - pthread_self(), \ - act_str, \ -- inet_ntoa(sin_addr), \ -+ str_ip, \ - ntohs(port)); - pthread_mutex_unlock(&server_debug_mutex); - } -@@ -37,7 +39,7 @@ void server_debug_print(const char *ch_str, const char *act_str, in_addr_t ip, u - void sermud_info_print(struct ServerMud *server_mud) - { - if (server_mud->debug == false) { -- uint32_t curr_connect = server_mud->curr_connect; -+ uint32_t curr_connect = 0; - - struct timeval begin; - gettimeofday(&begin, NULL); -@@ -48,6 +50,7 @@ void sermud_info_print(struct ServerMud *server_mud) - struct ServerMudWorker *begin_uint = server_mud->workers; - while (begin_uint != NULL) { - begin_recv_bytes += begin_uint->recv_bytes; -+ curr_connect += begin_uint->curr_connect; - begin_uint = begin_uint->next; - } - -@@ -122,45 +125,82 @@ int32_t sermud_listener_create_epfd_and_reg(struct ServerMud *server_mud) - } - - struct epoll_event ep_ev; -- ep_ev.data.ptr = (void *)&(server_mud->listener); - ep_ev.events = EPOLLIN | EPOLLET; -- if (epoll_ctl(server_mud->epfd, EPOLL_CTL_ADD, server_mud->listener.fd, &ep_ev) < 0) { -- PRINT_ERROR("server can't control epoll %d! ", errno); -- return PROGRAM_FAULT; -+ for (int i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ if (server_mud->listener.listen_fd_array[i] != -1) { -+ struct ServerHandler *server_handler = (struct ServerHandler *)malloc(sizeof(struct ServerHandler)); -+ memset_s(server_handler, sizeof(struct ServerHandler), 0, sizeof(struct ServerHandler)); -+ server_handler->fd = server_mud->listener.listen_fd_array[i]; -+ ep_ev.data.ptr = (void *)server_handler; -+ if (epoll_ctl(server_mud->epfd, EPOLL_CTL_ADD, server_mud->listener.listen_fd_array[i], &ep_ev) < 0) { -+ PRINT_ERROR("epoll_ctl failed %d! listen_fd=%d ", errno, server_mud->listener.listen_fd_array[i]); -+ return PROGRAM_FAULT; -+ } -+ } -+ } -+ -+ return PROGRAM_OK; -+} -+ -+static void sermud_accept_get_remote_ip(sockaddr_t *accept_addr, ip_addr_t *remote_ip, bool is_tcp_v6_flag) -+{ -+ remote_ip->addr_family = is_tcp_v6_flag ? AF_INET6 : AF_INET; -+ if (is_tcp_v6_flag == false) { -+ remote_ip->u_addr.ip4 = ((struct sockaddr_in *)accept_addr)->sin_addr; -+ } else { -+ remote_ip->u_addr.ip6 = ((struct sockaddr_in6 *)accept_addr)->sin6_addr; - } -+} - -- server_debug_print("server mud listener", "waiting", server_mud->ip, server_mud->port, server_mud->debug); -+int32_t sermud_set_socket_opt(int32_t accept_fd, struct ServerMud *server_mud) -+{ -+ if (set_tcp_keep_alive_info(accept_fd, server_mud->tcp_keepalive_idle, server_mud->tcp_keepalive_interval) < 0) { -+ PRINT_ERROR("cant't set_tcp_keep_alive_info! "); -+ return PROGRAM_FAULT; -+ } - -+ if (set_socket_unblock(accept_fd) < 0) { -+ PRINT_ERROR("server can't set the connect socket to unblock! "); -+ return PROGRAM_FAULT; -+ } - return PROGRAM_OK; - } - - // the listener thread, unblock, dissymmetric server accepts the connections --int32_t sermud_listener_accept_connects(struct ServerMud *server_mud) -+int32_t sermud_listener_accept_connects(struct epoll_event *curr_epev, struct ServerMud *server_mud) - { -+ int32_t fd = ((struct ServerHandler*)(curr_epev->data.ptr))->fd; -+ fault_inject_delay(INJECT_DELAY_ACCEPT); -+ - while (true) { -- struct sockaddr_in accept_addr; -- uint32_t sockaddr_in_len = sizeof(struct sockaddr_in); -+ sockaddr_t accept_addr; -+ bool is_tcp_v6_flag = (fd == server_mud->listener.listen_fd_array[V6_TCP]) ? true : false; -+ -+ uint32_t sockaddr_in_len = is_tcp_v6_flag ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); -+ - int32_t accept_fd; -- if (strcmp(server_mud->domain, "udp") == 0) { -- break; -- } -+ -+ int32_t listen_fd_index = is_tcp_v6_flag ? V6_TCP : V4_TCP; -+ int32_t listen_fd = server_mud->listener.listen_fd_array[listen_fd_index]; - - if (strcmp(server_mud->accept, "ac4") == 0) { -- accept_fd = accept4(server_mud->listener.fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len, SOCK_CLOEXEC); -+ accept_fd = accept4(listen_fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len, SOCK_CLOEXEC); - } else { -- accept_fd = accept(server_mud->listener.fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len); -+ accept_fd = accept(listen_fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len); - } -- -+ - if (accept_fd < 0) { - break; - } - -- if (set_socket_unblock(accept_fd) < 0) { -- PRINT_ERROR("server can't set the connect socket to unblock! "); -+ if (sermud_set_socket_opt(accept_fd, server_mud) < 0) { - return PROGRAM_FAULT; - } - -- ++(server_mud->curr_connect); -+ // sockaddr to ip, port -+ ip_addr_t remote_ip; -+ uint16_t remote_port = ((struct sockaddr_in *)&accept_addr)->sin_port; -+ sermud_accept_get_remote_ip(&accept_addr, &remote_ip, is_tcp_v6_flag); - - pthread_t *tid = (pthread_t *)malloc(sizeof(pthread_t)); - struct ServerMudWorker *worker = (struct ServerMudWorker *)malloc(sizeof(struct ServerMudWorker)); -@@ -169,26 +209,50 @@ int32_t sermud_listener_accept_connects(struct ServerMud *server_mud) - worker->epevs = (struct epoll_event *)malloc(sizeof(struct epoll_event)); - worker->recv_bytes = 0; - worker->pktlen = server_mud->pktlen; -- worker->ip = accept_addr.sin_addr.s_addr; -- worker->port = accept_addr.sin_port; -+ worker->ip = remote_ip; -+ worker->port = remote_port; - worker->api = server_mud->api; - worker->debug = server_mud->debug; - worker->next = server_mud->workers; - worker->epollcreate = server_mud->epollcreate; -+ worker->worker.is_v6 = is_tcp_v6_flag ? 1 : 0; -+ worker->domain = server_mud->domain; -+ worker->curr_connect = 1; - - server_mud->workers = worker; - -- if (pthread_create(tid, NULL, sermud_worker_create_and_run, server_mud) < 0) { -+ if (pthread_create(tid, NULL, sermud_worker_create_and_run, worker) < 0) { - PRINT_ERROR("server can't create poisx thread %d! ", errno); - return PROGRAM_FAULT; - } - -- server_debug_print("server mud listener", "accept", accept_addr.sin_addr.s_addr, accept_addr.sin_port, server_mud->debug); -+ server_debug_print("server mud listener", "accept", &remote_ip, remote_port, server_mud->debug); - } - - return PROGRAM_OK; - } - -+static int32_t server_handler_close(int32_t epfd, struct ServerHandler *server_handler) -+{ -+ int32_t fd = server_handler->fd; -+ struct epoll_event ep_ev; -+ if (server_handler) { -+ free(server_handler); -+ } -+ -+ if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ep_ev) < 0) { -+ PRINT_ERROR("server can't delete socket '%d' to control epoll %d! ", fd, errno); -+ return PROGRAM_FAULT; -+ } -+ -+ if (close(fd) < 0) { -+ PRINT_ERROR("server can't close the socket %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ -+ return 0; -+} -+ - // the worker thread, unblock, dissymmetric server processes the events - int32_t sermud_worker_proc_epevs(struct ServerMudWorker *worker_unit, const char* domain) - { -@@ -201,32 +265,60 @@ int32_t sermud_worker_proc_epevs(struct ServerMudWorker *worker_unit, const char - for (int32_t i = 0; i < epoll_nfds; ++i) { - struct epoll_event *curr_epev = worker_unit->epevs + i; - -- if (curr_epev->events == EPOLLERR || curr_epev->events == EPOLLHUP || curr_epev->events == EPOLLRDHUP) { -+ if (curr_epev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { -+ worker_unit->curr_connect--; - PRINT_ERROR("server epoll wait error %d! ", curr_epev->events); -- return PROGRAM_FAULT; -+ if (server_handler_close(worker_unit->epfd, (struct ServerHandler *)curr_epev->data.ptr) != 0) { -+ return PROGRAM_FAULT; -+ } - } - - if (curr_epev->events == EPOLLIN) { - struct ServerHandler *server_handler = (struct ServerHandler *)curr_epev->data.ptr; - -- int32_t server_ans_ret = server_ans(server_handler, worker_unit->pktlen, worker_unit->api, domain); -+ int32_t server_ans_ret = server_ans(server_handler->fd, worker_unit->pktlen, worker_unit->api, "tcp"); - if (server_ans_ret == PROGRAM_FAULT) { -- struct epoll_event ep_ev; -- if (epoll_ctl(worker_unit->epfd, EPOLL_CTL_DEL, server_handler->fd, &ep_ev) < 0) { -- PRINT_ERROR("server can't delete socket '%d' to control epoll %d! ", server_handler->fd, errno); -+ worker_unit->curr_connect--; -+ if (server_handler_close(worker_unit->epfd, server_handler) != 0) { - return PROGRAM_FAULT; - } - } else if (server_ans_ret == PROGRAM_ABORT) { -- if (close(server_handler->fd) < 0) { -- PRINT_ERROR("server can't close the socket %d! ", errno); -+ worker_unit->curr_connect--; -+ server_debug_print("server mud worker", "close", &worker_unit->ip, worker_unit->port, worker_unit->debug); -+ if (server_handler_close(worker_unit->epfd, server_handler) != 0) { - return PROGRAM_FAULT; - } -- server_debug_print("server mud worker", "close", worker_unit->ip, worker_unit->port, worker_unit->debug); - } else { - worker_unit->recv_bytes += worker_unit->pktlen; -- server_debug_print("server mud worker", "receive", worker_unit->ip, worker_unit->port, worker_unit->debug); -+ server_debug_print("server mud worker", "receive", &worker_unit->ip, worker_unit->port, worker_unit->debug); -+ } -+ } -+ } -+ -+ return PROGRAM_OK; -+} -+ -+static int32_t sermud_process_epollin_event(struct epoll_event *curr_epev, struct ServerMud *server_mud) -+{ -+ struct ServerHandler *server_handler = (struct ServerHandler *)curr_epev->data.ptr; -+ -+ if (server_handler->fd == server_mud->listener.listen_fd_array[V4_UDP] || -+ server_handler->fd == server_mud->listener.listen_fd_array[UDP_MULTICAST]) { -+ uint32_t pktlen = server_mud->pktlen > UDP_PKTLEN_MAX ? UDP_PKTLEN_MAX : server_mud->pktlen; -+ int32_t server_ans_ret = server_ans(server_handler->fd, pktlen, server_mud->api, "udp"); -+ if (server_ans_ret != PROGRAM_OK) { -+ if (server_handler_close(server_mud->epfd, server_handler) != 0) { -+ PRINT_ERROR("server_handler_close server_ans_ret %d! \n", server_ans_ret); -+ return PROGRAM_FAULT; - } - } -+ server_mud->workers->recv_bytes += pktlen; -+ } else { -+ int32_t sermud_listener_accept_connects_ret = sermud_listener_accept_connects(curr_epev, server_mud); -+ if (sermud_listener_accept_connects_ret < 0) { -+ PRINT_ERROR("server try accept error %d! ", sermud_listener_accept_connects_ret); -+ return PROGRAM_FAULT; -+ } - } - - return PROGRAM_OK; -@@ -244,15 +336,14 @@ int32_t sermud_listener_proc_epevs(struct ServerMud *server_mud) - for (int32_t i = 0; i < epoll_nfds; ++i) { - struct epoll_event *curr_epev = server_mud->epevs + i; - -- if (curr_epev->events == EPOLLERR || curr_epev->events == EPOLLHUP || curr_epev->events == EPOLLRDHUP) { -+ if (curr_epev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { - PRINT_ERROR("server epoll wait error %d! ", curr_epev->events); -- return PROGRAM_FAULT; -+ server_handler_close(server_mud->epfd, (struct ServerHandler *)curr_epev->data.ptr); -+ return PROGRAM_OK; - } - - if (curr_epev->events == EPOLLIN) { -- int32_t sermud_listener_accept_connects_ret = sermud_listener_accept_connects(server_mud); -- if (sermud_listener_accept_connects_ret < 0) { -- PRINT_ERROR("server try accept error %d! ", sermud_listener_accept_connects_ret); -+ if (sermud_process_epollin_event(curr_epev, server_mud) < 0) { - return PROGRAM_FAULT; - } - } -@@ -266,15 +357,15 @@ void *sermud_worker_create_and_run(void *arg) - { - pthread_detach(pthread_self()); - -- struct ServerMudWorker *worker_unit = ((struct ServerMud *)arg)->workers; -- char* domain = ((struct ServerMud *)arg)->domain; -+ struct ServerMudWorker *worker_unit = (struct ServerMudWorker *)arg; -+ char *domain = worker_unit->domain; - - if (sermud_worker_create_epfd_and_reg(worker_unit) < 0) { -- exit(PROGRAM_FAULT); -+ return (void *)PROGRAM_OK; - } - while (true) { - if (sermud_worker_proc_epevs(worker_unit, domain) < 0) { -- exit(PROGRAM_FAULT); -+ return (void *)PROGRAM_OK; - } - } - -@@ -284,26 +375,60 @@ void *sermud_worker_create_and_run(void *arg) - return (void *)PROGRAM_OK; - } - -+void sermud_memory_recycle(struct ServerMud *server_mud) -+{ -+ // recycle mem of epevs -+ if (server_mud->epevs) { -+ free(server_mud->epevs); -+ } -+ struct ServerMudWorker *head = server_mud->workers; -+ while (head) { -+ if (head->epevs) { -+ free(head->epevs); -+ } -+ struct ServerMudWorker *next = head->next; -+ free(head); -+ head = next; -+ } -+} -+ - // create the listener thread, unblock, dissymmetric server and run - void *sermud_listener_create_and_run(void *arg) - { - struct ServerMud *server_mud = (struct ServerMud *)arg; - -- if (create_socket_and_listen(&(server_mud->listener.fd), server_mud->ip, server_mud->groupip, server_mud->port, server_mud->domain) < 0) { -- exit(PROGRAM_FAULT); -+ uint32_t port = 0; -+ for (; port < UNIX_TCP_PORT_MAX; port++) { -+ if ((server_mud->port)[port]) { -+ if (create_socket_and_listen(server_mud->listener.listen_fd_array, &(server_mud->server_ip_info), -+ htons(port), server_mud->protocol_type_mode) < 0) { -+ PRINT_ERROR("create_socket_and_listen err"); -+ sermud_memory_recycle(server_mud); -+ exit(PROGRAM_FAULT); -+ } -+ } - } -+ - if (sermud_listener_create_epfd_and_reg(server_mud) < 0) { -- exit(PROGRAM_FAULT); -+ sermud_memory_recycle(server_mud); -+ exit(PROGRAM_FAULT); - } - while (true) { - if (sermud_listener_proc_epevs(server_mud) < 0) { -+ sermud_memory_recycle(server_mud); - exit(PROGRAM_FAULT); - } - } -- if (close(server_mud->listener.fd) < 0 || close(server_mud->epfd) < 0) { -- exit(PROGRAM_FAULT); -- } - -+ for (int i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ if (server_mud->listener.listen_fd_array[i] == -1) -+ continue; -+ if (close(server_mud->listener.listen_fd_array[i]) < 0) { -+ sermud_memory_recycle(server_mud); -+ exit(PROGRAM_FAULT); -+ } -+ } -+ sermud_memory_recycle(server_mud); - return (void *)PROGRAM_OK; - } - -@@ -319,19 +444,44 @@ int32_t sermud_create_and_run(struct ProgramParams *params) - } - - server_mud->listener.fd = -1; -- server_mud->workers = NULL; -+ for (int32_t i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ server_mud->listener.listen_fd_array[i] = -1; -+ } -+ -+ struct ServerMudWorker *workers = (struct ServerMudWorker *)malloc(sizeof(struct ServerMudWorker)); -+ if (workers == NULL) { -+ PRINT_ERROR("malloc truct ServerMudWorker failed "); -+ return PROGRAM_FAULT; -+ } -+ memset_s(workers, sizeof(struct ServerMudWorker), 0, sizeof(struct ServerMudWorker)); -+ workers->next = NULL; -+ server_mud->workers = workers; -+ - server_mud->epfd = -1; - server_mud->epevs = (struct epoll_event *)malloc(SERVER_EPOLL_SIZE_MAX * sizeof(struct epoll_event)); -- server_mud->curr_connect = 0; -- server_mud->ip = inet_addr(params->ip); -- server_mud->groupip = inet_addr(params->groupip); -- server_mud->port = htons(params->port); -+ server_mud->server_ip_info.ip.addr_family = params->addr_family; -+ -+ inet_pton(AF_INET, params->ip, &server_mud->server_ip_info.ip.u_addr.ip4); -+ inet_pton(AF_INET6, params->ipv6, &server_mud->server_ip_info.ip.u_addr.ip6); -+ -+ server_mud->server_ip_info.groupip.addr_family = params->addr_family; -+ inet_pton(AF_INET, params->groupip, &server_mud->server_ip_info.groupip.u_addr); -+ -+ server_mud->server_ip_info.groupip_interface.addr_family = params->addr_family; -+ inet_pton(AF_INET, params->groupip_interface, &server_mud->server_ip_info.groupip_interface.u_addr); -+ -+ server_mud->port = params->port; - server_mud->pktlen = params->pktlen; -- server_mud->domain = params->domain; -+ -+ server_mud->protocol_type_mode = program_get_protocol_mode_by_domain_ip(params->domain, params->ip, params->ipv6, -+ params->groupip); -+ - server_mud->api = params->api; - server_mud->debug = params->debug; - server_mud->epollcreate = params->epollcreate; - server_mud->accept = params->accept; -+ server_mud->tcp_keepalive_idle = params->tcp_keepalive_idle; -+ server_mud->tcp_keepalive_interval = params->tcp_keepalive_interval; - - if (pthread_create(tid, NULL, sermud_listener_create_and_run, server_mud) < 0) { - PRINT_ERROR("server can't create poisx thread %d! ", errno); -@@ -341,10 +491,17 @@ int32_t sermud_create_and_run(struct ProgramParams *params) - if (server_mud->debug == false) { - printf("[program informations]: \n\n"); - } -- while (true) { -- sermud_info_print(server_mud); -+ -+ if (strcmp(params->as, "server") == 0) { -+ while (true) { -+ sermud_info_print(server_mud); -+ } -+ } else if (strcmp(params->as, "loop") == 0) { -+ loopmod.model = params->model; -+ loopmod.server_mud_info = server_mud; - } - -+ - pthread_mutex_destroy(&server_debug_mutex); - - return PROGRAM_OK; -@@ -413,39 +570,62 @@ int32_t sersum_create_epfd_and_reg(struct ServerMumUnit *server_unit) - return PROGRAM_FAULT; - } - -- struct epoll_event ep_ev; -- ep_ev.data.ptr = (void *)&(server_unit->listener); -+ struct epoll_event ep_ev = {0}; - ep_ev.events = EPOLLIN | EPOLLET; -- if (epoll_ctl(server_unit->epfd, EPOLL_CTL_ADD, server_unit->listener.fd, &ep_ev) < 0) { -- PRINT_ERROR("server can't control epoll %d! ", errno); -- return PROGRAM_FAULT; -+ -+ for (int32_t i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ if (server_unit->listener.listen_fd_array[i] != -1) { -+ struct ServerHandler *server_handler = (struct ServerHandler *)malloc(sizeof(struct ServerHandler)); -+ memset_s(server_handler, sizeof(struct ServerHandler), 0, sizeof(struct ServerHandler)); -+ server_handler->fd = server_unit->listener.listen_fd_array[i]; -+ -+ ep_ev.data.ptr = (void *)server_handler; -+ if (epoll_ctl(server_unit->epfd, EPOLL_CTL_ADD, server_unit->listener.listen_fd_array[i], &ep_ev) < 0) { -+ PRINT_ERROR("epoll_ctl failed %d! listen_fd=%d ", errno, server_unit->listener.listen_fd_array[i]); -+ return PROGRAM_FAULT; -+ } -+ } - } - -- server_debug_print("server mum unit", "waiting", server_unit->ip, server_unit->port, server_unit->debug); -+ server_debug_print("server mum unit", "waiting", &server_unit->server_ip_info.ip, server_unit->port, -+ server_unit->debug); - - return PROGRAM_OK; - } - - // the single thread, unblock, mutliplexing IO server accepts the connections --int32_t sersum_accept_connects(struct ServerMumUnit *server_unit, struct ServerHandler *server_handler) -+int32_t sersum_accept_connects(struct epoll_event *cur_epev, struct ServerMumUnit *server_unit) - { -+ fault_inject_delay(INJECT_DELAY_ACCEPT); -+ int32_t fd = ((struct ServerHandler*)(cur_epev->data.ptr))->fd; - while (true) { -- struct sockaddr_in accept_addr; -- uint32_t sockaddr_in_len = sizeof(struct sockaddr_in); -+ sockaddr_t accept_addr; -+ bool is_tcp_v6 = (fd == (server_unit->listener.listen_fd_array[V6_TCP])) ? true : false; -+ -+ socklen_t sockaddr_in_len = is_tcp_v6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); - int32_t accept_fd; -- if (strcmp(server_unit->domain, "udp") == 0) { -- break; -- } -+ int32_t ret = 0; -+ -+ int32_t listen_index = (is_tcp_v6) ? V6_TCP : V4_TCP; -+ int32_t listen_fd = server_unit->listener.listen_fd_array[listen_index]; - - if (strcmp(server_unit->accept, "ac4") == 0) { -- accept_fd = accept4(server_unit->listener.fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len, SOCK_CLOEXEC); -+ accept_fd = accept4(listen_fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len, SOCK_CLOEXEC); - } else { -- accept_fd = accept(server_unit->listener.fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len); -+ accept_fd = accept(listen_fd, (struct sockaddr *)&accept_addr, &sockaddr_in_len); - } -- -+ - if (accept_fd < 0) { -+ if (errno != EWOULDBLOCK && errno != EAGAIN){ -+ PRINT_ERROR("accept_fd=%d , errno=%d ", accept_fd, errno); -+ } - break; - } -+ ret = set_tcp_keep_alive_info(accept_fd, server_unit->tcp_keepalive_idle, server_unit->tcp_keepalive_interval); -+ if (ret < 0) { -+ PRINT_ERROR("set_tcp_keep_alive_info ret=%d \n", ret); -+ return PROGRAM_FAULT; -+ } - - if (set_socket_unblock(accept_fd) < 0) { - PRINT_ERROR("server can't set the connect socket to unblock! "); -@@ -454,6 +634,8 @@ int32_t sersum_accept_connects(struct ServerMumUnit *server_unit, struct ServerH - - struct ServerHandler *server_handler = (struct ServerHandler *)malloc(sizeof(struct ServerHandler)); - server_handler->fd = accept_fd; -+ server_handler->is_v6 = (is_tcp_v6) ? 1 : 0; -+ - struct epoll_event ep_ev; - ep_ev.data.ptr = (void *)server_handler; - ep_ev.events = EPOLLIN | EPOLLET; -@@ -463,13 +645,98 @@ int32_t sersum_accept_connects(struct ServerMumUnit *server_unit, struct ServerH - } - - ++server_unit->curr_connect; -- -- server_debug_print("server mum unit", "accept", accept_addr.sin_addr.s_addr, accept_addr.sin_port, server_unit->debug); -+ -+ // sockaddr tp ip, port -+ ip_addr_t remote_ip; -+ uint16_t remote_port = ((struct sockaddr_in*)&accept_addr)->sin_port; -+ remote_ip.addr_family = (is_tcp_v6) ? AF_INET6 : AF_INET; -+ if (is_tcp_v6 == false) { -+ remote_ip.u_addr.ip4 = ((struct sockaddr_in *)&accept_addr)->sin_addr; -+ } else { -+ remote_ip.u_addr.ip6 = ((struct sockaddr_in6 *)&accept_addr)->sin6_addr; -+ } -+ -+ server_debug_print("server mum unit", "accept", &remote_ip, remote_port, server_unit->debug); - } - - return PROGRAM_OK; - } - -+static int sersum_get_remote_ip(struct ServerHandler *server_handler, ip_addr_t *remote_ip, uint16_t *remote_port) -+{ -+ sockaddr_t connect_addr; -+ socklen_t connect_addr_len = server_handler->is_v6 == 0 ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); -+ if (getpeername(server_handler->fd, (struct sockaddr *)&connect_addr, &connect_addr_len) < 0) { -+ PRINT_ERROR("server can't socket peername %d! ", errno); -+ return PROGRAM_ABORT; -+ } -+ -+ *remote_port = ((struct sockaddr_in *)&connect_addr)->sin_port; -+ if (((struct sockaddr *)&connect_addr)->sa_family == AF_INET) { -+ remote_ip->addr_family = AF_INET; -+ remote_ip->u_addr.ip4 = ((struct sockaddr_in *)&connect_addr)->sin_addr; -+ } else if (((struct sockaddr *)&connect_addr)->sa_family == AF_INET6) { -+ remote_ip->addr_family = AF_INET6; -+ remote_ip->u_addr.ip6 = ((struct sockaddr_in6 *)&connect_addr)->sin6_addr; -+ } -+ return PROGRAM_OK; -+} -+ -+static int sersum_process_tcp_accept_event(struct ServerMumUnit *server_unit, struct epoll_event *curr_epev) -+{ -+ struct ServerHandler *server_handler = (struct ServerHandler *)curr_epev->data.ptr; -+ ip_addr_t remote_ip; -+ uint16_t remote_port; -+ -+ if (sersum_get_remote_ip(server_handler, &remote_ip, &remote_port) != PROGRAM_OK) { -+ return PROGRAM_ABORT; -+ } -+ -+ int32_t server_ans_ret = server_ans(server_handler->fd, server_unit->pktlen, server_unit->api, "tcp"); -+ if (server_ans_ret == PROGRAM_FAULT) { -+ --server_unit->curr_connect; -+ server_handler_close(server_unit->epfd, server_handler); -+ } else if (server_ans_ret == PROGRAM_ABORT) { -+ --server_unit->curr_connect; -+ server_debug_print("server mum unit", "close", &remote_ip, remote_port, server_unit->debug); -+ server_handler_close(server_unit->epfd, server_handler); -+ } else { -+ server_unit->recv_bytes += server_unit->pktlen; -+ server_debug_print("server mum unit", "receive", &remote_ip, remote_port, server_unit->debug); -+ } -+ return PROGRAM_OK; -+} -+ -+static int sersum_process_epollin_event(struct ServerMumUnit *server_unit, struct epoll_event *curr_epev) -+{ -+ struct ServerHandler *server_handler = (struct ServerHandler *)curr_epev->data.ptr; -+ int32_t fd = server_handler->fd; -+ if (fd == (server_unit->listener.listen_fd_array[V4_TCP]) || -+ fd == (server_unit->listener.listen_fd_array[V6_TCP])) { -+ int32_t sersum_accept_connects_ret = sersum_accept_connects(curr_epev, server_unit); -+ if (sersum_accept_connects_ret < 0) { -+ PRINT_ERROR("server try accept error %d! ", sersum_accept_connects_ret); -+ return PROGRAM_ABORT; -+ } -+ } else if (fd == (server_unit->listener.listen_fd_array[V4_UDP]) || -+ fd == (server_unit->listener.listen_fd_array[UDP_MULTICAST])) { -+ uint32_t pktlen = server_unit->pktlen > UDP_PKTLEN_MAX ? UDP_PKTLEN_MAX : server_unit->pktlen; -+ int32_t server_ans_ret = server_ans(fd, pktlen, server_unit->api, "udp"); -+ if (server_ans_ret != PROGRAM_OK) { -+ if (server_handler_close(server_unit->epfd, server_handler) != 0) { -+ PRINT_ERROR("server_handler_close ret %d! \n", server_ans_ret); -+ return PROGRAM_ABORT; -+ } -+ } -+ server_unit->recv_bytes += pktlen; -+ } else { -+ if (sersum_process_tcp_accept_event(server_unit, curr_epev) != PROGRAM_OK) { -+ return PROGRAM_ABORT; -+ } -+ } -+ return PROGRAM_OK; -+} -+ - // the single thread, unblock, mutliplexing IO server processes the events - int32_t sersum_proc_epevs(struct ServerMumUnit *server_unit) - { -@@ -482,47 +749,16 @@ int32_t sersum_proc_epevs(struct ServerMumUnit *server_unit) - for (int32_t i = 0; i < epoll_nfds; ++i) { - struct epoll_event *curr_epev = server_unit->epevs + i; - -- if (curr_epev->events == EPOLLERR || curr_epev->events == EPOLLHUP || curr_epev->events == EPOLLRDHUP) { -- PRINT_ERROR("server epoll wait error %d! ", curr_epev->events); -- return PROGRAM_FAULT; -+ if (curr_epev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { -+ server_unit->curr_connect--; -+ if (server_handler_close(server_unit->epfd, (struct ServerHandler *)curr_epev->data.ptr) != 0) { -+ return PROGRAM_OK; -+ } - } - - if (curr_epev->events == EPOLLIN) { -- if (curr_epev->data.ptr == (void *)&(server_unit->listener) && strcmp(server_unit->domain, "udp") != 0) { -- int32_t sersum_accept_connects_ret = sersum_accept_connects(server_unit, &(server_unit->listener)); -- if (sersum_accept_connects_ret < 0) { -- PRINT_ERROR("server try accept error %d! ", sersum_accept_connects_ret); -- return PROGRAM_FAULT; -- } -- continue; -- } else { -- struct ServerHandler *server_handler = (struct ServerHandler *)curr_epev->data.ptr; -- struct sockaddr_in connect_addr; -- socklen_t connect_addr_len = sizeof(connect_addr); -- if (strcmp(server_unit->domain, "udp") != 0 && getpeername(server_handler->fd, (struct sockaddr *)&connect_addr, &connect_addr_len) < 0) { -- PRINT_ERROR("server can't socket peername %d! ", errno); -- return PROGRAM_FAULT; -- } -- -- int32_t server_ans_ret = server_ans(server_handler, server_unit->pktlen, server_unit->api, server_unit->domain); -- if (server_ans_ret == PROGRAM_FAULT) { -- --server_unit->curr_connect; -- struct epoll_event ep_ev; -- if (epoll_ctl(server_unit->epfd, EPOLL_CTL_DEL, server_handler->fd, &ep_ev) < 0) { -- PRINT_ERROR("server can't delete socket '%d' to control epoll %d! ", server_handler->fd, errno); -- return PROGRAM_FAULT; -- } -- } else if (server_ans_ret == PROGRAM_ABORT) { -- --server_unit->curr_connect; -- if (close(server_handler->fd) < 0) { -- PRINT_ERROR("server can't close the socket %d! ", errno); -- return PROGRAM_FAULT; -- } -- server_debug_print("server mum unit", "close", connect_addr.sin_addr.s_addr, connect_addr.sin_port, server_unit->debug); -- } else { -- server_unit->recv_bytes += server_unit->pktlen; -- server_debug_print("server mum unit", "receive", connect_addr.sin_addr.s_addr, connect_addr.sin_port, server_unit->debug); -- } -+ if (sersum_process_epollin_event(server_unit, curr_epev) != PROGRAM_OK) { -+ return PROGRAM_ABORT; - } - } - } -@@ -535,7 +771,9 @@ void *sersum_create_and_run(void *arg) - { - struct ServerMumUnit *server_unit = (struct ServerMumUnit *)arg; - -- if (create_socket_and_listen(&(server_unit->listener.fd), server_unit->ip, server_unit->groupip, server_unit->port, server_unit->domain) < 0) { -+ if (create_socket_and_listen(server_unit->listener.listen_fd_array, &(server_unit->server_ip_info), -+ server_unit->port, server_unit->protocol_type_mode) < 0) { -+ PRINT_ERROR("create_socket_and_listen err! \n"); - exit(PROGRAM_FAULT); - } - if (sersum_create_epfd_and_reg(server_unit) < 0) { -@@ -560,6 +798,7 @@ int32_t sermum_create_and_run(struct ProgramParams *params) - pthread_t *tids = (pthread_t *)malloc(thread_num * sizeof(pthread_t)); - struct ServerMum *server_mum = (struct ServerMum *)malloc(sizeof(struct ServerMum)); - struct ServerMumUnit *server_unit = (struct ServerMumUnit *)malloc(sizeof(struct ServerMumUnit)); -+ memset_s(server_unit, sizeof(struct ServerMumUnit), 0, sizeof(struct ServerMumUnit)); - - if (pthread_mutex_init(&server_debug_mutex, NULL) < 0) { - PRINT_ERROR("server can't init posix mutex %d! ", errno); -@@ -568,22 +807,47 @@ int32_t sermum_create_and_run(struct ProgramParams *params) - - server_mum->uints = server_unit; - server_mum->debug = params->debug; -+ uint32_t port = UNIX_TCP_PORT_MIN; - - for (uint32_t i = 0; i < thread_num; ++i) { - server_unit->listener.fd = -1; -+ for (int32_t i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ server_unit->listener.listen_fd_array[i] = -1; -+ } - server_unit->epfd = -1; - server_unit->epevs = (struct epoll_event *)malloc(SERVER_EPOLL_SIZE_MAX * sizeof(struct epoll_event)); - server_unit->curr_connect = 0; - server_unit->recv_bytes = 0; -- server_unit->ip = inet_addr(params->ip); -- server_unit->groupip = inet_addr(params->groupip); -- server_unit->port = htons(params->port); -+ server_unit->server_ip_info.ip.addr_family = params->addr_family; -+ inet_pton(AF_INET, params->ip, &server_unit->server_ip_info.ip.u_addr.ip4); -+ inet_pton(AF_INET6, params->ipv6, &server_unit->server_ip_info.ip.u_addr.ip6); -+ -+ server_unit->server_ip_info.groupip.addr_family = AF_INET; -+ inet_pton(AF_INET, params->groupip, &server_unit->server_ip_info.groupip.u_addr); -+ -+ server_unit->server_ip_info.groupip_interface.addr_family = AF_INET; -+ inet_pton(AF_INET, params->groupip_interface, &server_unit->server_ip_info.groupip_interface.u_addr); -+ -+ /* loop to set ports to each server_mums */ -+ while (!((params->port)[port])) { -+ port = (port + 1) % UNIX_TCP_PORT_MAX; -+ } -+ server_unit->port = htons(port++); - server_unit->pktlen = params->pktlen; -- server_unit->domain = params->domain; -+ -+ server_unit->protocol_type_mode = program_get_protocol_mode_by_domain_ip(params->domain, params->ip, -+ params->ipv6, params->groupip); -+ -+ // Create multicast sockets only on the first thread -+ if (i != 0) { -+ server_unit->protocol_type_mode = setbitnum_off(server_unit->protocol_type_mode, UDP_MULTICAST); -+ } - server_unit->api = params->api; - server_unit->debug = params->debug; - server_unit->epollcreate = params->epollcreate; - server_unit->accept = params->accept; -+ server_unit->tcp_keepalive_idle = params->tcp_keepalive_idle; -+ server_unit->tcp_keepalive_interval = params->tcp_keepalive_interval; - server_unit->next = (struct ServerMumUnit *)malloc(sizeof(struct ServerMumUnit)); - if (server_unit->next) { - memset_s(server_unit->next, sizeof(struct ServerMumUnit), 0, sizeof(struct ServerMumUnit)); -@@ -599,8 +863,14 @@ int32_t sermum_create_and_run(struct ProgramParams *params) - if (server_mum->debug == false) { - printf("[program informations]: \n\n"); - } -- while (true) { -- sermum_info_print(server_mum); -+ -+ if (strcmp(params->as, "server") == 0) { -+ while (true) { -+ sermum_info_print(server_mum); -+ } -+ } else if (strcmp(params->as, "loop") == 0) { -+ loopmod.model = params->model; -+ loopmod.server_mum_info = server_mum; - } - - pthread_mutex_destroy(&server_debug_mutex); -diff --git a/examples/src/utilities.c b/examples/src/utilities.c -index 7247b44..59d8bea 100644 ---- a/examples/src/utilities.c -+++ b/examples/src/utilities.c -@@ -11,35 +11,215 @@ - */ - - --#include "utilities.h" -+#include "parameter.h" - -+int32_t set_tcp_keep_alive_info(int32_t sockfd, int32_t tcp_keepalive_idle, int32_t tcp_keepalive_interval) -+{ -+ int32_t ret = 0; -+ int32_t keep_alive = 1; -+ int32_t keep_idle = 1; -+ int32_t keep_interval = 1; -+ -+ if ((tcp_keepalive_idle == PARAM_DEFAULT_KEEPALIVEIDLE) || -+ (tcp_keepalive_interval == PARAM_DEFAULT_KEEPALIVEIDLE)) { -+ return 0; -+ } -+ -+ keep_idle = tcp_keepalive_idle; -+ ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keep_alive, sizeof(keep_alive)); -+ if (ret != 0) { -+ PRINT_ERROR("setsockopt keep_alive err ret=%d \n", ret); -+ return ret; -+ } -+ -+ ret = setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keep_idle, sizeof(keep_idle)); -+ if (ret != 0) { -+ PRINT_ERROR("setsockopt keep_idle err ret=%d \n", ret); -+ return ret; -+ } -+ -+ keep_interval = tcp_keepalive_interval; -+ ret = setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)); -+ if (ret != 0) { -+ PRINT_ERROR("setsockopt keep_interval err ret=%d \n", ret); -+ return ret; -+ } -+ return ret; -+} -+ -+static int32_t process_unix_fd(int32_t *socket_fd, int32_t *listen_fd_array) -+{ -+ struct sockaddr_un socket_addr; -+ int32_t fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (fd < 0) { -+ PRINT_ERROR("can't create socket %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ *socket_fd = fd; -+ -+ unlink(SOCKET_UNIX_DOMAIN_FILE); -+ socket_addr.sun_family = AF_UNIX; -+ strcpy_s(socket_addr.sun_path, sizeof(socket_addr.sun_path), SOCKET_UNIX_DOMAIN_FILE); -+ if (bind(*socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_un)) < 0) { -+ PRINT_ERROR("can't bind the address to socket %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ -+ if (listen(*socket_fd, SERVER_SOCKET_LISTEN_BACKLOG) < 0) { -+ PRINT_ERROR("server socket can't lisiten %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ return PROGRAM_OK; -+} -+ -+static int32_t process_udp_groupip(int32_t fd, ip_addr_t *ip, ip_addr_t *groupip, sockaddr_t *socker_add_info, -+ ip_addr_t *groupip_interface) -+{ -+ struct ip_mreq mreq; -+ if (groupip->u_addr.ip4.s_addr) { -+ mreq.imr_multiaddr = groupip->u_addr.ip4; -+ if (groupip_interface->u_addr.ip4.s_addr) { -+ mreq.imr_interface = groupip_interface->u_addr.ip4; -+ } else { -+ mreq.imr_interface = ip->u_addr.ip4; -+ } -+ -+ if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) { -+ PRINT_ERROR("can't set the address to group %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ ((struct sockaddr_in *)socker_add_info)->sin_addr = groupip->u_addr.ip4; -+ return PROGRAM_OK; -+ } -+ return PROGRAM_OK; -+} -+ -+static int32_t server_create_sock(uint8_t protocol_mode, int32_t* fd_arry) -+{ -+ bool ret = true; -+ for (int32_t i = 0; i < PROTOCOL_MODE_MAX; i++) { -+ if (getbit_num(protocol_mode, i) == 0) -+ continue; -+ if (i == V4_TCP) { -+ fd_arry[i] = socket(AF_INET, SOCK_STREAM, 0); -+ } else if (i == V6_TCP) { -+ fd_arry[i] = socket(AF_INET6, SOCK_STREAM, 0); -+ } else if (i == V4_UDP) { -+ fd_arry[i] = socket(AF_INET, SOCK_DGRAM, 0); -+ } else if (i == UDP_MULTICAST) { -+ fd_arry[i] = socket(AF_INET, SOCK_DGRAM, 0); -+ } else { -+ continue; -+ } -+ if (fd_arry[i] < 0) { -+ PRINT_ERROR("can't create socket type=%d errno=%d! ", i, errno); -+ ret = false; -+ break; -+ } -+ } -+ -+ if (ret == false) { -+ for (int32_t i = 0; i< PROTOCOL_MODE_MAX; i++) { -+ if (fd_arry[i] > 0) { -+ close(fd_arry[i]); -+ } -+ } -+ return PROGRAM_FAULT; -+ } -+ return PROGRAM_OK; -+} -+ -+static int32_t socket_add_info_init(int32_t idx, uint16_t port, struct ServerIpInfo *server_ip_info, -+ sockaddr_t *socker_add_info, int32_t *listen_fd_array) -+{ -+ ip_addr_t *ip = &(server_ip_info->ip); -+ ip_addr_t *groupip = &(server_ip_info->groupip); -+ ip_addr_t *groupip_interface = &(server_ip_info->groupip_interface); -+ -+ uint32_t len = ((idx == V4_TCP || idx == V4_UDP || idx == UDP_MULTICAST) ? -+ sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); -+ memset_s(socker_add_info, len, 0, len); -+ -+ if (idx == V4_TCP || idx == V4_UDP) { -+ ((struct sockaddr_in *)socker_add_info)->sin_addr = ip->u_addr.ip4; -+ } else if (idx == V6_TCP) { -+ ((struct sockaddr_in6 *)socker_add_info)->sin6_addr = ip->u_addr.ip6; -+ } else if (idx == UDP_MULTICAST) { -+ if (process_udp_groupip(listen_fd_array[idx], ip, groupip, socker_add_info, groupip_interface) != PROGRAM_OK) { -+ return PROGRAM_FAULT; -+ } -+ } -+ -+ ((struct sockaddr *)socker_add_info)->sa_family = ((idx == V4_TCP || idx == V4_UDP || idx == UDP_MULTICAST) ? -+ AF_INET : AF_INET6); -+ ((struct sockaddr_in *)socker_add_info)->sin_port = port; -+ return PROGRAM_OK; -+} - - // create the socket and listen --int32_t create_socket_and_listen(int32_t *socket_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, const char *domain) -+int32_t create_socket_and_listen(int32_t *listen_fd_array, struct ServerIpInfo *server_ip_info, -+ uint16_t port, uint8_t protocol_mode) - { -- if (strcmp(domain, "tcp") == 0) { -- *socket_fd = socket(AF_INET, SOCK_STREAM, 0); -- if (*socket_fd < 0) { -- PRINT_ERROR("can't create socket %d! ", errno); -+ int32_t port_multi = 1; -+ uint32_t len = 0; -+ sockaddr_t socker_add_info; -+ -+ if (getbit_num(protocol_mode, UNIX) == 1) { -+ if (process_unix_fd(&listen_fd_array[UNIX], listen_fd_array) != PROGRAM_OK) { - return PROGRAM_FAULT; - } -- } else if (strcmp(domain, "unix") == 0) { -- *socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); -- if (*socket_fd < 0) { -- PRINT_ERROR("can't create socket %d! ", errno); -+ return PROGRAM_OK; -+ } -+ -+ if (server_create_sock(protocol_mode, listen_fd_array) != PROGRAM_OK) { -+ return PROGRAM_FAULT; -+ } -+ -+ for (int32_t i = 0;i< PROTOCOL_MODE_MAX; i++) { -+ if (listen_fd_array[i] <= 0) -+ continue; -+ if (setsockopt(listen_fd_array[i], SOL_SOCKET, SO_REUSEPORT, (void *)&port_multi, sizeof(int32_t)) < 0) { -+ PRINT_ERROR("can't set the option of socket %d! ", errno); - return PROGRAM_FAULT; - } -- } else if (strcmp(domain, "udp") == 0) { -- *socket_fd = socket(AF_INET, SOCK_DGRAM, 0); -- if (*socket_fd < 0) { -- PRINT_ERROR("can't create socket %d! ", errno); -+ if (set_socket_unblock(listen_fd_array[i]) < 0) { -+ PRINT_ERROR("can't set the socket to unblock! "); -+ return PROGRAM_FAULT; -+ } -+ if (socket_add_info_init(i, port, server_ip_info, &socker_add_info, listen_fd_array) != PROGRAM_OK) { -+ return PROGRAM_FAULT; -+ } -+ -+ len = ((i == V4_TCP || i == V4_UDP || i == UDP_MULTICAST) ? -+ sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); -+ -+ if (bind(listen_fd_array[i], (struct sockaddr *)&socker_add_info, len) < 0) { -+ PRINT_ERROR("can't bind the address %d!, i=%d, listen_fd_array[i]=%d ", errno, i, listen_fd_array[i]); - return PROGRAM_FAULT; - } -+ -+ if (i == V4_TCP || i == V6_TCP) { -+ if (listen(listen_fd_array[i], SERVER_SOCKET_LISTEN_BACKLOG) < 0) { -+ PRINT_ERROR("server socket can't lisiten %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ } - } -+ return PROGRAM_OK; -+} - -- int32_t port_multi = 1; -- if (setsockopt(*socket_fd, SOL_SOCKET, SO_REUSEPORT, (void *)&port_multi, sizeof(int32_t)) < 0) { -- PRINT_ERROR("can't set the option of socket %d! ", errno); -+static int32_t creat_socket_init(int32_t *socket_fd, struct ClientUnit *client_unit, sockaddr_t *server_addr) -+{ -+ ip_addr_t *ip = &client_unit->ip; -+ const char *domain = client_unit->domain; -+ -+ if (strcmp(domain, "tcp") == 0) { -+ *socket_fd = socket(ip->addr_family, SOCK_STREAM, 0); -+ } else { -+ *socket_fd = socket(AF_INET, SOCK_DGRAM, 0); -+ } -+ if (*socket_fd < 0) { -+ PRINT_ERROR("client can't create socket %d! ", errno); - return PROGRAM_FAULT; - } - -@@ -48,106 +228,118 @@ int32_t create_socket_and_listen(int32_t *socket_fd, in_addr_t ip, in_addr_t gro - return PROGRAM_FAULT; - } - -- if (strcmp(domain, "tcp") == 0) { -- struct sockaddr_in socket_addr; -- memset_s(&socket_addr, sizeof(socket_addr), 0, sizeof(socket_addr)); -- socket_addr.sin_family = AF_INET; -- socket_addr.sin_addr.s_addr = ip; -- socket_addr.sin_port = port; -- if (bind(*socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0) { -- PRINT_ERROR("can't bind the address to socket %d! ", errno); -- return PROGRAM_FAULT; -- } -+ ((struct sockaddr *)server_addr)->sa_family = ip->addr_family; - -- if (listen(*socket_fd, SERVER_SOCKET_LISTEN_BACKLOG) < 0) { -- PRINT_ERROR("server socket can't lisiten %d! ", errno); -- return PROGRAM_FAULT; -+ return PROGRAM_OK; -+} -+ -+static int32_t pocess_connect_sport(int32_t *socket_fd, struct ClientUnit *client_unit, sockaddr_t *server_addr) -+{ -+ uint16_t sport = client_unit->sport; -+ ip_addr_t *ip = &client_unit->ip; -+ uint32_t addr_len = ip->addr_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); -+ -+ if (sport) { -+ if (ip->addr_family == AF_INET) { -+ ((struct sockaddr_in *)server_addr)->sin_addr.s_addr = htonl(INADDR_ANY); -+ } else if (ip->addr_family == AF_INET6) { -+ ((struct sockaddr_in6 *)server_addr)->sin6_addr = in6addr_any; - } -- } else if (strcmp(domain, "unix") == 0) { -- struct sockaddr_un socket_addr; -- unlink(SOCKET_UNIX_DOMAIN_FILE); -- socket_addr.sun_family = AF_UNIX; -- strcpy_s(socket_addr.sun_path, sizeof(socket_addr.sun_path), SOCKET_UNIX_DOMAIN_FILE); -- if (bind(*socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_un)) < 0) { -+ ((struct sockaddr_in *)server_addr)->sin_port = sport; -+ if (bind(*socket_fd, (struct sockaddr *)server_addr, addr_len) < 0) { - PRINT_ERROR("can't bind the address to socket %d! ", errno); - return PROGRAM_FAULT; - } -+ } -+ return PROGRAM_OK; -+} - -- if (listen(*socket_fd, SERVER_SOCKET_LISTEN_BACKLOG) < 0) { -- PRINT_ERROR("server socket can't lisiten %d! ", errno); -+static int32_t pocess_unix_create_connect(int32_t *socket_fd) -+{ -+ *socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (*socket_fd < 0) { -+ PRINT_ERROR("client can't create socket %d! ", errno); -+ return PROGRAM_FAULT; -+ } -+ -+ struct sockaddr_un server_addr; -+ server_addr.sun_family = AF_UNIX; -+ strcpy_s(server_addr.sun_path, sizeof(server_addr.sun_path), SOCKET_UNIX_DOMAIN_FILE); -+ if (connect(*socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_un)) < 0) { -+ if (errno == EINPROGRESS) { -+ return PROGRAM_INPROGRESS; -+ } else { -+ PRINT_ERROR("client can't connect to the server %d! ", errno); - return PROGRAM_FAULT; - } -- } else if (strcmp(domain, "udp") == 0) { -- struct sockaddr_in socket_addr; -- memset_s(&socket_addr, sizeof(socket_addr), 0, sizeof(socket_addr)); -- socket_addr.sin_family = AF_INET; -- socket_addr.sin_port = port; -- -- if (groupip) { -- struct ip_mreq mreq; -- mreq.imr_multiaddr.s_addr = groupip; -- mreq.imr_interface.s_addr = ip; -- if (setsockopt(*socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) { -- PRINT_ERROR("can't set the address to group %d! ", errno); -- return PROGRAM_FAULT;; -+ } -+ return PROGRAM_OK; -+} -+ -+static int32_t pocess_udp_multicast(int32_t *socket_fd, struct ClientUnit *client_unit, sockaddr_t *server_addr) -+{ -+ const uint32_t loop = client_unit->loop; -+ ip_addr_t *groupip = &client_unit->groupip; -+ if (client_unit->protocol_type_mode == UDP_MULTICAST) { -+ /* set the local device for a multicast socket */ -+ ((struct sockaddr_in *)server_addr)->sin_addr = groupip->u_addr.ip4; -+ -+ struct in_addr localInterface; -+ localInterface.s_addr = client_unit->groupip_interface.u_addr.ip4.s_addr; -+ if (localInterface.s_addr) { -+ if (setsockopt(*socket_fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&localInterface, -+ sizeof(localInterface)) < 0) { -+ PRINT_ERROR("can't set the multicast interface %d! ", errno); -+ return PROGRAM_FAULT; - } -- socket_addr.sin_addr.s_addr = groupip; -- } else { -- socket_addr.sin_addr.s_addr = ip; - } - -- if (bind(*socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0) { -- PRINT_ERROR("can't bind the address to socket %d! ", errno); -+ /* sent multicast packets should be looped back to the local socket */ -+ if (setsockopt(*socket_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) == -1) { -+ PRINT_ERROR("can't set the multicast loop %d! ", errno); - return PROGRAM_FAULT; -- } -+ } - } -- - return PROGRAM_OK; - } - - // create the socket and connect --int32_t create_socket_and_connect(int32_t *socket_fd, in_addr_t ip, in_addr_t groupip, uint16_t port, uint16_t sport, const char *domain, const char *api) -+int32_t create_socket_and_connect(int32_t *socket_fd, struct ClientUnit *client_unit) - { -+ ip_addr_t *ip = &client_unit->ip; -+ const char *domain = client_unit->domain; -+ const char *api = client_unit->api; -+ -+ sockaddr_t server_addr; -+ - if (strcmp(domain, "tcp") == 0 || strcmp(domain, "udp") == 0) { -- if (strcmp(domain, "tcp") == 0) { -- *socket_fd = socket(AF_INET, SOCK_STREAM, 0); -- } else { -- *socket_fd = socket(AF_INET, SOCK_DGRAM, 0); -- } -- if (*socket_fd < 0) { -- PRINT_ERROR("client can't create socket %d! ", errno); -+ uint32_t addr_len = ip->addr_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); -+ memset_s(&server_addr, addr_len, 0, addr_len); -+ -+ if (creat_socket_init(socket_fd, client_unit, &server_addr) != PROGRAM_OK) { - return PROGRAM_FAULT; - } - -- if (set_socket_unblock(*socket_fd) < 0) { -- PRINT_ERROR("can't set the socket to unblock! "); -+ if (pocess_connect_sport(socket_fd, client_unit, &server_addr) < 0) { - return PROGRAM_FAULT; - } - -- struct sockaddr_in server_addr; -- memset_s(&server_addr, sizeof(server_addr), 0, sizeof(server_addr)); -- server_addr.sin_family = AF_INET; -- if (sport) { -- server_addr.sin_addr.s_addr = htonl(INADDR_ANY); -- server_addr.sin_port = sport; -- if (bind(*socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) { -- PRINT_ERROR("can't bind the address to socket %d! ", errno); -- return PROGRAM_FAULT; -- } -+ if (ip->addr_family == AF_INET) { -+ ((struct sockaddr_in *)&server_addr)->sin_addr = ip->u_addr.ip4; -+ } else if (ip->addr_family == AF_INET6) { -+ ((struct sockaddr_in6 *)&server_addr)->sin6_addr = ip->u_addr.ip6; - } -- server_addr.sin_addr.s_addr = ip; -- server_addr.sin_port = port; -+ ((struct sockaddr_in *)&server_addr)->sin_port = client_unit->port; -+ - if (strcmp(domain, "udp") == 0) { -- if (groupip) { -- server_addr.sin_addr.s_addr = groupip; -- if (setsockopt(*socket_fd, IPPROTO_IP, IP_MULTICAST_IF, &ip, sizeof(ip)) != 0) { -- PRINT_ERROR("can't set the multicast interface %d! ", errno); -- return PROGRAM_FAULT; -- } -+ int32_t ret = pocess_udp_multicast(socket_fd, client_unit, &server_addr); -+ if (ret != PROGRAM_OK) { -+ return ret; - } - } -+ - if (strcmp(domain, "udp") != 0 || strcmp(api, "recvfromsendto") != 0) { -- if (connect(*socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)) < 0) { -+ if (connect(*socket_fd, (struct sockaddr *)&server_addr, addr_len) < 0) { - if (errno == EINPROGRESS) { - return PROGRAM_INPROGRESS; - } else { -@@ -157,25 +349,11 @@ int32_t create_socket_and_connect(int32_t *socket_fd, in_addr_t ip, in_addr_t gr - } - } - } else if (strcmp(domain, "unix") == 0) { -- *socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); -- if (*socket_fd < 0) { -- PRINT_ERROR("client can't create socket %d! ", errno); -- return PROGRAM_FAULT; -- } -- -- struct sockaddr_un server_addr; -- server_addr.sun_family = AF_UNIX; -- strcpy_s(server_addr.sun_path, sizeof(server_addr.sun_path), SOCKET_UNIX_DOMAIN_FILE); -- if (connect(*socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_un)) < 0) { -- if (errno == EINPROGRESS) { -- return PROGRAM_INPROGRESS; -- } else { -- PRINT_ERROR("client can't connect to the server %d! ", errno); -- return PROGRAM_FAULT; -- } -+ int32_t ret = pocess_unix_create_connect(socket_fd); -+ if (ret != PROGRAM_OK) { -+ return ret; - } - } -- - return PROGRAM_OK; - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 3e6eeef..e272a04 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -655,7 +655,6 @@ int32_t stack_setup_thread(void) - goto OUT1; - } - } -- - for (uint32_t i = 0; i < queue_num; i++) { - if (get_global_cfg_params()->seperate_send_recv) { - if (i % 2 == 0) { -@@ -694,6 +693,7 @@ int32_t stack_setup_thread(void) - g_stack_group.stack_num = queue_num; - - return 0; -+ - OUT1: - for (int32_t i = 0; i < queue_num; ++i) { - if (t_params[i] != NULL) { --- -2.33.0 - diff --git a/0213-cleancode-improving-makefile-readability.patch b/0213-cleancode-improving-makefile-readability.patch deleted file mode 100644 index 4482934..0000000 --- a/0213-cleancode-improving-makefile-readability.patch +++ /dev/null @@ -1,1154 +0,0 @@ -From 871a94d0abdf14efb9dfe42b711acc37d842ce6d Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 8 Jul 2024 20:35:10 +0800 -Subject: [PATCH] cleancode: improving makefile readability - -Signed-off-by: Lemmy Huang ---- - build/build.sh | 8 +- - src/common/dir.mk | 13 --- - src/lstack/Makefile | 92 +++++++-------- - src/lstack/Printlog.mk | 14 +++ - src/lstack/api/dir.mk | 14 --- - src/lstack/api/lstack_epoll.c | 4 +- - src/lstack/api/lstack_rtw_api.c | 2 +- - src/lstack/api/lstack_signal.c | 4 +- - src/lstack/api/lstack_wrap.c | 3 +- - src/lstack/core/dir.mk | 13 --- - src/lstack/core/lstack_cfg.c | 5 +- - src/lstack/core/lstack_control_plane.c | 4 +- - src/lstack/core/lstack_dpdk.c | 3 +- - src/lstack/core/lstack_init.c | 5 +- - src/lstack/core/lstack_lwip.c | 4 +- - src/lstack/core/lstack_preload.c | 1 - - src/lstack/core/lstack_protocol_stack.c | 6 +- - src/lstack/core/lstack_stack_stat.c | 4 +- - src/lstack/include/lstack_cfg.h | 2 +- - src/lstack/include/lstack_dpdk.h | 4 +- - src/lstack/include/lstack_fault_inject.h | 2 + - src/lstack/include/lstack_lwip.h | 2 +- - src/lstack/include/lstack_protocol_stack.h | 4 +- - src/lstack/include/posix/lstack_epoll.h | 4 +- - src/lstack/netif/dir.mk | 15 --- - src/lstack/netif/lstack_ethdev.c | 2 +- - src/lstack/netif/lstack_fault_inject.c | 4 + - src/lstack/netif/lstack_flow.c | 2 +- - src/lstack/netif/lstack_tx_cache.c | 2 +- - src/lstack/netif/lstack_vdev.c | 4 +- - src/ltran/CMakeLists.txt | 127 ++++++++++++--------- - src/ltran/ltran_base.h | 2 +- - src/ltran/ltran_dfx.c | 2 +- - src/ltran/ltran_ethdev.c | 6 +- - src/ltran/ltran_ethdev.h | 2 +- - src/ltran/ltran_forward.c | 2 +- - src/ltran/ltran_instance.c | 6 +- - src/ltran/ltran_instance.h | 4 +- - src/ltran/ltran_monitor.c | 4 +- - src/ltran/ltran_param.c | 4 +- - src/ltran/ltran_param.h | 2 +- - src/ltran/ltran_stack.c | 2 +- - src/ltran/ltran_stat.c | 4 +- - src/ltran/ltran_stat.h | 2 +- - src/ltran/ltran_tcp_conn.h | 2 +- - src/ltran/ltran_tcp_sock.c | 2 +- - src/ltran/ltran_tcp_sock.h | 2 +- - src/ltran/main.c | 2 +- - 48 files changed, 200 insertions(+), 223 deletions(-) - delete mode 100644 src/common/dir.mk - create mode 100644 src/lstack/Printlog.mk - delete mode 100644 src/lstack/api/dir.mk - delete mode 100644 src/lstack/core/dir.mk - delete mode 100644 src/lstack/netif/dir.mk - -diff --git a/build/build.sh b/build/build.sh -index 622e1cc..ed6d444 100755 ---- a/build/build.sh -+++ b/build/build.sh -@@ -12,8 +12,10 @@ - export CURRENT_PATH=$(dirname $(readlink -f ${BASH_SOURCE[0]})) - cd $CURRENT_PATH - -+cpu_num=8 -+ - make -C ../src/lstack clean --make -C ../src/lstack -+make -C ../src/lstack -j${cpu_num} - if [ $? -ne 0 ]; then - echo "build lstack failed" - exit 1 -@@ -24,7 +26,7 @@ rm -f CMakeCache.txt - rm -f ltran gazellectl - rm -rf CMakeFiles - cmake . --make -+make -j${cpu_num} - if [ $? -ne 0 ]; then - echo "build ltran failed" - exit 1 -@@ -33,7 +35,7 @@ fi - cd - - cd ../examples - cmake . --make -+make -j${cpu_num} - if [ $? -ne 0 ]; then - echo "build examples failed" - exit 1 -diff --git a/src/common/dir.mk b/src/common/dir.mk -deleted file mode 100644 -index 68a2b72..0000000 ---- a/src/common/dir.mk -+++ /dev/null -@@ -1,13 +0,0 @@ --# Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --# gazelle is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. -- --SRC = dpdk_common.c gazelle_parse_config.c --$(eval $(call register_dir, ../common, $(SRC))) -- -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index ace33bd..dd4e2c4 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -7,40 +7,28 @@ - # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR - # PURPOSE. - # See the Mulan PSL v2 for more details. --LSTACK_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) --ROOT_DIR := $(dir $(abspath $(LSTACK_DIR))) -+ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -+ -+include $(ROOT_DIR)/Printlog.mk - --LWIP_INCLUDE_FILE ?= /usr/include/lwip - LIB_PATH ?= /usr/lib64 -+LWIP_INCLUDE_DIR ?= /usr/include/lwip - - DPDK_VERSION := $(shell rpm -q --queryformat '%{VERSION}' dpdk) - ifeq ($(DPDK_VERSION),21.11) -- DPDK_INCLUDE_FILE := /usr/local/include -+ DPDK_INCLUDE_DIR := /usr/local/include - else -- DPDK_INCLUDE_FILE := /usr/include/dpdk -+ DPDK_INCLUDE_DIR := /usr/include/dpdk - endif - - AR = ar - ARFLAGS = crDP - CC ?= gcc --OPTIMIZATION = -O2 -g - RM = rm -f --LDFLAGS = -shared -ldl -lm -lpthread -lrt -lnuma -lconfig -lboundscheck - ARCH := $(shell uname -m) - --ifneq ($(CC),clang) -- SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wno-deprecated-declarations -Wl,-z,relro, -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIC -D_FORTIFY_SOURCE=2 --else -- SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wno-deprecated-declarations -fPIC --endif --$(info $(CC):$(SEC_FLAGS)) -- --INC = -I$(LSTACK_DIR)/include \ -- -I$(LSTACK_DIR)/../common \ -- -I$(LWIP_INCLUDE_FILE) \ -- -I$(DPDK_INCLUDE_FILE) -- --CFLAGS += $(OPTIMIZATION) -fno-strict-aliasing $(INC) -Wno-error=unused-function -+CFLAGS = -O2 -g -+LDFLAGS = -shared -ldl -lm -lpthread -lrt -lnuma -lconfig -lboundscheck - - ifeq ($(GAZELLE_COVERAGE_ENABLE), 1) - LDFLAGS += -fprofile-arcs -ftest-coverage -@@ -48,7 +36,6 @@ ifeq ($(GAZELLE_COVERAGE_ENABLE), 1) - endif - - ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1) -- LDFLAGS += -DGAZELLE_FAULT_INJECT_ENABLE - CFLAGS += -DGAZELLE_FAULT_INJECT_ENABLE - endif - -@@ -56,19 +43,21 @@ ifeq ($(shell $(CC) -dumpmachine | cut -d"-" -f1), x86_64) - CFLAGS += -mssse3 - endif - --CFLAGS += $(SEC_FLAGS) -- --SRCS = --DIRS = core netif api ../common -+SEC_FLAGS = -Wall -Werror -fstack-protector-strong -Wno-deprecated-declarations -fPIC -+ifneq ($(CC),clang) -+ SEC_FLAGS += -Wl,-z,relro, -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -D_FORTIFY_SOURCE=2 -+endif - --define register_dir --SRCS += $(patsubst %, $(1)/%, $(2)) --endef -+INC = -I$(ROOT_DIR)/include \ -+ -I$(ROOT_DIR)/../ \ -+ -I$(LWIP_INCLUDE_DIR) \ -+ -I$(DPDK_INCLUDE_DIR) - --include $(patsubst %, %/dir.mk, $(DIRS)) -+CFLAGS += -fno-strict-aliasing -Wno-error=unused-function -+CFLAGS += -D__USE_GNU=1 -D_GNU_SOURCE=1 -+CFLAGS += $(SEC_FLAGS) -+CFLAGS += $(INC) - --# Linking object and library --OBJS = $(subst .c,.o,$(SRCS)) - - LWIP_LIB = $(LIB_PATH)/liblwip.a - LIBRTE_LIB = $(LIB_PATH)/librte_pci.so \ -@@ -98,9 +87,9 @@ ifeq ($(DPDK_VERSION), 19.11) - $(LIB_PATH)/librte_pmd_hinic.so \ - $(LIB_PATH)/librte_pmd_ixgbe.so \ - $(LIB_PATH)/librte_pmd_virtio.so -- ifneq ($(ARCH), loongarch64) -- LIBRTE_LIB += $(LIB_PATH)/librte_pmd_i40e.so -- endif -+ ifneq ($(ARCH), loongarch64) -+ LIBRTE_LIB += $(LIB_PATH)/librte_pmd_i40e.so -+ endif - else - LIBRTE_LIB += $(LIB_PATH)/librte_net_pcap.so \ - $(LIB_PATH)/librte_net_bond.so \ -@@ -109,31 +98,38 @@ else - $(LIB_PATH)/librte_net_virtio.so \ - $(LIB_PATH)/librte_telemetry.so \ - $(LIB_PATH)/librte_pcapng.so -- ifeq ($(filter loongarch64 riscv64, $(ARCH)),) -- LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so -- endif -+ ifeq ($(filter loongarch64 riscv64, $(ARCH)),) -+ LIBRTE_LIB += $(LIB_PATH)/librte_net_i40e.so -+ endif - endif - - DEP_LIBS = $(LWIP_LIB) $(LIBRTE_LIB) -+$(info $(CC):$(DEP_LIBS)) -+ -+SRCS = $(wildcard ./api/*.c ./core/*.c ./netif/*.c ../common/*.c) -+# Linking object and library -+OBJS = $(subst .c,.o,$(SRCS)) -+ - LDFLAGS += -Wl,--whole-archive $(DEP_LIBS) $(OBJS) -Wl,--no-whole-archive - -+$(info [CFLAGS] $(CFLAGS)) -+$(info [LDFLAGS] $(LDFLAGS)) -+ - # Target - LSTACK_SHARED_LIB = liblstack.so - LSTACK_STATIC_LIB = liblstack.a - --.PHONY: all -+.PHONY: all clean - all: $(LSTACK_SHARED_LIB) - --depend: .depend -- --.depend: $(SRCS) -- rm -f ./.depend -- $(foreach SRC,$(SRCS),$(CC) $(CFLAGS) -MM -MT $(SRC:.c=.o) $(SRC) >> .depend;) -- ---include .depend -- - $(LSTACK_SHARED_LIB): $(OBJS) -- $(CC) $(LDFLAGS) -Wl,--whole-archive -Wl,--no-whole-archive -o $@ -+ $(call printlog, BUILD, $@) -+ $(QUIET) $(CC) $(LDFLAGS) -o $@ -+ -+%.o: %.c -+ $(call printlog, BUILD, $@) -+ $(QUIET) $(CC) $(CFLAGS) -c $(filter %.c,$^) -o $@ - - clean: -- $(RM) $(LSTACK_SHARED_LIB) $(OBJS) .depend -+ $(call printlog, CLEAN, $(LSTACK_SHARED_LIB)) -+ $(QUIET) $(RM) $(LSTACK_SHARED_LIB) $(OBJS) -diff --git a/src/lstack/Printlog.mk b/src/lstack/Printlog.mk -new file mode 100644 -index 0000000..7604851 ---- /dev/null -+++ b/src/lstack/Printlog.mk -@@ -0,0 +1,14 @@ -+ -+ROOT_DIR ?= $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -+ -+ifeq ($(V),1) -+ QUIET = -+ printlog = -+else -+ QUIET = @ -+ printlog = @printf ' %-8s %s%s\n' \ -+ "$(1)" \ -+ "$(patsubst $(ROOT_DIR)/%,%,$(2))" \ -+ "$(if $(3), $(3))"; -+ MAKEFLAGS += --no-print-directory -+endif -diff --git a/src/lstack/api/dir.mk b/src/lstack/api/dir.mk -deleted file mode 100644 -index 729690d..0000000 ---- a/src/lstack/api/dir.mk -+++ /dev/null -@@ -1,14 +0,0 @@ --# Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --# gazelle is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. -- --SRC = lstack_epoll.c lstack_signal.c lstack_fork.c lstack_wrap.c lstack_rtw_api.c lstack_rtc_api.c lstack_dummy_api.c -- --$(eval $(call register_dir, api, $(SRC))) -- -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 2ac7150..9c0aef7 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -31,8 +31,8 @@ - #include "lstack_stack_stat.h" - #include "lstack_cfg.h" - #include "lstack_log.h" --#include "dpdk_common.h" --#include "gazelle_base_func.h" -+#include "common/dpdk_common.h" -+#include "common/gazelle_base_func.h" - #include "lstack_lwip.h" - #include "lstack_protocol_stack.h" - #include "posix/lstack_epoll.h" -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index e50fe37..e43be59 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -22,7 +22,7 @@ - #include "lstack_protocol_stack.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_rtw_api.h" - - -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_signal.c -index 314c14c..3dd5d03 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_signal.c -@@ -18,9 +18,9 @@ - #include - #include - --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_cfg.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_log.h" - #include "lstack_control_plane.h" - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 7101d98..3a60cbb 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -10,7 +10,6 @@ - * See the Mulan PSL v2 for more details. - */ - --#define _GNU_SOURCE - #include - #include - #include -@@ -31,7 +30,7 @@ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_preload.h" - - #include "lstack_rtc_api.h" -diff --git a/src/lstack/core/dir.mk b/src/lstack/core/dir.mk -deleted file mode 100644 -index 21b0d22..0000000 ---- a/src/lstack/core/dir.mk -+++ /dev/null -@@ -1,13 +0,0 @@ --# Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --# gazelle is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. -- --SRC = lstack_preload.c lstack_init.c lstack_cfg.c lstack_dpdk.c lstack_control_plane.c lstack_stack_stat.c lstack_lwip.c lstack_protocol_stack.c lstack_thread_rpc.c lstack_virtio.c lstack_port_map.c --$(eval $(call register_dir, core, $(SRC))) -- -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index a165cdb..4bc4217 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -10,7 +10,6 @@ - * See the Mulan PSL v2 for more details. - */ - --#define _GNU_SOURCE - #include - #include - #include -@@ -29,9 +28,9 @@ - #include - #include - --#include "gazelle_reg_msg.h" -+#include "common/gazelle_reg_msg.h" -+#include "common/gazelle_base_func.h" - #include "lstack_log.h" --#include "gazelle_base_func.h" - #include "lstack_cfg.h" - - #define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 04858c7..4ab12f6 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -26,8 +26,8 @@ - - #include "lstack_cfg.h" - #include "lstack_dpdk.h" --#include "gazelle_reg_msg.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_reg_msg.h" -+#include "common/gazelle_base_func.h" - #include "lstack_stack_stat.h" - #include "lstack_log.h" - #include "lstack_thread_rpc.h" -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 2de41e3..583bb09 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -10,7 +10,6 @@ - * See the Mulan PSL v2 for more details. - */ - --#define _GNU_SOURCE - #include - #include - #include -@@ -44,7 +43,7 @@ - #include - - #include "lstack_log.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" - #include "lstack_lwip.h" -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index c2499d7..d97b218 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -10,7 +10,6 @@ - * See the Mulan PSL v2 for more details. - */ - --#define _GNU_SOURCE - #include - #include - #include -@@ -41,10 +40,10 @@ - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" - #include "lstack_log.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "posix/lstack_epoll.h" - #include "posix/lstack_unistd.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_protocol_stack.h" - #include "lstack_preload.h" - #include "lstack_wrap.h" -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 3728100..6e50e4d 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -27,7 +27,7 @@ - #include - #include - --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_ethdev.h" - #include "lstack_protocol_stack.h" - #include "lstack_log.h" -@@ -35,7 +35,7 @@ - #include "lstack_stack_stat.h" - #include "posix/lstack_epoll.h" - #include "lstack_thread_rpc.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" - -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 1d68501..f7caef5 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -12,7 +12,6 @@ - #include - #include - #include --#define __USE_GNU - #include - #include - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index e272a04..1983c0b 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -9,7 +9,7 @@ - * PURPOSE. - * See the Mulan PSL v2 for more details. - */ --#define _GNU_SOURCE -+ - #include - #include - -@@ -22,9 +22,9 @@ - #include - #include - --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "lstack_thread_rpc.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_ethdev.h" -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 1e32c45..423be81 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -22,8 +22,8 @@ - #include "posix_api.h" - #include "lstack_control_plane.h" - #include "lstack_log.h" --#include "dpdk_common.h" --#include "gazelle_dfx_msg.h" -+#include "common/dpdk_common.h" -+#include "common/gazelle_dfx_msg.h" - #include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" - #include "posix/lstack_epoll.h" -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index a15088a..4fc99f3 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -20,7 +20,7 @@ - #include - - #include "lstack_protocol_stack.h" --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - #define BASE_BIN_SCALE 2 - #define BASE_OCT_SCALE 8 -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index dff1e44..91af3c5 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -14,8 +14,8 @@ - #define _GAZELLE_DPDK_H_ - - #include --#include "gazelle_opt.h" --#include "gazelle_dfx_msg.h" -+#include "common/gazelle_opt.h" -+#include "common/gazelle_dfx_msg.h" - - #define RXTX_CACHE_SZ (VDEV_RX_QUEUE_SZ) - -diff --git a/src/lstack/include/lstack_fault_inject.h b/src/lstack/include/lstack_fault_inject.h -index afd8faf..a65c61f 100644 ---- a/src/lstack/include/lstack_fault_inject.h -+++ b/src/lstack/include/lstack_fault_inject.h -@@ -15,6 +15,8 @@ - - #include - -+#include "common/gazelle_dfx_msg.h" -+ - int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_fault_inject_data inject, enum GAZELLE_STAT_MODE stat_mode); - - #endif /* __GAZELLE_INJECT_H__ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 85c9c20..0b952ec 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -14,7 +14,7 @@ - #define __GAZELLE_LWIP_H__ - #include - --#include "gazelle_dfx_msg.h" -+#include "common/gazelle_dfx_msg.h" - - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) - #define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || (sock->same_node_rx_ring != NULL && same_node_ring_count(sock))) -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 6ca4f14..5b04c6d 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -20,11 +20,11 @@ - #include - #include - --#include "gazelle_dfx_msg.h" -+#include "common/gazelle_opt.h" -+#include "common/gazelle_dfx_msg.h" - #include "lstack_thread_rpc.h" - #include "lstack_ethdev.h" - #include "lstack_tx_cache.h" --#include "gazelle_opt.h" - - #define SOCK_RECV_RING_SIZE (get_global_cfg_params()->recv_ring_size) - #define SOCK_RECV_FREE_THRES (32) -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index a7164f4..77b6ebb 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -20,8 +20,8 @@ - - #include - --#include "gazelle_dfx_msg.h" --#include "gazelle_opt.h" -+#include "common/gazelle_dfx_msg.h" -+#include "common/gazelle_opt.h" - - #ifdef __cplusplus - extern "C" { -diff --git a/src/lstack/netif/dir.mk b/src/lstack/netif/dir.mk -deleted file mode 100644 -index b551041..0000000 ---- a/src/lstack/netif/dir.mk -+++ /dev/null -@@ -1,15 +0,0 @@ --# Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --# gazelle is licensed under the Mulan PSL v2. --# You can use this software according to the terms and conditions of the Mulan PSL v2. --# You may obtain a copy of Mulan PSL v2 at: --# http://license.coscl.org.cn/MulanPSL2 --# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --# PURPOSE. --# See the Mulan PSL v2 for more details. -- --SRC = lstack_ethdev.c lstack_vdev.c lstack_flow.c lstack_tx_cache.c --ifeq ($(GAZELLE_FAULT_INJECT_ENABLE), 1) -- SRC += lstack_fault_inject.c --endif --$(eval $(call register_dir, netif, $(SRC))) -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 933c3e8..e23d313 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -24,7 +24,7 @@ - - #include - --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_cfg.h" - #include "lstack_vdev.h" - #include "lstack_stack_stat.h" -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -index 4edc6cc..4736e29 100644 ---- a/src/lstack/netif/lstack_fault_inject.c -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -20,6 +20,9 @@ - #include "lstack_log.h" - #include "lstack_vdev.h" - -+#ifdef GAZELLE_FAULT_INJECT_ENABLE -+#include "lstack_fault_inject.h" -+ - #define INJECT_MODULO 1000 /* used in modulus operator */ - #define INJECT_US_TO_MS 1000 /* transefer time unit us to ms */ - -@@ -371,3 +374,4 @@ int32_t handle_fault_inject_cmd(int32_t sockfd, struct gazelle_fault_inject_data - return inject_set_cmd(sockfd, inject); - } - -+#endif /* GAZELLE_FAULT_INJECT_ENABLE */ -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index 9e8792c..84497dc 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -22,7 +22,7 @@ - #include - #include - --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_cfg.h" -diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c -index ac5a9db..cda0003 100644 ---- a/src/lstack/netif/lstack_tx_cache.c -+++ b/src/lstack/netif/lstack_tx_cache.c -@@ -15,7 +15,7 @@ - #include "lwip/sockets.h" - #include "lstack_ethdev.h" - #include "lstack_log.h" --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - #include "lstack_protocol_stack.h" - #include "lstack_tx_cache.h" - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 75e4acc..63f9e40 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -29,9 +29,9 @@ - #include "lstack_ethdev.h" - #include "lstack_control_plane.h" - #include "lstack_log.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "lstack_protocol_stack.h" --#include "gazelle_reg_msg.h" -+#include "common/gazelle_reg_msg.h" - #include "lstack_lwip.h" - #include "lstack_flow.h" - #include "lstack_vdev.h" -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index fee3a94..8e9b1ea 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -12,25 +12,7 @@ cmake_minimum_required(VERSION 3.12.1) - project(ltran) - - set(COMMON_DIR ${PROJECT_SOURCE_DIR}/../common) --set(LWIP_DIR /usr/include/lwip) -- --set(CMAKE_VERBOSE_MAKEFILE ON) --if (CMAKE_C_COMPILER_ID STREQUAL "GNU") -- set(CMAKE_C_FLAGS "-g -fstack-protector-strong -Wall -Werror -fPIE -pie -pthread -D_FORTIFY_SOURCE=2 -O2 -fPIC") --elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") -- set(CMAKE_C_FLAGS "-O2 -g -fstack-protector-strong -Wall -Werror -fPIE -pthread") --endif() --set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D LTRAN_COMPILE") -- --if($ENV{GAZELLE_COVERAGE_ENABLE}) -- message("Enable Coverage compile option") -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs") --endif($ENV{GAZELLE_COVERAGE_ENABLE}) -- --if($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -- message("Enable Fault inject option") -- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGAZELLE_FAULT_INJECT_ENABLE") --endif($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -+set(LWIP_INCLUDE_DIR /usr/include/lwip) - - execute_process( - COMMAND rpm -qa dpdk -@@ -40,62 +22,99 @@ execute_process( - string(REGEX MATCH "[0-9]+\\.[0-9]+" DPDK_VERSION ${DPDK_VERSION_FULL}) - - if (DPDK_VERSION STREQUAL "21.11") -- set(DPDK_DIR /usr/local/include/) -+ set(DPDK_INCLUDE_DIR /usr/local/include/) - else() -- set(DPDK_DIR /usr/include/dpdk) -+ set(DPDK_INCLUDE_DIR /usr/include/dpdk) -+endif() -+ -+ -+set(CMAKE_C_FLAGS "-O2 -g") -+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLTRAN_COMPILE -D_GNU_SOURCE -fno-strict-aliasing") -+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -fstack-protector-strong -fPIE") -+if (CMAKE_C_COMPILER_ID STREQUAL "GNU") -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -D_FORTIFY_SOURCE=2 -fPIC") -+endif() -+ -+# gcc coredump in openEuler-20.03-LTS-XX aarch64 when add -march=native -+if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64|ppc64le|riscv64" ) -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -Wcast-align") - endif() - -+if($ENV{GAZELLE_COVERAGE_ENABLE}) -+ message("Enable Coverage compile option") -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs") -+endif($ENV{GAZELLE_COVERAGE_ENABLE}) -+ -+if($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -+ message("Enable Fault inject option") -+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGAZELLE_FAULT_INJECT_ENABLE") -+endif($ENV{GAZELLE_FAULT_INJECT_ENABLE}) -+ -+set(LTRAN_C_FLAGS -D__ARM_FEATURE_CRC32=1 -+ -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wold-style-definition -+ -Wpointer-arith -Wcast-qual -Wnested-externs -Wformat-nonliteral -Wformat-security -Wundef -+ -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -Wno-error=deprecated-declarations) -+ -+set(DPDK_C_FLAGS -DRTE_MACHINE_CPUFLAG_NEON -DRTE_MACHINE_CPUFLAG_CRC32 -+ -DRTE_MACHINE_CPUFLAG_PMULL -DRTE_MACHINE_CPUFLAG_AES -+ -DRTE_MACHINE_CPUFLAG_SHA1 -DRTE_MACHINE_CPUFLAG_SHA2 -+ -include rte_config.h) -+ -+set(DPDK_LINK_FLAGS -Wl,-lrte_meter -Wl,-lrte_gro -Wl,-lrte_hash -Wl,-lrte_kvargs -+ -Wl,-lrte_mbuf -Wl,-lrte_ethdev -Wl,-lrte_net -Wl,-lrte_timer -Wl,-lrte_mempool -+ -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci -Wl,-lrte_cmdline -+ -Wl,-lrte_bus_pci -Wl,-lrte_bus_vdev -Wl,-lrte_pdump) -+ - if (DPDK_VERSION STREQUAL "19.11") -- set(DPDK_LINK_FLAGS "-Wl,-lrte_pmd_bond -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe \ -- -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_virtio") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-lrte_pmd_bond -Wl,-lrte_pmd_hinic -Wl,-lrte_pmd_ixgbe -+ -Wl,-lrte_pmd_pcap -Wl,-lrte_pmd_virtio) - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64") -- set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_pmd_i40e") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-lrte_pmd_i40e) - endif() - else() -- set(DPDK_LINK_FLAGS "-Wl,-lrte_net_bond -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe \ -- -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-lrte_net_bond -Wl,-lrte_net_hinic -Wl,-lrte_net_ixgbe -+ -Wl,-lpcap -Wl,-lrte_net_pcap -Wl,-lrte_net_virtio -Wl,-lrte_pcapng -Wl,-lrte_telemetry) - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "loongarch64|riscv64") -- set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-lrte_net_i40e") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-lrte_net_i40e) - endif() - endif() - - if (DPDK_VERSION GREATER_EQUAL 23.11) -- set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_log -larchive -Wl,-lrte_eal") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -lrte_log -larchive -Wl,-lrte_eal) - else() -- set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -lrte_kni -Wl,-Bstatic -lrte_eal -Wl,-Bdynamic") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -lrte_kni -Wl,-Bstatic -Wl,-lrte_eal -Wl,-Bdynamic) - if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "ppc64le") -- set(DPDK_LINK_FLAGS "${DPDK_LINK_FLAGS} -Wl,-larchive") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-larchive) - endif() - endif() - -+# compile info -+# set(CMAKE_VERBOSE_MAKEFILE ON) -+message("[CMAKE_C_FLAGS] ${CMAKE_C_FLAGS}") -+message("[LTRAN_C_FLAGS] ${LTRAN_C_FLAGS}") -+message("[DPDK_C_FLAGS ] ${DPDK_C_FLAGS}") -+message("[DPDK_LINK_FLAGS] ${DPDK_LINK_FLAGS}") -+ - add_executable(ltran main.c ltran_param.c ltran_config.c ltran_ethdev.c ltran_stat.c ltran_errno.c -- ltran_monitor.c ltran_instance.c ltran_stack.c ltran_tcp_conn.c ltran_tcp_sock.c -- ltran_forward.c ltran_timer.c ${COMMON_DIR}/gazelle_dfx_msg.c ${COMMON_DIR}/dpdk_common.c -- ${COMMON_DIR}/gazelle_parse_config.c) -- --target_include_directories(ltran PRIVATE ${COMMON_DIR} ${PROJECT_SOURCE_DIR} ${LWIP_DIR} ${DPDK_DIR}) --target_compile_options(ltran PRIVATE -fno-strict-aliasing -D__ARM_FEATURE_CRC32=1 -DRTE_MACHINE_CPUFLAG_NEON -- -DRTE_MACHINE_CPUFLAG_CRC32 -DRTE_MACHINE_CPUFLAG_PMULL -DRTE_MACHINE_CPUFLAG_AES -- -DRTE_MACHINE_CPUFLAG_SHA1 -DRTE_MACHINE_CPUFLAG_SHA2 -include rte_config.h -- -D_GNU_SOURCE -W -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wold-style-definition -- -Wpointer-arith -Wcast-qual -Wnested-externs -Wformat-nonliteral -Wformat-security -Wundef -- -Wdeprecated -Wwrite-strings -Wno-implicit-fallthrough -D_FORTIFY_SOURCE=2 -Wno-error=deprecated-declarations) -+ ltran_monitor.c ltran_instance.c ltran_stack.c ltran_tcp_conn.c ltran_tcp_sock.c -+ ltran_forward.c ltran_timer.c -+ ${COMMON_DIR}/gazelle_dfx_msg.c -+ ${COMMON_DIR}/dpdk_common.c -+ ${COMMON_DIR}/gazelle_parse_config.c) - --# gcc coredump in openEuler-20.03-LTS-XX aarch64 when add -march=native --if(NOT CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "sw_64|aarch64|ppc64le|riscv64" ) -- target_compile_options(ltran PRIVATE -march=native -Wcast-align) --endif() -+target_include_directories(ltran PRIVATE ${COMMON_DIR}/../ ${PROJECT_SOURCE_DIR} ${LWIP_INCLUDE_DIR} ${DPDK_INCLUDE_DIR}) - --target_link_libraries(ltran PRIVATE config boundscheck rte_pdump -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines) -+# COMPILE_FLAGS and LINK_FLAGS are deprecated. -+target_compile_options(ltran PRIVATE ${LTRAN_C_FLAGS} ${DPDK_C_FLAGS}) -+target_link_options(ltran PRIVATE -+ -Wl,--whole-archive ${DPDK_LINK_FLAGS} -Wl,--no-whole-archive -+ -Wl,--as-needed -Wl,-export-dynamic -+ -Wl,-Map=ltran.map -Wl,--cref) -+target_link_libraries(ltran PRIVATE pthread config boundscheck -+ -Wl,-lm -Wl,-lrt -Wl,-lnuma -Wl,-ldl -+ -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines) - --set_target_properties(ltran PROPERTIES LINK_FLAGS "-L$ENV{DPDK_LIB_PATH} -Wl,--no-whole-archive \ -- -Wl,-lrte_meter -Wl,--whole-archive -Wl,-lrte_gro -Wl,-lrte_hash -Wl,-lrte_kvargs -Wl,-lrte_mbuf -Wl,-lrte_ethdev \ -- -Wl,-lrte_net -Wl,-lrte_timer -Wl,-lrte_mempool -Wl,-lrte_mempool_ring -Wl,-lrte_ring -Wl,-lrte_pci \ -- -Wl,-lrte_cmdline -Wl,-lrte_bus_pci\ -- -Wl,-lrte_bus_vdev ${DPDK_LINK_FLAGS} \ -- -Wl,--no-whole-archive -Wl,-lm -Wl,-lrt -Wl,-lnuma -Wl,-ldl -Wl,-export-dynamic -Wl,-export-dynamic \ -- -Wl,--as-needed -Wl,-export-dynamic -Wl,-Map=ltran.map -Wl,--cref") - - add_executable(gazellectl ltran_dfx.c ${COMMON_DIR}/gazelle_dfx_msg.c) --target_include_directories(gazellectl PRIVATE $ENV{DPDK_INCLUDE_FILE} ${COMMON_DIR} ${DPDK_DIR}) -+target_include_directories(gazellectl PRIVATE ${COMMON_DIR}/../ ${DPDK_INCLUDE_DIR}) - target_link_libraries(gazellectl PRIVATE boundscheck -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack) -diff --git a/src/ltran/ltran_base.h b/src/ltran/ltran_base.h -index f174a40..9462fe5 100644 ---- a/src/ltran/ltran_base.h -+++ b/src/ltran/ltran_base.h -@@ -15,7 +15,7 @@ - - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - #define GAZELLE_CMD_BUFFER_SIZE _POSIX_ARG_MAX - #define GAZELLE_PATH_BUFFER_SIZE PATH_MAX -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index cdcd7b3..005b09c 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -30,7 +30,7 @@ - - #include "ltran_stat.h" - #include "ltran_base.h" --#include "gazelle_dfx_msg.h" -+#include "common/gazelle_dfx_msg.h" - - /* seeing show_usage() */ - #define GAZELLE_TARGET_ARG_IDX 1 -diff --git a/src/ltran/ltran_ethdev.c b/src/ltran/ltran_ethdev.c -index 2f08d4a..68dc786 100644 ---- a/src/ltran/ltran_ethdev.c -+++ b/src/ltran/ltran_ethdev.c -@@ -30,13 +30,13 @@ - - #include - --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "ltran_param.h" - #include "ltran_log.h" - #include "ltran_base.h" --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - #include "ltran_errno.h" --#include "gazelle_reg_msg.h" -+#include "common/gazelle_reg_msg.h" - - uint32_t g_bond_num = 0; - FILE* g_log_file = NULL; -diff --git a/src/ltran/ltran_ethdev.h b/src/ltran/ltran_ethdev.h -index f720c55..b84baae 100644 ---- a/src/ltran/ltran_ethdev.h -+++ b/src/ltran/ltran_ethdev.h -@@ -15,7 +15,7 @@ - - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - struct port_info { - uint16_t num_ports; -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index c49da89..c2f53d6 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -28,7 +28,7 @@ - #include - #include - --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "ltran_instance.h" - #include "ltran_tcp_conn.h" - #include "ltran_tcp_sock.h" -diff --git a/src/ltran/ltran_instance.c b/src/ltran/ltran_instance.c -index fc5b0fb..428c1aa 100644 ---- a/src/ltran/ltran_instance.c -+++ b/src/ltran/ltran_instance.c -@@ -25,10 +25,10 @@ - #include "ltran_stat.h" - #include "ltran_log.h" - #include "ltran_base.h" --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - #include "ltran_errno.h" --#include "gazelle_dfx_msg.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_dfx_msg.h" -+#include "common/gazelle_base_func.h" - #include "ltran_instance.h" - - volatile unsigned long g_tx_loop_count __rte_cache_aligned; -diff --git a/src/ltran/ltran_instance.h b/src/ltran/ltran_instance.h -index 2b888ec..f0fe580 100644 ---- a/src/ltran/ltran_instance.h -+++ b/src/ltran/ltran_instance.h -@@ -17,8 +17,8 @@ - #include - #include - --#include "gazelle_opt.h" --#include "gazelle_reg_msg.h" -+#include "common/gazelle_opt.h" -+#include "common/gazelle_reg_msg.h" - - struct gazelle_stack; - struct gazelle_instance { -diff --git a/src/ltran/ltran_monitor.c b/src/ltran/ltran_monitor.c -index 457e8c8..93ab2d5 100644 ---- a/src/ltran/ltran_monitor.c -+++ b/src/ltran/ltran_monitor.c -@@ -29,8 +29,8 @@ - #include "ltran_log.h" - #include "ltran_stat.h" - #include "ltran_instance.h" --#include "gazelle_dfx_msg.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_dfx_msg.h" -+#include "common/gazelle_base_func.h" - #include "ltran_param.h" - #include "ltran_monitor.h" - -diff --git a/src/ltran/ltran_param.c b/src/ltran/ltran_param.c -index bd5a8e1..ad689f6 100644 ---- a/src/ltran/ltran_param.c -+++ b/src/ltran/ltran_param.c -@@ -23,8 +23,8 @@ - #include "ltran_errno.h" - #include "ltran_base.h" - #include "ltran_log.h" --#include "gazelle_dfx_msg.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_dfx_msg.h" -+#include "common/gazelle_base_func.h" - #include "ltran_param.h" - - #define HEX_BASE 16 -diff --git a/src/ltran/ltran_param.h b/src/ltran/ltran_param.h -index 75addcd..e48b781 100644 ---- a/src/ltran/ltran_param.h -+++ b/src/ltran/ltran_param.h -@@ -17,7 +17,7 @@ - #include - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - struct ltran_config { - struct { -diff --git a/src/ltran/ltran_stack.c b/src/ltran/ltran_stack.c -index 2aed6c9..299fb7a 100644 ---- a/src/ltran/ltran_stack.c -+++ b/src/ltran/ltran_stack.c -@@ -16,7 +16,7 @@ - #include "ltran_instance.h" - #include "ltran_log.h" - #include "ltran_jhash.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "ltran_stack.h" - - struct gazelle_stack_htable *g_stack_htable = NULL; -diff --git a/src/ltran/ltran_stat.c b/src/ltran/ltran_stat.c -index dfd5fc9..0a8d75c 100644 ---- a/src/ltran/ltran_stat.c -+++ b/src/ltran/ltran_stat.c -@@ -21,12 +21,12 @@ - #include "ltran_tcp_conn.h" - #include "ltran_instance.h" - #include "ltran_log.h" --#include "gazelle_dfx_msg.h" -+#include "common/gazelle_dfx_msg.h" - #include "ltran_timer.h" - #include "ltran_ethdev.h" - #include "ltran_base.h" - #include "ltran_stack.h" --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "ltran_forward.h" - - /* undefine lwip_ntohs in lwip/def.h */ -diff --git a/src/ltran/ltran_stat.h b/src/ltran/ltran_stat.h -index 16d03a1..75cb353 100644 ---- a/src/ltran/ltran_stat.h -+++ b/src/ltran/ltran_stat.h -@@ -17,7 +17,7 @@ - - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - /* - * When doing reads from the NIC or the client queues, -diff --git a/src/ltran/ltran_tcp_conn.h b/src/ltran/ltran_tcp_conn.h -index fa508bc..82c5faf 100644 ---- a/src/ltran/ltran_tcp_conn.h -+++ b/src/ltran/ltran_tcp_conn.h -@@ -18,7 +18,7 @@ - #include - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - struct gazelle_tcp_conn { - uint32_t tid; -diff --git a/src/ltran/ltran_tcp_sock.c b/src/ltran/ltran_tcp_sock.c -index 940ded8..4044fc0 100644 ---- a/src/ltran/ltran_tcp_sock.c -+++ b/src/ltran/ltran_tcp_sock.c -@@ -18,7 +18,7 @@ - #include "ltran_instance.h" - #include "ltran_base.h" - #include "ltran_jhash.h" --#include "gazelle_base_func.h" -+#include "common/gazelle_base_func.h" - #include "ltran_tcp_sock.h" - - struct gazelle_tcp_sock_htable *g_tcp_sock_htable = NULL; -diff --git a/src/ltran/ltran_tcp_sock.h b/src/ltran/ltran_tcp_sock.h -index a6e9571..e40891d 100644 ---- a/src/ltran/ltran_tcp_sock.h -+++ b/src/ltran/ltran_tcp_sock.h -@@ -17,7 +17,7 @@ - #include - #include - --#include "gazelle_opt.h" -+#include "common/gazelle_opt.h" - - struct gazelle_stack; - struct gazelle_tcp_sock { -diff --git a/src/ltran/main.c b/src/ltran/main.c -index 6cc8bc9..3d2310b 100644 ---- a/src/ltran/main.c -+++ b/src/ltran/main.c -@@ -20,7 +20,7 @@ - #include - #include - --#include "dpdk_common.h" -+#include "common/dpdk_common.h" - #include "ltran_log.h" - #include "ltran_param.h" - #include "ltran_stat.h" --- -2.33.0 - diff --git a/0214-add-.gitignore.patch b/0214-add-.gitignore.patch deleted file mode 100644 index 9217a9d..0000000 --- a/0214-add-.gitignore.patch +++ /dev/null @@ -1,50 +0,0 @@ -From da27acd950124efefb237b4cce69e42b9a769fa9 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 9 Jul 2024 15:37:30 +0800 -Subject: [PATCH] add .gitignore - -Signed-off-by: Lemmy Huang ---- - .gitignore | 17 +++++++++++++++++ - src/lstack/Makefile | 1 - - 2 files changed, 17 insertions(+), 1 deletion(-) - create mode 100644 .gitignore - -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..ec51d25 ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,17 @@ -+.vscode -+ -+**/*.so -+**/*.a -+**/*.o -+ -+**/CMakeCache.txt -+**/CMakeFiles -+examples/Makefile -+examples/cmake_install.cmake -+examples/example -+src/ltran/Makefile -+src/ltran/cmake_install.cmake -+src/ltran/ltran.map -+src/ltran/gazellectl -+src/ltran/ltran -+ -diff --git a/src/lstack/Makefile b/src/lstack/Makefile -index dd4e2c4..8a659c2 100644 ---- a/src/lstack/Makefile -+++ b/src/lstack/Makefile -@@ -104,7 +104,6 @@ else - endif - - DEP_LIBS = $(LWIP_LIB) $(LIBRTE_LIB) --$(info $(CC):$(DEP_LIBS)) - - SRCS = $(wildcard ./api/*.c ./core/*.c ./netif/*.c ../common/*.c) - # Linking object and library --- -2.33.0 - diff --git a/0215-cleancode-rename-gazelle-files-in-lwip.patch b/0215-cleancode-rename-gazelle-files-in-lwip.patch deleted file mode 100644 index daffb57..0000000 --- a/0215-cleancode-rename-gazelle-files-in-lwip.patch +++ /dev/null @@ -1,489 +0,0 @@ -From 8ce0711285aaa897b08cf894e2908fef9fffe112 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 9 Jul 2024 21:52:51 +0800 -Subject: [PATCH] cleancode: rename gazelle files in lwip - -Signed-off-by: Lemmy Huang ---- - src/common/gazelle_dfx_msg.h | 2 +- - src/lstack/api/lstack_epoll.c | 6 +++--- - src/lstack/api/lstack_fork.c | 2 +- - src/lstack/api/lstack_rtc_api.c | 4 ++-- - src/lstack/api/lstack_rtw_api.c | 2 +- - src/lstack/api/lstack_signal.c | 4 ++-- - src/lstack/api/lstack_wrap.c | 4 ++-- - src/lstack/core/lstack_cfg.c | 4 ++-- - src/lstack/core/lstack_control_plane.c | 4 ++-- - src/lstack/core/lstack_dpdk.c | 4 ++-- - src/lstack/core/lstack_init.c | 6 +++--- - src/lstack/core/lstack_lwip.c | 4 ++-- - src/lstack/core/lstack_preload.c | 4 ++-- - src/lstack/core/lstack_protocol_stack.c | 6 +++--- - src/lstack/core/lstack_stack_stat.c | 4 ++-- - src/lstack/core/lstack_thread_rpc.c | 2 +- - src/lstack/core/lstack_virtio.c | 2 +- - src/lstack/include/lstack_dpdk.h | 2 +- - src/lstack/include/lstack_protocol_stack.h | 2 +- - src/lstack/include/posix/lstack_epoll.h | 2 +- - src/lstack/netif/lstack_ethdev.c | 2 +- - src/lstack/netif/lstack_fault_inject.c | 2 +- - src/lstack/netif/lstack_flow.c | 2 +- - src/lstack/netif/lstack_vdev.c | 4 ++-- - src/ltran/ltran_instance.h | 2 +- - src/ltran/ltran_stack.h | 2 +- - src/ltran/ltran_tcp_conn.h | 4 ++-- - src/ltran/ltran_tcp_sock.c | 2 +- - src/ltran/ltran_tcp_sock.h | 2 +- - src/ltran/ltran_timer.c | 2 +- - 30 files changed, 47 insertions(+), 47 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 57bf631..a2ec07b 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -16,7 +16,7 @@ - #include - #include - --#include -+#include - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - #include "gazelle_fault_inject_common.h" -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 9c0aef7..7d00de7 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -19,13 +19,13 @@ - #include - #include - --#include -+#include - #include --#include -+#include - #include - #include - #include --#include -+#include - - #include "lstack_ethdev.h" - #include "lstack_stack_stat.h" -diff --git a/src/lstack/api/lstack_fork.c b/src/lstack/api/lstack_fork.c -index 43c212b..5cddee2 100644 ---- a/src/lstack/api/lstack_fork.c -+++ b/src/lstack/api/lstack_fork.c -@@ -13,7 +13,7 @@ - #include - #include - --#include -+#include - - pid_t lstack_fork(void) - { -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 18664ca..e77edec 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -14,8 +14,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - #include "posix/lstack_epoll.h" - #include "lstack_log.h" - #include "lstack_cfg.h" -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index e43be59..0f23ffd 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -15,7 +15,7 @@ - #include - #include - --#include -+#include - - #include "lstack_thread_rpc.h" - #include "posix/lstack_epoll.h" -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_signal.c -index 3dd5d03..9d0431b 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_signal.c -@@ -15,8 +15,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "common/gazelle_base_func.h" - #include "lstack_cfg.h" -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 3a60cbb..cf0d302 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -22,8 +22,8 @@ - #include - #include - --#include --#include -+#include -+#include - #include - - #include "posix/lstack_unistd.h" -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 4bc4217..a1f6c2f 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -24,8 +24,8 @@ - #include - - #include --#include --#include -+#include -+#include - #include - - #include "common/gazelle_reg_msg.h" -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 4ab12f6..5545b9f 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -21,8 +21,8 @@ - #include - #include - #include --#include --#include -+#include -+#include - - #include "lstack_cfg.h" - #include "lstack_dpdk.h" -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 583bb09..a095cbd 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -32,10 +32,10 @@ - #endif - #include - #include --#include -+#include - #include - #include --#include -+#include - #include - - #include -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index d97b218..a5a4a4e 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -28,11 +28,11 @@ - - #include - #include --#include -+#include - #include --#include -+#include - #include --#include -+#include - - #include "lstack_cfg.h" - #include "lstack_control_plane.h" -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 6e50e4d..75ef5f6 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -15,11 +15,11 @@ - #include - #include - #include --#include -+#include - #include - #include - #include --#include -+#include - #include - #include - #include -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index f7caef5..0974e9e 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -15,8 +15,8 @@ - #include - #include - --#include --#include -+#include -+#include - #include - - #include "lstack_log.h" -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 1983c0b..d8bdd3c 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -16,9 +16,9 @@ - #include - #include - #include --#include --#include --#include -+#include -+#include -+#include - #include - #include - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 423be81..e77f21a 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -15,11 +15,11 @@ - #include - #include - #include --#include -+#include -+#include - - #include "lstack_cfg.h" - #include "lstack_ethdev.h" --#include "posix_api.h" - #include "lstack_control_plane.h" - #include "lstack_log.h" - #include "common/dpdk_common.h" -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index e438c37..a6d2dbf 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -10,7 +10,7 @@ - * See the Mulan PSL v2 for more details. - */ - #include --#include -+#include - #include - - #include "lstack_log.h" -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index bc42bb9..36159c9 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -13,7 +13,7 @@ - #include - #include - #include --#include -+#include - #include - #include "lstack_cfg.h" - #include "lstack_log.h" -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 91af3c5..d058409 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -13,7 +13,7 @@ - #ifndef _GAZELLE_DPDK_H_ - #define _GAZELLE_DPDK_H_ - --#include -+#include - #include "common/gazelle_opt.h" - #include "common/gazelle_dfx_msg.h" - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 5b04c6d..7dce757 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -17,7 +17,7 @@ - #include - #include - --#include -+#include - #include - - #include "common/gazelle_opt.h" -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/posix/lstack_epoll.h -index 77b6ebb..6e02615 100644 ---- a/src/lstack/include/posix/lstack_epoll.h -+++ b/src/lstack/include/posix/lstack_epoll.h -@@ -18,7 +18,7 @@ - #include - #include - --#include -+#include - - #include "common/gazelle_dfx_msg.h" - #include "common/gazelle_opt.h" -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index e23d313..5685d11 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -19,7 +19,7 @@ - - #include - #include --#include -+#include - #include - - #include -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -index 4736e29..9fae745 100644 ---- a/src/lstack/netif/lstack_fault_inject.c -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -14,7 +14,7 @@ - #include - #include - --#include -+#include - - #include "lstack_cfg.h" - #include "lstack_log.h" -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index 84497dc..84c5c61 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -18,7 +18,7 @@ - #include - #include - --#include -+#include - #include - #include - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 63f9e40..a590b30 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -14,7 +14,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -201,7 +201,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - - uint16_t local_port = ntohs(qtuple->src_port); - if (get_global_cfg_params()->flow_bifurcation && get_global_cfg_params()->is_primary) { -- if (type == REG_RING_TCP_LISTEN_CLOSE || type == REG_RING_UDP_BIND_CLOSE) { // add enum type in reg_sock.h -+ if (type == REG_RING_TCP_LISTEN_CLOSE || type == REG_RING_UDP_BIND_CLOSE) { // add enum type in lwipgz_flow.h - port_map_mod(local_port, 0); - } else if (type == REG_RING_TCP_LISTEN || type == REG_RING_UDP_BIND) { - port_map_mod(local_port, 1); -diff --git a/src/ltran/ltran_instance.h b/src/ltran/ltran_instance.h -index f0fe580..9cb6d31 100644 ---- a/src/ltran/ltran_instance.h -+++ b/src/ltran/ltran_instance.h -@@ -13,7 +13,7 @@ - #ifndef __GAZELLE_INSTANCE_H__ - #define __GAZELLE_INSTANCE_H__ - --#include -+#include - #include - #include - -diff --git a/src/ltran/ltran_stack.h b/src/ltran/ltran_stack.h -index 693bb33..7dd1cb1 100644 ---- a/src/ltran/ltran_stack.h -+++ b/src/ltran/ltran_stack.h -@@ -13,7 +13,7 @@ - #ifndef __GAZELLE_STACK_H__ - #define __GAZELLE_STACK_H__ - --#include -+#include - - #include "ltran_stat.h" - -diff --git a/src/ltran/ltran_tcp_conn.h b/src/ltran/ltran_tcp_conn.h -index 82c5faf..87491de 100644 ---- a/src/ltran/ltran_tcp_conn.h -+++ b/src/ltran/ltran_tcp_conn.h -@@ -13,10 +13,10 @@ - #ifndef __GAZELLE_TCP_CONN_H__ - #define __GAZELLE_TCP_CONN_H__ - --#include -+#include - #include - #include --#include -+#include - - #include "common/gazelle_opt.h" - -diff --git a/src/ltran/ltran_tcp_sock.c b/src/ltran/ltran_tcp_sock.c -index 4044fc0..eef2821 100644 ---- a/src/ltran/ltran_tcp_sock.c -+++ b/src/ltran/ltran_tcp_sock.c -@@ -12,7 +12,7 @@ - - #include - --#include -+#include - - #include "ltran_tcp_conn.h" - #include "ltran_instance.h" -diff --git a/src/ltran/ltran_tcp_sock.h b/src/ltran/ltran_tcp_sock.h -index e40891d..6ca97ec 100644 ---- a/src/ltran/ltran_tcp_sock.h -+++ b/src/ltran/ltran_tcp_sock.h -@@ -13,7 +13,7 @@ - #ifndef __GAZELLE_TCP_SOCK_H__ - #define __GAZELLE_TCP_SOCK_H__ - --#include -+#include - #include - #include - -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 0832c5f..87046cb 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -17,7 +17,7 @@ - #include - #include - #include --#include -+#include - - #include "ltran_param.h" - #include "ltran_log.h" --- -2.33.0 - diff --git a/0216-cleancode-refactor-lwipsock.h.patch b/0216-cleancode-refactor-lwipsock.h.patch deleted file mode 100644 index 1726808..0000000 --- a/0216-cleancode-refactor-lwipsock.h.patch +++ /dev/null @@ -1,280 +0,0 @@ -From 2f7ca29c8b7a93079a5579062fc6751a6be6fd0c Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 10 Jul 2024 11:08:07 +0800 -Subject: [PATCH] cleancode: refactor lwipsock.h - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_rtc_api.c | 7 +--- - src/lstack/api/lstack_wrap.c | 11 ++++-- - src/lstack/core/lstack_init.c | 3 -- - src/lstack/core/lstack_lwip.c | 45 ++++++++----------------- - src/lstack/core/lstack_protocol_stack.c | 26 ++++---------- - src/lstack/include/lstack_lwip.h | 7 ++-- - 6 files changed, 33 insertions(+), 66 deletions(-) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index e77edec..57ff89f 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -68,12 +68,7 @@ int rtc_close(int s) - return lstack_epoll_close(s); - } - -- lwip_close(s); -- if (sock != NULL) { -- list_del_node_null(&sock->event_list); -- } -- -- return posix_api->close_fn(s); -+ return lwip_close(s); - } - - int rtc_shutdown(int fd, int how) -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index cf0d302..16fc876 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -175,6 +175,8 @@ static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *add - - int32_t fd = g_wrap_api->accept_fn(s, addr, addrlen); - if (fd >= 0) { -+ struct lwip_sock *sock = get_socket(fd); -+ SET_CONN_TYPE_LIBOS(sock->conn); - return fd; - } - -@@ -193,6 +195,8 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - - int32_t fd = g_wrap_api->accept4_fn(s, addr, addrlen, flags); - if (fd >= 0) { -+ struct lwip_sock *sock = get_socket(fd); -+ SET_CONN_TYPE_LIBOS(sock->conn); - return fd; - } - -@@ -452,10 +456,11 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - } - - ret = g_wrap_api->socket_fn(domain, type, protocol); -- /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */ -- if ((ret >= 0) && (type & SOCK_DGRAM)) { -+ if (ret >= 0) { - struct lwip_sock *sock = get_socket(ret); -- if (sock != NULL && sock->conn != NULL) { -+ SET_CONN_TYPE_LIBOS_OR_HOST(sock->conn); -+ /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */ -+ if (type & SOCK_DGRAM) { - SET_CONN_TYPE_LIBOS(sock->conn); - } - } -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index a5a4a4e..1b3882e 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -313,9 +313,6 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - } - -- /* lwip initialization */ -- lwip_sock_init(); -- - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_global_cfg_params()->kni_switch) { - set_kni_ip_mac(); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 75ef5f6..6fe4055 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -144,12 +144,12 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - return false; - } - --void do_lwip_init_sock(int32_t fd) -+int do_lwip_init_sock(int32_t fd) - { - struct protocol_stack *stack = get_protocol_stack(); -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = get_socket_by_fd(fd); - if (sock == NULL) { -- return; -+ return -1; - } - - reset_sock_data(sock); -@@ -157,7 +157,7 @@ void do_lwip_init_sock(int32_t fd) - sock->recv_ring = gazelle_ring_create_fast("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ); - if (sock->recv_ring == NULL) { - LSTACK_LOG(ERR, LSTACK, "sock_recv create failed. errno: %d.\n", rte_errno); -- return; -+ return -1; - } - - sock->send_ring = gazelle_ring_create_fast("sock_send", -@@ -166,7 +166,7 @@ void do_lwip_init_sock(int32_t fd) - if (sock->send_ring == NULL) { - gazelle_ring_free_fast(sock->recv_ring); - LSTACK_LOG(ERR, LSTACK, "sock_send create failed. errno: %d.\n", rte_errno); -- return; -+ return -1; - } - (void)replenish_send_idlembuf(stack, sock); - -@@ -174,6 +174,7 @@ void do_lwip_init_sock(int32_t fd) - - init_list_node_null(&sock->recv_list); - init_list_node_null(&sock->event_list); -+ return 0; - } - - void do_lwip_clean_sock(int fd) -@@ -1237,32 +1238,6 @@ void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_soc - } - } - --int do_lwip_close(int fd) --{ -- int ret = lwip_close(fd); -- do_lwip_clean_sock(fd); -- posix_api->close_fn(fd); -- return ret; --} -- --int do_lwip_socket(int domain, int type, int protocol) --{ -- int32_t fd = lwip_socket(domain, type, 0); -- if (fd < 0) { -- return fd; -- } -- -- do_lwip_init_sock(fd); -- -- struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL || sock->stack == NULL) { -- do_lwip_close(fd); -- return -1; -- } -- -- return fd; --} -- - uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - uint32_t max_num) - { -@@ -1583,3 +1558,11 @@ err_t find_same_node_ring(struct tcp_pcb *npcb) - } - return 0; - } -+ -+unsigned same_node_ring_count(struct lwip_sock *sock) -+{ -+ const unsigned long long cur_begin = __atomic_load_n(&sock->same_node_rx_ring->sndbegin, __ATOMIC_RELAXED); -+ const unsigned long long cur_end = __atomic_load_n(&sock->same_node_rx_ring->sndend, __ATOMIC_RELAXED); -+ -+ return cur_end - cur_begin; -+} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d8bdd3c..c6075d5 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -424,11 +424,6 @@ static struct protocol_stack *stack_thread_init(void *arg) - } - RTE_PER_LCORE(_lcore_id) = stack->cpu_id; - -- if (hugepage_init() != 0) { -- LSTACK_LOG(ERR, LSTACK, "hugepage init failed\n"); -- goto END; -- } -- - tcpip_init(NULL, NULL); - - if (use_ltran()) { -@@ -714,12 +709,9 @@ void stack_arp(struct rpc_msg *msg) - - void stack_socket(struct rpc_msg *msg) - { -- msg->result = do_lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -+ msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); - if (msg->result < 0) { -- msg->result = do_lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -- if (msg->result < 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); -- } -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); - } - } - -@@ -735,7 +727,7 @@ void stack_close(struct rpc_msg *msg) - return; - } - -- msg->result = do_lwip_close(fd); -+ msg->result = lwip_close(fd); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } -@@ -803,7 +795,7 @@ void stack_accept(struct rpc_msg *msg) - - struct lwip_sock *sock = get_socket(accept_fd); - if (sock == NULL || sock->stack == NULL) { -- do_lwip_close(accept_fd); -+ lwip_close(accept_fd); - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; - } -@@ -1046,12 +1038,8 @@ void stack_create_shadow_fd(struct rpc_msg *msg) - } - - int domain = addr->sa_family; -- if (NETCONN_IS_UDP(sock)) { -- clone_fd = do_lwip_socket(domain, SOCK_DGRAM, 0); -- } else { -- clone_fd = do_lwip_socket(domain, SOCK_STREAM, 0); -- } -- -+ int type = NETCONN_IS_UDP(sock) ? SOCK_DGRAM : SOCK_STREAM; -+ clone_fd = lwip_socket(domain, type, 0); - if (clone_fd < 0) { - LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); - msg->result = clone_fd; -@@ -1370,7 +1358,7 @@ static void stack_all_fds_close(void) - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { - struct lwip_sock *sock = get_socket(i); - if (sock && sock->stack == get_protocol_stack()) { -- do_lwip_close(i); -+ lwip_close(i); - } - } - } -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 0b952ec..b972f11 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -16,21 +16,20 @@ - - #include "common/gazelle_dfx_msg.h" - -+struct lwip_sock; -+unsigned same_node_ring_count(struct lwip_sock *sock); -+ - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) - #define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || (sock->same_node_rx_ring != NULL && same_node_ring_count(sock))) - #define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_pre_del) - #define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) - --struct lwip_sock; - struct rte_mempool; - struct rpc_msg; - struct rte_mbuf; - struct protocol_stack; - --int do_lwip_socket(int domain, int type, int protocol); --int do_lwip_close(int32_t fd); --void do_lwip_init_sock(int32_t fd); - void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); - - struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); --- -2.33.0 - diff --git a/0217-cleancode-refactor-posix-type-and-get_socket.patch b/0217-cleancode-refactor-posix-type-and-get_socket.patch deleted file mode 100644 index cbf98e2..0000000 --- a/0217-cleancode-refactor-posix-type-and-get_socket.patch +++ /dev/null @@ -1,1047 +0,0 @@ -From dcfb07a30a3e4f8eece68d1ad8c17cb8c2a58945 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 10 Jul 2024 16:37:01 +0800 -Subject: [PATCH] cleancode: refactor posix type and get_socket - - Changed: - get_socket_by_fd -> lwip_get_socket - get_socket - - SET_CONN_TYPE_LIBOS_OR_HOST -> POSIX_SET_TYPE - SET_CONN_TYPE_LIBOS - SET_CONN_TYPE_HOST - - CONN_TYPE_IS_LIBOS -> POSIX_IS_TYPE - CONN_TYPE_IS_HOST - - CONN_TYPE_HAS_LIBOS_AND_HOST -> POSIX_HAS_TYPE - CONN_TYPE_HAS_LIBOS - CONN_TYPE_HAS_HOST - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 34 ++++---- - src/lstack/api/lstack_rtc_api.c | 6 +- - src/lstack/api/lstack_rtw_api.c | 14 ++-- - src/lstack/api/lstack_wrap.c | 104 ++++++++++++------------ - src/lstack/core/lstack_lwip.c | 22 ++--- - src/lstack/core/lstack_preload.c | 44 +++++----- - src/lstack/core/lstack_protocol_stack.c | 40 ++++----- - src/lstack/core/lstack_stack_stat.c | 2 +- - src/lstack/core/lstack_thread_rpc.c | 4 +- - src/lstack/include/lstack_preload.h | 10 +-- - 10 files changed, 137 insertions(+), 143 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7d00de7..8146b4f 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -164,7 +164,7 @@ static uint32_t update_events(struct lwip_sock *sock) - - if ((sock->epoll_events & EPOLLOUT) && NETCONN_IS_OUTIDLE(sock)) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && CONN_TYPE_IS_LIBOS(sock->conn)) { -+ if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -190,7 +190,7 @@ static void rtc_raise_pending_events(struct wakeup_poll *wakeup, struct lwip_soc - - if (sock->sendevent) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && CONN_TYPE_IS_LIBOS(sock->conn)) { -+ if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -219,7 +219,7 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - pthread_spin_lock(&wakeup->event_list_lock); - if (NETCONN_IS_OUTIDLE(sock)) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && CONN_TYPE_IS_LIBOS(sock->conn)) { -+ if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -240,7 +240,7 @@ int32_t lstack_do_epoll_create(int32_t fd) - return fd; - } - -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "fd=%d sock is NULL errno=%d\n", fd, errno); - posix_api->close_fn(fd); -@@ -307,7 +307,7 @@ int32_t lstack_epoll_create(int32_t flags) - - int32_t lstack_epoll_close(int32_t fd) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "fd=%d sock is NULL errno=%d\n", fd, errno); - GAZELLE_RETURN(EINVAL); -@@ -391,14 +391,14 @@ int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *epoll_sock = get_socket_by_fd(epfd); -+ struct lwip_sock *epoll_sock = lwip_get_socket(epfd); - if (epoll_sock == NULL || epoll_sock->wakeup == NULL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - - struct wakeup_poll *wakeup = epoll_sock->wakeup; -- struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL || sock->conn == NULL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -@@ -431,18 +431,18 @@ int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *epoll_sock = get_socket_by_fd(epfd); -+ struct lwip_sock *epoll_sock = lwip_get_socket(epfd); - if (epoll_sock == NULL || epoll_sock->wakeup == NULL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - - struct wakeup_poll *wakeup = epoll_sock->wakeup; -- struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL || sock->conn == NULL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -- if (CONN_TYPE_HAS_HOST(sock->conn)) { -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { - int32_t ret = posix_api->epoll_ctl_fn(epfd, op, fd, event); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d errno=%d\n", fd, epfd, op, errno); -@@ -535,7 +535,7 @@ static int32_t poll_lwip_event(struct pollfd *fds, nfds_t nfds) - for (uint32_t i = 0; i < nfds; i++) { - /* sock->listen_next pointerto next stack listen */ - int32_t fd = fds[i].fd; -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - while (sock && sock->conn) { - uint32_t events = update_events(sock); - if (events) { -@@ -624,7 +624,7 @@ int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout) - - int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { -- struct lwip_sock *sock = get_socket_by_fd(epfd); -+ struct lwip_sock *sock = lwip_get_socket(epfd); - - if (sock == NULL || sock->wakeup == NULL) { - return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -@@ -673,7 +673,7 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - - int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { -- struct lwip_sock *sock = get_socket_by_fd(epfd); -+ struct lwip_sock *sock = lwip_get_socket(epfd); - if (sock == NULL || sock->wakeup == NULL) { - return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); - } -@@ -829,7 +829,7 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - for (uint32_t i = 0; i < nfds; i++) { - int32_t fd = fds[i].fd; - fds[i].revents = 0; -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - if (fd == wakeup->last_fds[i].fd && fds[i].events == wakeup->last_fds[i].events) { - /* fd close then socket may get same fd. */ -@@ -838,7 +838,7 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - } - } - -- if (sock == NULL || sock->conn == NULL || CONN_TYPE_HAS_HOST(sock->conn)) { -+ if (sock == NULL || sock->conn == NULL || POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { - update_kernel_poll(wakeup, i, fds + i); - } - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 57ff89f..97623b3 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -50,8 +50,8 @@ int rtc_socket(int domain, int type, int protocol) - - /* need call stack thread init function */ - ret = lwip_socket(domain, type, protocol); -- struct lwip_sock *sock = get_socket(ret); -- if (sock != NULL) { -+ if (ret >= 0) { -+ struct lwip_sock *sock = lwip_get_socket(ret); - sock->stack = get_protocol_stack(); - sock->epoll_events = 0; - sock->events = 0; -@@ -63,7 +63,7 @@ int rtc_socket(int domain, int type, int protocol) - - int rtc_close(int s) - { -- struct lwip_sock *sock = get_socket(s); -+ struct lwip_sock *sock = lwip_get_socket(s); - if (sock != NULL && sock->wakeup != NULL && sock->wakeup->epollfd == s) { - return lstack_epoll_close(s); - } -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 0f23ffd..f59b0cd 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -47,7 +47,7 @@ int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) - - int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) - { -- struct lwip_sock *sock = get_socket_by_fd(s); -+ struct lwip_sock *sock = lwip_get_socket(s); - - if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { - return stack_broadcast_bind(s, name, namelen); -@@ -137,7 +137,7 @@ ssize_t rtw_write(int s, const void *mem, size_t size) - - ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) - { -- struct lwip_sock *sock = get_socket_by_fd(s); -+ struct lwip_sock *sock = lwip_get_socket(s); - struct msghdr msg; - - msg.msg_name = NULL; -@@ -167,14 +167,14 @@ ssize_t rtw_recvmsg(int s, const struct msghdr *message, int flags) - - ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags) - { -- struct lwip_sock *sock = get_socket_by_fd(s); -+ struct lwip_sock *sock = lwip_get_socket(s); - return do_lwip_sendmsg_to_stack(sock, s, message, flags); - } - - static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, - struct sockaddr *addr, socklen_t *addrlen) - { -- struct lwip_sock *sock = get_socket_by_fd(sockfd); -+ struct lwip_sock *sock = lwip_get_socket(sockfd); - int ret; - - while (1) { -@@ -210,7 +210,7 @@ static inline ssize_t rtw_tcp_recvfrom(int sockfd, void *buf, size_t len, int fl - ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, - struct sockaddr *addr, socklen_t *addrlen) - { -- struct lwip_sock *sock = get_socket_by_fd(sockfd); -+ struct lwip_sock *sock = lwip_get_socket(sockfd); - if (NETCONN_IS_UDP(sock)) { - return rtw_udp_recvfrom(sockfd, buf, len, flags, addr, addrlen); - } else { -@@ -241,7 +241,7 @@ int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s - - int rtw_close(int s) - { -- struct lwip_sock *sock = get_socket(s); -+ struct lwip_sock *sock = lwip_get_socket(s); - if (sock && sock->wakeup && sock->wakeup->epollfd == s) { - return lstack_epoll_close(s); - } -@@ -250,7 +250,7 @@ int rtw_close(int s) - - int rtw_shutdown(int fd, int how) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock && sock->wakeup && sock->wakeup->epollfd == fd) { - GAZELLE_RETURN(ENOTSOCK); - } -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 16fc876..d3e1027 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -125,7 +125,7 @@ void wrap_api_set_dummy(void) - - static inline int32_t do_epoll_create1(int32_t flags) - { -- if (select_posix_path() == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->epoll_create1_fn(flags); - } - -@@ -134,7 +134,7 @@ static inline int32_t do_epoll_create1(int32_t flags) - - static inline int32_t do_epoll_create(int32_t size) - { -- if (select_posix_path() == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->epoll_create_fn(size); - } - -@@ -143,7 +143,7 @@ static inline int32_t do_epoll_create(int32_t size) - - static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event) - { -- if (select_posix_path() == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -@@ -152,7 +152,7 @@ static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct - - static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) - { -- if (select_posix_path() == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); - } - -@@ -169,14 +169,14 @@ static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, in - - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) - { -- if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->accept_fn(s, addr, addrlen); - } - - int32_t fd = g_wrap_api->accept_fn(s, addr, addrlen); - if (fd >= 0) { -- struct lwip_sock *sock = get_socket(fd); -- SET_CONN_TYPE_LIBOS(sock->conn); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - return fd; - } - -@@ -189,14 +189,14 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - - int32_t fd = g_wrap_api->accept4_fn(s, addr, addrlen, flags); - if (fd >= 0) { -- struct lwip_sock *sock = get_socket(fd); -- SET_CONN_TYPE_LIBOS(sock->conn); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - return fd; - } - -@@ -210,13 +210,13 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - } - - struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, &sock) == POSIX_KERNEL) { - return posix_api->bind_fn(s, name, namelen); - } - - /* select user path when udp enable and ip addr is multicast */ - if (IN_MULTICAST(ntohl(((struct sockaddr_in *)name)->sin_addr.s_addr))) { -- SET_CONN_TYPE_LIBOS(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - return g_wrap_api->bind_fn(s, name, namelen); - } - -@@ -233,7 +233,7 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - if (match_host_addr(&sock_addr)) { - /* maybe kni addr */ - if (posix_api->bind_fn(s, name, namelen) != 0) { -- SET_CONN_TYPE_LIBOS(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - } else { - /* reuse the port allocated by kernel when port == 0 */ - if (((struct sockaddr_in *)name)->sin_port == 0) { -@@ -248,7 +248,7 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - } - return g_wrap_api->bind_fn(s, name, namelen); - } else { -- SET_CONN_TYPE_HOST(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); - return posix_api->bind_fn(s, name, namelen); - } - } -@@ -303,11 +303,11 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - } - - struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, &sock) == POSIX_KERNEL) { - return posix_api->connect_fn(s, name, namelen); - } - -- sock = get_socket(s); -+ sock = lwip_get_socket(s); - if (sock == NULL) { - return posix_api->connect_fn(s, name, namelen); - } -@@ -323,10 +323,10 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - "listen_rx_ring_%d", remote_port); - if (is_local && rte_ring_lookup(listen_ring_name) == NULL) { - ret = posix_api->connect_fn(s, name, namelen); -- SET_CONN_TYPE_HOST(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); - } else { - ret = g_wrap_api->connect_fn(s, name, namelen); -- SET_CONN_TYPE_LIBOS(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - } - - return ret; -@@ -334,7 +334,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - - static inline int32_t do_listen(int32_t s, int32_t backlog) - { -- if (select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->listen_fn(s, backlog); - } - -@@ -352,7 +352,7 @@ static inline int32_t do_getpeername(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == PATH_LWIP) { -+ if (select_fd_posix_path(s, NULL) == POSIX_LWIP) { - return g_wrap_api->getpeername_fn(s, name, namelen); - } - -@@ -365,7 +365,7 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == PATH_LWIP) { -+ if (select_fd_posix_path(s, NULL) == POSIX_LWIP) { - return g_wrap_api->getsockname_fn(s, name, namelen); - } - -@@ -422,7 +422,7 @@ static bool unsupport_optname(int32_t level, int32_t optname) - - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { -- if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(level, optname)) { -+ if (select_fd_posix_path(s, NULL) == POSIX_LWIP && !unsupport_optname(level, optname)) { - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -431,7 +431,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v - - static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, const void *optval, socklen_t optlen) - { -- if (select_fd_posix_path(s, NULL) == PATH_KERNEL || unsupport_optname(level, optname)) { -+ if (select_fd_posix_path(s, NULL) == POSIX_KERNEL || unsupport_optname(level, optname)) { - return posix_api->setsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -445,7 +445,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - { - int32_t ret; - /* process not init completed or not hajacking thread */ -- if (select_posix_path() == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->socket_fn(domain, type, protocol); - } - -@@ -457,11 +457,11 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - - ret = g_wrap_api->socket_fn(domain, type, protocol); - if (ret >= 0) { -- struct lwip_sock *sock = get_socket(ret); -- SET_CONN_TYPE_LIBOS_OR_HOST(sock->conn); -+ struct lwip_sock *sock = lwip_get_socket(ret); -+ POSIX_SET_TYPE(sock, POSIX_LWIP | POSIX_KERNEL); - /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */ - if (type & SOCK_DGRAM) { -- SET_CONN_TYPE_LIBOS(sock->conn); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - } - } - -@@ -478,8 +478,8 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - return 0; - } - -- if (select_posix_path() == PATH_KERNEL || // maybe fd is created by open before posix_api_init called -- select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || // maybe fd is created by open before posix_api_init called -+ select_fd_posix_path(sockfd, NULL) == POSIX_KERNEL) { - return posix_api->recv_fn(sockfd, buf, len, flags); - } - -@@ -496,8 +496,8 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - return 0; - } - -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->read_fn(s, mem, len); - } - -@@ -506,8 +506,8 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - { -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->readv_fn(s, iov, iovcnt); - } - -@@ -516,8 +516,8 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) - { -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(sockfd, NULL) == POSIX_KERNEL) { - return posix_api->send_fn(sockfd, buf, len, flags); - } - -@@ -526,8 +526,8 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - { -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->write_fn(s, mem, size); - } - -@@ -537,8 +537,8 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - { - struct lwip_sock *sock; -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, &sock) == POSIX_KERNEL) { - return posix_api->writev_fn(s, iov, iovcnt); - } - -@@ -551,8 +551,8 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - GAZELLE_RETURN(EINVAL); - } - -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, NULL) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, NULL) == POSIX_KERNEL) { - return posix_api->recv_msg(s, message, flags); - } - -@@ -566,8 +566,8 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - } - - struct lwip_sock *sock; -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, &sock) == POSIX_KERNEL) { - return posix_api->send_msg(s, message, flags); - } - -@@ -586,7 +586,7 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t - } - - struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(sockfd, &sock) == PATH_LWIP) { -+ if (select_fd_posix_path(sockfd, &sock) == POSIX_LWIP) { - return g_wrap_api->recv_from(sockfd, buf, len, flags, addr, addrlen); - } - -@@ -597,7 +597,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - const struct sockaddr *addr, socklen_t addrlen) - { - struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(sockfd, &sock) != PATH_LWIP) { -+ if (select_fd_posix_path(sockfd, &sock) != POSIX_LWIP) { - return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen); - } - -@@ -607,8 +607,8 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - static inline int32_t do_close(int32_t s) - { - struct lwip_sock *sock = NULL; -- if (select_posix_path() == PATH_KERNEL || -- select_fd_posix_path(s, &sock) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || -+ select_fd_posix_path(s, &sock) == POSIX_KERNEL) { - /* we called lwip_socket, even if kernel fd */ - if (posix_api != NULL && !posix_api->ues_posix && - /* contain posix_api->close_fn if success */ -@@ -624,7 +624,7 @@ static inline int32_t do_close(int32_t s) - static int32_t do_shutdown(int fd, int how) - { - struct lwip_sock *sock = NULL; -- if (select_posix_path() == PATH_KERNEL || select_fd_posix_path(fd, &sock) == PATH_KERNEL) { -+ if (select_posix_path() == POSIX_KERNEL || select_fd_posix_path(fd, &sock) == POSIX_KERNEL) { - if (posix_api != NULL && !posix_api->ues_posix && g_wrap_api->shutdown_fn(fd, how) == 0) { - return 0; - } else { -@@ -637,7 +637,7 @@ static int32_t do_shutdown(int fd, int how) - - static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { -- if ((select_posix_path() == PATH_KERNEL) || fds == NULL || nfds == 0) { -+ if ((select_posix_path() == POSIX_KERNEL) || fds == NULL || nfds == 0) { - return posix_api->poll_fn(fds, nfds, timeout); - } - -@@ -676,7 +676,7 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - - static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { -- if ((select_posix_path() == PATH_KERNEL) || !(readfds || writefds || exceptfds) || nfds == 0) { -+ if ((select_posix_path() == POSIX_KERNEL) || !(readfds || writefds || exceptfds) || nfds == 0) { - return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - -@@ -691,8 +691,8 @@ static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set - val = va_arg(ap, typeof(val)); \ - va_end(ap); \ - struct lwip_sock *sock = NULL; \ -- if (select_posix_path() == PATH_KERNEL || \ -- select_fd_posix_path(_fd, &sock) == PATH_KERNEL) \ -+ if (select_posix_path() == POSIX_KERNEL || \ -+ select_fd_posix_path(_fd, &sock) == POSIX_KERNEL) \ - return _fcntl_fn(_fd, _cmd, val); \ - int32_t ret1 = _fcntl_fn(_fd, _cmd, val); \ - if (ret1 == -1) { \ -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 6fe4055..84ef782 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -147,7 +147,7 @@ static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_so - int do_lwip_init_sock(int32_t fd) - { - struct protocol_stack *stack = get_protocol_stack(); -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - return -1; - } -@@ -179,7 +179,7 @@ int do_lwip_init_sock(int32_t fd) - - void do_lwip_clean_sock(int fd) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || sock->stack == NULL) { - return; - } -@@ -819,7 +819,7 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (len == 0 && !NETCONN_IS_UDP(sock)) { - return 0; - } -@@ -1059,7 +1059,7 @@ 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); -+ struct lwip_sock *sock = lwip_get_socket(fd); - bool noblock = (flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn); - - if (recv_break_for_err(sock)) { -@@ -1095,7 +1095,7 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - - void do_lwip_add_recvlist(int32_t fd) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - if (sock && sock->stack && list_is_null(&sock->recv_list)) { - list_add_node(&sock->stack->recv_list, &sock->recv_list); -@@ -1166,7 +1166,7 @@ void do_lwip_connected_callback(struct netconn *conn) - } - - int32_t fd = conn->callback_arg.socket; -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || sock->conn == NULL) { - return; - } -@@ -1177,7 +1177,7 @@ void do_lwip_connected_callback(struct netconn *conn) - - posix_api->shutdown_fn(fd, SHUT_RDWR); - -- SET_CONN_TYPE_LIBOS(conn); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - - add_sock_event(sock, EPOLLOUT); - } -@@ -1207,8 +1207,8 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - if (netconn != NULL) { - conn->fd = netconn->callback_arg.socket; - conn->recv_cnt = (netconn->recvmbox == NULL) ? 0 : rte_ring_count(netconn->recvmbox->ring); -- struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); -- if (sock != NULL) { -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -+ if (sock != NULL && sock->conn != NULL) { - conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); - conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; - conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); -@@ -1473,7 +1473,7 @@ err_t same_node_ring_create(struct rte_ring **ring, int size, int port, char *na - static void init_same_node_ring(struct tcp_pcb *pcb) - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); - - pcb->client_rx_ring = NULL; - pcb->client_tx_ring = NULL; -@@ -1488,7 +1488,7 @@ static void init_same_node_ring(struct tcp_pcb *pcb) - err_t create_same_node_ring(struct tcp_pcb *pcb) - { - struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = get_socket(netconn->callback_arg.socket); -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); - - if (same_node_ring_create(&pcb->client_rx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "rx") != 0) { - goto END; -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 0974e9e..8cf4657 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -30,7 +30,7 @@ - - #define EXCLUDE_THRD_CNT 1 - const static char *g_exclude_thread[EXCLUDE_THRD_CNT] = {"eal-intr-thread"}; --static PER_THREAD enum KERNEL_LWIP_PATH g_preload_thrdpath = PATH_UNKNOW; -+static PER_THREAD enum posix_type g_preload_thrdpath = POSIX_ALL; - - struct lstack_preload { - int32_t preload_switch; -@@ -79,27 +79,27 @@ static void preload_get_thrdname(void) - LSTACK_PRE_LOG(LSTACK_INFO, "thread name=%s ok\n", g_preload_info.env_thrdname); - } - --enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket) -+enum posix_type select_fd_posix_path(int32_t fd, struct lwip_sock **socket) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - /* AF_UNIX case */ -- if (!sock || !sock->conn || CONN_TYPE_IS_HOST(sock->conn)) { -- return PATH_KERNEL; -+ if (!sock || !sock->conn || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { -+ return POSIX_KERNEL; - } - - if (socket) { - *socket = sock; - } - -- if (likely(CONN_TYPE_IS_LIBOS(sock->conn))) { -- return PATH_LWIP; -+ if (likely(POSIX_IS_TYPE(sock, POSIX_LWIP))) { -+ return POSIX_LWIP; - } - -- return PATH_UNKNOW; -+ return POSIX_ALL; - } - --enum KERNEL_LWIP_PATH select_posix_path(void) -+enum posix_type select_posix_path(void) - { - if (unlikely(posix_api == NULL)) { - /* -@@ -109,14 +109,14 @@ enum KERNEL_LWIP_PATH select_posix_path(void) - if (posix_api_init() != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); - } -- return PATH_KERNEL; -+ return POSIX_KERNEL; - } - - if (unlikely(posix_api->ues_posix)) { -- return PATH_KERNEL; -+ return POSIX_KERNEL; - } - -- if (g_preload_thrdpath != PATH_UNKNOW) { -+ if (g_preload_thrdpath != POSIX_ALL) { - return g_preload_thrdpath; - } - -@@ -126,31 +126,31 @@ enum KERNEL_LWIP_PATH select_posix_path(void) - - char thread_name[PATH_MAX] = {0}; - if (pthread_getname_np(pthread_self(), thread_name, PATH_MAX) != 0) { -- g_preload_thrdpath = PATH_KERNEL; -- return PATH_KERNEL; -+ g_preload_thrdpath = POSIX_KERNEL; -+ return POSIX_KERNEL; - } - - /* exclude dpdk thread */ - for (int i = 0; i < EXCLUDE_THRD_CNT; i++) { - if (strstr(thread_name, g_exclude_thread[i]) != NULL) { -- g_preload_thrdpath = PATH_KERNEL; -- return PATH_KERNEL; -+ g_preload_thrdpath = POSIX_KERNEL; -+ return POSIX_KERNEL; - } - } - - /* not set GAZELLE_THREAD_NAME, select all thread */ - if (g_preload_info.env_thrdname[0] == '\0') { -- g_preload_thrdpath = PATH_LWIP; -- return PATH_LWIP; -+ g_preload_thrdpath = POSIX_LWIP; -+ return POSIX_LWIP; - } - - if (strstr(thread_name, g_preload_info.env_thrdname) == NULL) { -- g_preload_thrdpath = PATH_KERNEL; -- return PATH_KERNEL; -+ g_preload_thrdpath = POSIX_KERNEL; -+ return POSIX_KERNEL; - } - -- g_preload_thrdpath = PATH_LWIP; -- return PATH_LWIP; -+ g_preload_thrdpath = POSIX_LWIP; -+ return POSIX_LWIP; - } - - int preload_info_init(void) -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index c6075d5..d17cb67 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -126,8 +126,8 @@ struct protocol_stack *get_protocol_stack(void) - - struct protocol_stack *get_protocol_stack_by_fd(int32_t fd) - { -- struct lwip_sock *sock = get_socket(fd); -- if (sock == NULL) { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL || sock->conn == NULL) { - return NULL; - } - -@@ -719,7 +719,7 @@ void stack_close(struct rpc_msg *msg) - { - int32_t fd = msg->args[MSG_ARG_0].i; - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -@@ -738,7 +738,7 @@ void stack_shutdown(struct rpc_msg *msg) - int fd = msg->args[MSG_ARG_0].i; - int how = msg->args[MSG_ARG_1].i; - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -@@ -767,7 +767,7 @@ void stack_listen(struct rpc_msg *msg) - int32_t fd = msg->args[MSG_ARG_0].i; - int32_t backlog = msg->args[MSG_ARG_1].i; - -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - msg->result = -1; - return; -@@ -793,7 +793,7 @@ void stack_accept(struct rpc_msg *msg) - return; - } - -- struct lwip_sock *sock = get_socket(accept_fd); -+ struct lwip_sock *sock = lwip_get_socket(accept_fd); - if (sock == NULL || sock->stack == NULL) { - lwip_close(accept_fd); - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -@@ -880,7 +880,7 @@ void stack_tcp_send(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack(); - int replenish_again; - -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); -@@ -917,7 +917,7 @@ void stack_udp_send(struct rpc_msg *msg) - int replenish_again; - uint32_t call_num; - -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); -@@ -1030,7 +1030,7 @@ void stack_create_shadow_fd(struct rpc_msg *msg) - socklen_t addr_len = msg->args[MSG_ARG_2].socklen; - - int32_t clone_fd = 0; -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); - msg->result = -1; -@@ -1046,7 +1046,7 @@ void stack_create_shadow_fd(struct rpc_msg *msg) - return; - } - -- struct lwip_sock *clone_sock = get_socket_by_fd(clone_fd); -+ struct lwip_sock *clone_sock = lwip_get_socket(clone_fd); - if (clone_sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); - msg->result = -1; -@@ -1114,7 +1114,7 @@ void stack_recvlist_count(struct rpc_msg *msg) - int32_t stack_broadcast_close(int32_t fd) - { - int32_t ret = 0; -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { - GAZELLE_RETURN(EBADF); -@@ -1139,7 +1139,7 @@ int32_t stack_broadcast_close(int32_t fd) - int stack_broadcast_shutdown(int fd, int how) - { - int32_t ret = 0; -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { - GAZELLE_RETURN(EBADF); -@@ -1186,7 +1186,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - socklen_t addr_len = sizeof(addr); - int32_t ret, clone_fd; - -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || cur_stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); - GAZELLE_RETURN(EBADF); -@@ -1216,9 +1216,9 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - } - - if (min_conn_stk_idx == i) { -- get_socket_by_fd(clone_fd)->conn->is_master_fd = 1; -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 1; - } else { -- get_socket_by_fd(clone_fd)->conn->is_master_fd = 0; -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 0; - } - - ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); -@@ -1232,7 +1232,7 @@ int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) - - static struct lwip_sock *get_min_accept_sock(int32_t fd) - { -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - struct lwip_sock *min_sock = NULL; - - while (sock) { -@@ -1282,7 +1282,7 @@ int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t - struct protocol_stack *stack = NULL; - int32_t ret, clone_fd; - -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || cur_stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); - GAZELLE_RETURN(EBADF); -@@ -1313,7 +1313,7 @@ int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *ad - { - int32_t ret = -1; - struct lwip_sock *min_sock = NULL; -- struct lwip_sock *sock = get_socket(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - struct protocol_stack *stack = NULL; - if (sock == NULL) { - GAZELLE_RETURN(EBADF); -@@ -1356,8 +1356,8 @@ int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *add - static void stack_all_fds_close(void) - { - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { -- struct lwip_sock *sock = get_socket(i); -- if (sock && sock->stack == get_protocol_stack()) { -+ struct lwip_sock *sock = lwip_get_socket(i); -+ if (sock && sock->conn && sock->stack == get_protocol_stack()) { - lwip_close(i); - } - } -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index e77f21a..e42efde 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -81,7 +81,7 @@ void time_stamp_into_recvmbox(struct lwip_sock *sock) - - void time_stamp_record(int fd, struct pbuf *pbuf) - { -- struct lwip_sock *sock = get_socket_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); - - if (get_protocol_stack_group()->latency_start && sock && pbuf) { - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index a6d2dbf..8ac06cb 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -474,7 +474,7 @@ int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) - } - - if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(get_socket_by_fd(fd)); -+ time_stamp_into_rpcmsg(lwip_get_socket(fd)); - } - - msg->args[MSG_ARG_0].i = fd; -@@ -495,7 +495,7 @@ int32_t rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) - } - - if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(get_socket_by_fd(fd)); -+ time_stamp_into_rpcmsg(lwip_get_socket(fd)); - } - - msg->args[MSG_ARG_0].i = fd; -diff --git a/src/lstack/include/lstack_preload.h b/src/lstack/include/lstack_preload.h -index 0ad7877..c30736a 100644 ---- a/src/lstack/include/lstack_preload.h -+++ b/src/lstack/include/lstack_preload.h -@@ -13,13 +13,7 @@ - #define __LSTACK_PRELOAD_H__ - #include - --enum KERNEL_LWIP_PATH { -- PATH_KERNEL = 0, -- PATH_LWIP, -- PATH_UNKNOW, --}; -- --enum KERNEL_LWIP_PATH select_posix_path(void); --enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket); -+enum posix_type select_posix_path(void); -+enum posix_type select_fd_posix_path(int32_t fd, struct lwip_sock **socket); - int preload_info_init(void); - #endif --- -2.33.0 - diff --git a/0218-fix-some-error-of-NULL-pointer.patch b/0218-fix-some-error-of-NULL-pointer.patch deleted file mode 100644 index a49c792..0000000 --- a/0218-fix-some-error-of-NULL-pointer.patch +++ /dev/null @@ -1,198 +0,0 @@ -From da10c78f9fa9b865ccc1a780a77f405dc093d04a Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 15 Jul 2024 15:27:53 +0800 -Subject: [PATCH] fix some error of NULL pointer - ---- - src/lstack/api/lstack_epoll.c | 23 ++++++++++++++++++----- - src/lstack/core/lstack_lwip.c | 15 ++++++++------- - src/lstack/core/lstack_port_map.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/netif/lstack_ethdev.c | 8 ++++++-- - src/lstack/netif/lstack_tx_cache.c | 1 + - 6 files changed, 35 insertions(+), 16 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 7d00de7..566443e 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -740,6 +740,7 @@ static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) - wakeup->events = calloc(POLL_KERNEL_EVENTS, sizeof(struct epoll_event)); - if (wakeup->events == NULL) { - free(wakeup->last_fds); -+ wakeup->last_fds = NULL; - GAZELLE_RETURN(EINVAL); - } - -@@ -760,7 +761,7 @@ static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) - return 0; - } - --static void resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) -+static int resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) - { - if (wakeup->last_fds) { - free(wakeup->last_fds); -@@ -768,6 +769,7 @@ static void resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) - wakeup->last_fds = calloc(nfds, sizeof(struct pollfd)); - if (wakeup->last_fds == NULL) { - LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -+ return -1; - } - - if (wakeup->events) { -@@ -776,9 +778,12 @@ static void resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) - wakeup->events = calloc(nfds, sizeof(struct epoll_event)); - if (wakeup->events == NULL) { - LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -+ free(wakeup->last_fds); -+ return -1; - } - - wakeup->last_max_nfds = nfds; -+ return 0; - } - - static void poll_bind_statck(struct wakeup_poll *wakeup, int32_t *stack_count) -@@ -811,14 +816,18 @@ static void update_kernel_poll(struct wakeup_poll *wakeup, uint32_t index, struc - } - } - --static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfds) -+static int poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfds) - { - int32_t stack_count[PROTOCOL_STACK_MAX] = {0}; - int32_t poll_change = 0; -+ int ret = 0; - - /* poll fds num more, recalloc fds size */ - if (nfds > wakeup->last_max_nfds) { -- resize_kernel_poll(wakeup, nfds); -+ ret = resize_kernel_poll(wakeup, nfds); -+ if (ret < 0) { -+ return -1; -+ } - poll_change = 1; - } - -@@ -855,13 +864,14 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - } - - if (poll_change == 0) { -- return; -+ return 0; - } - wakeup->last_nfds = nfds; - - if (get_global_cfg_params()->app_bind_numa) { - poll_bind_statck(wakeup, stack_count); - } -+ return 0; - } - - int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) -@@ -880,7 +890,10 @@ int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - } - } - -- poll_init(wakeup, fds, nfds); -+ if (poll_init(wakeup, fds, nfds) < 0) { -+ free(wakeup); -+ GAZELLE_RETURN(EINVAL); -+ } - - int32_t kernel_num = 0; - int32_t lwip_num = 0; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 75ef5f6..4d73d44 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -333,7 +333,7 @@ static ssize_t do_app_write(struct lwip_sock *sock, struct pbuf *pbufs[], void * - } - - /* reduce the branch in loop */ -- uint16_t copy_len = len - send_len; -+ size_t copy_len = len - send_len; - rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, copy_len); - pbufs[i]->tot_len = pbufs[i]->len = copy_len; - send_len += copy_len; -@@ -1358,12 +1358,13 @@ void netif_poll(struct netif *netif) - /* processes on same node handshake packet use this function */ - err_t netif_loop_output(struct netif *netif, struct pbuf *p) - { -- if (p != NULL) { -- const struct ip_hdr *iphdr; -- iphdr = (const struct ip_hdr *)p->payload; -- if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { -- return udp_netif_loop_output(netif, p); -- } -+ if (!p) { -+ return ERR_ARG; -+ } -+ const struct ip_hdr *iphdr; -+ iphdr = (const struct ip_hdr *)p->payload; -+ if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { -+ return udp_netif_loop_output(netif, p); - } - - struct tcp_pcb *pcb = p->pcb; -diff --git a/src/lstack/core/lstack_port_map.c b/src/lstack/core/lstack_port_map.c -index 5439394..ce9d8df 100644 ---- a/src/lstack/core/lstack_port_map.c -+++ b/src/lstack/core/lstack_port_map.c -@@ -39,4 +39,4 @@ uint16_t port_map_get(uint16_t port) - } - pthread_mutex_unlock(&g_rule_map_mutex); - return val; --} -\ No newline at end of file -+} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d8bdd3c..d1bbf9b 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -1000,7 +1000,7 @@ void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack - return; - } - copy_mbuf(mbuf_copy, mbuf); -- virtio_tap_process_tx(stack->queue_id, mbuf_copy); -+ virtio_tap_process_tx(cur_stack->queue_id, mbuf_copy); - } - return; - } -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 5685d11..d4d0878 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -319,10 +319,14 @@ static err_t eth_dev_init(struct netif *netif) - int32_t ethdev_init(struct protocol_stack *stack) - { - struct cfg_params *cfg = get_global_cfg_params(); -- -+ int ret = 0; -+ - vdev_dev_ops_init(&stack->dev_ops); - if (cfg->send_cache_mode) { -- tx_cache_init(stack->queue_id, stack, &stack->dev_ops); -+ ret = tx_cache_init(stack->queue_id, stack, &stack->dev_ops); -+ if (ret < 0) { -+ return ret; -+ } - } - - if (use_ltran()) { -diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c -index cda0003..9a48307 100644 ---- a/src/lstack/netif/lstack_tx_cache.c -+++ b/src/lstack/netif/lstack_tx_cache.c -@@ -45,6 +45,7 @@ int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops) - struct tx_cache *tx_cache = calloc(1, sizeof(struct tx_cache)); - if (tx_cache == NULL) { - LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache init failed\n", queue_id); -+ return -1; - } - - tx_cache->queue_id = queue_id; --- -2.33.0 - diff --git a/0219-cleancode-refactor-posix_api.patch b/0219-cleancode-refactor-posix_api.patch deleted file mode 100644 index 776865f..0000000 --- a/0219-cleancode-refactor-posix_api.patch +++ /dev/null @@ -1,775 +0,0 @@ -From a1523d108581cfc8aaf89b1116dde071ca5656d8 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 10 Jul 2024 17:40:43 +0800 -Subject: [PATCH] cleancode: refactor posix_api - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 16 +- - src/lstack/api/lstack_fork.c | 3 +- - src/lstack/api/lstack_rtw_api.c | 2 +- - src/lstack/api/lstack_wrap.c | 234 ++++++++++-------------- - src/lstack/core/lstack_control_plane.c | 4 +- - src/lstack/core/lstack_init.c | 4 +- - src/lstack/core/lstack_lwip.c | 5 +- - src/lstack/core/lstack_preload.c | 23 ++- - src/lstack/core/lstack_protocol_stack.c | 8 +- - src/lstack/include/lstack_preload.h | 6 +- - src/lstack/netif/lstack_flow.c | 1 + - 11 files changed, 139 insertions(+), 167 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 8146b4f..f8fd6d4 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -164,7 +164,7 @@ static uint32_t update_events(struct lwip_sock *sock) - - if ((sock->epoll_events & EPOLLOUT) && NETCONN_IS_OUTIDLE(sock)) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -+ if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -190,7 +190,7 @@ static void rtc_raise_pending_events(struct wakeup_poll *wakeup, struct lwip_soc - - if (sock->sendevent) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -+ if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -219,7 +219,7 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - pthread_spin_lock(&wakeup->event_list_lock); - if (NETCONN_IS_OUTIDLE(sock)) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (sock->conn && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -+ if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { - event |= EPOLLOUT; - } - } -@@ -398,7 +398,7 @@ int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - - struct wakeup_poll *wakeup = epoll_sock->wakeup; - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -@@ -438,7 +438,7 @@ int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - - struct wakeup_poll *wakeup = epoll_sock->wakeup; - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -@@ -536,7 +536,7 @@ static int32_t poll_lwip_event(struct pollfd *fds, nfds_t nfds) - /* sock->listen_next pointerto next stack listen */ - int32_t fd = fds[i].fd; - struct lwip_sock *sock = lwip_get_socket(fd); -- while (sock && sock->conn) { -+ while (!POSIX_IS_CLOSED(sock)) { - uint32_t events = update_events(sock); - if (events) { - fds[i].revents = events; -@@ -838,7 +838,7 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - } - } - -- if (sock == NULL || sock->conn == NULL || POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ if (POSIX_IS_CLOSED(sock) || POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { - update_kernel_poll(wakeup, i, fds + i); - } - -@@ -846,7 +846,7 @@ static void poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfd - wakeup->last_fds[i].events = fds[i].events; - poll_change = 1; - -- while (sock && sock->conn) { -+ while (!POSIX_IS_CLOSED(sock)) { - sock->epoll_events = fds[i].events | POLLERR; - sock->wakeup = wakeup; - stack_count[sock->stack->stack_idx]++; -diff --git a/src/lstack/api/lstack_fork.c b/src/lstack/api/lstack_fork.c -index 5cddee2..f5d0e95 100644 ---- a/src/lstack/api/lstack_fork.c -+++ b/src/lstack/api/lstack_fork.c -@@ -20,8 +20,9 @@ pid_t lstack_fork(void) - pid_t pid; - - pid = posix_api->fork_fn(); -+ /* child not support lwip */ - if (pid == 0) { -- posix_api_fork(); -+ posix_api->use_kernel = 1; - } - return pid; - } -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index f59b0cd..09c4e11 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -186,7 +186,7 @@ static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, - return -1; - } - sock = sock->listen_next; -- if (sock != NULL && sock->conn != NULL) { -+ if (!POSIX_IS_CLOSED(sock)) { - sockfd = sock->conn->callback_arg.socket; - } else { - if (sock == NULL) { -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index d3e1027..b19990e 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -37,12 +37,8 @@ - #include "lstack_rtw_api.h" - #include "lstack_dummy_api.h" - --#ifndef SOCK_TYPE_MASK --#define SOCK_TYPE_MASK 0xf --#endif -- --posix_api_t g_wrap_api_value; --posix_api_t *g_wrap_api; -+static posix_api_t g_wrap_api_value; -+static posix_api_t *g_wrap_api; - - void wrap_api_init(void) - { -@@ -68,10 +64,10 @@ void wrap_api_init(void) - g_wrap_api->writev_fn = lwip_writev; - g_wrap_api->recv_fn = lwip_recv; - g_wrap_api->send_fn = lwip_send; -- g_wrap_api->recv_msg = lwip_recvmsg; -- g_wrap_api->send_msg = lwip_sendmsg; -- g_wrap_api->recv_from = lwip_recvfrom; -- g_wrap_api->send_to = lwip_sendto; -+ g_wrap_api->recvmsg_fn = lwip_recvmsg; -+ g_wrap_api->sendmsg_fn = lwip_sendmsg; -+ g_wrap_api->recvfrom_fn = lwip_recvfrom; -+ g_wrap_api->sendto_fn = lwip_sendto; - g_wrap_api->epoll_wait_fn = rtc_epoll_wait; - g_wrap_api->poll_fn = rtc_poll; - g_wrap_api->close_fn = rtc_close; -@@ -97,10 +93,10 @@ void wrap_api_init(void) - g_wrap_api->writev_fn = rtw_writev; - g_wrap_api->recv_fn = rtw_recv; - g_wrap_api->send_fn = rtw_send; -- g_wrap_api->recv_msg = rtw_recvmsg; -- g_wrap_api->send_msg = rtw_sendmsg; -- g_wrap_api->recv_from = rtw_recvfrom; -- g_wrap_api->send_to = rtw_sendto; -+ g_wrap_api->recvmsg_fn = rtw_recvmsg; -+ g_wrap_api->sendmsg_fn = rtw_sendmsg; -+ g_wrap_api->recvfrom_fn = rtw_recvfrom; -+ g_wrap_api->sendto_fn = rtw_sendto; - g_wrap_api->epoll_wait_fn = rtw_epoll_wait; - g_wrap_api->poll_fn = rtw_poll; - g_wrap_api->close_fn = rtw_close; -@@ -118,8 +114,8 @@ void wrap_api_set_dummy(void) - g_wrap_api->send_fn = dummy_send; - g_wrap_api->write_fn = dummy_write; - g_wrap_api->writev_fn = dummy_writev; -- g_wrap_api->send_msg = dummy_sendmsg; -- g_wrap_api->send_to = dummy_sendto; -+ g_wrap_api->sendmsg_fn = dummy_sendmsg; -+ g_wrap_api->sendto_fn = dummy_sendto; - rte_wmb(); - } - -@@ -169,7 +165,7 @@ static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, in - - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) - { -- if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL) { - return posix_api->accept_fn(s, addr, addrlen); - } - -@@ -189,7 +185,7 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL) { - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - -@@ -209,8 +205,8 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(s, &sock) == POSIX_KERNEL) { -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (select_sock_posix_path(sock) == POSIX_KERNEL) { - return posix_api->bind_fn(s, name, namelen); - } - -@@ -230,30 +226,31 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - ((struct sockaddr_in6 *)name)->sin6_addr.s6_addr, IPV6_ADDR_LEN); - } - -- if (match_host_addr(&sock_addr)) { -- /* maybe kni addr */ -- if (posix_api->bind_fn(s, name, namelen) != 0) { -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- } else { -- /* 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; -+ if (!match_host_addr(&sock_addr)) { -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); -+ 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; - } -- return g_wrap_api->bind_fn(s, name, namelen); -+ /* not sure POSIX_LWIP or POSIX_KERNEL */ - } else { -- POSIX_SET_TYPE(sock, POSIX_KERNEL); -- return posix_api->bind_fn(s, name, namelen); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - } -+ return g_wrap_api->bind_fn(s, name, namelen); - } - --bool is_dst_ip_localhost(const struct sockaddr *addr) -+static bool is_dst_ip_localhost(const struct sockaddr *addr) - { - struct ifaddrs *ifap; - struct ifaddrs *ifa; -@@ -302,13 +299,8 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(s, &sock) == POSIX_KERNEL) { -- return posix_api->connect_fn(s, name, namelen); -- } -- -- sock = lwip_get_socket(s); -- if (sock == NULL) { -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (select_sock_posix_path(sock) == POSIX_KERNEL) { - return posix_api->connect_fn(s, name, namelen); - } - -@@ -334,7 +326,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - - static inline int32_t do_listen(int32_t s, int32_t backlog) - { -- if (select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL) { - return posix_api->listen_fn(s, backlog); - } - -@@ -352,7 +344,7 @@ static inline int32_t do_getpeername(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == POSIX_LWIP) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { - return g_wrap_api->getpeername_fn(s, name, namelen); - } - -@@ -365,7 +357,7 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t - GAZELLE_RETURN(EINVAL); - } - -- if (select_fd_posix_path(s, NULL) == POSIX_LWIP) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { - return g_wrap_api->getsockname_fn(s, name, namelen); - } - -@@ -422,7 +414,7 @@ static bool unsupport_optname(int32_t level, int32_t optname) - - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { -- if (select_fd_posix_path(s, NULL) == POSIX_LWIP && !unsupport_optname(level, optname)) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP && !unsupport_optname(level, optname)) { - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -431,7 +423,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v - - static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, const void *optval, socklen_t optlen) - { -- if (select_fd_posix_path(s, NULL) == POSIX_KERNEL || unsupport_optname(level, optname)) { -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL || unsupport_optname(level, optname)) { - return posix_api->setsockopt_fn(s, level, optname, optval, optlen); - } - -@@ -473,17 +465,14 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - if (buf == NULL) { - GAZELLE_RETURN(EINVAL); - } -- - if (len == 0) { - return 0; - } - -- if (select_posix_path() == POSIX_KERNEL || // maybe fd is created by open before posix_api_init called -- select_fd_posix_path(sockfd, NULL) == POSIX_KERNEL) { -- return posix_api->recv_fn(sockfd, buf, len, flags); -+ if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -+ return g_wrap_api->recv_fn(sockfd, buf, len, flags); - } -- -- return g_wrap_api->recv_fn(sockfd, buf, len, flags); -+ return posix_api->recv_fn(sockfd, buf, len, flags); - } - - static inline ssize_t do_read(int32_t s, void *mem, size_t len) -@@ -491,58 +480,46 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - if (mem == NULL) { - GAZELLE_RETURN(EINVAL); - } -- - if (len == 0) { - return 0; - } - -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -- return posix_api->read_fn(s, mem, len); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->read_fn(s, mem, len); - } -- -- return g_wrap_api->read_fn(s, mem, len); -+ return posix_api->read_fn(s, mem, len); - } - - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - { -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -- return posix_api->readv_fn(s, iov, iovcnt); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->readv_fn(s, iov, iovcnt); - } -- -- return g_wrap_api->readv_fn(s, iov, iovcnt); -+ return posix_api->readv_fn(s, iov, iovcnt); - } - - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) - { -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(sockfd, NULL) == POSIX_KERNEL) { -- return posix_api->send_fn(sockfd, buf, len, flags); -+ if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -+ return g_wrap_api->send_fn(sockfd, buf, len, flags); - } -- -- return g_wrap_api->send_fn(sockfd, buf, len, flags); -+ return posix_api->send_fn(sockfd, buf, len, flags); - } - - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - { -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -- return posix_api->write_fn(s, mem, size); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->write_fn(s, mem, size); - } -- -- return g_wrap_api->write_fn(s, mem, size); -+ return posix_api->write_fn(s, mem, size); - } - - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - { -- struct lwip_sock *sock; -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, &sock) == POSIX_KERNEL) { -- return posix_api->writev_fn(s, iov, iovcnt); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->writev_fn(s, iov, iovcnt); - } -- -- return g_wrap_api->writev_fn(s, iov, iovcnt); -+ return posix_api->writev_fn(s, iov, iovcnt); - } - - static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flags) -@@ -551,12 +528,10 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - GAZELLE_RETURN(EINVAL); - } - -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, NULL) == POSIX_KERNEL) { -- return posix_api->recv_msg(s, message, flags); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->recvmsg_fn(s, message, flags); - } -- -- return g_wrap_api->recv_msg(s, message, flags); -+ return posix_api->recvmsg_fn(s, message, flags); - } - - static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags) -@@ -565,13 +540,10 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - GAZELLE_RETURN(EINVAL); - } - -- struct lwip_sock *sock; -- if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, &sock) == POSIX_KERNEL) { -- return posix_api->send_msg(s, message, flags); -+ if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -+ return g_wrap_api->sendmsg_fn(s, message, flags); - } -- -- return g_wrap_api->send_msg(s, message, flags); -+ return posix_api->sendmsg_fn(s, message, flags); - } - - static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t flags, -@@ -580,58 +552,48 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t - if (buf == NULL) { - GAZELLE_RETURN(EINVAL); - } -- - if (len == 0) { - return 0; - } - -- struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(sockfd, &sock) == POSIX_LWIP) { -- return g_wrap_api->recv_from(sockfd, buf, len, flags, addr, addrlen); -+ if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -+ return g_wrap_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); - } -- -- return posix_api->recv_from(sockfd, buf, len, flags, addr, addrlen); -+ return posix_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); - } - - static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int32_t flags, - const struct sockaddr *addr, socklen_t addrlen) - { -- struct lwip_sock *sock = NULL; -- if (select_fd_posix_path(sockfd, &sock) != POSIX_LWIP) { -- return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen); -+ if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -+ return g_wrap_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); - } -- -- return g_wrap_api->send_to(sockfd, buf, len, flags, addr, addrlen); -+ return posix_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); - } - --static inline int32_t do_close(int32_t s) -+static inline int32_t do_close(int fd) - { -- struct lwip_sock *sock = NULL; -+ /* Can not use select_sock_posix_path() ! -+ * When fd created by lwip_stocket() set as POSIX_KERNEL, -+ * lwip_close() is still required. -+ */ - if (select_posix_path() == POSIX_KERNEL || -- select_fd_posix_path(s, &sock) == POSIX_KERNEL) { -- /* we called lwip_socket, even if kernel fd */ -- if (posix_api != NULL && !posix_api->ues_posix && -- /* contain posix_api->close_fn if success */ -- g_wrap_api->close_fn(s) == 0) { -- return 0; -- } else { -- return posix_api->close_fn(s); -- } -+ POSIX_IS_CLOSED(lwip_get_socket(fd))) { -+ return posix_api->close_fn(fd); - } -- return g_wrap_api->close_fn(s); -+ return g_wrap_api->close_fn(fd); - } - - static int32_t do_shutdown(int fd, int how) - { -- struct lwip_sock *sock = NULL; -- if (select_posix_path() == POSIX_KERNEL || select_fd_posix_path(fd, &sock) == POSIX_KERNEL) { -- if (posix_api != NULL && !posix_api->ues_posix && g_wrap_api->shutdown_fn(fd, how) == 0) { -- return 0; -- } else { -- return posix_api->shutdown_fn(fd, how); -- } -+ /* Can not use select_sock_posix_path() ! -+ * When fd created by lwip_stocket() set as POSIX_KERNEL, -+ * lwip_close() is still required. -+ */ -+ if (select_posix_path() == POSIX_KERNEL || -+ POSIX_IS_CLOSED(lwip_get_socket(fd))) { -+ return posix_api->shutdown_fn(fd, how); - } -- - return g_wrap_api->shutdown_fn(fd, how); - } - -@@ -660,15 +622,13 @@ static int32_t do_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec * - return ready; - } - --typedef int32_t (*sigaction_fn)(int32_t signum, const struct sigaction *act, struct sigaction *oldact); - static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct sigaction *oldact) - { -- if (posix_api == NULL) { -- sigaction_fn sf = (sigaction_fn)dlsym(RTLD_NEXT, "sigaction"); -- if (sf == NULL) { -- return -1; -+ if (unlikely(posix_api == NULL)) { -+ if (posix_api_init() != 0) { -+ GAZELLE_RETURN(EAGAIN); - } -- return sf(signum, act, oldact); -+ return posix_api->sigaction_fn(signum, act, oldact); - } - - return lstack_sigaction(signum, act, oldact); -@@ -676,10 +636,14 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - - static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { -- if ((select_posix_path() == POSIX_KERNEL) || !(readfds || writefds || exceptfds) || nfds == 0) { -+ if (nfds <= 0 || !(readfds || writefds || exceptfds)) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ if (select_posix_path() == POSIX_KERNEL) { - return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } -- -+ - return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - -@@ -690,9 +654,9 @@ static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set - va_start(ap, _cmd); \ - val = va_arg(ap, typeof(val)); \ - va_end(ap); \ -- struct lwip_sock *sock = NULL; \ -+ struct lwip_sock *sock = lwip_get_socket(_fd); \ - if (select_posix_path() == POSIX_KERNEL || \ -- select_fd_posix_path(_fd, &sock) == POSIX_KERNEL) \ -+ select_sock_posix_path(sock) == POSIX_KERNEL) \ - return _fcntl_fn(_fd, _cmd, val); \ - int32_t ret1 = _fcntl_fn(_fd, _cmd, val); \ - if (ret1 == -1) { \ -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 5545b9f..f1e3064 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -764,7 +764,7 @@ void control_server_thread(void *arg) - struct epoll_event evt_array; - while (1) { - /* wait init finish */ -- if (posix_api->ues_posix) { -+ if (posix_api->use_kernel) { - usleep(GAZELLE_10MS); - continue; - } -@@ -813,7 +813,7 @@ void control_client_thread(void *arg) - - while (1) { - /* wait init finish */ -- if (posix_api->ues_posix) { -+ if (posix_api->use_kernel) { - usleep(GAZELLE_10MS); - continue; - } -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 1b3882e..54ee97e 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -123,7 +123,7 @@ void gazelle_exit(void) - - __attribute__((destructor)) void gazelle_network_exit(void) - { -- if (posix_api != NULL && !posix_api->ues_posix) { -+ if (posix_api != NULL && !posix_api->use_kernel) { - lwip_exit(); - gazelle_exit(); - } -@@ -324,7 +324,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - LSTACK_EXIT(1, "set_process_start_flag failed\n"); - } - -- posix_api->ues_posix = 0; -+ posix_api->use_kernel = 0; - LSTACK_LOG(INFO, LSTACK, "gazelle_network_init success\n"); - rte_smp_mb(); - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 84ef782..2b39d05 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -79,6 +79,7 @@ static void reset_sock_data(struct lwip_sock *sock) - sock->send_pre_del = NULL; - } - -+ sock->type = 0; - sock->stack = NULL; - sock->wakeup = NULL; - sock->listen_next = NULL; -@@ -1167,7 +1168,7 @@ void do_lwip_connected_callback(struct netconn *conn) - - int32_t fd = conn->callback_arg.socket; - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - return; - } - -@@ -1208,7 +1209,7 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->fd = netconn->callback_arg.socket; - conn->recv_cnt = (netconn->recvmbox == NULL) ? 0 : rte_ring_count(netconn->recvmbox->ring); - struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -- if (sock != NULL && sock->conn != NULL) { -+ if (!POSIX_IS_CLOSED(sock)) { - conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); - conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; - conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 8cf4657..689d2bf 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -79,17 +79,22 @@ static void preload_get_thrdname(void) - LSTACK_PRE_LOG(LSTACK_INFO, "thread name=%s ok\n", g_preload_info.env_thrdname); - } - --enum posix_type select_fd_posix_path(int32_t fd, struct lwip_sock **socket) -+enum posix_type select_sock_posix_path(struct lwip_sock *sock) - { -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- /* AF_UNIX case */ -- if (!sock || !sock->conn || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { -+ if (unlikely(posix_api == NULL)) { -+ /* -+ * read/write/readv/writev may not be sockfd, -+ * posix api maybe not init. -+ */ -+ if (posix_api_init() != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n"); -+ } - return POSIX_KERNEL; - } - -- if (socket) { -- *socket = sock; -+ /* CLOSED means not sockfd, such as file fd or unix fd */ -+ if (POSIX_IS_CLOSED(sock) || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { -+ return POSIX_KERNEL; - } - - if (likely(POSIX_IS_TYPE(sock, POSIX_LWIP))) { -@@ -112,11 +117,11 @@ enum posix_type select_posix_path(void) - return POSIX_KERNEL; - } - -- if (unlikely(posix_api->ues_posix)) { -+ if (unlikely(posix_api->use_kernel)) { - return POSIX_KERNEL; - } - -- if (g_preload_thrdpath != POSIX_ALL) { -+ if (likely(g_preload_thrdpath != POSIX_ALL)) { - return g_preload_thrdpath; - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d17cb67..a809d8c 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -127,7 +127,7 @@ struct protocol_stack *get_protocol_stack(void) - struct protocol_stack *get_protocol_stack_by_fd(int32_t fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - return NULL; - } - -@@ -1126,7 +1126,7 @@ int32_t stack_broadcast_close(int32_t fd) - ret = -1; - } - -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - break; - } - fd = sock->conn->callback_arg.socket; -@@ -1151,7 +1151,7 @@ int stack_broadcast_shutdown(int fd, int how) - ret = -1; - } - -- if (sock == NULL || sock->conn == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - break; - } - fd = sock->conn->callback_arg.socket; -@@ -1357,7 +1357,7 @@ static void stack_all_fds_close(void) - { - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { - struct lwip_sock *sock = lwip_get_socket(i); -- if (sock && sock->conn && sock->stack == get_protocol_stack()) { -+ if (!POSIX_IS_CLOSED(sock) && sock->stack == get_protocol_stack()) { - lwip_close(i); - } - } -diff --git a/src/lstack/include/lstack_preload.h b/src/lstack/include/lstack_preload.h -index c30736a..d4ad385 100644 ---- a/src/lstack/include/lstack_preload.h -+++ b/src/lstack/include/lstack_preload.h -@@ -11,9 +11,9 @@ - */ - #ifndef __LSTACK_PRELOAD_H__ - #define __LSTACK_PRELOAD_H__ --#include - - enum posix_type select_posix_path(void); --enum posix_type select_fd_posix_path(int32_t fd, struct lwip_sock **socket); -+enum posix_type select_sock_posix_path(struct lwip_sock *sock); - int preload_info_init(void); --#endif -+ -+#endif /* __LSTACK_PRELOAD_H__ */ -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index 84c5c61..1ca3314 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -19,6 +19,7 @@ - #include - - #include -+#include - #include - #include - --- -2.33.0 - diff --git a/0220-cleancode-refactor-lwipgz_list.h.patch b/0220-cleancode-refactor-lwipgz_list.h.patch deleted file mode 100644 index 64d79c4..0000000 --- a/0220-cleancode-refactor-lwipgz_list.h.patch +++ /dev/null @@ -1,445 +0,0 @@ -From daacb87180fa9c98c53c001bb37929b9aaef46d9 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 15 Jul 2024 11:27:19 +0800 -Subject: [PATCH] cleancode: refactor lwipgz_list.h - - Changed: - list_is_empty -> list_head_empty - list_is_null -> list_node_null - - init_list_node -> list_init_head - init_list_node_null -> list_init_node - - list_add_node -> list_add_node - list_del_node_null -> list_del_node - list_del_node -> __list_del_node - list_for_each_safe -> list_for_each_node - Deprecated: - list_del_node_init - Added: - list_get_node_count - list_entry - -Signed-off-by: Lemmy Huang ---- - src/common/gazelle_base_func.h | 5 +- - src/lstack/api/lstack_epoll.c | 66 ++++++++++++------------- - src/lstack/api/lstack_rtc_api.c | 2 +- - src/lstack/core/lstack_lwip.c | 28 +++++------ - src/lstack/core/lstack_protocol_stack.c | 14 +++--- - src/lstack/core/lstack_stack_stat.c | 4 +- - 6 files changed, 60 insertions(+), 59 deletions(-) - -diff --git a/src/common/gazelle_base_func.h b/src/common/gazelle_base_func.h -index 2d629c1..be87ccd 100644 ---- a/src/common/gazelle_base_func.h -+++ b/src/common/gazelle_base_func.h -@@ -36,7 +36,8 @@ int32_t filename_check(const char* args); - - void gazelle_exit(void); - --#undef container_of --#define container_of(ptr, type, field) ((type *)(void*)(((char *)(ptr)) - offsetof(type, field))) -+/* Do not check if the type of ptr and type->member are the same */ -+#define container_of_uncheck_ptr(ptr, type, member) \ -+ ((type *)(void*)(((char *)(ptr)) - offsetof(type, member))) - - #endif /* ifndef __GAZELLE_BASE_FUNC_H__ */ -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 06c708b..2f48606 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -49,8 +49,8 @@ static void change_epollfd_kernel_thread(struct wakeup_poll *wakeup, struct prot - - static inline void add_wakeup_to_stack_wakeuplist(struct wakeup_poll *wakeup, struct protocol_stack *stack) - { -- if (list_is_null(&wakeup->wakeup_list[stack->stack_idx])) { -- list_add_node(&stack->wakeup_list, &wakeup->wakeup_list[stack->stack_idx]); -+ if (list_node_null(&wakeup->wakeup_list[stack->stack_idx])) { -+ list_add_node(&wakeup->wakeup_list[stack->stack_idx], &stack->wakeup_list); - } - } - -@@ -73,8 +73,8 @@ void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - } - - sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events); -- if (list_is_null(&sock->event_list)) { -- list_add_node(&wakeup->event_list, &sock->event_list); -+ if (list_node_null(&sock->event_list)) { -+ list_add_node(&sock->event_list, &wakeup->event_list); - } - return; - } -@@ -111,7 +111,7 @@ void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - } - - if (sock->events == 0) { -- list_del_node_null(&sock->event_list); -+ list_del_node(&sock->event_list); - } - return; - } -@@ -127,7 +127,7 @@ void wakeup_stack_epoll(struct protocol_stack *stack) - { - struct list_node *node, *temp; - -- list_for_each_safe(node, temp, &stack->wakeup_list) { -+ list_for_each_node(node, temp, &stack->wakeup_list) { - /* When temp is NULL, find the tail node in the wekeup_list and connect it to the back of the node */ - if (unlikely(temp == NULL)) { - struct list_node *nod = &stack->wakeup_list; -@@ -139,7 +139,7 @@ void wakeup_stack_epoll(struct protocol_stack *stack) - temp = nod; - } - -- struct wakeup_poll *wakeup = container_of((node - stack->stack_idx), struct wakeup_poll, wakeup_list); -+ struct wakeup_poll *wakeup = container_of_uncheck_ptr((node - stack->stack_idx), struct wakeup_poll, wakeup_list); - - if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -@@ -148,7 +148,7 @@ void wakeup_stack_epoll(struct protocol_stack *stack) - stack->stats.wakeup_events++; - } - -- list_del_node_null(&wakeup->wakeup_list[stack->stack_idx]); -+ list_del_node(&wakeup->wakeup_list[stack->stack_idx]); - } - } - -@@ -198,8 +198,8 @@ static void rtc_raise_pending_events(struct wakeup_poll *wakeup, struct lwip_soc - if (event) { - sock->events = event; - if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && -- list_is_null(&sock->event_list)) { -- list_add_node(&wakeup->event_list, &sock->event_list); -+ list_node_null(&sock->event_list)) { -+ list_add_node(&sock->event_list, &wakeup->event_list); - } - } - } -@@ -227,8 +227,8 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - if (event) { - sock->events = event; - if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && -- list_is_null(&sock->event_list)) { -- list_add_node(&wakeup->event_list, &sock->event_list); -+ list_node_null(&sock->event_list)) { -+ list_add_node(&sock->event_list, &wakeup->event_list); - } - } - pthread_spin_unlock(&wakeup->event_list_lock); -@@ -255,7 +255,7 @@ int32_t lstack_do_epoll_create(int32_t fd) - } - - for (uint32_t i = 0; i < PROTOCOL_STACK_MAX; i++) { -- init_list_node_null(&wakeup->wakeup_list[i]); -+ list_init_node(&wakeup->wakeup_list[i]); - } - - if (sem_init(&wakeup->wait, 0, 0) != 0) { -@@ -266,12 +266,12 @@ int32_t lstack_do_epoll_create(int32_t fd) - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- init_list_node_null(&wakeup->poll_list); -+ list_init_node(&wakeup->poll_list); - pthread_spin_lock(&stack_group->poll_list_lock); -- list_add_node(&stack_group->poll_list, &wakeup->poll_list); -+ list_add_node(&wakeup->poll_list, &stack_group->poll_list); - pthread_spin_unlock(&stack_group->poll_list_lock); - -- init_list_node(&wakeup->event_list); -+ list_init_head(&wakeup->event_list); - pthread_spin_init(&wakeup->event_list_lock, PTHREAD_PROCESS_PRIVATE); - - wakeup->type = WAKEUP_EPOLL; -@@ -327,15 +327,15 @@ int32_t lstack_epoll_close(int32_t fd) - - struct list_node *node, *temp; - pthread_spin_lock(&wakeup->event_list_lock); -- list_for_each_safe(node, temp, &wakeup->event_list) { -- struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list); -- list_del_node_null(&sock->event_list); -+ list_for_each_node(node, temp, &wakeup->event_list) { -+ struct lwip_sock *sock = list_entry(node, struct lwip_sock, event_list); -+ list_del_node(&sock->event_list); - } - pthread_spin_unlock(&wakeup->event_list_lock); - pthread_spin_destroy(&wakeup->event_list_lock); - - pthread_spin_lock(&stack_group->poll_list_lock); -- list_del_node_null(&wakeup->poll_list); -+ list_del_node(&wakeup->poll_list); - pthread_spin_unlock(&stack_group->poll_list_lock); - - sem_destroy(&wakeup->wait); -@@ -413,7 +413,7 @@ int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - break; - case EPOLL_CTL_DEL: - sock->epoll_events = 0; -- list_del_node_null(&sock->event_list); -+ list_del_node(&sock->event_list); - break; - default: - GAZELLE_RETURN(EINVAL); -@@ -464,7 +464,7 @@ int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - sock->epoll_events = 0; - wakeup->stack_fd_cnt[sock->stack->stack_idx]--; - pthread_spin_lock(&wakeup->event_list_lock); -- list_del_node_null(&sock->event_list); -+ list_del_node(&sock->event_list); - pthread_spin_unlock(&wakeup->event_list_lock); - break; - default: -@@ -482,18 +482,18 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - int32_t event_num = 0; - struct list_node *node, *temp; - -- list_for_each_safe(node, temp, &wakeup->event_list) { -- struct lwip_sock *sock = container_of(node, struct lwip_sock, event_list); -+ list_for_each_node(node, temp, &wakeup->event_list) { -+ struct lwip_sock *sock = list_entry(node, struct lwip_sock, event_list); - - if ((sock->epoll_events & sock->events) == 0) { -- list_del_node_null(node); -+ list_del_node(node); - continue; - } - - if (event_num >= maxevents) { - /* move list head after the current node, and start traversing from this node next time */ -- list_del_node_null(&wakeup->event_list); -- list_add_node(node, &wakeup->event_list); -+ list_del_node(&wakeup->event_list); -+ list_add_node(&wakeup->event_list, node); - break; - } - -@@ -502,14 +502,14 @@ int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event * - event_num++; - - if (sock->epoll_events & EPOLLET) { -- list_del_node_null(node); -+ list_del_node(node); - sock->events = 0; - } - - /* EPOLLONESHOT: generate event after epoll_ctl add/mod event again - epoll_event set 0 avoid generating event util epoll_ctl reset epoll_event */ - if (sock->epoll_events & EPOLLONESHOT) { -- list_del_node_null(node); -+ list_del_node(node); - sock->epoll_events = 0; - } - } -@@ -654,7 +654,7 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - } - - loop_flag = false; -- if (!kernel_num && list_is_empty(&wakeup->event_list) && tmptimeout != 0) { -+ if (!kernel_num && list_head_empty(&wakeup->event_list) && tmptimeout != 0) { - loop_flag = true; - } - } while (loop_flag); -@@ -721,7 +721,7 @@ static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) - __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); - - for (uint32_t i = 0; i < PROTOCOL_STACK_MAX; i++) { -- init_list_node_null(&wakeup->wakeup_list[i]); -+ list_init_node(&wakeup->wakeup_list[i]); - } - - wakeup->epollfd = posix_api->epoll_create_fn(POLL_KERNEL_EVENTS); -@@ -745,9 +745,9 @@ static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) - } - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- init_list_node_null(&wakeup->poll_list); -+ list_init_node(&wakeup->poll_list); - pthread_spin_lock(&stack_group->poll_list_lock); -- list_add_node(&stack_group->poll_list, &wakeup->poll_list); -+ list_add_node(&wakeup->poll_list, &stack_group->poll_list); - pthread_spin_unlock(&stack_group->poll_list_lock); - - int32_t stack_count[PROTOCOL_STACK_MAX] = {0}; -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 97623b3..ca0e7ec 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -56,7 +56,7 @@ int rtc_socket(int domain, int type, int protocol) - sock->epoll_events = 0; - sock->events = 0; - sock->wakeup = NULL; -- init_list_node_null(&sock->event_list); -+ list_init_node(&sock->event_list); - } - return ret; - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index f52f39f..c05a763 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -173,8 +173,8 @@ int do_lwip_init_sock(int32_t fd) - - sock->stack = stack; - -- init_list_node_null(&sock->recv_list); -- init_list_node_null(&sock->event_list); -+ list_init_node(&sock->recv_list); -+ list_init_node(&sock->event_list); - return 0; - } - -@@ -187,7 +187,7 @@ void do_lwip_clean_sock(int fd) - - if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL) { - pthread_spin_lock(&sock->wakeup->event_list_lock); -- list_del_node_null(&sock->event_list); -+ list_del_node(&sock->event_list); - pthread_spin_unlock(&sock->wakeup->event_list_lock); - } - -@@ -195,7 +195,7 @@ void do_lwip_clean_sock(int fd) - - reset_sock_data(sock); - -- list_del_node_null(&sock->recv_list); -+ list_del_node(&sock->recv_list); - } - - void do_lwip_free_pbuf(struct pbuf *pbuf) -@@ -1098,8 +1098,8 @@ void do_lwip_add_recvlist(int32_t fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); - -- if (sock && sock->stack && list_is_null(&sock->recv_list)) { -- list_add_node(&sock->stack->recv_list, &sock->recv_list); -+ if (sock && sock->stack && list_node_null(&sock->recv_list)) { -+ list_add_node(&sock->recv_list, &sock->stack->recv_list); - } - } - -@@ -1109,8 +1109,8 @@ void read_same_node_recv_list(struct protocol_stack *stack) - struct list_node *node, *temp; - struct lwip_sock *sock; - -- list_for_each_safe(node, temp, list) { -- sock = container_of(node, struct lwip_sock, recv_list); -+ list_for_each_node(node, temp, list) { -+ sock = list_entry(node, struct lwip_sock, recv_list); - - if (sock->same_node_rx_ring != NULL && same_node_ring_count(sock)) { - add_sock_event(sock, EPOLLIN); -@@ -1125,18 +1125,18 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - struct lwip_sock *sock; - uint32_t read_num = 0; - -- list_for_each_safe(node, temp, list) { -- sock = container_of(node, struct lwip_sock, recv_list); -+ list_for_each_node(node, temp, list) { -+ sock = list_entry(node, struct lwip_sock, recv_list); - - if (++read_num > max_num) { - /* list head move to next send */ - list_del_node(&stack->recv_list); -- list_add_node(&sock->recv_list, &stack->recv_list); -+ list_add_node(&stack->recv_list, &sock->recv_list); - break; - } - - if (sock->conn == NULL || sock->conn->recvmbox == NULL || rte_ring_count(sock->conn->recvmbox->ring) == 0) { -- list_del_node_null(&sock->recv_list); -+ list_del_node(&sock->recv_list); - continue; - } - -@@ -1215,7 +1215,7 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); - conn->events = sock->events; - conn->epoll_events = sock->epoll_events; -- conn->eventlist = !list_is_null(&sock->event_list); -+ conn->eventlist = !list_node_null(&sock->event_list); - } - } - } -@@ -1426,7 +1426,7 @@ err_t find_same_node_memzone(struct tcp_pcb *pcb, struct lwip_sock *nsock) - - /* rcvlink init in alloc_socket() */ - /* remove from g_rcv_process_list in free_socket */ -- list_add_node(&nsock->stack->same_node_recv_list, &nsock->recv_list); -+ list_add_node(&nsock->recv_list, &nsock->stack->same_node_recv_list); - return 0; - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 4f5cfae..9bb1b6a 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -328,9 +328,9 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - stack->stack_idx = t_params->idx; - stack->lwip_stats = &lwip_stats; - -- init_list_node(&stack->recv_list); -- init_list_node(&stack->same_node_recv_list); -- init_list_node(&stack->wakeup_list); -+ list_init_head(&stack->recv_list); -+ list_init_head(&stack->same_node_recv_list); -+ list_init_head(&stack->wakeup_list); - - sys_calibrate_tsc(); - stack_stat_init(); -@@ -588,7 +588,7 @@ int32_t stack_group_init(void) - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - stack_group->stack_num = 0; - -- init_list_node(&stack_group->poll_list); -+ list_init_head(&stack_group->poll_list); - pthread_spin_init(&stack_group->poll_list_lock, PTHREAD_PROCESS_PRIVATE); - pthread_spin_init(&stack_group->socket_lock, PTHREAD_PROCESS_PRIVATE); - if (sem_init(&stack_group->sem_stack_setup, 0, 0) < 0) { -@@ -1013,7 +1013,7 @@ void stack_clean_epoll(struct rpc_msg *msg) - struct protocol_stack *stack = get_protocol_stack(); - struct wakeup_poll *wakeup = (struct wakeup_poll *)msg->args[MSG_ARG_0].p; - -- list_del_node_null(&wakeup->wakeup_list[stack->stack_idx]); -+ list_del_node(&wakeup->wakeup_list[stack->stack_idx]); - } - - void stack_mempool_size(struct rpc_msg *msg) -@@ -1103,7 +1103,7 @@ void stack_recvlist_count(struct rpc_msg *msg) - struct list_node *node; - struct list_node *temp; - -- list_for_each_safe(node, temp, list) { -+ list_for_each_node(node, temp, list) { - count++; - } - -@@ -1258,7 +1258,7 @@ static void inline del_accept_in_event(struct lwip_sock *sock) - if (!NETCONN_IS_ACCEPTIN(sock)) { - sock->events &= ~EPOLLIN; - if (sock->events == 0) { -- list_del_node_null(&sock->event_list); -+ list_del_node(&sock->event_list); - } - } - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index e42efde..0411d9e 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -230,8 +230,8 @@ static void get_wakeup_stat(struct protocol_stack_group *stack_group, struct pro - - pthread_spin_lock(&stack_group->poll_list_lock); - -- list_for_each_safe(node, temp, &stack_group->poll_list) { -- struct wakeup_poll *wakeup = container_of(node, struct wakeup_poll, poll_list); -+ list_for_each_node(node, temp, &stack_group->poll_list) { -+ struct wakeup_poll *wakeup = list_entry(node, struct wakeup_poll, poll_list); - - if (wakeup->bind_stack == stack) { - stat->kernel_events += wakeup->stat.kernel_events; --- -2.33.0 - diff --git a/0221-fix-EPOLLIN-event-dropd.patch b/0221-fix-EPOLLIN-event-dropd.patch deleted file mode 100644 index 87d1a34..0000000 --- a/0221-fix-EPOLLIN-event-dropd.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 065b0fe7ac355ba741f7a2be96738c4792e13cfe Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Thu, 18 Jul 2024 11:59:52 +0000 -Subject: [PATCH] fix EPOLLIN event dropd - ---- - src/lstack/api/lstack_epoll.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 06c708b..ff80003 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -208,6 +208,7 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - { - uint32_t event = 0; - -+ pthread_spin_lock(&wakeup->event_list_lock); - if (NETCONN_IS_DATAIN(sock) || NETCONN_IS_ACCEPTIN(sock)) { - event |= EPOLLIN; - } -@@ -216,7 +217,6 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - event |= EPOLLERR | EPOLLIN; - } - -- pthread_spin_lock(&wakeup->event_list_lock); - if (NETCONN_IS_OUTIDLE(sock)) { - /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ - if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { --- -2.33.0 - diff --git a/0222-cleancode-refactor-lwipgz_hlist.h.patch b/0222-cleancode-refactor-lwipgz_hlist.h.patch deleted file mode 100644 index 9bd4e81..0000000 --- a/0222-cleancode-refactor-lwipgz_hlist.h.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 288f7301ecafb2c53ab4671361109803af118668 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Thu, 11 Jul 2024 16:04:00 +0800 -Subject: [PATCH] cleancode: refactor lwipgz_hlist.h - - Changed: - INIT_HLIST_HEAD -> hlist_init_head - INIT_HLIST_NODE -> hlist_init_node - hlist_empty -> hlist_head_empty - hlist_unhashed -> hlist_node_null - hlist_del_init -> hlist_del_node - Not changed: - hlist_add_head - hlist_add_before - hlist_add_after - Deprecated: - INIT_HLIST_CTRL - hlist_ctl_del - hlist_pop_tail - hlist_pop_head - hlist_ctl_add_tail - hlist_ctl_add_head - hlist_ctl_add_after - hlist_ctl_add_before - -Signed-off-by: Lemmy Huang ---- - src/ltran/ltran_stack.c | 6 +++--- - src/ltran/ltran_tcp_conn.c | 6 +++--- - src/ltran/ltran_tcp_sock.c | 6 +++--- - src/ltran/ltran_timer.c | 6 +++--- - 4 files changed, 12 insertions(+), 12 deletions(-) - -diff --git a/src/ltran/ltran_stack.c b/src/ltran/ltran_stack.c -index 299fb7a..737d883 100644 ---- a/src/ltran/ltran_stack.c -+++ b/src/ltran/ltran_stack.c -@@ -43,7 +43,7 @@ struct gazelle_stack_htable *gazelle_stack_htable_create(uint32_t max_stack_num) - } - - for (i = 0; i < GAZELLE_MAX_STACK_HTABLE_SIZE; i++) { -- INIT_HLIST_HEAD(&stack_htable->array[i].chain); -+ hlist_init_head(&stack_htable->array[i].chain); - stack_htable->array[i].chain_size = 0; - } - stack_htable->cur_stack_num = 0; -@@ -68,7 +68,7 @@ void gazelle_stack_htable_destroy(void) - while (node != NULL) { - stack = hlist_entry(node, typeof(*stack), stack_node); - node = node->next; -- hlist_del_init(&stack->stack_node); -+ hlist_del_node(&stack->stack_node); - free(stack); - } - } -@@ -181,7 +181,7 @@ void gazelle_stack_del_by_tid(struct gazelle_stack_htable *stack_htable, uint32_ - } - } - -- hlist_del_init(&stack->stack_node); -+ hlist_del_node(&stack->stack_node); - stack_htable->cur_stack_num--; - stack_hbucket->chain_size--; - -diff --git a/src/ltran/ltran_tcp_conn.c b/src/ltran/ltran_tcp_conn.c -index 026d22a..2c8f8ef 100644 ---- a/src/ltran/ltran_tcp_conn.c -+++ b/src/ltran/ltran_tcp_conn.c -@@ -40,7 +40,7 @@ struct gazelle_tcp_conn_htable *gazelle_tcp_conn_htable_create(uint32_t max_conn - } - - for (i = 0; i < GAZELLE_MAX_CONN_HTABLE_SIZE; i++) { -- INIT_HLIST_HEAD(&conn_htable->array[i].chain); -+ hlist_init_head(&conn_htable->array[i].chain); - conn_htable->array[i].chain_size = 0; - } - conn_htable->cur_conn_num = 0; -@@ -65,7 +65,7 @@ void gazelle_tcp_conn_htable_destroy(void) - while (node != NULL) { - conn = hlist_entry(node, typeof(*conn), conn_node); - node = node->next; -- hlist_del_init(&conn->conn_node); -+ hlist_del_node(&conn->conn_node); - rte_free(conn); - } - } -@@ -175,7 +175,7 @@ void gazelle_conn_del_by_quintuple(struct gazelle_tcp_conn_htable *conn_htable, - return; - } - -- hlist_del_init(&conn->conn_node); -+ hlist_del_node(&conn->conn_node); - rte_free(conn); - conn_htable->cur_conn_num--; - conn_hbucket->chain_size--; -diff --git a/src/ltran/ltran_tcp_sock.c b/src/ltran/ltran_tcp_sock.c -index eef2821..1e06bd7 100644 ---- a/src/ltran/ltran_tcp_sock.c -+++ b/src/ltran/ltran_tcp_sock.c -@@ -51,7 +51,7 @@ struct gazelle_tcp_sock_htable *gazelle_tcp_sock_htable_create(uint32_t max_tcp_ - } - - for (i = 0; i < GAZELLE_MAX_TCP_SOCK_HTABLE_SIZE; i++) { -- INIT_HLIST_HEAD(&tcp_sock_htable->array[i].chain); -+ hlist_init_head(&tcp_sock_htable->array[i].chain); - tcp_sock_htable->array[i].chain_size = 0; - } - tcp_sock_htable->cur_tcp_sock_num = 0; -@@ -77,7 +77,7 @@ void gazelle_tcp_sock_htable_destroy(void) - while (node != NULL) { - tcp_sock = hlist_entry(node, typeof(*tcp_sock), tcp_sock_node); - node = node->next; -- hlist_del_init(&tcp_sock->tcp_sock_node); -+ hlist_del_node(&tcp_sock->tcp_sock_node); - free(tcp_sock); - } - } -@@ -186,7 +186,7 @@ void gazelle_sock_del_by_ipporttid(struct gazelle_tcp_sock_htable *tcp_sock_htab - return; - } - -- hlist_del_init(&tcp_sock->tcp_sock_node); -+ hlist_del_node(&tcp_sock->tcp_sock_node); - free(tcp_sock); - tcp_sock_htable->cur_tcp_sock_num--; - tcp_sock_hbucket->chain_size--; -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 87046cb..51d6544 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -63,7 +63,7 @@ void gazelle_detect_sock_logout(struct gazelle_tcp_sock_htable *tcp_sock_htable) - tcp_sock = hlist_entry(node, typeof(*tcp_sock), tcp_sock_node); - node = node->next; - if (!INSTANCE_IS_ON(tcp_sock)) { -- hlist_del_init(&tcp_sock->tcp_sock_node); -+ hlist_del_node(&tcp_sock->tcp_sock_node); - tcp_sock_htable->cur_tcp_sock_num--; - tcp_sock_htable->array[i].chain_size--; - LTRAN_DEBUG("delete the tcp sock htable: tid %u ip %u port %u\n", -@@ -99,7 +99,7 @@ void gazelle_detect_conn_logout(struct gazelle_tcp_conn_htable *conn_htable) - conn = hlist_entry(node, typeof(*conn), conn_node); - node = node->next; - if (!INSTANCE_IS_ON(conn)) { -- hlist_del_init(&conn->conn_node); -+ hlist_del_node(&conn->conn_node); - conn_htable->cur_conn_num--; - conn_htable->array[i].chain_size--; - LTRAN_DEBUG("delete the tcp conn htable: tid %u quintuple[%u %u %u %u %u]\n", -@@ -146,7 +146,7 @@ void gazelle_delete_aging_conn(struct gazelle_tcp_conn_htable *conn_htable) - continue; - } - -- hlist_del_init(&conn->conn_node); -+ hlist_del_node(&conn->conn_node); - conn_htable->cur_conn_num--; - conn_htable->array[i].chain_size--; - if (conn->sock) { --- -2.33.0 - diff --git a/0223-add-sem-post-when-update-event.patch b/0223-add-sem-post-when-update-event.patch deleted file mode 100644 index 45a1a1c..0000000 --- a/0223-add-sem-post-when-update-event.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2ad0be3590c8ac380c2b0e87f28653b994916c65 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Thu, 18 Jul 2024 13:40:15 +0000 -Subject: [PATCH] add sem post when update event - ---- - src/lstack/api/lstack_epoll.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index e92faac..417499b 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -229,6 +229,7 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && - list_node_null(&sock->event_list)) { - list_add_node(&sock->event_list, &wakeup->event_list); -+ sem_post(&wakeup->wait); - } - } - pthread_spin_unlock(&wakeup->event_list_lock); --- -2.33.0 - diff --git a/0224-cleancode-refactor-sys_now-and-lwip_ioctl.patch b/0224-cleancode-refactor-sys_now-and-lwip_ioctl.patch deleted file mode 100644 index 369aba0..0000000 --- a/0224-cleancode-refactor-sys_now-and-lwip_ioctl.patch +++ /dev/null @@ -1,673 +0,0 @@ -From 107e0eda4e255dc93aa94a9ffa31427f912341f5 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 12 Jul 2024 11:02:59 +0800 -Subject: [PATCH] cleancode: refactor sys_now and lwip_ioctl - -Signed-off-by: Lemmy Huang ---- - src/common/gazelle_dfx_msg.h | 8 ++++- - src/lstack/api/lstack_epoll.c | 4 ++- - src/lstack/api/lstack_wrap.c | 47 +++++++++++-------------- - src/lstack/core/lstack_cfg.c | 1 - - src/lstack/core/lstack_control_plane.c | 21 ++++++----- - src/lstack/core/lstack_dpdk.c | 10 +++--- - src/lstack/core/lstack_init.c | 2 -- - src/lstack/core/lstack_lwip.c | 19 +++++----- - src/lstack/core/lstack_protocol_stack.c | 12 +++---- - src/lstack/core/lstack_stack_stat.c | 29 +++------------ - src/lstack/include/lstack_stack_stat.h | 1 - - src/lstack/include/lstack_thread_rpc.h | 1 - - src/lstack/netif/lstack_ethdev.c | 3 +- - src/ltran/ltran_forward.c | 10 +++--- - src/ltran/ltran_stat.c | 2 +- - src/ltran/ltran_stat.h | 6 ---- - src/ltran/ltran_timer.c | 14 +++----- - src/ltran/ltran_timer.h | 4 +-- - test/unitest/stub.c | 6 ---- - 19 files changed, 79 insertions(+), 121 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index a2ec07b..8eb54ff 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -87,6 +87,12 @@ enum GAZELLE_LATENCY_TYPE { - GAZELLE_LATENCY_MAX, - }; - -+enum GAZELLE_TCP_LIST_STATE { -+ GAZELLE_ACTIVE_LIST, -+ GAZELLE_LISTEN_LIST, -+ GAZELLE_TIME_WAIT_LIST, -+}; -+ - struct gazelle_stack_stat { - uint64_t wakeup_events; - uint64_t write_lwip_cnt; -@@ -240,7 +246,6 @@ struct gazelle_stat_lstack_proto { - }; - - --/* same as define in lwip/tcp.h - struct tcp_pcb_dp */ - struct gazelle_stat_lstack_conn_info { - uint32_t state; - gz_addr_t rip; -@@ -252,6 +257,7 @@ struct gazelle_stat_lstack_conn_info { - uint32_t send_ring_cnt; - uint32_t recv_ring_cnt; - uint32_t tcp_sub_state; -+ - uint32_t cwn; - uint32_t rcv_wnd; - uint32_t snd_wnd; -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 2f48606..3ad22b9 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -650,7 +650,9 @@ int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t - } - } - if (tmptimeout > 0) { -- tmptimeout = update_timeout(tmptimeout, poll_ts); -+ if (tmptimeout <= sys_now() - poll_ts) { -+ tmptimeout = 0; -+ } - } - - loop_flag = false; -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index b19990e..976a3f3 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -647,36 +647,31 @@ static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set - return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - --#define WRAP_VA_PARAM(_fd, _cmd, _lwip_fcntl, _fcntl_fn) \ -+#define POSIX_VA_PARAM(fd, cmd, type, lwip_fn, kernel_fn) \ - do { \ -- unsigned long val; \ -- va_list ap; \ -- va_start(ap, _cmd); \ -- val = va_arg(ap, typeof(val)); \ -- va_end(ap); \ -- struct lwip_sock *sock = lwip_get_socket(_fd); \ -- if (select_posix_path() == POSIX_KERNEL || \ -- select_sock_posix_path(sock) == POSIX_KERNEL) \ -- return _fcntl_fn(_fd, _cmd, val); \ -- int32_t ret1 = _fcntl_fn(_fd, _cmd, val); \ -- if (ret1 == -1) { \ -- LSTACK_LOG(ERR, LSTACK, "fd(%d) kernel path call failed, errno is %d, maybe not error\n", \ -- _fd, errno); \ -- return ret1; \ -+ unsigned long __val; \ -+ va_list __ap; \ -+ va_start(__ap, cmd); \ -+ __val = va_arg(__ap, typeof(__val)); \ -+ va_end(__ap); \ -+ /* always try kernel */ \ -+ int __ret1 = kernel_fn(fd, cmd, __val); \ -+ if (__ret1 == -1 || select_sock_posix_path(lwip_get_socket(fd)) == POSIX_KERNEL) { \ -+ return __ret1; \ - } \ -- int32_t ret2 = _lwip_fcntl(_fd, _cmd, val); \ -+ int __ret2 = lwip_fn(fd, cmd, (type)__val); \ - /* - * if function not implemented, fcntl get/set context will not be modifyed by user path, - * return kernel path result - */ \ -- if (ret2 == -1) { \ -+ if (__ret2 == -1) { \ - if (errno == ENOSYS) { \ -- return ret1; \ -+ return __ret1; \ - } \ - LSTACK_LOG(ERR, LSTACK, "fd(%d) user path call failed, errno is %d, maybe not error\n", \ -- _fd, errno); \ -+ fd, errno); \ - } \ -- return ret2; \ -+ return __ret2; \ - } while (0) - - /* -------------------------------------------------------- -@@ -701,15 +696,15 @@ int32_t epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, - } - int32_t fcntl64(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_fcntl, posix_api->fcntl64_fn); -+ POSIX_VA_PARAM(s, cmd, int, lwip_fcntl, posix_api->fcntl64_fn); - } - int32_t fcntl(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_fcntl, posix_api->fcntl_fn); -+ POSIX_VA_PARAM(s, cmd, int, lwip_fcntl, posix_api->fcntl_fn); - } - int32_t ioctl(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_ioctl, posix_api->ioctl_fn); -+ POSIX_VA_PARAM(s, cmd, void*, lwip_ioctl, posix_api->ioctl_fn); - } - int32_t accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) - { -@@ -853,15 +848,15 @@ int32_t __wrap_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxe - } - int32_t __wrap_fcntl64(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_fcntl, posix_api->fcntl64_fn); -+ POSIX_VA_PARAM(s, cmd, int, lwip_fcntl, posix_api->fcntl64_fn); - } - int32_t __wrap_fcntl(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_fcntl, posix_api->fcntl_fn); -+ POSIX_VA_PARAM(s, cmd, int, lwip_fcntl, posix_api->fcntl_fn); - } - int32_t __wrap_ioctl(int32_t s, int32_t cmd, ...) - { -- WRAP_VA_PARAM(s, cmd, lwip_ioctl, posix_api->ioctl_fn); -+ POSIX_VA_PARAM(s, cmd, void*, lwip_ioctl, posix_api->ioctl_fn); - } - - int32_t __wrap_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index a1f6c2f..cd81edb 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -25,7 +25,6 @@ - - #include - #include --#include - #include - - #include "common/gazelle_reg_msg.h" -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index f1e3064..11f5129 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -18,11 +18,14 @@ - #include - #include - --#include - #include - #include -+#include -+ -+#include - #include - #include -+#include - - #include "lstack_cfg.h" - #include "lstack_dpdk.h" -@@ -353,7 +356,7 @@ static int32_t client_reg_proc_attach(__attribute__((__unused__)) bool is_reconn - return 0; - } - --static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_type, -+static int32_t reg_conn(enum GAZELLE_TCP_LIST_STATE table_state, enum reg_ring_type reg_type, - const struct gazelle_stat_lstack_conn *conn) - { - struct gazelle_quintuple qtuple; -@@ -370,7 +373,7 @@ static int32_t reg_conn(enum tcp_list_state table_state, enum reg_ring_type reg_ - qtuple.dst_ip = conn->conn_list[i].rip; - qtuple.dst_port = lwip_htons(conn->conn_list[i].r_port); - -- if ((table_state == LISTEN_LIST) && (!match_host_addr((ip_addr_t *)&qtuple.src_ip))) { -+ if ((table_state == GAZELLE_LISTEN_LIST) && (!match_host_addr((ip_addr_t *)&qtuple.src_ip))) { - continue; - } - -@@ -398,16 +401,16 @@ void thread_register_phase1(struct rpc_msg *msg) - } - - struct gazelle_stat_lstack_conn *conn = (struct gazelle_stat_lstack_conn *)msg->args[MSG_ARG_0].p; -- ret = reg_conn(ACTIVE_LIST, REG_RING_TCP_CONNECT, conn); -+ ret = reg_conn(GAZELLE_ACTIVE_LIST, REG_RING_TCP_CONNECT, conn); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "ACTIVE_LIST rereg conn fail ret=%d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "GAZELLE_ACTIVE_LIST rereg conn fail ret=%d\n", ret); - msg->result = ret; - return; - } - -- ret = reg_conn(TIME_WAIT_LIST, REG_RING_TCP_CONNECT, conn); -+ ret = reg_conn(GAZELLE_TIME_WAIT_LIST, REG_RING_TCP_CONNECT, conn); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "TIME_WAIT_LIST rereg conn fail ret=%d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "GAZELLE_TIME_WAIT_LIST rereg conn fail ret=%d\n", ret); - } - msg->result = ret; - } -@@ -416,9 +419,9 @@ void thread_register_phase2(struct rpc_msg *msg) - { - struct gazelle_stat_lstack_conn *conn = (struct gazelle_stat_lstack_conn *)msg->args[MSG_ARG_0].p; - -- int32_t ret = reg_conn(LISTEN_LIST, REG_RING_TCP_LISTEN, conn); -+ int32_t ret = reg_conn(GAZELLE_LISTEN_LIST, REG_RING_TCP_LISTEN, conn); - if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "LISTEN_LIST rereg conn fail ret=%d\n", ret); -+ LSTACK_LOG(ERR, LSTACK, "GAZELLE_LISTEN_LIST rereg conn fail ret=%d\n", ret); - } - - msg->result = ret; -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index a095cbd..e17242c 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -32,16 +32,14 @@ - #endif - #include - #include --#include --#include --#include --#include --#include -- - #include - #include - #include - -+#include -+#include -+#include -+ - #include "lstack_log.h" - #include "common/dpdk_common.h" - #include "lstack_protocol_stack.h" -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 54ee97e..e89e19c 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -29,8 +29,6 @@ - #include - #include - #include --#include --#include - #include - #include - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c05a763..271e94f 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -12,20 +12,21 @@ - - #include - #include -+#include -+ -+#include -+#include -+ - #include - #include - #include - #include --#include - #include - #include - #include - #include - #include - #include --#include --#include --#include - - #include "common/gazelle_base_func.h" - #include "lstack_ethdev.h" -@@ -355,7 +356,7 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - (void)gazelle_ring_read(sock->send_ring, (void **)pbufs, write_num); - - if (get_protocol_stack_group()->latency_start) { -- uint64_t time_stamp = get_current_time(); -+ uint64_t time_stamp = sys_now_us(); - time_stamp_into_pbuf(write_num, pbufs, time_stamp); - } - -@@ -912,7 +913,7 @@ static bool recv_break_for_err(struct lwip_sock *sock) - static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf **pbuf) - { - int32_t expect = 1; // only get one pbuf -- uint64_t time_stamp = get_current_time(); -+ uint64_t time_stamp = sys_now_us(); - - if (sock->recv_lastdata != NULL) { - *pbuf = sock->recv_lastdata; -@@ -1250,20 +1251,20 @@ uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, - } - - for (pcb = tcp_active_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -- conn[conn_num].state = ACTIVE_LIST; -+ conn[conn_num].state = GAZELLE_ACTIVE_LIST; - copy_pcb_to_conn(conn + conn_num, pcb); - conn_num++; - } - - for (pcb = tcp_tw_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -- conn[conn_num].state = TIME_WAIT_LIST; -+ conn[conn_num].state = GAZELLE_TIME_WAIT_LIST; - copy_pcb_to_conn(conn + conn_num, pcb); - conn_num++; - } - - for (struct tcp_pcb_listen *pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL && conn_num < max_num; - pcbl = pcbl->next) { -- conn[conn_num].state = LISTEN_LIST; -+ conn[conn_num].state = GAZELLE_LISTEN_LIST; - conn[conn_num].lip = *((gz_addr_t *)&pcbl->local_ip); - conn[conn_num].l_port = pcbl->local_port; - conn[conn_num].tcp_sub_state = pcbl->state; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 9bb1b6a..6f2e84e 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -12,15 +12,14 @@ - - #include - #include -+#include -+#include - - #include --#include -+#include - #include --#include - #include - #include --#include --#include - - #include "common/gazelle_base_func.h" - #include "lstack_thread_rpc.h" -@@ -332,9 +331,6 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - list_init_head(&stack->same_node_recv_list); - list_init_head(&stack->wakeup_list); - -- sys_calibrate_tsc(); -- stack_stat_init(); -- - stack_group->stacks[t_params->idx] = stack; - set_stack_idx(t_params->idx); - -@@ -424,7 +420,7 @@ static struct protocol_stack *stack_thread_init(void *arg) - } - RTE_PER_LCORE(_lcore_id) = stack->cpu_id; - -- tcpip_init(NULL, NULL); -+ lwip_init(); - - if (use_ltran()) { - if (client_reg_thrd_ring() != 0) { -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 0411d9e..91ca49a 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -31,25 +31,6 @@ - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" - --#define US_PER_SEC 1000000 -- --static uint64_t g_cycles_per_us; -- --void stack_stat_init(void) --{ -- uint64_t freq = rte_get_tsc_hz(); -- g_cycles_per_us = (freq + US_PER_SEC - 1) / US_PER_SEC; --} -- --uint64_t get_current_time(void) --{ -- if (g_cycles_per_us == 0) { -- return 0; -- } -- -- return (rte_rdtsc() / g_cycles_per_us); --} -- - void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) - { - if (!get_protocol_stack_group()->latency_start) { -@@ -71,12 +52,12 @@ void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) - - void time_stamp_into_rpcmsg(struct lwip_sock *sock) - { -- sock->stamp.rpc_time_stamp = get_current_time(); -+ sock->stamp.rpc_time_stamp = sys_now_us(); - } - - void time_stamp_into_recvmbox(struct lwip_sock *sock) - { -- sock->stamp.mbox_time_stamp = get_current_time(); -+ sock->stamp.mbox_time_stamp = sys_now_us(); - } - - void time_stamp_record(int fd, struct pbuf *pbuf) -@@ -108,7 +89,7 @@ void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct - return; - } - -- latency = get_current_time() - stamp; -+ latency = sys_now_us() - stamp; - latency_stat = &stack_latency->latency[type]; - - latency_stat->latency_total += latency; -@@ -147,7 +128,7 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - } - - if (time_record == 0) { -- lt->stamp_seg[type] = get_current_time() - lt->stamp; -+ lt->stamp_seg[type] = sys_now_us() - lt->stamp; - } else { - lt->stamp_seg[type] = time_record > (lt->stamp_seg[type - 1] + lt->stamp) ? - (time_record - lt->stamp) : lt->stamp_seg[type - 1]; -@@ -212,7 +193,7 @@ static void set_latency_start_flag(bool start) - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "memset_s faile\n"); - } -- stack->latency.start_time = get_current_time(); -+ stack->latency.start_time = sys_now_us(); - - for (uint32_t j = 0; j < GAZELLE_LATENCY_MAX; j++) { - stack->latency.latency[j].latency_min = ~((uint64_t)0); -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index 9fca04a..ef33365 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -31,7 +31,6 @@ void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct - void stack_stat_init(void); - int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg); - int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); --uint64_t get_current_time(void); - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info); - void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); - void lstack_calculate_aggregate(int type, uint32_t len); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index fa98b0c..d268366 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -14,7 +14,6 @@ - #define __GAZELLE_THREAD_RPC_H__ - - #include --#include - #include - - #include "lstack_lockless_queue.h" -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index d4d0878..cf66e15 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #include - -@@ -181,7 +182,7 @@ int32_t eth_dev_poll(void) - } - - if (!use_ltran() && get_protocol_stack_group()->latency_start) { -- uint64_t time_stamp = get_current_time(); -+ uint64_t time_stamp = sys_now_us(); - time_stamp_into_mbuf(nr_pkts, stack->pkts, time_stamp); - } - -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index c2f53d6..0de9c1c 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -24,7 +24,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -70,7 +69,7 @@ static void calculate_ltran_latency(struct gazelle_stack *stack, const struct rt - return; - } - -- latency = get_current_time() - lt->stamp; -+ latency = gazelle_now_us() - lt->stamp; - - stack->stack_stats.latency_total += latency; - stack->stack_stats.latency_pkts++; -@@ -595,7 +594,7 @@ static __rte_always_inline void upstream_forward_loop(uint32_t port_id, uint32_t - struct rte_mbuf *buf[GAZELLE_PACKET_READ_SIZE] __rte_cache_aligned; - for (loop_cnt = 0; loop_cnt < UPSTREAM_LOOP_TIMES; loop_cnt++) { - if (get_start_latency_flag() == GAZELLE_ON) { -- time_stamp = get_current_time(); -+ time_stamp = gazelle_now_us(); - } - - rx_count = rte_eth_rx_burst(port_id, queue_id, buf, GAZELLE_PACKET_READ_SIZE); -@@ -657,9 +656,8 @@ void upstream_forward(const uint16_t *port) - uint32_t queue_num = get_ltran_config()->bond.rx_queue_num; - uint32_t port_id = get_bond_port()[g_port_index]; - unsigned long now_time; -- unsigned long last_time = get_current_time(); -+ unsigned long last_time = gazelle_now_us(); - unsigned long aging_conn_last_time = last_time; -- calibrate_time(); - - while (get_ltran_stop_flag() != GAZELLE_TRUE) { - for (queue_id = 0; queue_id < queue_num; queue_id++) { -@@ -673,7 +671,7 @@ void upstream_forward(const uint16_t *port) - } - #endif - -- now_time = get_current_time(); -+ now_time = gazelle_now_us(); - if (now_time - aging_conn_last_time > GAZELLE_CONN_INTERVAL) { - gazelle_delete_aging_conn(gazelle_get_tcp_conn_htable()); - aging_conn_last_time = now_time; -diff --git a/src/ltran/ltran_stat.c b/src/ltran/ltran_stat.c -index 0a8d75c..72de448 100644 ---- a/src/ltran/ltran_stat.c -+++ b/src/ltran/ltran_stat.c -@@ -75,7 +75,7 @@ void set_start_latency_flag(int32_t flag) - } - - g_start_latency = flag; -- g_start_time_stamp = get_current_time(); -+ g_start_time_stamp = gazelle_now_us(); - } - - int32_t get_start_latency_flag(void) -diff --git a/src/ltran/ltran_stat.h b/src/ltran/ltran_stat.h -index 75cb353..7945d67 100644 ---- a/src/ltran/ltran_stat.h -+++ b/src/ltran/ltran_stat.h -@@ -36,12 +36,6 @@ enum GAZELLE_CLIENT_STATE { - GAZELLE_CLIENT_STATE_MAX - }; - --enum GAZELLE_TCP_LIST_STATE { -- GAZELLE_ACTIVE_LIST, -- GAZELLE_LISTEN_LIST, -- GAZELLE_TIME_WAIT_LIST, --}; -- - enum GAZELLE_TCP_STATE { - GAZELLE_TCP_STATE_CLS, - GAZELLE_TCP_STATE_LSN, -diff --git a/src/ltran/ltran_timer.c b/src/ltran/ltran_timer.c -index 51d6544..f1c0e6e 100644 ---- a/src/ltran/ltran_timer.c -+++ b/src/ltran/ltran_timer.c -@@ -26,22 +26,16 @@ - #include "ltran_instance.h" - #include "ltran_timer.h" - --static uint64_t g_cycles_per_us = 0; -- --uint64_t get_current_time(void) -+uint64_t gazelle_now_us(void) - { -- if (g_cycles_per_us == 0) { -- return 0; -+ static uint64_t g_cycles_per_us = 0; -+ if (unlikely(g_cycles_per_us == 0)) { -+ g_cycles_per_us = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S; - } - - return (rte_rdtsc() / g_cycles_per_us); - } - --void calibrate_time(void) --{ -- g_cycles_per_us = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S; --} -- - void gazelle_detect_sock_logout(struct gazelle_tcp_sock_htable *tcp_sock_htable) - { - uint32_t i; -diff --git a/src/ltran/ltran_timer.h b/src/ltran/ltran_timer.h -index abc08b9..6c7aeef 100644 ---- a/src/ltran/ltran_timer.h -+++ b/src/ltran/ltran_timer.h -@@ -13,11 +13,11 @@ - #ifndef __GAZELLE_TIMER_H__ - #define __GAZELLE_TIMER_H__ - -+uint64_t gazelle_now_us(void); -+ - struct gazelle_tcp_conn_htable; - struct gazelle_tcp_sock_htable; - --unsigned long get_current_time(void); --void calibrate_time(void); - void gazelle_detect_conn_logout(struct gazelle_tcp_conn_htable *conn_htable); - void gazelle_detect_sock_logout(struct gazelle_tcp_sock_htable *tcp_sock_htable); - void gazelle_delete_aging_conn(struct gazelle_tcp_conn_htable *conn_htable); -diff --git a/test/unitest/stub.c b/test/unitest/stub.c -index 8f37c90..8478b50 100644 ---- a/test/unitest/stub.c -+++ b/test/unitest/stub.c -@@ -10,14 +10,8 @@ - * See the Mulan PSL v2 for more details. - */ - --#include - #include - --uint64_t get_current_time(void) --{ -- return 0; --} -- - int rte_pdump_init(void) - { - return 0; --- -2.33.0 - diff --git a/0225-POSIX-fix-select-timeout-disable-and-build-failed-in.patch b/0225-POSIX-fix-select-timeout-disable-and-build-failed-in.patch deleted file mode 100644 index dc2d007..0000000 --- a/0225-POSIX-fix-select-timeout-disable-and-build-failed-in.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a1d1d5a6d24748883cfe6bb7018681bc3af00f87 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 22 Jul 2024 15:13:22 +0800 -Subject: [PATCH] POSIX: fix select timeout disable and build failed in - openEuler 2003 - ---- - src/lstack/api/lstack_wrap.c | 3 ++- - src/lstack/core/lstack_preload.c | 1 + - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 976a3f3..397870e 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -636,8 +636,9 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - - static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { -+ /* while input args are invalid, param timeout will steal be executed in kernel */ - if (nfds <= 0 || !(readfds || writefds || exceptfds)) { -- GAZELLE_RETURN(EINVAL); -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - - if (select_posix_path() == POSIX_KERNEL) { -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 689d2bf..0a1df7d 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include - #include --- -2.33.0 - diff --git a/0226-support-kernel-connect.patch b/0226-support-kernel-connect.patch deleted file mode 100644 index 3568380..0000000 --- a/0226-support-kernel-connect.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 34a090b2cfb88cb2e711d02c0f3eddf3a3656fac Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Fri, 19 Jul 2024 07:34:47 +0000 -Subject: [PATCH] support kernel connect - ---- - src/lstack/api/lstack_epoll.c | 2 +- - src/lstack/api/lstack_wrap.c | 10 +++++++++- - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 417499b..6426de4 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -439,7 +439,7 @@ int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_ - - struct wakeup_poll *wakeup = epoll_sock->wakeup; - struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -+ if (POSIX_IS_CLOSED(sock) || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { - return posix_api->epoll_ctl_fn(epfd, op, fd, event); - } - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index b19990e..a6ea485 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -317,8 +317,16 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name - ret = posix_api->connect_fn(s, name, namelen); - POSIX_SET_TYPE(sock, POSIX_KERNEL); - } 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); -- POSIX_SET_TYPE(sock, POSIX_LWIP); -+ if (ret == 0) { -+ POSIX_SET_TYPE(sock, POSIX_LWIP); -+ } else { -+ ret = posix_api->connect_fn(s, name, namelen); -+ if (ret == 0) { -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); -+ } -+ } - } - - return ret; --- -2.33.0 - diff --git a/0227-Check-the-return-of-lwip_init.patch b/0227-Check-the-return-of-lwip_init.patch deleted file mode 100644 index 5056f8a..0000000 --- a/0227-Check-the-return-of-lwip_init.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 7cb4456d14405d1d9dbeb890642a339ef13165da Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 22 Jul 2024 15:09:33 +0800 -Subject: [PATCH] Check the return of lwip_init - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_protocol_stack.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 6f2e84e..2867711 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -421,6 +421,11 @@ static struct protocol_stack *stack_thread_init(void *arg) - RTE_PER_LCORE(_lcore_id) = stack->cpu_id; - - lwip_init(); -+ /* Using errno to return lwip_init() result. */ -+ if (errno != 0) { -+ LSTACK_LOG(ERR, LSTACK, "lwip_init failed, errno %d\n", errno); -+ goto END; -+ } - - if (use_ltran()) { - if (client_reg_thrd_ring() != 0) { --- -2.33.0 - diff --git a/0228-vitio_user-modify-mbuf-index-for-bond4.patch b/0228-vitio_user-modify-mbuf-index-for-bond4.patch deleted file mode 100644 index a9833c4..0000000 --- a/0228-vitio_user-modify-mbuf-index-for-bond4.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0f841d29ed2f17f54bc4c13ef01f364ef4c633ac Mon Sep 17 00:00:00 2001 -From: hkk -Date: Sat, 20 Jul 2024 16:52:52 +0800 -Subject: [PATCH] vitio_user: modify mbuf index for bond4 - ---- - src/lstack/core/lstack_virtio.c | 6 ++++-- - src/ltran/ltran_dfx.c | 4 ++-- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 36159c9..f907a99 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -205,6 +205,7 @@ static int virtio_port_init(uint16_t port) - int retval; - uint16_t rx_queue_num = g_virtio_instance.rx_queue_num; - uint16_t tx_queue_num = g_virtio_instance.tx_queue_num; -+ int mbuf_total_num = get_global_cfg_params()->num_cpu * get_global_cfg_params()->num_process; - - LSTACK_LOG(INFO, LSTACK, "virtio_port_init port= %u rx_queue_num=%u tx_queue_num=%u \n", - port, rx_queue_num, tx_queue_num); -@@ -226,7 +227,8 @@ static int virtio_port_init(uint16_t port) - } - - for (uint16_t q = 0; q < tx_queue_num; q++) { -- retval = rte_eth_tx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, rte_eth_dev_socket_id(port), NULL); -+ retval = rte_eth_tx_queue_setup(port, q % mbuf_total_num, VIRTIO_TX_RX_RING_SIZE, -+ rte_eth_dev_socket_id(port), NULL); - if (retval < 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eth_tx_queue_setup failed (queue %u) retval=%d \n", q, retval); - return retval; -@@ -341,4 +343,4 @@ bool virtio_distribute_pkg_to_kernel(uint16_t dst_port) - } - - return (port_map_get(dst_port) == 0); --} -\ No newline at end of file -+} -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 005b09c..1bf5451 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1177,11 +1177,11 @@ static void gazelle_print_lstack_stat_virtio(void *buf, const struct gazelle_sta - struct gazelle_stat_lstack_virtio *virtio = &stat->data.virtio; - printf("\nStatistics of lstack virtio:\n"); - -- printf("\nlstack_port_id =%u virtio_port_id =%u rx_queue_num =%u tx_queue_num =%u \n", -+ printf("\nlstack_port_id: %u virtio_port_id: %u rx_queue_num: %u tx_queue_num: %u \n", - virtio->lstack_port_id, virtio->virtio_port_id, virtio->rx_queue_num, - virtio->tx_queue_num); - -- printf("\n%-8s %-8s %-8s %-8s %-8s\n", "queue_id", "rx_pkg", "rx_drop", "tx_pkg", "tx_drop"); -+ printf("\n%-8s %-8s %-8s %-8s %-8s\n", "queue_id", "rx_pkg", "rx_drop", "tx_pkg", "tx_drop"); - for (int i = 0; i < virtio->rx_queue_num; i++) { - printf("%-8d %-8lu %-8lu %-8lu %-8lu\n", i, - virtio->rx_pkg[i], virtio->rx_drop[i], virtio->tx_pkg[i], virtio->tx_drop[i]); --- -2.33.0 - diff --git a/0229-fix-redis-coredump-when-hugetlbs-pagesize-is-1024M.patch b/0229-fix-redis-coredump-when-hugetlbs-pagesize-is-1024M.patch deleted file mode 100644 index 3a20129..0000000 --- a/0229-fix-redis-coredump-when-hugetlbs-pagesize-is-1024M.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 5dff08d02b2561ca39d7e569b9870f7a315080f0 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Tue, 16 Jul 2024 22:24:04 +0800 -Subject: [PATCH] fix redis coredump when hugetlbs pagesize is 1024M - ---- - src/lstack/core/lstack_init.c | 16 +++++++++------- - 1 file changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index a5a4a4e..629c790 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -113,8 +113,16 @@ void gazelle_exit(void) - /* 1: wait until app thread call send functio complete */ - sleep(1); - stack_group_exit(); -+} - -+void dpdk_exit(void) -+{ - if (!use_ltran()) { -+ int ret = rte_pdump_uninit(); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_pdump_uninit failed\n"); -+ } -+ - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - dpdk_kni_release(); - #endif -@@ -126,13 +134,7 @@ __attribute__((destructor)) void gazelle_network_exit(void) - if (posix_api != NULL && !posix_api->use_kernel) { - lwip_exit(); - gazelle_exit(); -- } -- -- if (!use_ltran()) { -- int32_t ret = rte_pdump_uninit(); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "rte_pdump_uninit failed\n"); -- } -+ dpdk_exit(); - } - } - --- -2.33.0 - diff --git a/0230-dfx-optimize-gazellectl-x-for-bond.patch b/0230-dfx-optimize-gazellectl-x-for-bond.patch deleted file mode 100644 index f2891a7..0000000 --- a/0230-dfx-optimize-gazellectl-x-for-bond.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 99b72b69ea7ce93077d890829e3db812fa34e2cb Mon Sep 17 00:00:00 2001 -From: zhangmengxuan -Date: Wed, 10 Jul 2024 17:23:21 +0800 -Subject: [PATCH] dfx: optimize gazellectl -x for bond - ---- - src/ltran/ltran_dfx.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 005b09c..5bda330 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -204,22 +204,19 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - struct nic_eth_xstats *xstats = &stat->data.nic_xstats; - static const char *nic_stats_border = "########################"; - -+ printf("###### NIC extended statistics for port %-2d #########\n", xstats->port_id); - if (xstats->bonding.mode >= 0) { - printf("############# NIC bonding mode display #############\n"); - printf("%s############################\n", nic_stats_border); -- printf("Bonding mode: [%d]\n", xstats->bonding.mode); -+ printf("Bonding mode: [%d]\n", xstats->bonding.mode); - printf("Bonding miimon: [%d]\n", xstats->bonding.miimon); -- printf("Port range: 0->%d; Bonding port is %d\n", xstats->port_id, xstats->port_id); - printf("Slaves(%d): [", xstats->bonding.slave_count); - for (int i = 0; i < xstats->bonding.slave_count - 1; i++) { - printf("%d ", xstats->bonding.slaves[i]); - } - printf("%d]\n", xstats->bonding.slaves[xstats->bonding.slave_count - 1]); - printf("Primary: [%d]\n", xstats->bonding.primary_port_id); -- printf("%s############################\n", nic_stats_border); - } -- -- printf("###### NIC extended statistics for port %-2d #########\n", xstats->port_id); - printf("%s############################\n", nic_stats_border); - if (xstats->len <= 0 || xstats->len > RTE_ETH_XSTATS_MAX_LEN) { - printf("xstats item(%d) num error!\n", xstats->len); --- -2.33.0 - diff --git a/0231-virtio-fix-dfx-error-with-multiple-cpus.patch b/0231-virtio-fix-dfx-error-with-multiple-cpus.patch deleted file mode 100644 index 3ab0878..0000000 --- a/0231-virtio-fix-dfx-error-with-multiple-cpus.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 61b535e5956122e8e07426218b718a05f9ff81b3 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Thu, 25 Jul 2024 20:20:50 +0800 -Subject: [PATCH] virtio: fix dfx error with multiple cpus - ---- - src/lstack/core/lstack_stack_stat.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 91ca49a..406e27c 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -413,6 +413,10 @@ int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg) - (stat_mode == GAZELLE_STAT_LTRAN_START_LATENCY || stat_mode == GAZELLE_STAT_LTRAN_STOP_LATENCY)) { - continue; - } -+ -+ if (i > 0 && stat_mode == GAZELLE_STAT_LSTACK_SHOW_VIRTIO) { -+ break; -+ } - - dfx.tid = stack->tid; - dfx.stack_id = i; --- -2.33.0 - diff --git a/0232-fix-issue-create-virtio_user-based-on-bond4-main-net.patch b/0232-fix-issue-create-virtio_user-based-on-bond4-main-net.patch deleted file mode 100644 index 55d1b9f..0000000 --- a/0232-fix-issue-create-virtio_user-based-on-bond4-main-net.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 81b3494fbb9a6b346560220bf4b4dc10ae8f9881 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Wed, 24 Jul 2024 15:30:48 +0800 -Subject: [PATCH] fix issue: create virtio_user based on bond4 main network - card - ---- - src/lstack/core/lstack_dpdk.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index e17242c..50fbdf6 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -798,6 +798,7 @@ int32_t init_dpdk_ethdev(void) - LSTACK_LOG(ERR, LSTACK, "bond device create failed, ret=%d\n", ret); - return -1; - } -+ port_id = rte_eth_bond_primary_get(get_protocol_stack_group()->port_id); - } else { - port_id = ethdev_port_id(cfg->mac_addr); - if (port_id < 0) { -@@ -818,8 +819,14 @@ int32_t init_dpdk_ethdev(void) - } - } - #endif -- if (get_global_cfg_params()->flow_bifurcation && virtio_port_create(port_id) != 0) { -- return -1; -+ if (cfg->flow_bifurcation) { -+ if (cfg->kni_switch) { -+ LSTACK_LOG(ERR, LSTACK, "flow_bifurcation and kni_switch cannot both be enabled, please check them\n"); -+ return -1; -+ } -+ if (virtio_port_create(port_id) != 0) { -+ return -1; -+ } - } - - return 0; --- -2.33.0 - diff --git a/0233-virtio_user-modify-mbuf-index-for-bond4.patch b/0233-virtio_user-modify-mbuf-index-for-bond4.patch deleted file mode 100644 index efc84b2..0000000 --- a/0233-virtio_user-modify-mbuf-index-for-bond4.patch +++ /dev/null @@ -1,34 +0,0 @@ -From c7cb61ee76b78908b5a4a544cd04ea15e497cfe9 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Tue, 30 Jul 2024 21:11:52 +0800 -Subject: [PATCH] virtio_user: modify mbuf index for bond4 - ---- - src/lstack/core/lstack_virtio.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index f907a99..70b025c 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -227,7 +227,7 @@ static int virtio_port_init(uint16_t port) - } - - for (uint16_t q = 0; q < tx_queue_num; q++) { -- retval = rte_eth_tx_queue_setup(port, q % mbuf_total_num, VIRTIO_TX_RX_RING_SIZE, -+ retval = rte_eth_tx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, - rte_eth_dev_socket_id(port), NULL); - if (retval < 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eth_tx_queue_setup failed (queue %u) retval=%d \n", q, retval); -@@ -236,7 +236,7 @@ static int virtio_port_init(uint16_t port) - } - - for (uint16_t q = 0; q < rx_queue_num; q++) { -- struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[q]; -+ struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[q % mbuf_total_num]; - retval = rte_eth_rx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, rte_eth_dev_socket_id(port), - NULL, rxtx_mbuf_pool); - if (retval < 0) { --- -2.33.0 - diff --git a/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch b/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch deleted file mode 100644 index dbb7ace..0000000 --- a/0234-WRAP-fix-double-connect-lead-posix-api-disable.patch +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index 70dde64..0000000 --- a/0235-virtio_user-add-vlan-info-for-kernerl-packets-when-v.patch +++ /dev/null @@ -1,51 +0,0 @@ -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 deleted file mode 100644 index b9445e2..0000000 --- a/0236-virtio_user-solve-the-issue-that-failed-to-bind-virt.patch +++ /dev/null @@ -1,88 +0,0 @@ -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 deleted file mode 100644 index 29d6f3f..0000000 --- a/0237-refector-fill-udp-sendring.patch +++ /dev/null @@ -1,223 +0,0 @@ -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/0238-virtio_user-The-program-establishes-a-network-connec.patch b/0238-virtio_user-The-program-establishes-a-network-connec.patch deleted file mode 100644 index ccabe82..0000000 --- a/0238-virtio_user-The-program-establishes-a-network-connec.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 5d0f8bead56a19862ac1e5a9dbd30797e24be6b4 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Sat, 10 Aug 2024 17:11:55 +0800 -Subject: [PATCH] virtio_user: The program establishes a network connection - when network card status is up - ---- - src/lstack/core/lstack_virtio.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index f95b289..b8114e8 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -147,6 +147,13 @@ static int virtio_netif_up(void) - } - - posix_api->close_fn(sockfd); -+ /* -+ * For virtio_user IPv6 addresses, the kernel will check if they are valid, -+ * so wait a few seconds for the address status to change from scope global tentative to scope global. -+ * 3:systerm check ipv6 addr -+ */ -+ sleep(3); -+ - return 0; - } - --- -2.33.0 - diff --git a/0239-WRAP-fix-ltran-mode-did-not-bind-kernel-while-open-k.patch b/0239-WRAP-fix-ltran-mode-did-not-bind-kernel-while-open-k.patch deleted file mode 100644 index caaa59b..0000000 --- a/0239-WRAP-fix-ltran-mode-did-not-bind-kernel-while-open-k.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 19ba97492e3e658301e801d1866a68ac17d87f2f Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 10 Aug 2024 15:34:42 +0800 -Subject: [PATCH] WRAP:fix ltran mode did not bind kernel while open kni - ---- - src/lstack/api/lstack_wrap.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index afcd227..73281e9 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -204,8 +204,9 @@ static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t - 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) { -+ /* lstack not sense if ltran enable kni, so only checks use_ltran. */ -+ if (!get_global_cfg_params()->use_ltran && !get_global_cfg_params()->kni_switch && -+ !get_global_cfg_params()->flow_bifurcation) { - return 0; - } - ret = posix_api->bind_fn(s, name, namelen); --- -2.33.0 - diff --git a/0240-WRAP-fix-bind-log-error.patch b/0240-WRAP-fix-bind-log-error.patch deleted file mode 100644 index d47cf47..0000000 --- a/0240-WRAP-fix-bind-log-error.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 7601cb5b7f384750bb08c15179c43b8e4417d9c6 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 12 Aug 2024 14:32:08 +0800 -Subject: [PATCH] WRAP: fix bind log error - ---- - src/lstack/api/lstack_wrap.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 73281e9..8c3c731 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -201,12 +201,13 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - - static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t namelen) - { -- struct lwip_sock *sock = NULL; -+ struct lwip_sock *sock = lwip_get_socket(s); - int times = 10; - int ret = 0; - /* lstack not sense if ltran enable kni, so only checks use_ltran. */ - if (!get_global_cfg_params()->use_ltran && !get_global_cfg_params()->kni_switch && - !get_global_cfg_params()->flow_bifurcation) { -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - return 0; - } - ret = posix_api->bind_fn(s, name, namelen); -@@ -232,7 +233,6 @@ static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t - } - /* 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); -@@ -266,7 +266,8 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - memcpy_s(sock_addr.u_addr.ip6.addr, IPV6_ADDR_LEN, - ((struct sockaddr_in6 *)name)->sin6_addr.s6_addr, IPV6_ADDR_LEN); - } -- -+ -+ /* TODO: if addr == 127.0.0.1, try kernel and lwip */ - if (!match_host_addr(&sock_addr)) { - POSIX_SET_TYPE(sock, POSIX_KERNEL); - return posix_api->bind_fn(s, name, namelen); --- -2.33.0 - diff --git a/0241-virtio-mod-virtio_user_name-when-multi-process-is-on.patch b/0241-virtio-mod-virtio_user_name-when-multi-process-is-on.patch deleted file mode 100644 index 266f5df..0000000 --- a/0241-virtio-mod-virtio_user_name-when-multi-process-is-on.patch +++ /dev/null @@ -1,154 +0,0 @@ -From d6fab15b942ec7452c1a485741ecec7bb876390f Mon Sep 17 00:00:00 2001 -From: hkk -Date: Tue, 13 Aug 2024 10:09:50 +0800 -Subject: [PATCH] virtio: mod virtio_user_name when multi process is on - ---- - src/lstack/core/lstack_virtio.c | 57 ++++++++++++++++++++++++++------- - 1 file changed, 45 insertions(+), 12 deletions(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index b8114e8..9862b48 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include "lstack_cfg.h" -@@ -21,14 +22,14 @@ - #include "lstack_virtio.h" - #include "securec.h" - --#define VIRTIO_USER_NAME "virtio_user0" -+#define VIRTIO_USER_NAME "virtio_user" - #define VIRTIO_DPDK_PARA_LEN 256 - #define VIRTIO_TX_RX_RING_SIZE 1024 - - #define VIRTIO_MASK_BITS(mask) (32 - __builtin_clz(mask)) - - static struct virtio_instance g_virtio_instance = {0}; -- -+static char g_virtio_user_name[IFNAMSIZ] = {0}; - struct virtio_instance* virtio_instance_get(void) - { - return &g_virtio_instance; -@@ -46,7 +47,7 @@ static int virtio_set_ipv6_addr(void) - return -1; - } - -- int ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME, sizeof(VIRTIO_USER_NAME)); -+ int ret = strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), g_virtio_user_name, strlen(g_virtio_user_name)); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv6_addr strncpy failed ret =%d errno=%d \n", ret, errno); - posix_api->close_fn(sockfd); -@@ -95,7 +96,7 @@ static int virtio_set_ipv4_addr(void) - struct ifreq ifr; - memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); - -- ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME); -+ ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), g_virtio_user_name); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "virtio_set_ipv4_addr strcpy_s failed ret=%d errno %d \n", ret, errno); - posix_api->close_fn(sockfd); -@@ -132,7 +133,7 @@ static int virtio_netif_up(void) - - struct ifreq ifr; - memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); -- int ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), VIRTIO_USER_NAME); -+ int ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), g_virtio_user_name); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "virtio_netif_up strcpy_s failed ret=%d errno %d \n", ret, errno); - posix_api->close_fn(sockfd); -@@ -291,15 +292,47 @@ static int32_t virtio_port_start(uint16_t virtio_port) - g_virtio_instance.rx_queue_num, g_virtio_instance.tx_queue_num); - return 0; - } -+ -+static int virtio_get_netif_num(void) -+{ -+ int netif_num = 0; -+ struct ifaddrs *ifaddr, *ifa; -+ -+ if (getifaddrs(&ifaddr) == -1) { -+ LSTACK_LOG(ERR, LSTACK, "getifaddrs failed \n"); -+ return -1; -+ } -+ -+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { -+ if (strncmp(ifa->ifa_name, VIRTIO_USER_NAME, sizeof(VIRTIO_USER_NAME) - 1) == 0) { -+ netif_num++; -+ } -+ } -+ -+ freeifaddrs(ifaddr); -+ return netif_num; -+} -+ - int virtio_port_create(int lstack_net_port) - { - char portargs[VIRTIO_DPDK_PARA_LEN] = {0}; - - struct rte_ether_addr addr; - uint16_t virtio_port_id = 0xffff; // invalid val -- - struct rte_eth_dev_info dev_info; -- int ret = rte_eth_dev_info_get(lstack_net_port, &dev_info); -+ -+ int ret = virtio_get_netif_num(); -+ if (ret < 0) { -+ return -1; -+ } -+ -+ ret = sprintf_s(g_virtio_user_name, sizeof(g_virtio_user_name), VIRTIO_USER_NAME "%d", ret); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "sprintf_s failed ret=%d \n", ret); -+ return -1; -+ } -+ -+ ret = rte_eth_dev_info_get(lstack_net_port, &dev_info); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "get dev info ret=%d\n", ret); - return ret; -@@ -325,22 +358,22 @@ int virtio_port_create(int lstack_net_port) - g_virtio_instance.rx_queue_num : g_virtio_instance.tx_queue_num; - retval = snprintf(portargs, sizeof(portargs), - "path=/dev/vhost-net,queues=%u,queue_size=%u,iface=%s,mac=" RTE_ETHER_ADDR_PRT_FMT, -- actual_queue_num, VIRTIO_TX_RX_RING_SIZE, VIRTIO_USER_NAME, RTE_ETHER_ADDR_BYTES(&addr)); -+ actual_queue_num, VIRTIO_TX_RX_RING_SIZE, g_virtio_user_name, RTE_ETHER_ADDR_BYTES(&addr)); - if (retval < 0) { - LSTACK_LOG(ERR, LSTACK, "virtio portargs snprintf failed ret=%d \n", retval); - return retval; - } - LSTACK_LOG(INFO, LSTACK, "virtio portargs=%s \n", portargs); - -- retval = rte_eal_hotplug_add("vdev", VIRTIO_USER_NAME, portargs); -+ retval = rte_eal_hotplug_add("vdev", g_virtio_user_name, portargs); - if (retval < 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eal_hotplug_add failed retval=%d : %s\n", retval, strerror(-retval)); - return retval; - } - -- retval = rte_eth_dev_get_port_by_name(VIRTIO_USER_NAME, &virtio_port_id); -+ retval = rte_eth_dev_get_port_by_name(g_virtio_user_name, &virtio_port_id); - if (retval != 0) { -- rte_eal_hotplug_remove("vdev", VIRTIO_USER_NAME); -+ rte_eal_hotplug_remove("vdev", g_virtio_user_name); - LSTACK_LOG(ERR, LSTACK, "virtio_user0 not found\n"); - return -1; - } -@@ -351,7 +384,7 @@ int virtio_port_create(int lstack_net_port) - retval = virtio_port_start(virtio_port_id); - if (retval != 0) { - LSTACK_LOG(ERR, LSTACK, "virtio_port_start failed ret=%d\n", retval); -- rte_eal_hotplug_remove("vdev", VIRTIO_USER_NAME); -+ rte_eal_hotplug_remove("vdev", g_virtio_user_name); - return retval; - } - return 0; --- -2.33.0 - diff --git a/0242-fix-redis-coredump-ctrl-c-during-the-pressure-test.patch b/0242-fix-redis-coredump-ctrl-c-during-the-pressure-test.patch deleted file mode 100644 index b755200..0000000 --- a/0242-fix-redis-coredump-ctrl-c-during-the-pressure-test.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c080e30b41f47848de441e96232d255e541a7c1a Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Thu, 1 Aug 2024 15:55:50 +0800 -Subject: [PATCH] fix redis coredump: ctrl+c during the pressure test - ---- - src/lstack/core/lstack_protocol_stack.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 2867711..f0f2735 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -882,7 +882,7 @@ void stack_tcp_send(struct rpc_msg *msg) - int replenish_again; - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); - return; -@@ -919,6 +919,6 @@ void stack_udp_send(struct rpc_msg *msg) - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - msg->result = -1; - LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); - return; --- -2.33.0 - diff --git a/0243-virtio_user-check-netif-status.patch b/0243-virtio_user-check-netif-status.patch deleted file mode 100644 index 8d2273d..0000000 --- a/0243-virtio_user-check-netif-status.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 1b994a0e9cd2dfa59076b35e3e4c82b1a18c9e1d Mon Sep 17 00:00:00 2001 -From: hkk -Date: Mon, 19 Aug 2024 16:34:54 +0800 -Subject: [PATCH] virtio_user: check netif status - ---- - src/lstack/core/lstack_virtio.c | 35 +++++++++++++++++++++++++++++++-- - 1 file changed, 33 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 9862b48..4a91ed7 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -26,6 +26,9 @@ - #define VIRTIO_DPDK_PARA_LEN 256 - #define VIRTIO_TX_RX_RING_SIZE 1024 - -+#define VIRTIO_NETIF_CHECK_MAX_TIMES 10 -+#define VIRTIO_NETIF_CMD_OUTPUT 4096 -+ - #define VIRTIO_MASK_BITS(mask) (32 - __builtin_clz(mask)) - - static struct virtio_instance g_virtio_instance = {0}; -@@ -123,6 +126,27 @@ static int virtio_set_ipv4_addr(void) - return 0; - } - -+static int virtio_ipv6_is_tentative(void) -+{ -+ FILE *fp; -+ char output[VIRTIO_NETIF_CMD_OUTPUT] = {0}; -+ int not_ready = 0; -+ /* ipv6 tentative state means not ready */ -+ const char *cmd = "ip a |grep tentative"; -+ -+ fp = popen(cmd, "r"); -+ if (fp == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "%s execution failed \n", cmd); -+ return -1; -+ } -+ -+ if (fgets(output, sizeof(output), fp) != NULL) { -+ not_ready = 1; -+ } -+ pclose(fp); -+ return not_ready; -+} -+ - static int virtio_netif_up(void) - { - int sockfd = posix_api->socket_fn(AF_INET, SOCK_DGRAM, 0); -@@ -151,9 +175,16 @@ static int virtio_netif_up(void) - /* - * For virtio_user IPv6 addresses, the kernel will check if they are valid, - * so wait a few seconds for the address status to change from scope global tentative to scope global. -- * 3:systerm check ipv6 addr - */ -- sleep(3); -+ for (int i = 0; i < VIRTIO_NETIF_CHECK_MAX_TIMES; i++) { -+ ret = virtio_ipv6_is_tentative(); -+ if (ret == 0) { -+ break; -+ } else if (ret < 0) { -+ return -1; -+ } -+ sleep(1); -+ } - - return 0; - } --- -2.33.0 - diff --git a/0244-virtio-solve-compilation-error-in-2003sp3.patch b/0244-virtio-solve-compilation-error-in-2003sp3.patch deleted file mode 100644 index 9112e37..0000000 --- a/0244-virtio-solve-compilation-error-in-2003sp3.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 4a30424a4ce6135cbd118bc36f00b35955255f41 Mon Sep 17 00:00:00 2001 -From: hantwofish -Date: Tue, 20 Aug 2024 17:28:37 +0800 -Subject: [PATCH] virtio: solve compilation error in 2003sp3 - ---- - src/lstack/core/lstack_virtio.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 4a91ed7..7a8d947 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include "lstack_cfg.h" - #include "lstack_log.h" --- -2.33.0 - diff --git a/0245-CMAKE-fix-ltran-build-error-in-2403.patch b/0245-CMAKE-fix-ltran-build-error-in-2403.patch deleted file mode 100644 index ffe9a36..0000000 --- a/0245-CMAKE-fix-ltran-build-error-in-2403.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0e6641552d16987b7e0706e1edb4992e7bd5e7d9 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 26 Aug 2024 17:21:44 +0800 -Subject: [PATCH] CMAKE: fix ltran build error in 2403 - ---- - src/ltran/CMakeLists.txt | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/ltran/CMakeLists.txt b/src/ltran/CMakeLists.txt -index 8e9b1ea..f94ed83 100644 ---- a/src/ltran/CMakeLists.txt -+++ b/src/ltran/CMakeLists.txt -@@ -80,12 +80,12 @@ else() - endif() - - if (DPDK_VERSION GREATER_EQUAL 23.11) -- set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -lrte_log -larchive -Wl,-lrte_eal) -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -lrte_log -Wl,-lrte_eal) - else() - set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -lrte_kni -Wl,-Bstatic -Wl,-lrte_eal -Wl,-Bdynamic) -- if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "ppc64le") -- set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-larchive) -- endif() -+endif() -+if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "ppc64le") -+ set(DPDK_LINK_FLAGS ${DPDK_LINK_FLAGS} -Wl,-larchive) - endif() - - # compile info --- -2.34.1 - diff --git a/0246-fix-mbuf_total-calculation-error.patch b/0246-fix-mbuf_total-calculation-error.patch deleted file mode 100644 index e428785..0000000 --- a/0246-fix-mbuf_total-calculation-error.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 783ea4a8f8949cb943a94cb6fdb1690852f7faa3 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 16 Aug 2024 05:55:40 +0800 -Subject: [PATCH] fix mbuf_total calculation error - ---- - src/lstack/core/lstack_protocol_stack.c | 20 +++++++++++--------- - 1 file changed, 11 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 6e980a8..ba90d86 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -548,29 +548,31 @@ static void* gazelle_stack_thread(void *arg) - - int32_t stack_group_init_mempool(void) - { -- struct cfg_params *global_cfg_parmas = get_global_cfg_params(); -- uint32_t total_mbufs = get_global_cfg_params()->mbuf_count_per_conn * get_global_cfg_params()->tcp_conn_count; -+ struct cfg_params *cfg_params = get_global_cfg_params(); -+ uint32_t total_mbufs = 0; -+ uint32_t total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; -+ uint32_t total_nic_mbufs = cfg_params->nic.rxqueue_size + cfg_params->nic.txqueue_size; - struct rte_mempool *rxtx_mbuf = NULL; - uint32_t cpu_id = 0; - unsigned numa_id = 0; - int queue_id = 0; - - LSTACK_LOG(INFO, LSTACK, -- "config::num_cpu=%d num_process=%d \n", global_cfg_parmas->num_cpu, global_cfg_parmas->num_process); -+ "config::num_cpu=%d num_process=%d \n", cfg_params->num_cpu, cfg_params->num_process); - -- for (int cpu_idx = 0; cpu_idx < get_global_cfg_params()->num_queue; cpu_idx++) { -- cpu_id = global_cfg_parmas->cpus[cpu_idx]; -+ for (int cpu_idx = 0; cpu_idx < cfg_params->num_queue; cpu_idx++) { -+ cpu_id = cfg_params->cpus[cpu_idx]; - numa_id = numa_node_of_cpu(cpu_id); - -- for (int process_idx = 0; process_idx < global_cfg_parmas->num_process; process_idx++) { -- queue_id = cpu_idx * global_cfg_parmas->num_process + process_idx; -+ for (int process_idx = 0; process_idx < cfg_params->num_process; process_idx++) { -+ queue_id = cpu_idx * cfg_params->num_process + process_idx; - if (queue_id >= PROTOCOL_STACK_MAX) { - LSTACK_LOG(ERR, LSTACK, "index is over\n"); - return -1; - } - -- rxtx_mbuf = create_pktmbuf_mempool( -- "rxtx_mbuf", total_mbufs / get_global_cfg_params()->num_queue, RXTX_CACHE_SZ, queue_id, numa_id); -+ total_mbufs = (total_conn_mbufs / cfg_params->num_queue) + total_nic_mbufs + MBUFPOOL_RESERVE_NUM; -+ rxtx_mbuf = create_pktmbuf_mempool("rxtx_mbuf", total_mbufs, RXTX_CACHE_SZ, queue_id, numa_id); - if (rxtx_mbuf == NULL) { - LSTACK_LOG(ERR, LSTACK, "cpuid=%u, numid=%d , rxtx_mbuf idx= %d create_pktmbuf_mempool fail\n", - cpu_id, numa_id, queue_id); --- -2.33.0 - diff --git a/0247-cfg-modify-maximum-tcp_conn_count-to-2w.patch b/0247-cfg-modify-maximum-tcp_conn_count-to-2w.patch deleted file mode 100644 index 999bb59..0000000 --- a/0247-cfg-modify-maximum-tcp_conn_count-to-2w.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5c0ece87e2ce183119f29f5d6a2c53465a622ac9 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Sat, 17 Aug 2024 05:15:57 +0800 -Subject: [PATCH] cfg: modify maximum tcp_conn_count to 2w - ---- - src/lstack/core/lstack_cfg.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index cd81edb..882e60a 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -917,7 +917,7 @@ static int32_t parse_use_ltran(void) - static int32_t parse_tcp_conn_count(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.tcp_conn_count, "tcp_conn_count", TCP_CONN_COUNT, 1, TCP_CONN_COUNT, ret); -+ PARSE_ARG(g_config_params.tcp_conn_count, "tcp_conn_count", TCP_CONN_COUNT, 1, GAZELLE_MAX_CLIENTS, ret); - return ret; - } - --- -2.33.0 - diff --git a/0248-tools-fix-sync-patch-script-date-wrong-and-update-th.patch b/0248-tools-fix-sync-patch-script-date-wrong-and-update-th.patch deleted file mode 100644 index eb264d4..0000000 --- a/0248-tools-fix-sync-patch-script-date-wrong-and-update-th.patch +++ /dev/null @@ -1,47 +0,0 @@ -From ccab3a40054a7d95e144bca8f9e0fd0c376cbaf6 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 26 Aug 2024 21:12:17 +0800 -Subject: [PATCH] tools: fix sync patch script date wrong and update the way - get patchnum - ---- - tools/sync-gazelle-src.sh | 16 +++++++++++----- - 1 file changed, 11 insertions(+), 5 deletions(-) - -diff --git a/tools/sync-gazelle-src.sh b/tools/sync-gazelle-src.sh -index 8d44ca2..142e770 100644 ---- a/tools/sync-gazelle-src.sh -+++ b/tools/sync-gazelle-src.sh -@@ -63,10 +63,16 @@ for commitid in ${COMMIT_ID};do - git checkout -b $TARGET_BRANCH origin/$TARGET_BRANCH - git pull https://gitee.com/src-openeuler/gazelle.git $TARGET_BRANCH - fi -- patchnum=$(ls ./*.patch | wc -l) -- let patchnum+=1 -- let Patchnum=9000+$patchnum -- patchnum=$(printf "%04d\n" $patchnum) -+ -+ #get patchnum from spec file. -+ patchnum=$(grep -o "Patch[0-9]\+" *.spec | tail -n 1 | awk -Fh '{print $2}') -+ if [ -z $patchnum ];then -+ #there is no patch in spec file. get patch by conunt patches in dir. -+ patchnum=$(ls ./*.patch | wc -l) -+ let Patchnum=9000+$patchnum -+ patchnum=$(printf "%04d\n" $patchnum) -+ fi -+ let patchnum+=1 - new_patchname=$(echo $patchname | sed -e "s/^0001-/${patchnum}-/g") - - echo $new_patchname -@@ -82,7 +88,7 @@ for commitid in ${COMMIT_ID};do - - #add changelog in spec file - changelog_line=$(grep -n '^%changelog' gazelle.spec | cut -f1 -d':') -- changelog_data=$(date | awk '{print $1,$2,$3,$6}') -+ changelog_data=$(date +"%a %b %d %Y") - changelog_version=$(grep '^Version' gazelle.spec | awk '{print $2}') - - if [ -z "$done_once" ];then --- -2.33.0 - diff --git a/0249-epoll-fix-wild-pointer-detected-by-cooddy.patch b/0249-epoll-fix-wild-pointer-detected-by-cooddy.patch deleted file mode 100644 index bd3952c..0000000 --- a/0249-epoll-fix-wild-pointer-detected-by-cooddy.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2adb9415c567037a44f6adf7df3b91ced624cb51 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 27 Aug 2024 16:23:03 +0800 -Subject: [PATCH] epoll: fix wild pointer detected by cooddy - ---- - src/lstack/api/lstack_epoll.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index b83da70..5b0bee4 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -782,6 +782,7 @@ static int resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) - if (wakeup->events == NULL) { - LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); - free(wakeup->last_fds); -+ wakeup->last_fds = NULL; - return -1; - } - --- -2.33.0 - diff --git a/0250-tools-fix-script-generate-patchname-wrong.patch b/0250-tools-fix-script-generate-patchname-wrong.patch deleted file mode 100644 index 813e176..0000000 --- a/0250-tools-fix-script-generate-patchname-wrong.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 878bd892608e312276945a57430c86909cefb459 Mon Sep 17 00:00:00 2001 -From: yinbin6 -Date: Fri, 30 Aug 2024 16:15:03 +0800 -Subject: [PATCH] tools: fix script generate patchname wrong - ---- - tools/sync-gazelle-src.sh | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tools/sync-gazelle-src.sh b/tools/sync-gazelle-src.sh -index 142e770..ccfa8eb 100644 ---- a/tools/sync-gazelle-src.sh -+++ b/tools/sync-gazelle-src.sh -@@ -65,14 +65,14 @@ for commitid in ${COMMIT_ID};do - fi - - #get patchnum from spec file. -- patchnum=$(grep -o "Patch[0-9]\+" *.spec | tail -n 1 | awk -Fh '{print $2}') -+ patchnum=$(grep -o "Patch[0-9]\+" *.spec | tail -n 1 | awk -Fh '{print $2}' | awk '{print $1 - 9000}') - if [ -z $patchnum ];then - #there is no patch in spec file. get patch by conunt patches in dir. - patchnum=$(ls ./*.patch | wc -l) -- let Patchnum=9000+$patchnum -- patchnum=$(printf "%04d\n" $patchnum) - fi - let patchnum+=1 -+ let Patchnum=9000+$patchnum -+ patchnum=$(printf "%04d\n" $patchnum) - new_patchname=$(echo $patchname | sed -e "s/^0001-/${patchnum}-/g") - - echo $new_patchname --- -2.33.0 - diff --git a/0251-fix-when-errno-is-ENOTCONN-ignore-it.patch b/0251-fix-when-errno-is-ENOTCONN-ignore-it.patch deleted file mode 100644 index 6d85770..0000000 --- a/0251-fix-when-errno-is-ENOTCONN-ignore-it.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 015eea5899cfea961247686d711a67917cb7a7b9 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Thu, 5 Sep 2024 14:37:07 +0800 -Subject: [PATCH] fix: when errno is ENOTCONN, ignore it - ---- - src/lstack/core/lstack_protocol_stack.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ba90d86..49b3ec8 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -559,18 +559,18 @@ int32_t stack_group_init_mempool(void) - - LSTACK_LOG(INFO, LSTACK, - "config::num_cpu=%d num_process=%d \n", cfg_params->num_cpu, cfg_params->num_process); -- -+ - for (int cpu_idx = 0; cpu_idx < cfg_params->num_queue; cpu_idx++) { - cpu_id = cfg_params->cpus[cpu_idx]; - numa_id = numa_node_of_cpu(cpu_id); -- -+ - for (int process_idx = 0; process_idx < cfg_params->num_process; process_idx++) { - queue_id = cpu_idx * cfg_params->num_process + process_idx; - if (queue_id >= PROTOCOL_STACK_MAX) { - LSTACK_LOG(ERR, LSTACK, "index is over\n"); - return -1; - } -- -+ - total_mbufs = (total_conn_mbufs / cfg_params->num_queue) + total_nic_mbufs + MBUFPOOL_RESERVE_NUM; - rxtx_mbuf = create_pktmbuf_mempool("rxtx_mbuf", total_mbufs, RXTX_CACHE_SZ, queue_id, numa_id); - if (rxtx_mbuf == NULL) { -@@ -578,7 +578,7 @@ int32_t stack_group_init_mempool(void) - cpu_id, numa_id, queue_id); - return -1; - } -- -+ - get_protocol_stack_group()->total_rxtx_pktmbuf_pool[queue_id] = rxtx_mbuf; - } - } -@@ -723,13 +723,13 @@ void stack_close(struct rpc_msg *msg) - int32_t fd = msg->args[MSG_ARG_0].i; - struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = lwip_get_socket(fd); -- -+ - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; - rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ - return; - } -- -+ - msg->result = lwip_close(fd); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -@@ -750,7 +750,7 @@ void stack_shutdown(struct rpc_msg *msg) - } - - msg->result = lwip_shutdown(fd, how); -- if (msg->result != 0) { -+ if (msg->result != 0 && errno != ENOTCONN) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), fd, msg->result); - } - -@@ -935,7 +935,7 @@ void stack_udp_send(struct rpc_msg *msg) - rpc_call_replenish(&stack->rpc_queue, sock); - return; - } -- -+ - __sync_fetch_and_sub(&sock->call_num, 1); - return; - } --- -2.33.0 - diff --git a/0252-rtc-do_lwip_init_sock-no-need-to-create-ring-in-rtc-.patch b/0252-rtc-do_lwip_init_sock-no-need-to-create-ring-in-rtc-.patch deleted file mode 100644 index c8cc8bc..0000000 --- a/0252-rtc-do_lwip_init_sock-no-need-to-create-ring-in-rtc-.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6b097278f9d70f3cc976d7a7078447975de6a4b7 Mon Sep 17 00:00:00 2001 -From: zhengjiebing -Date: Mon, 29 Jul 2024 14:07:21 +0800 -Subject: [PATCH] rtc: do_lwip_init_sock no need to create ring in rtc mode - ---- - src/lstack/api/lstack_rtc_api.c | 8 -------- - src/lstack/core/lstack_lwip.c | 9 +++++++++ - 2 files changed, 9 insertions(+), 8 deletions(-) - -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index ca0e7ec..e30718c 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -50,14 +50,6 @@ int rtc_socket(int domain, int type, int protocol) - - /* need call stack thread init function */ - ret = lwip_socket(domain, type, protocol); -- if (ret >= 0) { -- struct lwip_sock *sock = lwip_get_socket(ret); -- sock->stack = get_protocol_stack(); -- sock->epoll_events = 0; -- sock->events = 0; -- sock->wakeup = NULL; -- list_init_node(&sock->event_list); -- } - return ret; - } - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 271e94f..4ea13ad 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -154,6 +154,15 @@ int do_lwip_init_sock(int32_t fd) - return -1; - } - -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ sock->stack = stack; -+ sock->epoll_events = 0; -+ sock->events = 0; -+ sock->wakeup = NULL; -+ list_init_node(&sock->event_list); -+ return 0; -+ } -+ - reset_sock_data(sock); - - sock->recv_ring = gazelle_ring_create_fast("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ); --- -2.33.0 - diff --git a/0253-example-solve-double-free.patch b/0253-example-solve-double-free.patch deleted file mode 100644 index 51d8bd5..0000000 --- a/0253-example-solve-double-free.patch +++ /dev/null @@ -1,99 +0,0 @@ -From c49e92c7fc0a76fbc605c2b67fd46deba7953e1a Mon Sep 17 00:00:00 2001 -From: hkk -Date: Thu, 5 Sep 2024 09:55:36 +0800 -Subject: [PATCH] example: solve double free - ---- - examples/src/server.c | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - -diff --git a/examples/src/server.c b/examples/src/server.c -index 7bc7d9e..b53e005 100644 ---- a/examples/src/server.c -+++ b/examples/src/server.c -@@ -69,7 +69,7 @@ void sermud_info_print(struct ServerMud *server_mud) - struct timeval end; - gettimeofday(&end, NULL); - uint64_t end_time = (uint64_t)end.tv_sec * 1000 + (uint64_t)end.tv_usec / 1000; -- -+ - double bytes_sub = end_recv_bytes > begin_recv_bytes ? (double)(end_recv_bytes - begin_recv_bytes) : 0; - double time_sub = end_time > begin_time ? (double)(end_time - begin_time) / 1000 : 0; - -@@ -93,7 +93,7 @@ int32_t sermud_worker_create_epfd_and_reg(struct ServerMudWorker *worker_unit) - } else { - worker_unit->epfd = epoll_create(SERVER_EPOLL_SIZE_MAX); - } -- -+ - if (worker_unit->epfd < 0) { - PRINT_ERROR("server can't create epoll %d! ", worker_unit->epfd); - return PROGRAM_FAULT; -@@ -118,7 +118,7 @@ int32_t sermud_listener_create_epfd_and_reg(struct ServerMud *server_mud) - } else { - server_mud->epfd = epoll_create(SERVER_EPOLL_SIZE_MAX); - } -- -+ - if (server_mud->epfd < 0) { - PRINT_ERROR("server can't create epoll %d! ", server_mud->epfd); - return PROGRAM_FAULT; -@@ -236,15 +236,16 @@ static int32_t server_handler_close(int32_t epfd, struct ServerHandler *server_h - { - int32_t fd = server_handler->fd; - struct epoll_event ep_ev; -- if (server_handler) { -- free(server_handler); -- } - - if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ep_ev) < 0) { - PRINT_ERROR("server can't delete socket '%d' to control epoll %d! ", fd, errno); - return PROGRAM_FAULT; - } - -+ if (server_handler) { -+ free(server_handler); -+ } -+ - if (close(fd) < 0) { - PRINT_ERROR("server can't close the socket %d! ", errno); - return PROGRAM_FAULT; -@@ -335,7 +336,7 @@ int32_t sermud_listener_proc_epevs(struct ServerMud *server_mud) - - for (int32_t i = 0; i < epoll_nfds; ++i) { - struct epoll_event *curr_epev = server_mud->epevs + i; -- -+ - if (curr_epev->events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { - PRINT_ERROR("server epoll wait error %d! ", curr_epev->events); - server_handler_close(server_mud->epfd, (struct ServerHandler *)curr_epev->data.ptr); -@@ -540,7 +541,7 @@ void sermum_info_print(struct ServerMum *server_mum) - struct timeval end; - gettimeofday(&end, NULL); - uint64_t end_time = (uint64_t)end.tv_sec * 1000 + (uint64_t)end.tv_usec / 1000; -- -+ - double bytes_sub = end_recv_bytes > begin_recv_bytes ? (double)(end_recv_bytes - begin_recv_bytes) : 0; - double time_sub = end_time > begin_time ? (double)(end_time - begin_time) / 1000 : 0; - -@@ -564,7 +565,7 @@ int32_t sersum_create_epfd_and_reg(struct ServerMumUnit *server_unit) - } else { - server_unit->epfd = epoll_create(SERVER_EPOLL_SIZE_MAX); - } -- -+ - if (server_unit->epfd < 0) { - PRINT_ERROR("server can't create epoll %d! ", server_unit->epfd); - return PROGRAM_FAULT; -@@ -784,7 +785,7 @@ void *sersum_create_and_run(void *arg) - exit(PROGRAM_FAULT); - } - } -- -+ - close(server_unit->listener.fd); - close(server_unit->epfd); - --- -2.33.0 - diff --git a/0254-WRAP-support-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch b/0254-WRAP-support-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch deleted file mode 100644 index 36c72d1..0000000 --- a/0254-WRAP-support-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 34d3415bab0de76e2d704cda1c786c06e110e2e7 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 11 Sep 2024 16:50:17 +0800 -Subject: [PATCH] WRAP: support setsockopt SO_SNDTIMEO SO_SNBUF - ---- - src/lstack/api/lstack_wrap.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8c3c731..92ce73b 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -424,8 +424,6 @@ static bool unsupport_socket_optname(int32_t optname) - { - if ((optname == SO_BROADCAST) || - (optname == SO_PROTOCOL) || -- (optname == SO_SNDTIMEO) || -- (optname == SO_SNDBUF) || - (optname == SO_RCVBUF) || - (optname == SO_DONTROUTE)) { - return true; --- -2.33.0 - diff --git a/0255-DFX-adapt-log-optimization.patch b/0255-DFX-adapt-log-optimization.patch deleted file mode 100644 index fa8028e..0000000 --- a/0255-DFX-adapt-log-optimization.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 0093be5afee0264c669111a0137a580b2c314b6c Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 18 Sep 2024 15:24:17 +0800 -Subject: [PATCH] DFX: adapt log optimization - ---- - src/common/gazelle_dfx_msg.h | 8 ++++++++ - src/lstack/core/lstack_protocol_stack.c | 2 -- - src/ltran/ltran_dfx.c | 7 +++++++ - 3 files changed, 15 insertions(+), 2 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 8eb54ff..08f9df1 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -195,6 +195,14 @@ struct gazelle_stat_lstack_snmp { - uint32_t tcp_acceptmbox_full; - uint32_t tcp_listen_drops; - uint32_t tcp_in_empty_acks; -+ /* GAZELLE TCP */ -+ uint32_t tcp_rst_in_keepalive_timeout; -+ uint32_t tcp_rst_wrong_syn_in_timewait; -+ uint32_t tcp_rst_wrong_ack_in_syn_rcvd; -+ uint32_t tcp_ooseq_data_drop; -+ uint32_t tcp_free_pcb_in_syn_maxrtx; -+ uint32_t tcp_free_pcb_in_maxrtx; -+ uint32_t tcp_alloc_pcb_fails; - - /* UDP */ - uint32_t udp_in_datagrams; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 49b3ec8..00900e7 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -886,7 +886,6 @@ void stack_tcp_send(struct rpc_msg *msg) - struct lwip_sock *sock = lwip_get_socket(fd); - if (POSIX_IS_CLOSED(sock)) { - msg->result = -1; -- LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); - return; - } - -@@ -922,7 +921,6 @@ void stack_udp_send(struct rpc_msg *msg) - struct lwip_sock *sock = lwip_get_socket(fd); - if (POSIX_IS_CLOSED(sock)) { - msg->result = -1; -- LSTACK_LOG(ERR, LSTACK, "get sock error! fd=%d, len=%ld\n", fd, len); - return; - } - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 9815009..fc30054 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1005,6 +1005,13 @@ static void gazelle_print_lstack_tcp_stat(const struct gazelle_stat_lstack_snmp - printf("tcp_acceptmbox_full: %u\n", snmp->tcp_acceptmbox_full); - printf("tcp_listen_drops: %u\n", snmp->tcp_listen_drops); - printf("tcp_in_empty_acks: %u\n", snmp->tcp_in_empty_acks); -+ printf("tcp_rst_in_keepalive_timeout: %u\n", snmp->tcp_rst_in_keepalive_timeout); -+ printf("tcp_rst_wrong_syn_in_timewait: %u\n", snmp->tcp_rst_wrong_syn_in_timewait); -+ printf("tcp_rst_wrong_ack_in_syn_rcvd: %u\n", snmp->tcp_rst_wrong_ack_in_syn_rcvd); -+ printf("tcp_ooseq_data_drop: %u\n", snmp->tcp_ooseq_data_drop); -+ printf("tcp_free_pcb_in_syn_maxrtx: %u\n", snmp->tcp_free_pcb_in_syn_maxrtx); -+ printf("tcp_free_pcb_in_maxrtx: %u\n", snmp->tcp_free_pcb_in_maxrtx); -+ printf("tcp_alloc_pcb_fails: %u\n", snmp->tcp_alloc_pcb_fails); - } - - static void gazelle_print_ltran_stat_lb_rate(void *buf, const struct gazelle_stat_msg_request *req_msg) --- -2.33.0 - diff --git a/0256-LOG-add-log-when-udp-send_ring-is-exhausted.patch b/0256-LOG-add-log-when-udp-send_ring-is-exhausted.patch deleted file mode 100644 index 85446e2..0000000 --- a/0256-LOG-add-log-when-udp-send_ring-is-exhausted.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 66b11c7916740615be6012938e82abd821a1b06e Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Mon, 23 Sep 2024 20:17:10 +0800 -Subject: [PATCH] LOG:add log when udp send_ring is exhausted - ---- - src/lstack/core/lstack_lwip.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 636bbc7..a7b7202 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -497,6 +497,7 @@ static ssize_t do_lwip_udp_fill_sendring(struct lwip_sock *sock, const void *buf - } - - if (write_avail < write_num) { -+ LSTACK_LOG(WARNING, LSTACK, "sock send_ring is already exhausted.\n"); - sem_timedwait_nsecs(&sock->snd_ring_sem); - GAZELLE_RETURN(ENOMEM); - } --- -2.33.0 - diff --git a/0257-cleancode-refactor-rtc_api-rtw_api-and-dummy_api.patch b/0257-cleancode-refactor-rtc_api-rtw_api-and-dummy_api.patch deleted file mode 100644 index 13b6996..0000000 --- a/0257-cleancode-refactor-rtc_api-rtw_api-and-dummy_api.patch +++ /dev/null @@ -1,1035 +0,0 @@ -From 85e907b495391a89096bfb7e5c9cb901d0f9f56b Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sat, 31 Aug 2024 11:31:13 +0800 -Subject: [PATCH] cleancode: refactor rtc_api rtw_api and dummy_api - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_dummy_api.c | 32 ++++-- - src/lstack/api/lstack_epoll.c | 2 +- - src/lstack/api/lstack_fork.c | 28 ----- - src/lstack/api/lstack_rtc_api.c | 92 +++++++++++----- - src/lstack/api/lstack_rtw_api.c | 104 +++++++++++------- - .../api/{lstack_signal.c => lstack_unistd.c} | 31 +++++- - src/lstack/api/lstack_wrap.c | 91 ++------------- - src/lstack/core/lstack_init.c | 31 ++---- - src/lstack/core/lstack_lwip.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/core/lstack_stack_stat.c | 2 +- - src/lstack/include/{posix => }/lstack_epoll.h | 0 - src/lstack/include/lstack_rtc_api.h | 43 +------- - src/lstack/include/lstack_rtw_api.h | 35 +----- - .../include/{posix => }/lstack_unistd.h | 13 +-- - src/lstack/include/lstack_wrap.h | 2 +- - 16 files changed, 217 insertions(+), 293 deletions(-) - delete mode 100644 src/lstack/api/lstack_fork.c - rename src/lstack/api/{lstack_signal.c => lstack_unistd.c} (89%) - rename src/lstack/include/{posix => }/lstack_epoll.h (100%) - rename src/lstack/include/{posix => }/lstack_unistd.h (78%) - -diff --git a/src/lstack/api/lstack_dummy_api.c b/src/lstack/api/lstack_dummy_api.c -index f327916..3a867b3 100644 ---- a/src/lstack/api/lstack_dummy_api.c -+++ b/src/lstack/api/lstack_dummy_api.c -@@ -13,6 +13,10 @@ - #include - #include - -+#include -+#include -+#include -+ - #define DUMMY_SLEEP_S 5 - - static inline ssize_t dummy_exit(void) -@@ -22,34 +26,48 @@ static inline ssize_t dummy_exit(void) - return -1; - } - --int dummy_socket(int domain, int type, int protocol) -+static int dummy_socket(int domain, int type, int protocol) - { - sleep(DUMMY_SLEEP_S); - return -1; - } - --ssize_t dummy_write(int s, const void *mem, size_t size) -+static ssize_t dummy_write(int s, const void *mem, size_t size) - { - return dummy_exit(); - } - --ssize_t dummy_writev(int s, const struct iovec *iov, int iovcnt) -+static ssize_t dummy_writev(int s, const struct iovec *iov, int iovcnt) - { - return dummy_exit(); - } - --ssize_t dummy_send(int sockfd, const void *buf, size_t len, int flags) -+static ssize_t dummy_send(int sockfd, const void *buf, size_t len, int flags) - { - return dummy_exit(); - } - --ssize_t dummy_sendmsg(int s, const struct msghdr *message, int flags) -+static ssize_t dummy_sendmsg(int s, const struct msghdr *message, int flags) - { - return dummy_exit(); - } - --ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, -- const struct sockaddr *addr, socklen_t addrlen) -+static ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen) - { - return dummy_exit(); - } -+ -+void dummy_api_init(posix_api_t *api) -+{ -+ api->socket_fn = dummy_socket; -+ api->send_fn = dummy_send; -+ api->write_fn = dummy_write; -+ api->writev_fn = dummy_writev; -+ api->sendmsg_fn = dummy_sendmsg; -+ api->sendto_fn = dummy_sendto; -+ -+ rte_wmb(); -+ /* 1: wait until app thread call send functio complete */ -+ sleep(1); -+} -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 5b0bee4..1c13076 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -35,7 +35,7 @@ - #include "common/gazelle_base_func.h" - #include "lstack_lwip.h" - #include "lstack_protocol_stack.h" --#include "posix/lstack_epoll.h" -+#include "lstack_epoll.h" - - #define EPOLL_KERNEL_INTERVAL 10 /* ms */ - #define SEC_TO_NSEC 1000000000 -diff --git a/src/lstack/api/lstack_fork.c b/src/lstack/api/lstack_fork.c -deleted file mode 100644 -index f5d0e95..0000000 ---- a/src/lstack/api/lstack_fork.c -+++ /dev/null -@@ -1,28 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#include --#include -- --#include -- --pid_t lstack_fork(void) --{ -- pid_t pid; -- -- pid = posix_api->fork_fn(); -- /* child not support lwip */ -- if (pid == 0) { -- posix_api->use_kernel = 1; -- } -- return pid; --} -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index e30718c..7689c83 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -10,37 +10,16 @@ - * See the Mulan PSL v2 for more details. - */ - --#include --#include --#include --#include --#include - #include --#include "posix/lstack_epoll.h" -+#include -+ -+#include "lstack_epoll.h" - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_protocol_stack.h" --#include "lstack_thread_rpc.h" - #include "lstack_rtc_api.h" - --int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) --{ -- LSTACK_LOG(ERR, LSTACK, "rtc_poll: rtc currently does not support poll\n"); -- return -1; --} -- --int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) --{ -- LSTACK_LOG(ERR, LSTACK, "rtc_select: rtc currently does not support select\n"); -- return -1; --} -- --int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) --{ -- return lstack_rtc_epoll_wait(epfd, events, maxevents, timeout); --} -- --int rtc_socket(int domain, int type, int protocol) -+static int rtc_socket(int domain, int type, int protocol) - { - int ret; - -@@ -53,7 +32,7 @@ int rtc_socket(int domain, int type, int protocol) - return ret; - } - --int rtc_close(int s) -+static int rtc_close(int s) - { - struct lwip_sock *sock = lwip_get_socket(s); - if (sock != NULL && sock->wakeup != NULL && sock->wakeup->epollfd == s) { -@@ -63,12 +42,12 @@ int rtc_close(int s) - return lwip_close(s); - } - --int rtc_shutdown(int fd, int how) -+static int rtc_shutdown(int fd, int how) - { - return lwip_shutdown(fd, how); - } - --int rtc_epoll_create(int flags) -+static int rtc_epoll_create(int flags) - { - if (stack_setup_app_thread() < 0) { - exit(1); -@@ -77,7 +56,7 @@ int rtc_epoll_create(int flags) - return lstack_epoll_create(flags); - } - --int rtc_epoll_create1(int flags) -+static int rtc_epoll_create1(int flags) - { - if (stack_setup_app_thread() < 0) { - exit(1); -@@ -86,7 +65,60 @@ int rtc_epoll_create1(int flags) - return lstack_epoll_create1(flags); - } - --int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -+static int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { - return lstack_rtc_epoll_ctl(epfd, op, fd, event); - } -+ -+static int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+{ -+ return lstack_rtc_epoll_wait(epfd, events, maxevents, timeout); -+} -+ -+static int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) -+{ -+ LSTACK_LOG(ERR, LSTACK, "rtc_poll: rtc currently does not support poll\n"); -+ return -1; -+} -+ -+static int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ LSTACK_LOG(ERR, LSTACK, "rtc_select: rtc currently does not support select\n"); -+ return -1; -+} -+ -+void rtc_api_init(posix_api_t *api) -+{ -+ api->close_fn = rtc_close; -+ api->shutdown_fn = rtc_shutdown; -+ api->socket_fn = rtc_socket; -+ api->accept_fn = lwip_accept; -+ api->accept4_fn = lwip_accept4; -+ api->bind_fn = lwip_bind; -+ api->listen_fn = lwip_listen; -+ api->connect_fn = lwip_connect; -+ -+ api->setsockopt_fn = lwip_setsockopt; -+ api->getsockopt_fn = lwip_getsockopt; -+ api->getpeername_fn = lwip_getpeername; -+ api->getsockname_fn = lwip_getsockname; -+ -+ api->read_fn = lwip_read; -+ api->readv_fn = lwip_readv; -+ api->write_fn = lwip_write; -+ api->writev_fn = lwip_writev; -+ api->recv_fn = lwip_recv; -+ api->send_fn = lwip_send; -+ api->recvmsg_fn = (ssize_t (*)(int, const struct msghdr *, int))lwip_recvmsg; // TODO: fix unnecessary 'const' in lwipgz_posix_api.h -+ api->sendmsg_fn = lwip_sendmsg; -+ api->recvfrom_fn = lwip_recvfrom; -+ api->sendto_fn = lwip_sendto; -+ -+ api->epoll_ctl_fn = rtc_epoll_ctl; -+ api->epoll_create1_fn = rtc_epoll_create1; -+ api->epoll_create_fn = rtc_epoll_create; -+ api->epoll_wait_fn = rtc_epoll_wait; -+ -+ api->poll_fn = rtc_poll; -+ api->select_fn = rtc_select; -+} -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 09c4e11..d8634cc 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -10,23 +10,18 @@ - * See the Mulan PSL v2 for more details. - */ - --#include --#include --#include --#include -- - #include -+#include - - #include "lstack_thread_rpc.h" --#include "posix/lstack_epoll.h" -+#include "lstack_epoll.h" - #include "lstack_protocol_stack.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" - #include "common/gazelle_base_func.h" - #include "lstack_rtw_api.h" - -- --int rtw_socket(int domain, int type, int protocol) -+static int rtw_socket(int domain, int type, int protocol) - { - struct protocol_stack *stack = get_bind_protocol_stack(); - if (stack == NULL) { -@@ -35,17 +30,17 @@ int rtw_socket(int domain, int type, int protocol) - return rpc_call_socket(&stack->rpc_queue, domain, type, protocol); - } - --int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -+static int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) - { - return stack_broadcast_accept(s, addr, addrlen); - } - --int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) -+static int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) - { - return stack_broadcast_accept4(s, addr, addrlen, flags); - } - --int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) -+static int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) - { - struct lwip_sock *sock = lwip_get_socket(s); - -@@ -56,7 +51,7 @@ int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) - } - } - --int rtw_listen(int s, int backlog) -+static int rtw_listen(int s, int backlog) - { - if (!get_global_cfg_params()->tuple_filter && - !get_global_cfg_params()->listen_shadow) { -@@ -66,7 +61,7 @@ int rtw_listen(int s, int backlog) - } - } - --int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) -+static int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(s); - if (stack == NULL) { -@@ -75,7 +70,7 @@ int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) - return rpc_call_connect(&stack->rpc_queue, s, name, namelen); - } - --int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -+static int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(s); - if (stack == NULL) { -@@ -84,7 +79,7 @@ int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t - return rpc_call_setsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - --int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -+static int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(s); - if (stack == NULL) { -@@ -93,7 +88,7 @@ int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optle - return rpc_call_getsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - --int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -+static int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(s); - if (stack == NULL) { -@@ -102,7 +97,7 @@ int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) - return rpc_call_getpeername(&stack->rpc_queue, s, name, namelen); - } - --int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -+static int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) - { - struct protocol_stack *stack = get_protocol_stack_by_fd(s); - if (stack == NULL) { -@@ -111,12 +106,12 @@ int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) - return rpc_call_getsockname(&stack->rpc_queue, s, name, namelen); - } - --ssize_t rtw_read(int s, void *mem, size_t len) -+static ssize_t rtw_read(int s, void *mem, size_t len) - { - return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); - } - --ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) -+static ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) - { - struct msghdr msg; - -@@ -130,12 +125,12 @@ ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) - return do_lwip_recvmsg_from_stack(s, &msg, 0); - } - --ssize_t rtw_write(int s, const void *mem, size_t size) -+static ssize_t rtw_write(int s, const void *mem, size_t size) - { - return do_lwip_send_to_stack(s, mem, size, 0, NULL, 0); - } - --ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) -+static ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) - { - struct lwip_sock *sock = lwip_get_socket(s); - struct msghdr msg; -@@ -150,22 +145,22 @@ ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) - return do_lwip_sendmsg_to_stack(sock, s, &msg, 0); - } - --ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags) -+static ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags) - { - return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); - } - --ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags) -+static ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags) - { - return do_lwip_send_to_stack(sockfd, buf, len, flags, NULL, 0); - } - --ssize_t rtw_recvmsg(int s, const struct msghdr *message, int flags) -+static ssize_t rtw_recvmsg(int s, struct msghdr *message, int flags) - { - return do_lwip_recvmsg_from_stack(s, message, flags); - } - --ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags) -+static ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags) - { - struct lwip_sock *sock = lwip_get_socket(s); - return do_lwip_sendmsg_to_stack(sock, s, message, flags); -@@ -207,8 +202,8 @@ static inline ssize_t rtw_tcp_recvfrom(int sockfd, void *buf, size_t len, int fl - } - - --ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -- struct sockaddr *addr, socklen_t *addrlen) -+static ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -+ struct sockaddr *addr, socklen_t *addrlen) - { - struct lwip_sock *sock = lwip_get_socket(sockfd); - if (NETCONN_IS_UDP(sock)) { -@@ -218,28 +213,28 @@ ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, - } - } - --ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -- const struct sockaddr *addr, socklen_t addrlen) -+static ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -+ const struct sockaddr *addr, socklen_t addrlen) - { - return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); - } - --int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+static int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) - { - return lstack_rtw_epoll_wait(epfd, events, maxevents, timeout); - } - --int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) -+static int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) - { - return lstack_poll(fds, nfds, timeout); - } - --int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+static int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) - { - return lstack_select(nfds, readfds, writefds, exceptfds, timeout); - } - --int rtw_close(int s) -+static int rtw_close(int s) - { - struct lwip_sock *sock = lwip_get_socket(s); - if (sock && sock->wakeup && sock->wakeup->epollfd == s) { -@@ -248,7 +243,7 @@ int rtw_close(int s) - return stack_broadcast_close(s); - } - --int rtw_shutdown(int fd, int how) -+static int rtw_shutdown(int fd, int how) - { - struct lwip_sock *sock = lwip_get_socket(fd); - if (sock && sock->wakeup && sock->wakeup->epollfd == fd) { -@@ -258,18 +253,53 @@ int rtw_shutdown(int fd, int how) - return stack_broadcast_shutdown(fd, how); - } - --int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -+static int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { - return lstack_rtw_epoll_ctl(epfd, op, fd, event); - } - --int rtw_epoll_create1(int flags) -+static int rtw_epoll_create1(int flags) - { - return lstack_epoll_create1(flags); - } - --int rtw_epoll_create(int flags) -+static int rtw_epoll_create(int flags) - { - return lstack_epoll_create(flags); - } - -+void rtw_api_init(posix_api_t *api) -+{ -+ api->close_fn = rtw_close; -+ api->shutdown_fn = rtw_shutdown; -+ api->socket_fn = rtw_socket; -+ api->accept_fn = rtw_accept; -+ api->accept4_fn = rtw_accept4; -+ api->bind_fn = rtw_bind; -+ api->listen_fn = rtw_listen; -+ api->connect_fn = rtw_connect; -+ -+ api->setsockopt_fn = rtw_setsockopt; -+ api->getsockopt_fn = rtw_getsockopt; -+ api->getpeername_fn = rtw_getpeername; -+ api->getsockname_fn = rtw_getsockname; -+ -+ api->read_fn = rtw_read; -+ api->readv_fn = rtw_readv; -+ api->write_fn = rtw_write; -+ api->writev_fn = rtw_writev; -+ api->recv_fn = rtw_recv; -+ api->send_fn = rtw_send; -+ api->recvmsg_fn = (ssize_t (*)(int, const struct msghdr *, int))rtw_recvmsg; // TODO: fix unnecessary 'const' in lwipgz_posix_api.h -+ api->sendmsg_fn = rtw_sendmsg; -+ api->recvfrom_fn = rtw_recvfrom; -+ api->sendto_fn = rtw_sendto; -+ -+ api->epoll_ctl_fn = rtw_epoll_ctl; -+ api->epoll_create1_fn = rtw_epoll_create1; -+ api->epoll_create_fn = rtw_epoll_create; -+ api->epoll_wait_fn = rtw_epoll_wait; -+ -+ api->poll_fn = rtw_poll; -+ api->select_fn = rtw_select; -+} -\ No newline at end of file -diff --git a/src/lstack/api/lstack_signal.c b/src/lstack/api/lstack_unistd.c -similarity index 89% -rename from src/lstack/api/lstack_signal.c -rename to src/lstack/api/lstack_unistd.c -index 9d0431b..1f78626 100644 ---- a/src/lstack/api/lstack_signal.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -11,22 +11,22 @@ - */ - - #include --#include --#include - #include --#include -+#include -+ - #include - #include - -+#include "lstack_unistd.h" - #include "common/gazelle_base_func.h" --#include "lstack_cfg.h" --#include "common/dpdk_common.h" - #include "lstack_log.h" -+#include "lstack_cfg.h" - #include "lstack_control_plane.h" - - static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGKILL}; - #define HIJACK_SIGNAL_COUNT (sizeof(g_hijack_signal) / sizeof(g_hijack_signal[0])) - #define BACKTRACE_SIZE 64 -+ - static void dump_stack(void) - { - char **stack_trace = NULL; -@@ -71,17 +71,24 @@ static void lstack_sig_default_handler(int sig) - (void)kill(getpid(), sig); - } - --void lstack_signal_init(void) -+int lstack_signal_init(void) - { - unsigned int i; - struct sigaction action; - -+ /* to prevent crash, just ignore SIGPIPE when socket is closed */ -+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { -+ return -1; -+ } -+ - sigemptyset(&action.sa_mask); - action.sa_flags = (int)(SA_NODEFER | SA_RESETHAND); - action.sa_handler = lstack_sig_default_handler; - for (i = 0; i < HIJACK_SIGNAL_COUNT; i++) { - posix_api->sigaction_fn(g_hijack_signal[i], &action, NULL); - } -+ -+ return 0; - } - - int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigaction *old_action) -@@ -104,3 +111,15 @@ int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigacti - - return posix_api->sigaction_fn(sig_num, action, old_action); - } -+ -+pid_t lstack_fork(void) -+{ -+ pid_t pid; -+ -+ pid = posix_api->fork_fn(); -+ /* child not support lwip */ -+ if (pid == 0) { -+ posix_api->use_kernel = 1; -+ } -+ return pid; -+} -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 92ce73b..1d5529d 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -10,29 +10,22 @@ - * See the Mulan PSL v2 for more details. - */ - --#include --#include -+#include - #include -- --#include --#include - #include - #include --#include - #include --#include - - #include - #include - #include - --#include "posix/lstack_unistd.h" -+#include "common/gazelle_base_func.h" - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_lwip.h" --#include "common/gazelle_base_func.h" - #include "lstack_preload.h" -- -+#include "lstack_unistd.h" - #include "lstack_rtc_api.h" - #include "lstack_rtw_api.h" - #include "lstack_dummy_api.h" -@@ -45,78 +38,18 @@ void wrap_api_init(void) - if (g_wrap_api != NULL) { - return; - } -- - g_wrap_api = &g_wrap_api_value; -+ - if (get_global_cfg_params()->stack_mode_rtc) { -- g_wrap_api->socket_fn = rtc_socket; -- g_wrap_api->accept_fn = lwip_accept; -- g_wrap_api->accept4_fn = lwip_accept4; -- g_wrap_api->bind_fn = lwip_bind; -- g_wrap_api->listen_fn = lwip_listen; -- g_wrap_api->connect_fn = lwip_connect; -- g_wrap_api->setsockopt_fn = lwip_setsockopt; -- g_wrap_api->getsockopt_fn = lwip_getsockopt; -- g_wrap_api->getpeername_fn = lwip_getpeername; -- g_wrap_api->getsockname_fn = lwip_getsockname; -- g_wrap_api->read_fn = lwip_read; -- g_wrap_api->readv_fn = lwip_readv; -- g_wrap_api->write_fn = lwip_write; -- g_wrap_api->writev_fn = lwip_writev; -- g_wrap_api->recv_fn = lwip_recv; -- g_wrap_api->send_fn = lwip_send; -- g_wrap_api->recvmsg_fn = lwip_recvmsg; -- g_wrap_api->sendmsg_fn = lwip_sendmsg; -- g_wrap_api->recvfrom_fn = lwip_recvfrom; -- g_wrap_api->sendto_fn = lwip_sendto; -- g_wrap_api->epoll_wait_fn = rtc_epoll_wait; -- g_wrap_api->poll_fn = rtc_poll; -- g_wrap_api->close_fn = rtc_close; -- g_wrap_api->shutdown_fn = rtc_shutdown; -- g_wrap_api->epoll_ctl_fn = rtc_epoll_ctl; -- g_wrap_api->epoll_create1_fn = rtc_epoll_create1; -- g_wrap_api->epoll_create_fn = rtc_epoll_create; -- g_wrap_api->select_fn = rtc_select; -+ rtc_api_init(g_wrap_api); - } else { -- g_wrap_api->socket_fn = rtw_socket; -- g_wrap_api->accept_fn = rtw_accept; -- g_wrap_api->accept4_fn = rtw_accept4; -- g_wrap_api->bind_fn = rtw_bind; -- g_wrap_api->listen_fn = rtw_listen; -- g_wrap_api->connect_fn = rtw_connect; -- g_wrap_api->setsockopt_fn = rtw_setsockopt; -- g_wrap_api->getsockopt_fn = rtw_getsockopt; -- g_wrap_api->getpeername_fn = rtw_getpeername; -- g_wrap_api->getsockname_fn = rtw_getsockname; -- g_wrap_api->read_fn = rtw_read; -- g_wrap_api->readv_fn = rtw_readv; -- g_wrap_api->write_fn = rtw_write; -- g_wrap_api->writev_fn = rtw_writev; -- g_wrap_api->recv_fn = rtw_recv; -- g_wrap_api->send_fn = rtw_send; -- g_wrap_api->recvmsg_fn = rtw_recvmsg; -- g_wrap_api->sendmsg_fn = rtw_sendmsg; -- g_wrap_api->recvfrom_fn = rtw_recvfrom; -- g_wrap_api->sendto_fn = rtw_sendto; -- g_wrap_api->epoll_wait_fn = rtw_epoll_wait; -- g_wrap_api->poll_fn = rtw_poll; -- g_wrap_api->close_fn = rtw_close; -- g_wrap_api->shutdown_fn = rtw_shutdown; -- g_wrap_api->epoll_ctl_fn = rtw_epoll_ctl; -- g_wrap_api->epoll_create1_fn = rtw_epoll_create1; -- g_wrap_api->epoll_create_fn = rtw_epoll_create; -- g_wrap_api->select_fn = rtw_select; -- } --} -- --void wrap_api_set_dummy(void) --{ -- g_wrap_api->socket_fn = dummy_socket; -- g_wrap_api->send_fn = dummy_send; -- g_wrap_api->write_fn = dummy_write; -- g_wrap_api->writev_fn = dummy_writev; -- g_wrap_api->sendmsg_fn = dummy_sendmsg; -- g_wrap_api->sendto_fn = dummy_sendto; -- rte_wmb(); -+ rtw_api_init(g_wrap_api); -+ } -+} -+ -+void wrap_api_exit(void) -+{ -+ dummy_api_init(g_wrap_api); - } - - static inline int32_t do_epoll_create1(int32_t flags) -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index e0f7bd7..37264a1 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -20,27 +20,26 @@ - #include - #include - #include --#include - #include - #include - #include - #include - --#include -+#include -+ - #include - #include - #include - #include - -+#include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_control_plane.h" - #include "lstack_ethdev.h" - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" --#include "lstack_log.h" - #include "common/dpdk_common.h" --#include "posix/lstack_epoll.h" --#include "posix/lstack_unistd.h" -+#include "lstack_unistd.h" - #include "common/gazelle_base_func.h" - #include "lstack_protocol_stack.h" - #include "lstack_preload.h" -@@ -107,9 +106,7 @@ static int32_t check_process_conflict(void) - - void gazelle_exit(void) - { -- wrap_api_set_dummy(); -- /* 1: wait until app thread call send functio complete */ -- sleep(1); -+ wrap_api_exit(); - stack_group_exit(); - } - -@@ -170,18 +167,6 @@ static void create_control_thread(void) - LSTACK_LOG(INFO, LSTACK, "create control_easy_thread success\n"); - } - --static void gazelle_signal_init(void) --{ -- /* to prevent crash , just ignore SIGPIPE when socket is closed */ -- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { -- LSTACK_PRE_LOG(LSTACK_ERR, "signal error, errno:%d.", errno); -- LSTACK_EXIT(1, "signal SIGPIPE SIG_IGN\n"); -- } -- -- /* register core sig handler func to dumped stack */ -- lstack_signal_init(); --} -- - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - static void set_kni_ip_mac() - { -@@ -278,7 +263,11 @@ __attribute__((constructor)) void gazelle_network_init(void) - } - } - -- gazelle_signal_init(); -+ /* register core sig handler func to dumped stack */ -+ if (lstack_signal_init() != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "signal init failed, errno %d\n", errno); -+ LSTACK_EXIT(1, "signal init failed, errno %d\n", errno); -+ } - - /* Init control plane and dpdk init */ - create_control_thread(); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index a7b7202..89142a4 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -34,7 +34,7 @@ - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" --#include "posix/lstack_epoll.h" -+#include "lstack_epoll.h" - #include "lstack_thread_rpc.h" - #include "common/dpdk_common.h" - #include "lstack_cfg.h" -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 00900e7..f56e911 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -31,7 +31,7 @@ - #include "lstack_lwip.h" - #include "lstack_cfg.h" - #include "lstack_control_plane.h" --#include "posix/lstack_epoll.h" -+#include "lstack_epoll.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" - #include "lstack_protocol_stack.h" -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 406e27c..b6619f6 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -26,7 +26,7 @@ - #include "common/gazelle_dfx_msg.h" - #include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" --#include "posix/lstack_epoll.h" -+#include "lstack_epoll.h" - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" -diff --git a/src/lstack/include/posix/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -similarity index 100% -rename from src/lstack/include/posix/lstack_epoll.h -rename to src/lstack/include/lstack_epoll.h -diff --git a/src/lstack/include/lstack_rtc_api.h b/src/lstack/include/lstack_rtc_api.h -index 3a41e6f..b4b7e1c 100644 ---- a/src/lstack/include/lstack_rtc_api.h -+++ b/src/lstack/include/lstack_rtc_api.h -@@ -12,47 +12,14 @@ - - #ifndef _LSTACK_RTC_API_H_ - #define _LSTACK_RTC_API_H_ --#include --#include --#include -+ -+#include - - /* don't include lwip/sockets.h, conflict with sys/socket.h */ --/* extern lwip_api here */ - extern int lwip_fcntl(int s, int cmd, int val); --extern int lwip_ioctl(int s, long cmd, ...); --extern int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); --extern int lwip_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); --extern int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); --extern int lwip_shutdown(int s, int how); --extern int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen); --extern int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen); --extern int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); --extern int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); --extern int lwip_close(int s); --extern int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); --extern int lwip_listen(int s, int backlog); --extern ssize_t lwip_recv(int s, void *mem, size_t len, int flags); --extern ssize_t lwip_read(int s, void *mem, size_t len); --extern ssize_t lwip_readv(int s, const struct iovec *iov, int iovcnt); --extern ssize_t lwip_recvfrom(int s, void *mem, size_t len, int flags, -- struct sockaddr *from, socklen_t *fromlen); --extern ssize_t lwip_recvmsg(int s, const struct msghdr *message, int flags); --extern ssize_t lwip_send(int s, const void *dataptr, size_t size, int flags); --extern ssize_t lwip_sendmsg(int s, const struct msghdr *message, int flags); --extern ssize_t lwip_sendto(int s, const void *dataptr, size_t size, int flags, -- const struct sockaddr *to, socklen_t tolen); --extern int lwip_socket(int domain, int type, int protocol); --extern ssize_t lwip_write(int s, const void *dataptr, size_t size); --extern ssize_t lwip_writev(int s, const struct iovec *iov, int iovcnt); -+extern int lwip_ioctl(int s, long cmd, void *argp); - --int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout); --int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); --int rtc_socket(int domain, int type, int protocol); --int rtc_close(int s); --int rtc_shutdown(int fd, int how); --int rtc_epoll_create(int flags); --int rtc_epoll_create1(int flags); --int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); --int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -+void dummy_api_init(posix_api_t *api); -+void rtc_api_init(posix_api_t *api); - - #endif /* __LSTACK_RTC_API_H_ */ -diff --git a/src/lstack/include/lstack_rtw_api.h b/src/lstack/include/lstack_rtw_api.h -index a38b656..437901a 100644 ---- a/src/lstack/include/lstack_rtw_api.h -+++ b/src/lstack/include/lstack_rtw_api.h -@@ -13,39 +13,8 @@ - #ifndef _LSTACK_RTW_API_H_ - #define _LSTACK_RTW_API_H_ - --#include --#include --#include -+#include - --int rtw_socket(int domain, int type, int protocol); --int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen); --int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags); --int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen); --int rtw_listen(int s, int backlog); --int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen); --int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen); --int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); --int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen); --int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen); --ssize_t rtw_read(int s, void *mem, size_t len); --ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt); --ssize_t rtw_write(int s, const void *mem, size_t size); --ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt); --ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags); --ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags); --ssize_t rtw_recvmsg(int s, const struct msghdr *message, int flags); --ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags); --ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -- struct sockaddr *addr, socklen_t *addrlen); --ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -- const struct sockaddr *addr, socklen_t addrlen); --int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout); --int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout); --int rtw_close(int s); --int rtw_shutdown(int fd, int how); --int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); --int rtw_epoll_create1(int flags); --int rtw_epoll_create(int flags); --int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -+void rtw_api_init(posix_api_t *api); - - #endif /* _LSTACK_RTW_API_H_ */ -diff --git a/src/lstack/include/posix/lstack_unistd.h b/src/lstack/include/lstack_unistd.h -similarity index 78% -rename from src/lstack/include/posix/lstack_unistd.h -rename to src/lstack/include/lstack_unistd.h -index 484a792..3bcee5a 100644 ---- a/src/lstack/include/posix/lstack_unistd.h -+++ b/src/lstack/include/lstack_unistd.h -@@ -13,16 +13,11 @@ - #ifndef _GAZELLE_UNISTD_H_ - #define _GAZELLE_UNISTD_H_ - --#ifdef __cplusplus --extern "C" { --#endif -+#include -+#include - -+int lstack_signal_init(void); -+int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigaction *old_action); - pid_t lstack_fork(void); --void lstack_signal_init(void); --int lstack_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); -- --#ifdef __cplusplus --} --#endif - - #endif /* _GAZELLE_UNISTD_H_ */ -diff --git a/src/lstack/include/lstack_wrap.h b/src/lstack/include/lstack_wrap.h -index dab5222..a45b0d5 100644 ---- a/src/lstack/include/lstack_wrap.h -+++ b/src/lstack/include/lstack_wrap.h -@@ -14,7 +14,7 @@ - #define _LSTACK_WRAP_H_ - - void wrap_api_init(void); --void wrap_api_set_dummy(void); -+void wrap_api_exit(void); - - #endif - --- -2.33.0 - diff --git a/0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch b/0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch deleted file mode 100644 index 3cce58f..0000000 --- a/0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch +++ /dev/null @@ -1,2604 +0,0 @@ -From 7e4d7c638681df4f32c0d719c62b4e38ef69c1eb Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sat, 31 Aug 2024 14:51:41 +0800 -Subject: [PATCH] cleancode: move some API from stack to rpc and rtw - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 17 +- - src/lstack/api/lstack_rtc_api.c | 7 +- - src/lstack/api/lstack_rtw_api.c | 250 ++++++- - src/lstack/api/lstack_wrap.c | 1 - - src/lstack/core/lstack_dpdk.c | 5 +- - src/lstack/core/lstack_lwip.c | 47 +- - src/lstack/core/lstack_protocol_stack.c | 757 ++------------------- - src/lstack/core/lstack_thread_rpc.c | 610 +++++++++++++---- - src/lstack/include/lstack_dpdk.h | 33 +- - src/lstack/include/lstack_epoll.h | 12 +- - src/lstack/include/lstack_lwip.h | 9 +- - src/lstack/include/lstack_protocol_stack.h | 51 +- - src/lstack/include/lstack_rpc_proc.h | 47 -- - src/lstack/include/lstack_thread_rpc.h | 81 +-- - src/lstack/netif/lstack_ethdev.c | 56 ++ - 15 files changed, 927 insertions(+), 1056 deletions(-) - delete mode 100644 src/lstack/include/lstack_rpc_proc.h - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 1c13076..ce3d267 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -19,15 +19,9 @@ - #include - #include - --#include - #include --#include --#include --#include --#include - #include - --#include "lstack_ethdev.h" - #include "lstack_stack_stat.h" - #include "lstack_cfg.h" - #include "lstack_log.h" -@@ -306,6 +300,17 @@ int32_t lstack_epoll_create(int32_t flags) - return lstack_do_epoll_create(fd); - } - -+static void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct protocol_stack *stack = NULL; -+ -+ for (int32_t i = 0; i < stack_group->stack_num; i++) { -+ stack = stack_group->stacks[i]; -+ rpc_call_clean_epoll(&stack->rpc_queue, wakeup); -+ } -+} -+ - int32_t lstack_epoll_close(int32_t fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 7689c83..60d3b23 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -42,11 +42,6 @@ static int rtc_close(int s) - return lwip_close(s); - } - --static int rtc_shutdown(int fd, int how) --{ -- return lwip_shutdown(fd, how); --} -- - static int rtc_epoll_create(int flags) - { - if (stack_setup_app_thread() < 0) { -@@ -90,7 +85,7 @@ static int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *excep - void rtc_api_init(posix_api_t *api) - { - api->close_fn = rtc_close; -- api->shutdown_fn = rtc_shutdown; -+ api->shutdown_fn = lwip_shutdown; - api->socket_fn = rtc_socket; - api->accept_fn = lwip_accept; - api->accept4_fn = lwip_accept4; -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index d8634cc..7ceff20 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -13,14 +13,258 @@ - #include - #include - -+#include "common/gazelle_base_func.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" - #include "lstack_thread_rpc.h" --#include "lstack_epoll.h" - #include "lstack_protocol_stack.h" --#include "lstack_cfg.h" - #include "lstack_lwip.h" --#include "common/gazelle_base_func.h" -+#include "lstack_epoll.h" - #include "lstack_rtw_api.h" - -+/* when fd is listenfd, listenfd of all protocol stack thread will be closed */ -+static int stack_broadcast_close(int fd) -+{ -+ int ret = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (sock == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ do { -+ sock = sock->listen_next; -+ if (stack == NULL || rpc_call_close(&stack->rpc_queue, fd)) { -+ ret = -1; -+ } -+ -+ if (POSIX_IS_CLOSED(sock)) { -+ break; -+ } -+ fd = sock->conn->callback_arg.socket; -+ stack = get_protocol_stack_by_fd(fd); -+ } while (1); -+ -+ return ret; -+} -+ -+static int stack_broadcast_shutdown(int fd, int how) -+{ -+ int32_t ret = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (sock == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ do { -+ sock = sock->listen_next; -+ if (stack == NULL || rpc_call_shutdown(&stack->rpc_queue, fd, how)) { -+ ret = -1; -+ } -+ -+ if (POSIX_IS_CLOSED(sock)) { -+ break; -+ } -+ fd = sock->conn->callback_arg.socket; -+ stack = get_protocol_stack_by_fd(fd); -+ } while (1); -+ -+ return ret; -+} -+ -+/* choice one stack bind */ -+static int stack_single_bind(int fd, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_bind(&stack->rpc_queue, fd, name, namelen); -+} -+ -+/* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ -+static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -+ struct protocol_stack *stack = NULL; -+ int ret, clone_fd; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL || cur_stack == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ ret = rpc_call_bind(&cur_stack->rpc_queue, fd, name, namelen); -+ if (ret < 0) { -+ close(fd); -+ return ret; -+ } -+ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ for (int i = 0; i < stack_group->stack_num; ++i) { -+ stack = stack_group->stacks[i]; -+ if (stack != cur_stack) { -+ clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, name, namelen); -+ if (clone_fd < 0) { -+ stack_broadcast_close(fd); -+ return clone_fd; -+ } -+ } -+ } -+ return 0; -+} -+ -+static void inline del_accept_in_event(struct lwip_sock *sock) -+{ -+ pthread_spin_lock(&sock->wakeup->event_list_lock); -+ -+ if (!NETCONN_IS_ACCEPTIN(sock)) { -+ sock->events &= ~EPOLLIN; -+ if (sock->events == 0) { -+ list_del_node(&sock->event_list); -+ } -+ } -+ -+ pthread_spin_unlock(&sock->wakeup->event_list_lock); -+} -+ -+static struct lwip_sock *get_min_accept_sock(int fd) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ struct lwip_sock *min_sock = NULL; -+ -+ while (sock) { -+ if (!NETCONN_IS_ACCEPTIN(sock)) { -+ sock = sock->listen_next; -+ continue; -+ } -+ -+ if (min_sock == NULL || min_sock->stack->conn_num > sock->stack->conn_num) { -+ min_sock = sock; -+ } -+ -+ sock = sock->listen_next; -+ } -+ -+ return min_sock; -+} -+ -+/* ergodic the protocol stack thread to find the connection, because all threads are listening */ -+static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ int ret = -1; -+ struct lwip_sock *min_sock = NULL; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ struct protocol_stack *stack = NULL; -+ if (sock == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ if (netconn_is_nonblocking(sock->conn)) { -+ min_sock = get_min_accept_sock(fd); -+ } else { -+ while ((min_sock = get_min_accept_sock(fd)) == NULL) { -+ lstack_block_wait(sock->wakeup, 0); -+ } -+ } -+ -+ if (min_sock && min_sock->conn) { -+ stack = get_protocol_stack_by_fd(min_sock->conn->callback_arg.socket); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); -+ } -+ -+ if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) { -+ del_accept_in_event(min_sock); -+ } -+ -+ if (ret < 0) { -+ errno = EAGAIN; -+ } -+ return ret; -+} -+ -+static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ if (get_global_cfg_params()->nonblock_mode) -+ return stack_broadcast_accept4(fd, addr, addrlen, O_NONBLOCK); -+ else -+ return stack_broadcast_accept4(fd, addr, addrlen, 0); -+} -+ -+/* choice one stack listen */ -+static int stack_single_listen(int fd, int backlog) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_listen(&stack->rpc_queue, fd, backlog); -+} -+ -+/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ -+static int stack_broadcast_listen(int fd, int backlog) -+{ -+ typedef union sockaddr_union { -+ struct sockaddr sa; -+ struct sockaddr_in in; -+ struct sockaddr_in6 in6; -+ } sockaddr_t; -+ -+ struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -+ struct protocol_stack *stack = NULL; -+ sockaddr_t addr; -+ socklen_t addr_len = sizeof(addr); -+ int ret, clone_fd; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL || cur_stack == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ ret = rpc_call_getsockname(&cur_stack->rpc_queue, fd, (struct sockaddr *)&addr, &addr_len); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ int min_conn_stk_idx = get_min_conn_stack(stack_group); -+ -+ for (int32_t i = 0; i < stack_group->stack_num; ++i) { -+ stack = stack_group->stacks[i]; -+ if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -+ continue; -+ } -+ if (stack != cur_stack) { -+ clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, (struct sockaddr *)&addr, addr_len); -+ if (clone_fd < 0) { -+ stack_broadcast_close(fd); -+ return clone_fd; -+ } -+ } else { -+ clone_fd = fd; -+ } -+ -+ if (min_conn_stk_idx == i) { -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 1; -+ } else { -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 0; -+ } -+ -+ ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); -+ if (ret < 0) { -+ stack_broadcast_close(fd); -+ return ret; -+ } -+ } -+ return 0; -+} -+ - static int rtw_socket(int domain, int type, int protocol) - { - struct protocol_stack *stack = get_bind_protocol_stack(); -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 1d5529d..8f80f98 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - - #include - #include -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 50fbdf6..f87e362 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -43,7 +43,6 @@ - #include "lstack_log.h" - #include "common/dpdk_common.h" - #include "lstack_protocol_stack.h" --#include "lstack_thread_rpc.h" - #include "lstack_lwip.h" - #include "lstack_cfg.h" - #include "lstack_virtio.h" -@@ -765,9 +764,9 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count) - return 0; - } - --int32_t init_dpdk_ethdev(void) -+int init_dpdk_ethdev(void) - { -- int32_t ret; -+ int ret; - int slave_port_id[GAZELLE_MAX_BOND_NUM]; - int port_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 89142a4..3454961 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -29,15 +29,12 @@ - #include - - #include "common/gazelle_base_func.h" --#include "lstack_ethdev.h" --#include "lstack_protocol_stack.h" - #include "lstack_log.h" --#include "lstack_dpdk.h" -+#include "lstack_cfg.h" -+#include "lstack_protocol_stack.h" - #include "lstack_stack_stat.h" - #include "lstack_epoll.h" --#include "lstack_thread_rpc.h" --#include "common/dpdk_common.h" --#include "lstack_cfg.h" -+#include "lstack_dpdk.h" - #include "lstack_lwip.h" - - static const uint8_t fin_packet = 0; -@@ -841,43 +838,24 @@ ssize_t gazelle_same_node_ring_send(struct lwip_sock *sock, const void *buf, siz - return act_len; - } - --PER_THREAD uint16_t stack_sock_num[GAZELLE_MAX_STACK_NUM] = {0}; --PER_THREAD uint16_t max_sock_stack = 0; -- --static inline void thread_bind_stack(struct lwip_sock *sock) --{ -- if (likely(sock->already_bind_numa || !sock->stack)) { -- return; -- } -- sock->already_bind_numa = 1; -- -- if (get_global_cfg_params()->app_bind_numa == 0) { -- return; -- } -- -- stack_sock_num[sock->stack->stack_idx]++; -- if (stack_sock_num[sock->stack->stack_idx] > max_sock_stack) { -- max_sock_stack = stack_sock_num[sock->stack->stack_idx]; -- bind_to_stack_numa(sock->stack); -- } --} -- - 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) - { -+ struct lwip_sock *sock; - ssize_t send = 0; -- -+ - if (buf == NULL) { - GAZELLE_RETURN(EINVAL); - } -- - 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); -+ sock = lwip_get_socket(fd); -+ if (unlikely(sock->already_bind_numa == 0 && sock->stack)) { -+ thread_bind_stack(sock->stack); -+ sock->already_bind_numa = 1; -+ } - - if (sock->same_node_tx_ring != NULL) { - return gazelle_same_node_ring_send(sock, buf, len, flags); -@@ -1131,7 +1109,10 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - return -1; - } - -- thread_bind_stack(sock); -+ if (unlikely(sock->already_bind_numa == 0 && sock->stack)) { -+ thread_bind_stack(sock->stack); -+ sock->already_bind_numa = 1; -+ } - - if (sock->same_node_rx_ring != NULL) { - return gazelle_same_node_ring_recv(sock, buf, len, flags); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f56e911..bcca1a7 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -22,14 +22,12 @@ - #include - - #include "common/gazelle_base_func.h" --#include "lstack_thread_rpc.h" - #include "common/dpdk_common.h" - #include "lstack_log.h" -+#include "lstack_cfg.h" - #include "lstack_dpdk.h" - #include "lstack_ethdev.h" --#include "lstack_vdev.h" - #include "lstack_lwip.h" --#include "lstack_cfg.h" - #include "lstack_control_plane.h" - #include "lstack_epoll.h" - #include "lstack_stack_stat.h" -@@ -64,18 +62,6 @@ static void stack_wait_quit(struct protocol_stack *stack) - } - } - --void bind_to_stack_numa(struct protocol_stack *stack) --{ -- int32_t ret; -- pthread_t tid = pthread_self(); -- -- ret = pthread_setaffinity_np(tid, sizeof(stack->idle_cpuset), &stack->idle_cpuset); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "thread %d setaffinity to stack %hu failed\n", rte_gettid(), stack->queue_id); -- return; -- } --} -- - static inline void set_stack_idx(uint16_t idx) - { - g_stack_p = g_stack_group.stacks[idx]; -@@ -97,27 +83,6 @@ struct protocol_stack_group *get_protocol_stack_group(void) - return &g_stack_group; - } - --int get_min_conn_stack(struct protocol_stack_group *stack_group) --{ -- int min_conn_stk_idx = 0; -- int min_conn_num = GAZELLE_MAX_CLIENTS; -- for (int i = 0; i < stack_group->stack_num; i++) { -- struct protocol_stack* stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv) { -- if (!stack->is_send_thread && stack->conn_num < min_conn_num) { -- min_conn_stk_idx = i; -- min_conn_num = stack->conn_num; -- } -- } else { -- if (stack->conn_num < min_conn_num) { -- min_conn_stk_idx = i; -- min_conn_num = stack->conn_num; -- } -- } -- } -- return min_conn_stk_idx; --} -- - struct protocol_stack *get_protocol_stack(void) - { - return g_stack_p; -@@ -179,6 +144,57 @@ struct protocol_stack *get_bind_protocol_stack(void) - return stack_group->stacks[index]; - } - -+int get_min_conn_stack(struct protocol_stack_group *stack_group) -+{ -+ struct protocol_stack* stack; -+ int min_conn_stk_idx = 0; -+ int min_conn_num = GAZELLE_MAX_CLIENTS; -+ -+ for (int i = 0; i < stack_group->stack_num; i++) { -+ stack = stack_group->stacks[i]; -+ if (get_global_cfg_params()->seperate_send_recv) { -+ if (!stack->is_send_thread && stack->conn_num < min_conn_num) { -+ min_conn_stk_idx = i; -+ min_conn_num = stack->conn_num; -+ } -+ } else { -+ if (stack->conn_num < min_conn_num) { -+ min_conn_stk_idx = i; -+ min_conn_num = stack->conn_num; -+ } -+ } -+ } -+ return min_conn_stk_idx; -+} -+ -+void bind_to_stack_numa(struct protocol_stack *stack) -+{ -+ int32_t ret; -+ pthread_t tid = pthread_self(); -+ -+ ret = pthread_setaffinity_np(tid, sizeof(stack->idle_cpuset), &stack->idle_cpuset); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "thread %d setaffinity to stack %hu failed\n", rte_gettid(), stack->queue_id); -+ return; -+ } -+} -+ -+void thread_bind_stack(struct protocol_stack *stack) -+{ -+ static PER_THREAD uint16_t stack_sock_num[GAZELLE_MAX_STACK_NUM] = {0}; -+ static PER_THREAD uint16_t max_sock_stack = 0; -+ -+ if (get_global_cfg_params()->app_bind_numa == 0) { -+ return; -+ } -+ -+ stack_sock_num[stack->stack_idx]++; -+ if (stack_sock_num[stack->stack_idx] > max_sock_stack) { -+ max_sock_stack = stack_sock_num[stack->stack_idx]; -+ bind_to_stack_numa(stack); -+ } -+} -+ - static uint32_t get_protocol_traffic(struct protocol_stack *stack) - { - if (use_ltran()) { -@@ -232,6 +248,11 @@ void low_power_idling(struct protocol_stack *stack) - } - } - -+struct thread_params { -+ uint16_t queue_id; -+ uint16_t idx; -+}; -+ - static int32_t create_thread(void *arg, char *thread_name, stack_thread_func func) - { - /* thread may run slow, if arg is temp var maybe have relese */ -@@ -373,7 +394,7 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - return 0; - } - --void wait_sem_value(sem_t *sem, int32_t wait_value) -+static void wait_sem_value(sem_t *sem, int32_t wait_value) - { - int32_t sem_val; - do { -@@ -546,7 +567,7 @@ static void* gazelle_stack_thread(void *arg) - return NULL; - } - --int32_t stack_group_init_mempool(void) -+static int stack_group_init_mempool(void) - { - struct cfg_params *cfg_params = get_global_cfg_params(); - uint32_t total_mbufs = 0; -@@ -702,655 +723,9 @@ OUT2: - return -1; - } - --void stack_arp(struct rpc_msg *msg) --{ -- struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; -- struct protocol_stack *stack = get_protocol_stack(); -- -- eth_dev_recv(mbuf, stack); --} -- --void stack_socket(struct rpc_msg *msg) --{ -- msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -- if (msg->result < 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); -- } --} -- --void stack_close(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -- return; -- } -- -- msg->result = lwip_close(fd); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_shutdown(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- int how = msg->args[MSG_ARG_1].i; -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- return; -- } -- -- msg->result = lwip_shutdown(fd, how); -- if (msg->result != 0 && errno != ENOTCONN) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), fd, msg->result); -- } -- -- posix_api->shutdown_fn(fd, how); --} -- --void stack_bind(struct rpc_msg *msg) --{ -- msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].socklen); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_listen(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- int32_t backlog = msg->args[MSG_ARG_1].i; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- msg->result = -1; -- return; -- } -- -- /* new listen add to stack listen list */ -- msg->result = lwip_listen(fd, backlog); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_accept(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- msg->result = -1; -- struct protocol_stack *stack = get_protocol_stack(); -- -- int32_t accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); -- if (accept_fd < 0) { -- stack->stats.accept_fail++; -- LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -- return; -- } -- -- struct lwip_sock *sock = lwip_get_socket(accept_fd); -- if (sock == NULL || sock->stack == NULL) { -- lwip_close(accept_fd); -- LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -- return; -- } -- -- msg->result = accept_fd; -- sock->stack->conn_num++; -- if (rte_ring_count(sock->conn->recvmbox->ring)) { -- do_lwip_add_recvlist(accept_fd); -- } --} -- --void stack_connect(struct rpc_msg *msg) --{ -- msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].socklen); -- if (msg->result < 0) { -- msg->result = -errno; -- } --} -- --void stack_getpeername(struct rpc_msg *msg) --{ -- msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_getsockname(struct rpc_msg *msg) --{ -- msg->result = lwip_getsockname(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_getsockopt(struct rpc_msg *msg) --{ -- msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -- msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -- msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -- } --} -- --void stack_setsockopt(struct rpc_msg *msg) --{ -- msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -- msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].socklen); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -- msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -- } --} -- --void stack_fcntl(struct rpc_msg *msg) --{ -- msg->result = lwip_fcntl(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].l); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_ioctl(struct rpc_msg *msg) --{ -- msg->result = lwip_ioctl(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].l, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --void stack_recv(struct rpc_msg *msg) --{ -- msg->result = lwip_recv(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].size, -- msg->args[MSG_ARG_3].i); --} -- --void stack_tcp_send(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- size_t len = msg->args[MSG_ARG_1].size; -- struct protocol_stack *stack = get_protocol_stack(); -- int replenish_again; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- msg->result = -1; -- return; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -- -- replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); -- if (replenish_again < 0) { -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; -- } -- -- if (NETCONN_IS_DATAOUT(sock) || replenish_again > 0) { -- if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- return; -- } -- } -- -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; --} -- --void stack_udp_send(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- size_t len = msg->args[MSG_ARG_1].size; -- struct protocol_stack *stack = get_protocol_stack(); -- int replenish_again; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- msg->result = -1; -- return; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -- -- replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 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; --} -- --/* any protocol stack thread receives arp packet and sync it to other threads so that it can have the arp table */ --void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- struct rte_mbuf *mbuf_copy = NULL; -- struct protocol_stack *stack = NULL; -- int32_t ret; -- -- for (int32_t i = 0; i < stack_group->stack_num; i++) { -- stack = stack_group->stacks[i]; -- if (cur_stack == stack) { -- continue; -- } -- -- /* stack maybe not init in app thread yet */ -- if (stack == NULL || !(netif_is_up(&stack->netif))) { -- continue; -- } -- -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -- stack->stats.rx_allocmbuf_fail++; -- return; -- } -- copy_mbuf(mbuf_copy, mbuf); -- -- ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -- if (ret != 0) { -- rte_pktmbuf_free(mbuf_copy); -- return; -- } -- } --#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -- if (get_global_cfg_params()->kni_switch) { -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -- cur_stack->stats.rx_allocmbuf_fail++; -- return; -- } -- copy_mbuf(mbuf_copy, mbuf); -- kni_handle_tx(mbuf_copy); -- } --#endif -- if (get_global_cfg_params()->flow_bifurcation) { -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -- cur_stack->stats.rx_allocmbuf_fail++; -- return; -- } -- copy_mbuf(mbuf_copy, mbuf); -- virtio_tap_process_tx(cur_stack->queue_id, mbuf_copy); -- } -- return; --} -- --void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- struct protocol_stack *stack = NULL; -- -- for (int32_t i = 0; i < stack_group->stack_num; i++) { -- stack = stack_group->stacks[i]; -- rpc_call_clean_epoll(&stack->rpc_queue, wakeup); -- } --} -- --void stack_clean_epoll(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct wakeup_poll *wakeup = (struct wakeup_poll *)msg->args[MSG_ARG_0].p; -- -- list_del_node(&wakeup->wakeup_list[stack->stack_idx]); --} -- --void stack_mempool_size(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- -- msg->result = rte_mempool_avail_count(stack->rxtx_mbuf_pool); --} -- --void stack_create_shadow_fd(struct rpc_msg *msg) --{ -- int32_t fd = msg->args[MSG_ARG_0].i; -- struct sockaddr *addr = msg->args[MSG_ARG_1].p; -- socklen_t addr_len = msg->args[MSG_ARG_2].socklen; -- -- int32_t clone_fd = 0; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -- msg->result = -1; -- return; -- } -- -- int domain = addr->sa_family; -- int type = NETCONN_IS_UDP(sock) ? SOCK_DGRAM : SOCK_STREAM; -- clone_fd = lwip_socket(domain, type, 0); -- if (clone_fd < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = clone_fd; -- return; -- } -- -- struct lwip_sock *clone_sock = lwip_get_socket(clone_fd); -- if (clone_sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -- msg->result = -1; -- return; -- } -- -- do_lwip_clone_sockopt(clone_sock, sock); -- -- while (sock->listen_next) { -- sock = sock->listen_next; -- } -- sock->listen_next = clone_sock; -- -- int32_t ret = lwip_bind(clone_fd, addr, addr_len); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = ret; -- return; -- } -- -- msg->result = clone_fd; --} -- --void stack_replenish_sendring(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p; -- -- msg->result = do_lwip_replenish_sendring(stack, sock); -- if (msg->result == true) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- } --} -- --void stack_get_conntable(struct rpc_msg *msg) --{ -- struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -- uint32_t max_num = msg->args[MSG_ARG_1].u; -- -- msg->result = do_lwip_get_conntable(conn, max_num); --} -- --void stack_get_connnum(struct rpc_msg *msg) --{ -- msg->result = do_lwip_get_connnum(); --} -- --void stack_recvlist_count(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct list_node *list = &stack->recv_list; -- uint32_t count = 0; -- struct list_node *node; -- struct list_node *temp; -- -- list_for_each_node(node, temp, list) { -- count++; -- } -- -- msg->result = count; --} -- --/* when fd is listenfd, listenfd of all protocol stack thread will be closed */ --int32_t stack_broadcast_close(int32_t fd) --{ -- int32_t ret = 0; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- do { -- sock = sock->listen_next; -- if (stack == NULL || rpc_call_close(&stack->rpc_queue, fd)) { -- ret = -1; -- } -- -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -- fd = sock->conn->callback_arg.socket; -- stack = get_protocol_stack_by_fd(fd); -- } while (1); -- -- return ret; --} -- --int stack_broadcast_shutdown(int fd, int how) --{ -- int32_t ret = 0; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- do { -- sock = sock->listen_next; -- if (stack == NULL || rpc_call_shutdown(&stack->rpc_queue, fd, how)) { -- ret = -1; -- } -- -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -- fd = sock->conn->callback_arg.socket; -- stack = get_protocol_stack_by_fd(fd); -- } while (1); -- -- return ret; --} -- --/* choice one stack listen */ --int32_t stack_single_listen(int32_t fd, int32_t backlog) --{ -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (stack == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- return rpc_call_listen(&stack->rpc_queue, fd, backlog); --} -- --/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ --int32_t stack_broadcast_listen(int32_t fd, int32_t backlog) --{ -- typedef union sockaddr_union { -- struct sockaddr sa; -- struct sockaddr_in in; -- struct sockaddr_in6 in6; -- } sockaddr_t; -- -- struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -- struct protocol_stack *stack = NULL; -- sockaddr_t addr; -- socklen_t addr_len = sizeof(addr); -- int32_t ret, clone_fd; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || cur_stack == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -- GAZELLE_RETURN(EBADF); -- } -- -- ret = rpc_call_getsockname(&cur_stack->rpc_queue, fd, (struct sockaddr *)&addr, &addr_len); -- if (ret != 0) { -- return ret; -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- int min_conn_stk_idx = get_min_conn_stack(stack_group); -- -- for (int32_t i = 0; i < stack_group->stack_num; ++i) { -- stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -- continue; -- } -- if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, (struct sockaddr *)&addr, addr_len); -- if (clone_fd < 0) { -- stack_broadcast_close(fd); -- return clone_fd; -- } -- } else { -- clone_fd = fd; -- } -- -- if (min_conn_stk_idx == i) { -- lwip_get_socket(clone_fd)->conn->is_master_fd = 1; -- } else { -- lwip_get_socket(clone_fd)->conn->is_master_fd = 0; -- } -- -- ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); -- if (ret < 0) { -- stack_broadcast_close(fd); -- return ret; -- } -- } -- return 0; --} -- --static struct lwip_sock *get_min_accept_sock(int32_t fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct lwip_sock *min_sock = NULL; -- -- while (sock) { -- if (!NETCONN_IS_ACCEPTIN(sock)) { -- sock = sock->listen_next; -- continue; -- } -- -- if (min_sock == NULL || min_sock->stack->conn_num > sock->stack->conn_num) { -- min_sock = sock; -- } -- -- sock = sock->listen_next; -- } -- -- return min_sock; --} -- --static void inline del_accept_in_event(struct lwip_sock *sock) --{ -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- -- if (!NETCONN_IS_ACCEPTIN(sock)) { -- sock->events &= ~EPOLLIN; -- if (sock->events == 0) { -- list_del_node(&sock->event_list); -- } -- } -- -- pthread_spin_unlock(&sock->wakeup->event_list_lock); --} -- --/* choice one stack bind */ --int32_t stack_single_bind(int32_t fd, const struct sockaddr *name, socklen_t namelen) --{ -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (stack == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- return rpc_call_bind(&stack->rpc_queue, fd, name, namelen); --} -- --/* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ --int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t namelen) --{ -- struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -- struct protocol_stack *stack = NULL; -- int32_t ret, clone_fd; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || cur_stack == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -- GAZELLE_RETURN(EBADF); -- } -- -- ret = rpc_call_bind(&cur_stack->rpc_queue, fd, name, namelen); -- if (ret < 0) { -- close(fd); -- return ret; -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- for (int32_t i = 0; i < stack_group->stack_num; ++i) { -- stack = stack_group->stacks[i]; -- if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, name, namelen); -- if (clone_fd < 0) { -- stack_broadcast_close(fd); -- return clone_fd; -- } -- } -- } -- return 0; --} -- --/* ergodic the protocol stack thread to find the connection, because all threads are listening */ --int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *addrlen, int flags) --{ -- int32_t ret = -1; -- struct lwip_sock *min_sock = NULL; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = NULL; -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- if (netconn_is_nonblocking(sock->conn)) { -- min_sock = get_min_accept_sock(fd); -- } else { -- while ((min_sock = get_min_accept_sock(fd)) == NULL) { -- lstack_block_wait(sock->wakeup, 0); -- } -- } -- -- if (min_sock && min_sock->conn) { -- stack = get_protocol_stack_by_fd(min_sock->conn->callback_arg.socket); -- if (stack == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); -- } -- -- if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) { -- del_accept_in_event(min_sock); -- } -- -- if (ret < 0) { -- errno = EAGAIN; -- } -- return ret; --} -- --int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen) --{ -- if (get_global_cfg_params()->nonblock_mode) -- return stack_broadcast_accept4(fd, addr, addrlen, O_NONBLOCK); -- else -- return stack_broadcast_accept4(fd, addr, addrlen, 0); --} -- --static void stack_all_fds_close(void) -+void stack_exit(void) - { -+ /* close all fd */ - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { - struct lwip_sock *sock = lwip_get_socket(i); - if (!POSIX_IS_CLOSED(sock) && sock->stack == get_protocol_stack()) { -@@ -1359,16 +734,6 @@ static void stack_all_fds_close(void) - } - } - --static void stack_exit(void) --{ -- stack_all_fds_close(); --} -- --void stack_exit_by_rpc(struct rpc_msg *msg) --{ -- stack_exit(); --} -- - void stack_group_exit(void) - { - int i; -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 8ac06cb..3e9889a 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -13,22 +13,27 @@ - #include - #include - -+#include "lwip/lwipgz_posix_api.h" -+ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_dpdk.h" --#include "lstack_rpc_proc.h" - #include "lstack_stack_stat.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" -+#include "lstack_epoll.h" -+#include "lstack_lwip.h" - - static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; - static struct rpc_stats g_rpc_stats; -+ - struct rpc_stats *rpc_stats_get(void) - { - return &g_rpc_stats; - } - --static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) -+__rte_always_inline -+static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) - { - int ret; - struct rpc_msg *msg = NULL; -@@ -42,23 +47,11 @@ static inline __attribute__((always_inline)) struct rpc_msg *get_rpc_msg(struct - - static void rpc_msg_init(struct rpc_msg *msg, rpc_msg_func func, struct rpc_msg_pool *pool) - { -- msg->rpcpool = pool; -- pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); -- msg->func = func; -- msg->sync_flag = 1; -+ msg->func = func; -+ msg->rpcpool = pool; -+ msg->sync_flag = 1; - msg->recall_flag = 0; --} -- --static struct rpc_msg *rpc_msg_alloc_except(rpc_msg_func func) --{ -- struct rpc_msg *msg = calloc(1, sizeof(struct rpc_msg)); -- if (msg == NULL) { -- return NULL; -- } -- -- rpc_msg_init(msg, func, NULL); -- -- return msg; -+ pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); - } - - static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) -@@ -92,9 +85,27 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - return msg; - } - --static inline __attribute__((always_inline)) int32_t rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) -+__rte_always_inline -+static void rpc_msg_free(struct rpc_msg *msg) -+{ -+ pthread_spin_destroy(&msg->lock); -+ if (msg->rpcpool != NULL && msg->rpcpool->mempool != NULL) { -+ rte_mempool_put(msg->rpcpool->mempool, (void *)msg); -+ } else { -+ free(msg); -+ } -+} -+ -+__rte_always_inline -+static void rpc_call(rpc_queue *queue, struct rpc_msg *msg) - { -- int32_t ret; -+ lockless_queue_mpsc_push(queue, &msg->queue_node); -+} -+ -+__rte_always_inline -+static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) -+{ -+ int ret; - - pthread_spin_trylock(&msg->lock); - rpc_call(queue, msg); -@@ -107,12 +118,39 @@ static inline __attribute__((always_inline)) int32_t rpc_sync_call(rpc_queue *qu - return ret; - } - --int32_t rpc_msgcnt(rpc_queue *queue) -+int rpc_msgcnt(rpc_queue *queue) - { - return lockless_queue_count(queue); - } - --int rpc_poll_msg(rpc_queue *queue, uint32_t max_num) -+static struct rpc_msg *rpc_msg_alloc_except(rpc_msg_func func) -+{ -+ struct rpc_msg *msg = calloc(1, sizeof(struct rpc_msg)); -+ if (msg == NULL) { -+ return NULL; -+ } -+ -+ rpc_msg_init(msg, func, NULL); -+ return msg; -+} -+ -+static void stack_exit_by_rpc(struct rpc_msg *msg) -+{ -+ stack_exit(); -+} -+ -+int rpc_call_stack_exit(rpc_queue *queue) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc_except(stack_exit_by_rpc); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ rpc_call(queue, msg); -+ return 0; -+} -+ -+int rpc_poll_msg(rpc_queue *queue, int max_num) - { - int force_quit = 0; - struct rpc_msg *msg = NULL; -@@ -149,101 +187,165 @@ int rpc_poll_msg(rpc_queue *queue, uint32_t max_num) - return force_quit; - } - --int32_t rpc_call_conntable(rpc_queue *queue, void *conn_table, uint32_t max_conn) -+ -+static void callback_socket(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_get_conntable); -- if (msg == NULL) { -- return -1; -+ msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -+ if (msg->result < 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); - } -- -- msg->args[MSG_ARG_0].p = conn_table; -- msg->args[MSG_ARG_1].u = max_conn; -- -- return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_connnum(rpc_queue *queue) -+static void callback_close(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_get_connnum); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -+ return; - } - -- return rpc_sync_call(queue, msg); -+ msg->result = lwip_close(fd); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ } - } - --int32_t rpc_call_shadow_fd(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) -+static void callback_shutdown(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_create_shadow_fd); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ int how = msg->args[MSG_ARG_1].i; -+ struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); -+ return; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].socklen = addrlen; -+ msg->result = lwip_shutdown(fd, how); -+ if (msg->result != 0 && errno != ENOTCONN) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), fd, msg->result); -+ } - -- return rpc_sync_call(queue, msg); -+ posix_api->shutdown_fn(fd, how); - } - --int32_t rpc_call_thread_regphase1(rpc_queue *queue, void *conn) -+static void callback_bind(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase1); -- if (msg == NULL) { -- return -1; -+ msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].socklen); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } -- msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_thread_regphase2(rpc_queue *queue, void *conn) -+static void callback_listen(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase2); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ int backlog = msg->args[MSG_ARG_1].i; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ msg->result = -1; -+ return; -+ } -+ -+ /* new listen add to stack listen list */ -+ msg->result = lwip_listen(fd, backlog); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } -- msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_mbufpoolsize(rpc_queue *queue) -+static void callback_create_shadow_fd(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_mempool_size); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ struct sockaddr *addr = msg->args[MSG_ARG_1].p; -+ socklen_t addr_len = msg->args[MSG_ARG_2].socklen; -+ -+ int clone_fd = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -+ msg->result = -1; -+ return; - } - -- return rpc_sync_call(queue, msg); --} -+ int domain = addr->sa_family; -+ int type = NETCONN_IS_UDP(sock) ? SOCK_DGRAM : SOCK_STREAM; -+ clone_fd = lwip_socket(domain, type, 0); -+ if (clone_fd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = clone_fd; -+ return; -+ } - --int32_t rpc_call_recvlistcnt(rpc_queue *queue) --{ -- struct rpc_msg *msg = rpc_msg_alloc(stack_recvlist_count); -- if (msg == NULL) { -- return -1; -+ struct lwip_sock *clone_sock = lwip_get_socket(clone_fd); -+ if (clone_sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -+ msg->result = -1; -+ return; - } - -- return rpc_sync_call(queue, msg); -+ do_lwip_clone_sockopt(clone_sock, sock); -+ -+ while (sock->listen_next) { -+ sock = sock->listen_next; -+ } -+ sock->listen_next = clone_sock; -+ -+ int ret = lwip_bind(clone_fd, addr, addr_len); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = ret; -+ return; -+ } -+ -+ msg->result = clone_fd; - } - --int32_t rpc_call_arp(rpc_queue *queue, void *mbuf) -+static void callback_accept(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_arp); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ msg->result = -1; -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ int accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); -+ if (accept_fd < 0) { -+ stack->stats.accept_fail++; -+ LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -+ return; - } - -- msg->sync_flag = 0; -- msg->args[MSG_ARG_0].p = mbuf; -+ struct lwip_sock *sock = lwip_get_socket(accept_fd); -+ if (sock == NULL || sock->stack == NULL) { -+ lwip_close(accept_fd); -+ LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -+ return; -+ } - -- rpc_call(queue, msg); -+ msg->result = accept_fd; -+ sock->stack->conn_num++; -+ if (rte_ring_count(sock->conn->recvmbox->ring)) { -+ do_lwip_add_recvlist(accept_fd); -+ } -+} - -- return 0; -+static void callback_connect(struct rpc_msg *msg) -+{ -+ msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].socklen); -+ if (msg->result < 0) { -+ msg->result = -errno; -+ } - } - --int32_t rpc_call_socket(rpc_queue *queue, int32_t domain, int32_t type, int32_t protocol) -+int rpc_call_socket(rpc_queue *queue, int domain, int type, int protocol) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_socket); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_socket); - if (msg == NULL) { - return -1; - } -@@ -255,9 +357,9 @@ int32_t rpc_call_socket(rpc_queue *queue, int32_t domain, int32_t type, int32_t - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_close(rpc_queue *queue, int fd) -+int rpc_call_close(rpc_queue *queue, int fd) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_close); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_close); - if (msg == NULL) { - return -1; - } -@@ -267,20 +369,9 @@ int32_t rpc_call_close(rpc_queue *queue, int fd) - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_stack_exit(rpc_queue *queue) -+int rpc_call_shutdown(rpc_queue *queue, int fd, int how) - { -- struct rpc_msg *msg = rpc_msg_alloc_except(stack_exit_by_rpc); -- if (msg == NULL) { -- return -1; -- } -- -- rpc_call(queue, msg); -- return 0; --} -- --int32_t rpc_call_shutdown(rpc_queue *queue, int fd, int how) --{ -- struct rpc_msg *msg = rpc_msg_alloc(stack_shutdown); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_shutdown); - if (msg == NULL) { - return -1; - } -@@ -291,48 +382,50 @@ int32_t rpc_call_shutdown(rpc_queue *queue, int fd, int how) - return rpc_sync_call(queue, msg); - } - --void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) -+int rpc_call_bind(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_clean_epoll); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_bind); - if (msg == NULL) { -- return; -+ return -1; - } - -- msg->args[MSG_ARG_0].p = wakeup; -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].cp = addr; -+ msg->args[MSG_ARG_2].socklen = addrlen; - -- rpc_sync_call(queue, msg); -+ return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_bind(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen) -+int rpc_call_listen(rpc_queue *queue, int s, int backlog) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_bind); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_listen); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].socklen = addrlen; -+ msg->args[MSG_ARG_0].i = s; -+ msg->args[MSG_ARG_1].i = backlog; - - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_listen(rpc_queue *queue, int s, int backlog) -+int rpc_call_shadow_fd(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_listen); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_create_shadow_fd); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].i = s; -- msg->args[MSG_ARG_1].i = backlog; -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].cp = addr; -+ msg->args[MSG_ARG_2].socklen = addrlen; - - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -+int rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_accept); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_accept); - if (msg == NULL) { - return -1; - } -@@ -345,9 +438,9 @@ int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) -+int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_connect); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_connect); - if (msg == NULL) { - return -1; - } -@@ -356,7 +449,7 @@ int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, - msg->args[MSG_ARG_1].cp = addr; - msg->args[MSG_ARG_2].socklen = addrlen; - -- int32_t ret = rpc_sync_call(queue, msg); -+ int ret = rpc_sync_call(queue, msg); - if (ret < 0) { - errno = -ret; - return -1; -@@ -364,9 +457,45 @@ int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, - return ret; - } - --int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) -+static void callback_getpeername(struct rpc_msg *msg) -+{ -+ msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static void callback_getsockname(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_getpeername); -+ msg->result = lwip_getsockname(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static void callback_getsockopt(struct rpc_msg *msg) -+{ -+ msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -+ msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -+ } -+} -+ -+static void callback_setsockopt(struct rpc_msg *msg) -+{ -+ msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -+ msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].socklen); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -+ } -+} -+ -+int rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_getpeername); - if (msg == NULL) { - return -1; - } -@@ -378,9 +507,9 @@ int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, so - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) -+int rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_getsockname); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_getsockname); - if (msg == NULL) { - return -1; - } -@@ -392,9 +521,9 @@ int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, so - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen) -+int rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_getsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_getsockopt); - if (msg == NULL) { - return -1; - } -@@ -408,9 +537,9 @@ int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, vo - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen) -+int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_setsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_setsockopt); - if (msg == NULL) { - return -1; - } -@@ -424,51 +553,91 @@ int32_t rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, co - return rpc_sync_call(queue, msg); - } - --int32_t rpc_call_fcntl(rpc_queue *queue, int fd, int cmd, long val) -+static void callback_tcp_send(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_fcntl); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ size_t len = msg->args[MSG_ARG_1].size; -+ struct protocol_stack *stack = get_protocol_stack(); -+ int replenish_again; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ msg->result = -1; -+ return; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].i = cmd; -- msg->args[MSG_ARG_2].l = val; -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ } - -- return rpc_sync_call(queue, msg); -+ replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); -+ if (replenish_again < 0) { -+ __sync_fetch_and_sub(&sock->call_num, 1); -+ return; -+ } -+ -+ if (NETCONN_IS_DATAOUT(sock) || replenish_again > 0) { -+ if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); -+ return; -+ } -+ } -+ -+ __sync_fetch_and_sub(&sock->call_num, 1); -+ return; - } - --int32_t rpc_call_ioctl(rpc_queue *queue, int fd, long cmd, void *argp) -+static void callback_udp_send(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_ioctl); -- if (msg == NULL) { -- return -1; -+ int fd = msg->args[MSG_ARG_0].i; -+ size_t len = msg->args[MSG_ARG_1].size; -+ struct protocol_stack *stack = get_protocol_stack(); -+ int replenish_again; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ msg->result = -1; -+ return; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].l = cmd; -- msg->args[MSG_ARG_2].p = argp; -+ if (get_protocol_stack_group()->latency_start) { -+ calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ } - -- return rpc_sync_call(queue, msg); -+ replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 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; - } - --int32_t rpc_call_replenish(rpc_queue *queue, void *sock) -+int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_replenish_sendring); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_udp_send); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].p = sock; -+ if (get_protocol_stack_group()->latency_start) { -+ time_stamp_into_rpcmsg(lwip_get_socket(fd)); -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].size = len; -+ msg->args[MSG_ARG_2].i = flags; - msg->sync_flag = 0; - - rpc_call(queue, msg); - return 0; - } - --int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) -+int rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_tcp_send); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_tcp_send); - if (msg == NULL) { - return -1; - } -@@ -483,28 +652,173 @@ int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) - msg->sync_flag = 0; - - rpc_call(queue, msg); -+ return 0; -+} -+ -+static void callback_replenish_sendring(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p; -+ -+ msg->result = do_lwip_replenish_sendring(stack, sock); -+ if (msg->result == true) { -+ msg->recall_flag = 1; -+ rpc_call(&stack->rpc_queue, msg); -+ } -+} -+ -+int rpc_call_replenish(rpc_queue *queue, void *sock) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_replenish_sendring); -+ if (msg == NULL) { -+ return -1; -+ } - -+ msg->args[MSG_ARG_0].p = sock; -+ msg->sync_flag = 0; -+ -+ rpc_call(queue, msg); - return 0; - } - --int32_t rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) -+static void callback_recvlist_count(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct list_node *list = &stack->recv_list; -+ int count = 0; -+ struct list_node *node; -+ struct list_node *temp; -+ -+ list_for_each_node(node, temp, list) { -+ count++; -+ } -+ msg->result = count; -+} -+ -+int rpc_call_recvlistcnt(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc(stack_udp_send); -+ struct rpc_msg *msg = rpc_msg_alloc(callback_recvlist_count); - if (msg == NULL) { - return -1; - } - -- if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(lwip_get_socket(fd)); -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_clean_epoll(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct wakeup_poll *wakeup = (struct wakeup_poll *)msg->args[MSG_ARG_0].p; -+ -+ list_del_node(&wakeup->wakeup_list[stack->stack_idx]); -+} -+ -+void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_clean_epoll); -+ if (msg == NULL) { -+ return; -+ } -+ -+ msg->args[MSG_ARG_0].p = wakeup; -+ -+ rpc_sync_call(queue, msg); -+} -+ -+static void callback_arp(struct rpc_msg *msg) -+{ -+ struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ eth_dev_recv(mbuf, stack); -+} -+ -+int rpc_call_arp(rpc_queue *queue, void *mbuf) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_arp); -+ if (msg == NULL) { -+ return -1; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].size = len; -- msg->args[MSG_ARG_2].i = flags; - msg->sync_flag = 0; -+ msg->args[MSG_ARG_0].p = mbuf; - - rpc_call(queue, msg); - - return 0; - } - -+static void callback_mempool_size(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ msg->result = rte_mempool_avail_count(stack->rxtx_mbuf_pool); -+} -+ -+static void callback_get_conntable(struct rpc_msg *msg) -+{ -+ struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -+ unsigned max_num = msg->args[MSG_ARG_1].u; -+ -+ msg->result = do_lwip_get_conntable(conn, max_num); -+} -+ -+static void callback_get_connnum(struct rpc_msg *msg) -+{ -+ msg->result = do_lwip_get_connnum(); -+} -+ -+int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_get_conntable); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].p = conn_table; -+ msg->args[MSG_ARG_1].u = max_conn; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+int rpc_call_connnum(rpc_queue *queue) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_get_connnum); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+int rpc_call_mbufpoolsize(rpc_queue *queue) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(callback_mempool_size); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+extern void thread_register_phase1(struct rpc_msg *msg); -+int rpc_call_thread_regphase1(rpc_queue *queue, void *conn) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase1); -+ if (msg == NULL) { -+ return -1; -+ } -+ msg->args[MSG_ARG_0].p = conn; -+ return rpc_sync_call(queue, msg); -+} -+ -+extern void thread_register_phase2(struct rpc_msg *msg); -+int rpc_call_thread_regphase2(rpc_queue *queue, void *conn) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase2); -+ if (msg == NULL) { -+ return -1; -+ } -+ msg->args[MSG_ARG_0].p = conn; -+ return rpc_sync_call(queue, msg); -+} -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index d058409..965a0cb 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -13,7 +13,10 @@ - #ifndef _GAZELLE_DPDK_H_ - #define _GAZELLE_DPDK_H_ - --#include -+#include -+#include -+#include -+ - #include "common/gazelle_opt.h" - #include "common/gazelle_dfx_msg.h" - -@@ -32,32 +35,34 @@ - */ - #define MBUF_MAX_NUM 0xfffffff - -+struct protocol_stack; -+ -+int32_t dpdk_eal_init(void); -+void lstack_log_level_init(void); -+ -+int dpdk_ethdev_init(int port_id); -+int dpdk_ethdev_start(void); -+int init_dpdk_ethdev(void); -+ - int thread_affinity_default(void); - int thread_affinity_init(int cpu_id); - --struct protocol_stack; --struct rte_mempool; --struct rte_ring; --struct rte_mbuf; -+int32_t create_shared_ring(struct protocol_stack *stack); - int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num); --int32_t dpdk_eal_init(void); - int32_t pktmbuf_pool_init(struct protocol_stack *stack); - struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t size, - uint32_t flags, int32_t idx); --int32_t create_shared_ring(struct protocol_stack *stack); --void lstack_log_level_init(void); --int dpdk_ethdev_init(int port_id); --int dpdk_ethdev_start(void); -+struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -+ uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); -+int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve); -+ - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void); - void dpdk_restore_pci(void); - #endif - int32_t dpdk_init_lstack_kni(void); --bool port_in_stack_queue(gz_addr_t *src_ip, gz_addr_t *dst_ip, uint16_t src_port, uint16_t dst_port); --struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -- uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); - - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); --int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve); - void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); -+ - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 6e02615..e7ae26b 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -19,14 +19,11 @@ - #include - - #include -+#include - - #include "common/gazelle_dfx_msg.h" - #include "common/gazelle_opt.h" - --#ifdef __cplusplus --extern "C" { --#endif -- - enum wakeup_type { - WAKEUP_EPOLL = 0, - WAKEUP_POLL, -@@ -61,9 +58,6 @@ struct wakeup_poll { - pthread_spinlock_t event_list_lock; - }; - --struct netconn; --struct lwip_sock; -- - void add_sock_event(struct lwip_sock *sock, uint32_t event); - void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event); - void del_sock_event(struct lwip_sock *sock, uint32_t event); -@@ -91,8 +85,4 @@ static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) - } - } - --#ifdef __cplusplus --} --#endif -- - #endif /* _GAZELLE_EPOLL_H_ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index b972f11..0c7bb62 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -15,8 +15,12 @@ - #include - - #include "common/gazelle_dfx_msg.h" -+#include "common/dpdk_common.h" - - struct lwip_sock; -+struct rpc_msg; -+struct protocol_stack; -+ - unsigned same_node_ring_count(struct lwip_sock *sock); - - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) -@@ -25,11 +29,6 @@ unsigned same_node_ring_count(struct lwip_sock *sock); - #define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) - --struct rte_mempool; --struct rpc_msg; --struct rte_mbuf; --struct protocol_stack; -- - void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); - - struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 7dce757..fdd5388 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -17,6 +17,10 @@ - #include - #include - -+#include -+#include -+#include -+ - #include - #include - -@@ -35,10 +39,6 @@ - - #define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->nic.rxqueue_size + 1024) - --struct rte_mempool; --struct rte_ring; --struct rte_mbuf; -- - struct protocol_stack { - uint32_t tid; - uint16_t queue_id; -@@ -111,50 +111,23 @@ struct protocol_stack_group { - }; - - long get_stack_tid(void); -+ - struct protocol_stack *get_protocol_stack(void); - struct protocol_stack *get_protocol_stack_by_fd(int32_t fd); - struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - -+int get_min_conn_stack(struct protocol_stack_group *stack_group); -+void bind_to_stack_numa(struct protocol_stack *stack); -+void thread_bind_stack(struct protocol_stack *stack); -+ - int32_t stack_group_init(void); - void stack_group_exit(void); -+void stack_exit(void); -+ - int32_t stack_setup_thread(void); - int32_t stack_setup_app_thread(void); - --void bind_to_stack_numa(struct protocol_stack *stack); --int32_t init_dpdk_ethdev(void); -- --void wait_sem_value(sem_t *sem, int32_t wait_value); -- --/* any protocol stack thread receives arp packet and sync it to other threads so that it can have the arp table */ --void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack); -- --/* when fd is listenfd, listenfd of all protocol stack thread will be closed */ --int32_t stack_broadcast_close(int32_t fd); -- --int stack_broadcast_shutdown(int fd, int how); -- --/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ --int32_t stack_broadcast_listen(int32_t fd, int backlog); --int32_t stack_single_listen(int32_t fd, int32_t backlog); -- --/* bind sync to all protocol stack thread, only for udp protocol */ --int32_t stack_broadcast_bind(int32_t fd, const struct sockaddr *name, socklen_t namelen); --int32_t stack_single_bind(int32_t fd, const struct sockaddr *name, socklen_t namelen); -- --/* ergodic the protocol stack thread to find the connection, because all threads are listening */ --int32_t stack_broadcast_accept(int32_t fd, struct sockaddr *addr, socklen_t *addrlen); --int32_t stack_broadcast_accept4(int32_t fd, struct sockaddr *addr, socklen_t *addrlen, int32_t flags); -- --struct wakeup_poll; --void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup); -- --void stack_send_pkts(struct protocol_stack *stack); -- --struct thread_params { -- uint16_t queue_id; -- uint16_t idx; --}; -- - int stack_polling(uint32_t wakeup_tick); -+ - #endif -diff --git a/src/lstack/include/lstack_rpc_proc.h b/src/lstack/include/lstack_rpc_proc.h -deleted file mode 100644 -index 77b18bd..0000000 ---- a/src/lstack/include/lstack_rpc_proc.h -+++ /dev/null -@@ -1,47 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#ifndef __GAZELLE_RPC_PROC_H__ --#define __GAZELLE_RPC_PROC_H__ --#include "lstack_thread_rpc.h" -- --void stack_clean_epoll(struct rpc_msg *msg); --void stack_arp(struct rpc_msg *msg); --void stack_socket(struct rpc_msg *msg); --void stack_close(struct rpc_msg *msg); --void stack_shutdown(struct rpc_msg *msg); --void stack_bind(struct rpc_msg *msg); --void stack_listen(struct rpc_msg *msg); --void stack_accept(struct rpc_msg *msg); --void stack_connect(struct rpc_msg *msg); --void stack_recv(struct rpc_msg *msg); --void stack_getpeername(struct rpc_msg *msg); --void stack_getsockname(struct rpc_msg *msg); --void stack_getsockopt(struct rpc_msg *msg); --void stack_setsockopt(struct rpc_msg *msg); --void stack_fcntl(struct rpc_msg *msg); --void stack_ioctl(struct rpc_msg *msg); --void stack_tcp_send(struct rpc_msg *msg); --void stack_udp_send(struct rpc_msg *msg); --void stack_mempool_size(struct rpc_msg *msg); --void stack_rpcpool_size(struct rpc_msg *msg); --void stack_create_shadow_fd(struct rpc_msg *msg); --void stack_replenish_sendring(struct rpc_msg *msg); --void stack_get_conntable(struct rpc_msg *msg); --void stack_get_connnum(struct rpc_msg *msg); --void stack_recvlist_count(struct rpc_msg *msg); --void stack_exit_by_rpc(struct rpc_msg *msg); -- --void thread_register_phase1(struct rpc_msg *msg); --void thread_register_phase2(struct rpc_msg *msg); -- --#endif -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index d268366..c2654bb 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -35,8 +35,8 @@ struct rpc_stats { - struct rpc_msg; - typedef void (*rpc_msg_func)(struct rpc_msg *msg); - union rpc_msg_arg { -- int32_t i; -- uint32_t u; -+ int i; -+ unsigned int u; - long l; - unsigned long ul; - void *p; -@@ -63,50 +63,43 @@ static inline void rpc_queue_init(rpc_queue *queue) - { - lockless_queue_init(queue); - } -- - struct rpc_stats *rpc_stats_get(void); --int32_t rpc_msgcnt(rpc_queue *queue); --int rpc_poll_msg(rpc_queue *queue, uint32_t max_num); -+int rpc_msgcnt(rpc_queue *queue); -+int rpc_poll_msg(rpc_queue *queue, int max_num); -+ -+int rpc_call_stack_exit(rpc_queue *queue); -+ -+/* #include will conflict with lwip/sockets.h */ -+struct sockaddr; -+ -+int rpc_call_close(rpc_queue *queue, int fd); -+int rpc_call_shutdown(rpc_queue *queue, int fd, int how); -+int rpc_call_socket(rpc_queue *queue, int domain, int type, int protocol); -+int rpc_call_bind(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); -+int rpc_call_listen(rpc_queue *queue, int s, int backlog); -+int rpc_call_shadow_fd(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); -+int rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); -+int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); -+ -+int rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); -+int rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); -+int rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen); -+int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen); -+ -+int rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags); -+int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); -+ -+int rpc_call_replenish(rpc_queue *queue, void *sock); -+int rpc_call_recvlistcnt(rpc_queue *queue); -+ - void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup); --int32_t rpc_call_shadow_fd(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_recvlistcnt(rpc_queue *queue); --int32_t rpc_call_thread_regphase1(rpc_queue *queue, void *conn); --int32_t rpc_call_thread_regphase2(rpc_queue *queue, void *conn); --int32_t rpc_call_conntable(rpc_queue *queue, void *conn_table, uint32_t max_conn); --int32_t rpc_call_connnum(rpc_queue *queue); --int32_t rpc_call_arp(rpc_queue *queue, void *mbuf); --int32_t rpc_call_socket(rpc_queue *queue, int32_t domain, int32_t type, int32_t protocol); --int32_t rpc_call_close(rpc_queue *queue, int32_t fd); --int32_t rpc_call_shutdown(rpc_queue *queue, int fd, int how); --int32_t rpc_call_bind(rpc_queue *queue, int32_t fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_listen(rpc_queue *queue, int s, int backlog); --int32_t rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); --int32_t rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); --int32_t rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags); --int32_t rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); --int32_t rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); --int32_t rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); --int32_t rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen); --int32_t rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen); --int32_t rpc_call_fcntl(rpc_queue *queue, int fd, int cmd, long val); --int32_t rpc_call_ioctl(rpc_queue *queue, int fd, long cmd, void *argp); --int32_t rpc_call_replenish(rpc_queue *queue, void *sock); --int32_t rpc_call_mbufpoolsize(rpc_queue *queue); --int32_t rpc_call_stack_exit(rpc_queue *queue); -- --static inline __attribute__((always_inline)) void rpc_call(rpc_queue *queue, struct rpc_msg *msg) --{ -- lockless_queue_mpsc_push(queue, &msg->queue_node); --} -+int rpc_call_arp(rpc_queue *queue, void *mbuf); - --static inline __attribute__((always_inline)) void rpc_msg_free(struct rpc_msg *msg) --{ -- pthread_spin_destroy(&msg->lock); -- if (msg->rpcpool != NULL && msg->rpcpool->mempool != NULL) { -- rte_mempool_put(msg->rpcpool->mempool, (void *)msg); -- } else { -- free(msg); -- } --} -+int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn); -+int rpc_call_connnum(rpc_queue *queue); -+int rpc_call_mbufpoolsize(rpc_queue *queue); -+ -+int rpc_call_thread_regphase1(rpc_queue *queue, void *conn); -+int rpc_call_thread_regphase2(rpc_queue *queue, void *conn); - - #endif -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index cf66e15..4f3cbc1 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -43,6 +43,62 @@ - #define MBUF_MAX_LEN 1514 - #define PACKET_READ_SIZE 32 - -+/* any protocol stack thread receives arp packet and sync it to other threads, -+ * so that it can have the arp table */ -+static void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cur_stack) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct rte_mbuf *mbuf_copy = NULL; -+ struct protocol_stack *stack = NULL; -+ int32_t ret; -+ -+ for (int32_t i = 0; i < stack_group->stack_num; i++) { -+ stack = stack_group->stacks[i]; -+ if (cur_stack == stack) { -+ continue; -+ } -+ -+ /* stack maybe not init in app thread yet */ -+ if (stack == NULL || !(netif_is_up(&stack->netif))) { -+ continue; -+ } -+ -+ ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -+ if (ret != 0) { -+ stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ -+ ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ if (ret != 0) { -+ rte_pktmbuf_free(mbuf_copy); -+ return; -+ } -+ } -+#if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) -+ if (get_global_cfg_params()->kni_switch) { -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -+ if (ret != 0) { -+ cur_stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ kni_handle_tx(mbuf_copy); -+ } -+#endif -+ if (get_global_cfg_params()->flow_bifurcation) { -+ ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -+ if (ret != 0) { -+ cur_stack->stats.rx_allocmbuf_fail++; -+ return; -+ } -+ copy_mbuf(mbuf_copy, mbuf); -+ virtio_tap_process_tx(cur_stack->queue_id, mbuf_copy); -+ } -+ return; -+} -+ - void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - { - int32_t ret; --- -2.33.0 - diff --git a/0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch b/0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch deleted file mode 100644 index 1d2c323..0000000 --- a/0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch +++ /dev/null @@ -1,693 +0,0 @@ -From 710bb34f1b46e0df4d82fe46fc36e729160ea1d7 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 1 Sep 2024 00:21:52 +0800 -Subject: [PATCH] cleancode: add rpc_async_call, remove rpc_msg_arg.socklen, - fix some format - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_lwip.c | 27 +---- - src/lstack/core/lstack_protocol_stack.c | 25 ++--- - src/lstack/core/lstack_thread_rpc.c | 124 +++++++++++---------- - src/lstack/include/lstack_lwip.h | 27 +++-- - src/lstack/include/lstack_protocol_stack.h | 13 +-- - src/lstack/include/lstack_thread_rpc.h | 25 +++-- - 6 files changed, 117 insertions(+), 124 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 3454961..91f4838 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -588,23 +588,6 @@ bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock * - return replenish_again; - } - --int do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -- size_t len, int32_t flags) --{ -- ssize_t ret; -- /* send all send_ring, so len set lwip send max. */ -- if (NETCONN_IS_UDP(sock)) { -- ret = lwip_send(fd, sock, len, flags); -- } else { -- ret = lwip_send(fd, sock, UINT16_MAX, flags); -- } -- if (ret < 0 && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { -- return -1; -- } -- -- return do_lwip_replenish_sendring(stack, sock); --} -- - static inline void free_recv_ring_readover(struct rte_ring *ring) - { - void *pbufs[SOCK_RECV_RING_SIZE]; -@@ -753,10 +736,10 @@ static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int - - static inline void notice_stack_udp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) - { -- __sync_fetch_and_add(&sock->call_num, 1); -- while (rpc_call_udp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { -- usleep(1000); // 1000: wait 1ms to exec again -- } -+ __sync_fetch_and_add(&sock->call_num, 1); -+ while (rpc_call_udp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { -+ usleep(1000); // 1000: wait 1ms to exec again -+ } - } - - static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) -@@ -875,7 +858,7 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - // send = 0 : tcp peer close connection ? - if (send <= 0) { - return send; -- } -+ } - } - - notice_stack_send(sock, fd, send, flags); -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index bcca1a7..f1eeba1 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -88,7 +88,7 @@ struct protocol_stack *get_protocol_stack(void) - return g_stack_p; - } - --struct protocol_stack *get_protocol_stack_by_fd(int32_t fd) -+struct protocol_stack *get_protocol_stack_by_fd(int fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); - if (POSIX_IS_CLOSED(sock)) { -@@ -468,7 +468,7 @@ END: - return NULL; - } - --int stack_polling(uint32_t wakeup_tick) -+int stack_polling(unsigned wakeup_tick) - { - int force_quit; - struct cfg_params *cfg = get_global_cfg_params(); -@@ -536,12 +536,11 @@ int stack_polling(uint32_t wakeup_tick) - static void* gazelle_stack_thread(void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; -- - uint16_t queue_id = t_params->queue_id; -- uint32_t wakeup_tick = 0; -- -- struct protocol_stack *stack = stack_thread_init(arg); -+ struct protocol_stack *stack; -+ unsigned wakeup_tick = 0; - -+ stack = stack_thread_init(arg); - free(arg); - if (stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id); -@@ -607,7 +606,7 @@ static int stack_group_init_mempool(void) - return 0; - } - --int32_t stack_group_init(void) -+int stack_group_init(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - stack_group->stack_num = 0; -@@ -632,7 +631,7 @@ int32_t stack_group_init(void) - return 0; - } - --int32_t stack_setup_app_thread(void) -+int stack_setup_app_thread(void) - { - static PER_THREAD int first_flags = 1; - static _Atomic uint32_t queue_id = 0; -@@ -660,21 +659,21 @@ int32_t stack_setup_app_thread(void) - return 0; - } - --int32_t stack_setup_thread(void) -+int stack_setup_thread(void) - { -- int32_t ret; -+ int ret, i; - char name[PATH_MAX]; - int queue_num = get_global_cfg_params()->num_queue; - struct thread_params *t_params[PROTOCOL_STACK_MAX] = {NULL}; - int process_index = get_global_cfg_params()->process_idx; - -- for (uint32_t i = 0; i < queue_num; ++i) { -+ for (i = 0; i < queue_num; ++i) { - t_params[i] = malloc(sizeof(struct thread_params)); - if (t_params[i] == NULL) { - goto OUT1; - } - } -- for (uint32_t i = 0; i < queue_num; i++) { -+ for (i = 0; i < queue_num; i++) { - if (get_global_cfg_params()->seperate_send_recv) { - if (i % 2 == 0) { - ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_RECV_THREAD_NAME, process_index, i / 2); -@@ -714,7 +713,7 @@ int32_t stack_setup_thread(void) - return 0; - - OUT1: -- for (int32_t i = 0; i < queue_num; ++i) { -+ for (i = 0; i < queue_num; ++i) { - if (t_params[i] != NULL) { - free(t_params[i]); - } -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 3e9889a..b4a5953 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -45,20 +45,20 @@ static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) - return msg; - } - --static void rpc_msg_init(struct rpc_msg *msg, rpc_msg_func func, struct rpc_msg_pool *pool) -+__rte_always_inline -+static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func, struct rpc_msg_pool *pool) - { - msg->func = func; - msg->rpcpool = pool; -- msg->sync_flag = 1; - msg->recall_flag = 0; - pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); - } - --static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) -+static struct rpc_msg *rpc_msg_alloc(rpc_func_t func) - { -- struct rpc_msg *msg = NULL; -+ struct rpc_msg *msg; - -- if (g_rpc_pool == NULL) { -+ if (unlikely(g_rpc_pool == NULL)) { - g_rpc_pool = calloc(1, sizeof(struct rpc_msg_pool)); - if (g_rpc_pool == NULL) { - LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); -@@ -66,8 +66,8 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - exit(-1); - } - -- g_rpc_pool->mempool = create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), -- 0, rte_gettid()); -+ g_rpc_pool->mempool = -+ create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), 0, rte_gettid()); - if (g_rpc_pool->mempool == NULL) { - LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); - g_rpc_stats.call_alloc_fail++; -@@ -76,12 +76,12 @@ static struct rpc_msg *rpc_msg_alloc(rpc_msg_func func) - } - - msg = get_rpc_msg(g_rpc_pool); -- if (msg == NULL) { -+ if (unlikely(msg == NULL)) { - g_rpc_stats.call_alloc_fail++; - return NULL; - } -- rpc_msg_init(msg, func, g_rpc_pool); - -+ rpc_msg_init(msg, func, g_rpc_pool); - return msg; - } - -@@ -97,8 +97,9 @@ static void rpc_msg_free(struct rpc_msg *msg) - } - - __rte_always_inline --static void rpc_call(rpc_queue *queue, struct rpc_msg *msg) -+static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg) - { -+ msg->sync_flag = 0; - lockless_queue_mpsc_push(queue, &msg->queue_node); - } - -@@ -108,7 +109,9 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - int ret; - - pthread_spin_trylock(&msg->lock); -- rpc_call(queue, msg); -+ -+ msg->sync_flag = 1; -+ lockless_queue_mpsc_push(queue, &msg->queue_node); - - // waiting stack unlock - pthread_spin_lock(&msg->lock); -@@ -123,7 +126,7 @@ int rpc_msgcnt(rpc_queue *queue) - return lockless_queue_count(queue); - } - --static struct rpc_msg *rpc_msg_alloc_except(rpc_msg_func func) -+static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) - { - struct rpc_msg *msg = calloc(1, sizeof(struct rpc_msg)); - if (msg == NULL) { -@@ -146,14 +149,14 @@ int rpc_call_stack_exit(rpc_queue *queue) - return -1; - } - -- rpc_call(queue, msg); -+ rpc_async_call(queue, msg); - return 0; - } - - int rpc_poll_msg(rpc_queue *queue, int max_num) - { - int force_quit = 0; -- struct rpc_msg *msg = NULL; -+ struct rpc_msg *msg; - - while (max_num--) { - lockless_queue_node *node = lockless_queue_mpsc_pop(queue); -@@ -163,24 +166,24 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - - msg = container_of(node, struct rpc_msg, queue_node); - -- if (msg->func) { -+ if (likely(msg->func)) { - msg->func(msg); - } else { - g_rpc_stats.call_null++; - } - -- if (msg->func == stack_exit_by_rpc) { -+ if (unlikely(msg->func == stack_exit_by_rpc)) { - force_quit = 1; - } -+ if (msg->recall_flag) { -+ msg->recall_flag = 0; -+ continue; -+ } - -- if (!msg->recall_flag) { -- if (msg->sync_flag) { -- pthread_spin_unlock(&msg->lock); -- } else { -- rpc_msg_free(msg); -- } -+ if (msg->sync_flag) { -+ pthread_spin_unlock(&msg->lock); - } else { -- msg->recall_flag = 0; -+ rpc_msg_free(msg); - } - } - -@@ -204,7 +207,7 @@ static void callback_close(struct rpc_msg *msg) - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -+ rpc_async_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ - return; - } - -@@ -223,7 +226,7 @@ static void callback_shutdown(struct rpc_msg *msg) - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -+ rpc_async_call(&stack->rpc_queue, msg); - return; - } - -@@ -237,7 +240,7 @@ static void callback_shutdown(struct rpc_msg *msg) - - static void callback_bind(struct rpc_msg *msg) - { -- msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].socklen); -+ msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].u); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); - } -@@ -265,7 +268,7 @@ static void callback_create_shadow_fd(struct rpc_msg *msg) - { - int fd = msg->args[MSG_ARG_0].i; - struct sockaddr *addr = msg->args[MSG_ARG_1].p; -- socklen_t addr_len = msg->args[MSG_ARG_2].socklen; -+ socklen_t addr_len = msg->args[MSG_ARG_2].u; - - int clone_fd = 0; - struct lwip_sock *sock = lwip_get_socket(fd); -@@ -337,7 +340,7 @@ static void callback_accept(struct rpc_msg *msg) - - static void callback_connect(struct rpc_msg *msg) - { -- msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].socklen); -+ msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].u); - if (msg->result < 0) { - msg->result = -errno; - } -@@ -391,7 +394,7 @@ int rpc_call_bind(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen - - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].socklen = addrlen; -+ msg->args[MSG_ARG_2].u = addrlen; - - return rpc_sync_call(queue, msg); - } -@@ -418,7 +421,7 @@ int rpc_call_shadow_fd(rpc_queue *queue, int fd, const struct sockaddr *addr, so - - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].socklen = addrlen; -+ msg->args[MSG_ARG_2].u = addrlen; - - return rpc_sync_call(queue, msg); - } -@@ -447,7 +450,7 @@ int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, sock - - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].socklen = addrlen; -+ msg->args[MSG_ARG_2].u = addrlen; - - int ret = rpc_sync_call(queue, msg); - if (ret < 0) { -@@ -486,7 +489,7 @@ static void callback_getsockopt(struct rpc_msg *msg) - static void callback_setsockopt(struct rpc_msg *msg) - { - msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -- msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].socklen); -+ msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].u); - if (msg->result != 0) { - LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), - msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -@@ -548,7 +551,7 @@ int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const - msg->args[MSG_ARG_1].i = level; - msg->args[MSG_ARG_2].i = optname; - msg->args[MSG_ARG_3].cp = optval; -- msg->args[MSG_ARG_4].socklen = optlen; -+ msg->args[MSG_ARG_4].u = optlen; - - return rpc_sync_call(queue, msg); - } -@@ -556,13 +559,13 @@ int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const - static void callback_tcp_send(struct rpc_msg *msg) - { - int fd = msg->args[MSG_ARG_0].i; -- size_t len = msg->args[MSG_ARG_1].size; -+ size_t len = UINT16_MAX; /* ignore msg->args[MSG_ARG_1].size; */ - struct protocol_stack *stack = get_protocol_stack(); -- int replenish_again; -+ int ret; -+ msg->result = -1; - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- msg->result = -1; -+ if (unlikely(POSIX_IS_CLOSED(sock))) { - return; - } - -@@ -570,16 +573,18 @@ static void callback_tcp_send(struct rpc_msg *msg) - calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); - } - -- replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); -- if (replenish_again < 0) { -+ ret = lwip_send(fd, sock, len, 0); -+ if (unlikely(ret < 0) && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { - __sync_fetch_and_sub(&sock->call_num, 1); - return; - } -+ msg->result = 0; - -- if (NETCONN_IS_DATAOUT(sock) || replenish_again > 0) { -+ ret = do_lwip_replenish_sendring(stack, sock); -+ if (ret > 0 || NETCONN_IS_DATAOUT(sock)) { - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { - msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -+ rpc_async_call(&stack->rpc_queue, msg); - return; - } - } -@@ -593,11 +598,11 @@ static void callback_udp_send(struct rpc_msg *msg) - int fd = msg->args[MSG_ARG_0].i; - size_t len = msg->args[MSG_ARG_1].size; - struct protocol_stack *stack = get_protocol_stack(); -- int replenish_again; -+ int ret; -+ msg->result = -1; - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- msg->result = -1; -+ if (unlikely(POSIX_IS_CLOSED(sock))) { - return; - } - -@@ -605,8 +610,15 @@ static void callback_udp_send(struct rpc_msg *msg) - calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); - } - -- replenish_again = do_lwip_send(stack, sock->conn->callback_arg.socket, sock, len, 0); -- if ((replenish_again > 0) && (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1)) { -+ ret = lwip_send(fd, sock, len, 0); -+ if (unlikely(ret < 0) && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { -+ __sync_fetch_and_sub(&sock->call_num, 1); -+ return; -+ } -+ msg->result = 0; -+ -+ ret = do_lwip_replenish_sendring(stack, sock); -+ if (ret > 0 && (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1)) { - rpc_call_replenish(&stack->rpc_queue, sock); - return; - } -@@ -629,9 +641,8 @@ int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].size = len; - msg->args[MSG_ARG_2].i = flags; -- msg->sync_flag = 0; - -- rpc_call(queue, msg); -+ rpc_async_call(queue, msg); - return 0; - } - -@@ -649,9 +660,8 @@ int rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) - msg->args[MSG_ARG_0].i = fd; - msg->args[MSG_ARG_1].size = len; - msg->args[MSG_ARG_2].i = flags; -- msg->sync_flag = 0; - -- rpc_call(queue, msg); -+ rpc_async_call(queue, msg); - return 0; - } - -@@ -663,7 +673,7 @@ static void callback_replenish_sendring(struct rpc_msg *msg) - msg->result = do_lwip_replenish_sendring(stack, sock); - if (msg->result == true) { - msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -+ rpc_async_call(&stack->rpc_queue, msg); - } - } - -@@ -675,9 +685,8 @@ int rpc_call_replenish(rpc_queue *queue, void *sock) - } - - msg->args[MSG_ARG_0].p = sock; -- msg->sync_flag = 0; - -- rpc_call(queue, msg); -+ rpc_async_call(queue, msg); - return 0; - } - -@@ -713,16 +722,17 @@ static void callback_clean_epoll(struct rpc_msg *msg) - list_del_node(&wakeup->wakeup_list[stack->stack_idx]); - } - --void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) -+int rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) - { - struct rpc_msg *msg = rpc_msg_alloc(callback_clean_epoll); - if (msg == NULL) { -- return; -+ return -1; - } - - msg->args[MSG_ARG_0].p = wakeup; - - rpc_sync_call(queue, msg); -+ return 0; - } - - static void callback_arp(struct rpc_msg *msg) -@@ -740,11 +750,9 @@ int rpc_call_arp(rpc_queue *queue, void *mbuf) - return -1; - } - -- msg->sync_flag = 0; - msg->args[MSG_ARG_0].p = mbuf; - -- rpc_call(queue, msg); -- -+ rpc_async_call(queue, msg); - return 0; - } - -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index 0c7bb62..dcb7dac 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -29,15 +29,23 @@ unsigned same_node_ring_count(struct lwip_sock *sock); - #define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) - --void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); -- -+/* lwip api */ - struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); - struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); - void do_lwip_get_from_sendring_over(struct lwip_sock *sock); --bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock); - ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, uint8_t apiflags); - --/* app write/read ring */ -+/* lwip api */ -+void do_lwip_free_pbuf(struct pbuf *pbuf); -+struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type); -+ -+/* lwip api */ -+void do_lwip_add_recvlist(int32_t fd); -+/* stack api */ -+void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num); -+ -+ -+/* app api */ - ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, - const struct msghdr *message, int32_t flags); - ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int32_t flags); -@@ -47,17 +55,14 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, - struct sockaddr *addr, socklen_t *addrlen); - --void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num); --void do_lwip_add_recvlist(int32_t fd); --int do_lwip_send(struct protocol_stack *stack, int32_t fd, struct lwip_sock *sock, -- size_t len, int32_t flags); -+/* stack api */ -+bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock); -+ -+void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); - - uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint32_t max_num); - uint32_t do_lwip_get_connnum(void); - --void do_lwip_free_pbuf(struct pbuf *pbuf); --struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type); -- - void read_same_node_recv_list(struct protocol_stack *stack); - - #endif -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index fdd5388..08a3901 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -31,11 +31,8 @@ - #include "lstack_tx_cache.h" - - #define SOCK_RECV_RING_SIZE (get_global_cfg_params()->recv_ring_size) --#define SOCK_RECV_FREE_THRES (32) - #define SOCK_RECV_RING_SIZE_MAX (2048) - #define SOCK_SEND_RING_SIZE_MAX (2048) --#define SOCK_SEND_REPLENISH_THRES (16) --#define WAKEUP_MAX_NUM (32) - - #define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->nic.rxqueue_size + 1024) - -@@ -113,7 +110,7 @@ struct protocol_stack_group { - long get_stack_tid(void); - - struct protocol_stack *get_protocol_stack(void); --struct protocol_stack *get_protocol_stack_by_fd(int32_t fd); -+struct protocol_stack *get_protocol_stack_by_fd(int fd); - struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - -@@ -121,13 +118,13 @@ int get_min_conn_stack(struct protocol_stack_group *stack_group); - void bind_to_stack_numa(struct protocol_stack *stack); - void thread_bind_stack(struct protocol_stack *stack); - --int32_t stack_group_init(void); -+int stack_group_init(void); - void stack_group_exit(void); - void stack_exit(void); - --int32_t stack_setup_thread(void); --int32_t stack_setup_app_thread(void); -+int stack_setup_thread(void); -+int stack_setup_app_thread(void); - --int stack_polling(uint32_t wakeup_tick); -+int stack_polling(unsigned wakeup_tick); - - #endif -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index c2654bb..6f8e03e 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -32,8 +32,6 @@ struct rpc_stats { - uint64_t call_alloc_fail; - }; - --struct rpc_msg; --typedef void (*rpc_msg_func)(struct rpc_msg *msg); - union rpc_msg_arg { - int i; - unsigned int u; -@@ -41,22 +39,25 @@ union rpc_msg_arg { - unsigned long ul; - void *p; - const void *cp; -- socklen_t socklen; - size_t size; - }; --struct rpc_msg_pool { -- struct rte_mempool *mempool; --}; -+ -+struct rpc_msg; -+typedef void (*rpc_func_t)(struct rpc_msg *msg); - struct rpc_msg { -- pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */ - int8_t sync_flag : 1; - int8_t recall_flag : 1; -- int64_t result; /* func return val */ -- lockless_queue_node queue_node; -- struct rpc_msg_pool *rpcpool; - -- rpc_msg_func func; /* msg handle func hook */ -+ long result; /* func return val */ -+ rpc_func_t func; /* msg handle func hook */ - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ -+ -+ struct rpc_msg_pool { -+ struct rte_mempool *mempool; -+ } *rpcpool; -+ -+ pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */ -+ lockless_queue_node queue_node; - }; - - static inline void rpc_queue_init(rpc_queue *queue) -@@ -92,7 +93,7 @@ int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); - int rpc_call_replenish(rpc_queue *queue, void *sock); - int rpc_call_recvlistcnt(rpc_queue *queue); - --void rpc_call_clean_epoll(rpc_queue *queue, void *wakeup); -+int rpc_call_clean_epoll(rpc_queue *queue, void *wakeup); - int rpc_call_arp(rpc_queue *queue, void *mbuf); - - int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn); --- -2.33.0 - diff --git a/0260-cleancode-declare-different-cfg_params-types.patch b/0260-cleancode-declare-different-cfg_params-types.patch deleted file mode 100644 index fb2c1a9..0000000 --- a/0260-cleancode-declare-different-cfg_params-types.patch +++ /dev/null @@ -1,347 +0,0 @@ -From 3313619bd53f1bafc5e48eb4642213fd5208c0e2 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 1 Sep 2024 11:33:12 +0800 -Subject: [PATCH] cleancode: declare different cfg_params types - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_cfg.c | 10 +- - src/lstack/core/lstack_dpdk.c | 8 +- - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/core/lstack_virtio.c | 4 +- - src/lstack/include/lstack_cfg.h | 161 +++++++++++---------- - src/lstack/include/lstack_protocol_stack.h | 2 +- - src/lstack/netif/lstack_ethdev.c | 4 +- - src/lstack/netif/lstack_vdev.c | 2 +- - 8 files changed, 104 insertions(+), 89 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 882e60a..659a2a7 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -1300,9 +1300,9 @@ static int32_t parse_use_sockmap(void) - static int32_t parse_nic_rxqueue_size(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.nic.rxqueue_size, "nic_rxqueue_size", 4096, -+ PARSE_ARG(g_config_params.rxqueue_size, "nic_rxqueue_size", 4096, - NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -- if (!rte_is_power_of_2(g_config_params.nic.rxqueue_size)) { -+ if (!rte_is_power_of_2(g_config_params.rxqueue_size)) { - LSTACK_LOG(ERR, LSTACK, "nic queue size only support power of two\n"); - return -1; - } -@@ -1312,9 +1312,9 @@ static int32_t parse_nic_rxqueue_size(void) - static int32_t parse_nic_txqueue_size(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.nic.txqueue_size, "nic_txqueue_size", 2048, -+ PARSE_ARG(g_config_params.txqueue_size, "nic_txqueue_size", 2048, - NIC_QUEUE_SIZE_MIN, NIC_QUEUE_SIZE_MAX, ret); -- if (!rte_is_power_of_2(g_config_params.nic.txqueue_size)) { -+ if (!rte_is_power_of_2(g_config_params.txqueue_size)) { - LSTACK_LOG(ERR, LSTACK, "nic queue size only support power of two\n"); - return -1; - } -@@ -1352,7 +1352,7 @@ static int32_t parse_stack_thread_mode(void) - static int32_t parse_nic_vlan_mode(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.nic.vlan_mode, "nic_vlan_mode", -1, -1, 4094, ret); -+ PARSE_ARG(g_config_params.vlan_mode, "nic_vlan_mode", -1, -1, 4094, ret); - return ret; - } - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index f87e362..1fe0f0a 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -432,8 +432,8 @@ static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint - - eth_params->port_id = port_id; - eth_params->nb_queues = nb_queues; -- eth_params->nb_rx_desc = get_global_cfg_params()->nic.rxqueue_size; -- eth_params->nb_tx_desc = get_global_cfg_params()->nic.txqueue_size; -+ eth_params->nb_rx_desc = get_global_cfg_params()->rxqueue_size; -+ eth_params->nb_tx_desc = get_global_cfg_params()->txqueue_size; - eth_params->conf.link_speeds = RTE_ETH_LINK_SPEED_AUTONEG; - eth_params->conf.txmode.mq_mode = RTE_ETH_MQ_TX_NONE; - eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; -@@ -571,7 +571,7 @@ int32_t dpdk_ethdev_init(int port_id) - } - - /* after rte_eth_dev_configure */ -- if ((get_global_cfg_params()->nic.vlan_mode != -1) && -+ if ((get_global_cfg_params()->vlan_mode != -1) && - ((stack_group->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) == RTE_ETH_RX_OFFLOAD_VLAN_FILTER)) { - /* - * vlan filter can be configured for switch,nic and software. -@@ -583,7 +583,7 @@ int32_t dpdk_ethdev_init(int port_id) - */ - if ((get_global_cfg_params()->bond_mode != BONDING_MODE_8023AD) && - (get_global_cfg_params()->bond_mode != BONDING_MODE_ALB)) { -- ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->nic.vlan_mode, 1); -+ ret = rte_eth_dev_vlan_filter(port_id, get_global_cfg_params()->vlan_mode, 1); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk add vlan filter failed ret = %d\n", ret); - return -1; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index f1eeba1..d03b744 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -571,7 +571,7 @@ static int stack_group_init_mempool(void) - struct cfg_params *cfg_params = get_global_cfg_params(); - uint32_t total_mbufs = 0; - uint32_t total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; -- uint32_t total_nic_mbufs = cfg_params->nic.rxqueue_size + cfg_params->nic.txqueue_size; -+ uint32_t total_nic_mbufs = cfg_params->rxqueue_size + cfg_params->txqueue_size; - struct rte_mempool *rxtx_mbuf = NULL; - uint32_t cpu_id = 0; - unsigned numa_id = 0; -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 7a8d947..fefb06d 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -226,10 +226,10 @@ void virtio_tap_process_rx(uint16_t port, uint32_t queue_id) - * 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) { -+ if (get_global_cfg_params()->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; -+ pkts_burst[i]->vlan_tci = (u16_t)get_global_cfg_params()->vlan_mode; - } - } - -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 4fc99f3..5e2d6fc 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -50,93 +50,108 @@ - #define LSTACK_LPM_PKTS_IN_DETECT 1000 - #define LSTACK_LPM_RX_PKTS 20 - -- - #define LSTACK_LPM_PKTS_IN_DETECT_MIN 5 - #define LSTACK_LPM_PKTS_IN_DETECT_MAX 65535 - -+struct dev_addr { - #define DEV_ADDR_TYPE_EMPTY 0 - #define DEV_ADDR_TYPE_MAC 1 - #define DEV_ADDR_TYPE_PCI 2 -- --struct dev_addr { -- uint8_t addr_type; // 0:empty, 1:mac, 2:pci -+ uint8_t addr_type; - union addr_union { - struct rte_ether_addr mac_addr; - struct rte_pci_addr pci_addr; - } addr; - }; - --struct secondary_attach_arg { -- uint8_t socket_num; -- uint64_t socket_size; -- uint32_t socket_per_size[GAZELLE_MAX_NUMA_NODES]; -- uintptr_t base_virtaddr; -- char file_prefix[PATH_MAX]; --}; -- --struct cfg_nic_params { -- uint32_t rxqueue_size; -- uint32_t txqueue_size; -- int32_t vlan_mode; --}; -- - struct cfg_params { -- ip4_addr_t host_addr; -- ip6_addr_t host_addr6; -- ip4_addr_t netmask; -- ip4_addr_t gateway_addr; -- uint8_t mac_addr[ETHER_ADDR_LEN]; -- uint16_t num_cpu; -- uint32_t cpus[CFG_MAX_CPUS]; -- uint32_t send_cpus[CFG_MAX_CPUS]; -- uint32_t recv_cpus[CFG_MAX_CPUS]; -- uint16_t app_exclude_num_cpu; -- uint32_t app_exclude_cpus[CFG_MAX_CPUS]; -- uint8_t num_ports; -- uint16_t ports[CFG_MAX_PORTS]; - char log_file[PATH_MAX]; -- uint16_t low_power_mod; -- uint16_t lpm_rx_pkts; -- uint32_t lpm_detect_ms; -- uint32_t lpm_pkts_in_detect; -- uint32_t tcp_conn_count; -- uint32_t mbuf_count_per_conn; -- uint32_t read_connect_number; -- uint32_t rpc_number; -- uint32_t nic_read_number; -- uint8_t use_ltran; // false:lstack read from nic. true:lstack read form ltran process. -- -- uint16_t num_process; -- uint16_t num_listen_port; -- uint16_t is_primary; -- uint16_t num_queue; -- uint16_t tot_queue_num; -- uint8_t process_idx; -- uint32_t process_numa[PROTOCOL_STACK_MAX]; -- -- bool kni_switch; -- bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread. -- bool app_bind_numa; -- bool main_thread_affinity; -- bool seperate_send_recv; -- int dpdk_argc; -- char **dpdk_argv; -- struct secondary_attach_arg sec_attach_arg; -- char unix_socket_filename[NAME_MAX]; -- uint16_t send_ring_size; -- uint16_t recv_ring_size; -- bool tuple_filter; -- int8_t bond_mode; -- int32_t bond_miimon; -- struct dev_addr bond_slave_addr[GAZELLE_MAX_BOND_NUM]; -- bool use_sockmap; -- bool udp_enable; -- struct cfg_nic_params nic; -- bool stack_mode_rtc; -- bool nonblock_mode; -- uint32_t rpc_msg_max; -- bool send_cache_mode; -- bool flow_bifurcation; -+ -+ struct { // dpdk -+ char **dpdk_argv; -+ uint8_t dpdk_argc; -+ struct secondary_attach_arg { -+ uint8_t socket_num; -+ uint64_t socket_size; -+ uint32_t socket_per_size[GAZELLE_MAX_NUMA_NODES]; -+ uintptr_t base_virtaddr; -+ char file_prefix[PATH_MAX]; -+ } sec_attach_arg; -+ }; -+ -+ struct { // eth -+ ip4_addr_t host_addr; -+ ip6_addr_t host_addr6; -+ ip4_addr_t netmask; -+ ip4_addr_t gateway_addr; -+ uint8_t mac_addr[ETHER_ADDR_LEN]; -+ int8_t bond_mode; -+ int32_t bond_miimon; -+ struct dev_addr bond_slave_addr[GAZELLE_MAX_BOND_NUM]; -+ }; -+ -+ struct { // low_power -+ uint16_t low_power_mod; -+ uint16_t lpm_rx_pkts; -+ uint32_t lpm_detect_ms; -+ uint32_t lpm_pkts_in_detect; -+ }; -+ -+ struct { // eth_rxtx -+ uint32_t rxqueue_size; -+ uint32_t txqueue_size; -+ uint16_t num_queue; -+ uint16_t tot_queue_num; -+ bool send_cache_mode; -+ bool flow_bifurcation; -+ int32_t vlan_mode; -+ }; -+ -+ struct { // stack -+ uint16_t num_cpu; -+ uint32_t cpus[CFG_MAX_CPUS]; -+ -+ bool main_thread_affinity; -+ bool app_bind_numa; -+ uint16_t app_exclude_num_cpu; -+ uint32_t app_exclude_cpus[CFG_MAX_CPUS]; -+ -+ bool stack_mode_rtc; -+ bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread. -+ -+ uint32_t read_connect_number; -+ uint32_t nic_read_number; -+ uint32_t rpc_number; -+ uint32_t rpc_msg_max; -+ }; -+ -+ struct { // socket -+ uint16_t send_ring_size; -+ uint16_t recv_ring_size; -+ uint32_t tcp_conn_count; -+ uint32_t mbuf_count_per_conn; -+ }; -+ -+ struct { // deprecated -+ char unix_socket_filename[NAME_MAX]; -+ bool use_ltran; // false:lstack read from nic. true:lstack read form ltran process. -+ bool nonblock_mode; -+ bool udp_enable; -+ bool kni_switch; -+ }; -+ -+ struct { // experiment -+ uint16_t num_process; -+ uint16_t is_primary; -+ uint8_t process_idx; -+ uint32_t process_numa[PROTOCOL_STACK_MAX]; -+ bool tuple_filter; -+ bool use_sockmap; -+ -+ bool seperate_send_recv; -+ uint32_t send_cpus[CFG_MAX_CPUS]; -+ uint32_t recv_cpus[CFG_MAX_CPUS]; -+ }; - }; - - struct cfg_params *get_global_cfg_params(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 08a3901..8cb0020 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -34,7 +34,7 @@ - #define SOCK_RECV_RING_SIZE_MAX (2048) - #define SOCK_SEND_RING_SIZE_MAX (2048) - --#define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->nic.rxqueue_size + 1024) -+#define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->rxqueue_size + 1024) - - struct protocol_stack { - uint32_t tid; -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 4f3cbc1..1a721f6 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -418,8 +418,8 @@ int32_t ethdev_init(struct protocol_stack *stack) - } - - /* 0-4094: The vlaue range for VLAN IDs is 0 to 4094. */ -- if (get_global_cfg_params()->nic.vlan_mode >= 0 && get_global_cfg_params()->nic.vlan_mode <= 4094) { -- netif_set_vlan_tci(&stack->netif, (u16_t)get_global_cfg_params()->nic.vlan_mode); -+ if (get_global_cfg_params()->vlan_mode >= 0 && get_global_cfg_params()->vlan_mode <= 4094) { -+ netif_set_vlan_tci(&stack->netif, (u16_t)get_global_cfg_params()->vlan_mode); - } - - netif_set_link_up(&stack->netif); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 9ca77ba..e1a63a7 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -145,7 +145,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - } - - /* skip gro when tcp/ip cksum offloads disable */ -- if (get_protocol_stack_group()->rx_offload == 0 || (get_global_cfg_params()->nic.vlan_mode >= 0 -+ if (get_protocol_stack_group()->rx_offload == 0 || (get_global_cfg_params()->vlan_mode >= 0 - && !(get_protocol_stack_group()->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP))) { - return pkt_num; - } --- -2.33.0 - diff --git a/0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch b/0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch deleted file mode 100644 index 1290f60..0000000 --- a/0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 7718bd104226b2444e1a3a7405e4daed9ac046f9 Mon Sep 17 00:00:00 2001 -From: hkk -Date: Wed, 25 Sep 2024 15:01:02 +0800 -Subject: [PATCH] Fill in a portion of mbuf to send_ring, when mbuf is - insufficient. - ---- - src/lstack/core/lstack_lwip.c | 31 +++++++++++++++++++--- - src/lstack/include/lstack_protocol_stack.h | 2 +- - 2 files changed, 29 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 91f4838..7677e46 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -109,18 +109,43 @@ static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, u - return pbuf; - } - -+static uint32_t update_replenish_mbuf_cnt(struct protocol_stack *stack, struct lwip_sock *sock) -+{ -+ const uint32_t min_alloc_mbuf_num = 4; -+ struct rte_ring *ring = sock->send_ring; -+ -+ uint32_t replenish_cnt = gazelle_ring_free_count(ring); -+ if (replenish_cnt <= min_alloc_mbuf_num) { -+ return replenish_cnt; -+ } -+ -+ uint32_t resu = replenish_cnt; -+ uint32_t tcp_conn_count = get_global_cfg_params()->tcp_conn_count; -+ uint16_t send_ring_size = get_global_cfg_params()->send_ring_size; -+ uint16_t proportion = stack->conn_num / tcp_conn_count; -+ uint32_t replenish_mbuf_cnt_cal = (send_ring_size >> proportion); -+ -+ if (replenish_mbuf_cnt_cal <= min_alloc_mbuf_num) { -+ resu = min_alloc_mbuf_num; -+ } else if (replenish_mbuf_cnt_cal < replenish_cnt) { -+ resu = replenish_mbuf_cnt_cal; -+ } else { -+ resu = replenish_cnt + 1; -+ } -+ -+ return resu - 1; -+} -+ - /* true: need replenish again */ - static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_sock *sock) - { - void *pbuf[SOCK_SEND_RING_SIZE_MAX]; -- - struct rte_ring *ring = sock->send_ring; - -- uint32_t replenish_cnt = gazelle_ring_free_count(ring); -+ uint32_t replenish_cnt = update_replenish_mbuf_cnt(stack, sock); - if (replenish_cnt == 0) { - return false; - } -- - if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt, true) != 0) { - stack->stats.tx_allocmbuf_fail++; - return true; -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 8cb0020..4d10ac2 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -34,7 +34,7 @@ - #define SOCK_RECV_RING_SIZE_MAX (2048) - #define SOCK_SEND_RING_SIZE_MAX (2048) - --#define MBUFPOOL_RESERVE_NUM (get_global_cfg_params()->rxqueue_size + 1024) -+#define MBUFPOOL_RESERVE_NUM (2 * get_global_cfg_params()->rxqueue_size + 1024) - - struct protocol_stack { - uint32_t tid; --- -2.33.0 - diff --git a/0262-add-pingpong-dfx-support.patch b/0262-add-pingpong-dfx-support.patch deleted file mode 100644 index f23a349..0000000 --- a/0262-add-pingpong-dfx-support.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 8de32dd108ac0666aabf01aa68b017389a390b26 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Fri, 27 Sep 2024 15:41:42 +0800 -Subject: [PATCH] add pingpong dfx support - ---- - src/common/gazelle_dfx_msg.h | 1 + - src/lstack/core/lstack_lwip.c | 1 + - src/ltran/ltran_dfx.c | 7 ++++--- - 3 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 08f9df1..266c239 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -281,6 +281,7 @@ struct gazelle_stat_lstack_conn_info { - uint32_t keep_idle; - uint32_t keep_intvl; - uint32_t keep_cnt; -+ uint8_t pingpong; - }; - - struct gazelle_stat_lstack_conn { -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 7677e46..2eb872c 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1257,6 +1257,7 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->keep_idle = pcb->keep_idle; - conn->keep_intvl = pcb->keep_intvl; - conn->keep_cnt = pcb->keep_cnt; -+ conn->pingpong = tcp_in_pingpong(pcb); - - if (netconn != NULL) { - conn->fd = netconn->callback_arg.socket; -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index fc30054..7fa117a 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -1242,7 +1242,7 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" - " lastack rcv_nxt events epoll_ev evlist fd Local Address" - " Foreign Address State" -- " keep-alive keep-alive(idle,intvl,cnt)\n"); -+ " keep-alive keep-alive(idle,intvl,cnt) pingpong\n"); - uint32_t unread_pkts = 0; - uint32_t unsend_pkts = 0; - for (i = 0; i < conn->conn_num && i < GAZELLE_LSTACK_MAX_CONN; i++) { -@@ -1261,12 +1261,13 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); - sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); - printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -- "%-52s %-52s %s %-5d %s\n", i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, -+ "%-52s %-52s %s %-5d %s %d\n", -+ i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, - conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, - conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, - conn_info->epoll_events, conn_info->eventlist, conn_info->fd, - str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state), -- conn_info->keepalive, keepalive_info_str); -+ conn_info->keepalive, keepalive_info_str, conn_info->pingpong); - } else if (conn_info->state == GAZELLE_LISTEN_LIST) { - inet_ntop(domain, lip, str_ip, sizeof(str_ip)); - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); --- -2.33.0 - diff --git a/0263-add-interrupt-mode-support.patch b/0263-add-interrupt-mode-support.patch deleted file mode 100644 index ce48934..0000000 --- a/0263-add-interrupt-mode-support.patch +++ /dev/null @@ -1,977 +0,0 @@ -From 2cfaac4ec2a653af30d7368fbc1c2bdec4fa8bdf Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sun, 29 Sep 2024 14:41:19 +0800 -Subject: [PATCH] add interrupt mode support - ---- - src/common/gazelle_dfx_msg.h | 10 + - src/lstack/core/lstack_cfg.c | 25 ++ - src/lstack/core/lstack_dpdk.c | 27 +- - src/lstack/core/lstack_init.c | 5 + - src/lstack/core/lstack_interrupt.c | 346 ++++++++++++++++++++++++ - src/lstack/core/lstack_protocol_stack.c | 24 +- - src/lstack/core/lstack_stack_stat.c | 6 + - src/lstack/core/lstack_thread_rpc.c | 10 +- - src/lstack/core/lstack_virtio.c | 9 + - src/lstack/include/lstack_cfg.h | 1 + - src/lstack/include/lstack_interrupt.h | 34 +++ - src/lstack/include/lstack_thread_rpc.h | 12 +- - src/lstack/include/lstack_tx_cache.h | 1 + - src/lstack/include/lstack_virtio.h | 2 +- - src/lstack/netif/lstack_tx_cache.c | 27 +- - src/lstack/netif/lstack_vdev.c | 2 + - src/ltran/ltran_dfx.c | 34 +++ - 17 files changed, 559 insertions(+), 16 deletions(-) - create mode 100644 src/lstack/core/lstack_interrupt.c - create mode 100644 src/lstack/include/lstack_interrupt.h - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 266c239..1a89e65 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -60,6 +60,7 @@ enum GAZELLE_STAT_MODE { - GAZELLE_STAT_LSTACK_SHOW_XSTATS, - GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, - GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, -+ GAZELLE_STAT_LSTACK_SHOW_INTR, - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - GAZELLE_STAT_FAULT_INJECT_SET, -@@ -345,6 +346,14 @@ struct nic_eth_features { - uint64_t tx_offload; - }; - -+struct interrupt_stats { -+ uint64_t virtio_user_event_cnt; -+ uint64_t nic_event_cnt; -+ uint64_t remote_event_cnt; -+ uint64_t local_event_cnt; -+ uint64_t timeout_event_cnt; -+}; -+ - struct gazelle_stack_dfx_data { - /* indicates whether the current message is the last */ - uint32_t eof; -@@ -362,6 +371,7 @@ struct gazelle_stack_dfx_data { - struct nic_eth_xstats nic_xstats; - struct nic_eth_features nic_features; - struct gazelle_stat_lstack_proto proto_data; -+ struct interrupt_stats intr_stats; - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - struct gazelle_fault_inject_data inject; -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 659a2a7..f239b60 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -85,6 +85,7 @@ static int32_t parse_defaule_nonblock_mode(void); - static int32_t parse_rpc_msg_max(void); - static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); -+static int32_t parse_stack_interrupt(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -152,6 +153,7 @@ static struct config_vector_t g_config_tbl[] = { - { "rpc_msg_max", parse_rpc_msg_max }, - { "send_cache_mode", parse_send_cache_mode }, - { "flow_bifurcation", parse_flow_bifurcation}, -+ { "stack_interrupt", parse_stack_interrupt}, - { NULL, NULL } - }; - -@@ -1383,3 +1385,26 @@ static int32_t parse_flow_bifurcation(void) - PARSE_ARG(g_config_params.flow_bifurcation, "flow_bifurcation", 0, 0, 1, ret); - return ret; - } -+ -+static int32_t parse_stack_interrupt(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.stack_interrupt, "stack_interrupt", false, false, true, ret); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid enable intr value %d. only support 0 or 1\n", \ -+ g_config_params.stack_interrupt); -+ } -+ -+ if (g_config_params.stack_interrupt == true) { -+ if (g_config_params.stack_mode_rtc == true) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "rtc mode not support interrupt mode now.\n"); -+ return -1; -+ } -+ if (g_config_params.bond_mode >= 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "bond mode not support interrupt mode.\n"); -+ return -1; -+ } -+ } -+ -+ return ret; -+} -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 1fe0f0a..530332b 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -258,8 +258,8 @@ struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t si - - int32_t create_shared_ring(struct protocol_stack *stack) - { -- rpc_queue_init(&stack->rpc_queue); -- rpc_queue_init(&stack->dfx_rpc_queue); -+ rpc_queue_init(&stack->rpc_queue, stack->queue_id); -+ rpc_queue_init(&stack->dfx_rpc_queue, stack->queue_id); - - if (use_ltran()) { - stack->rx_ring = gazelle_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -@@ -439,6 +439,7 @@ static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint - eth_params->conf.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; - /* used for tcp port alloc */ - eth_params->reta_mask = dev_info.reta_size - 1; -+ eth_params->conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt; - - eth_params_checksum(ð_params->conf, &dev_info); - -@@ -630,10 +631,11 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i - - int32_t dpdk_ethdev_start(void) - { -+ int i; - int32_t ret; - const struct protocol_stack_group *stack_group = get_protocol_stack_group(); - -- for (int32_t i = 0; i < get_global_cfg_params()->tot_queue_num; i++) { -+ for (i = 0; i < get_global_cfg_params()->tot_queue_num; i++) { - ret = dpdk_ethdev_setup(stack_group->eth_params, i); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_setup fail queueid=%d, ret=%d\n", i, ret); -@@ -647,6 +649,14 @@ int32_t dpdk_ethdev_start(void) - return ret; - } - -+ /* after rte_eth_dev_start */ -+ for (i = 0; i < get_global_cfg_params()->tot_queue_num; i++) { -+ struct intr_dpdk_event_args intr_arg; -+ intr_arg.port_id = stack_group->eth_params->port_id; -+ intr_arg.queue_id = i; -+ intr_register(i, INTR_DPDK_EVENT, &intr_arg); -+ } -+ - return 0; - } - -@@ -799,10 +809,21 @@ int init_dpdk_ethdev(void) - } - port_id = rte_eth_bond_primary_get(get_protocol_stack_group()->port_id); - } else { -+ struct rte_eth_dev_info dev_info; - port_id = ethdev_port_id(cfg->mac_addr); - if (port_id < 0) { - return -1; - } -+ -+ if (rte_eth_dev_info_get(port_id, &dev_info) < 0) { -+ return -1; -+ } -+ if (strcmp(dev_info.driver_name, "net_hinic") == 0 && -+ get_global_cfg_params()->stack_interrupt == true) { -+ LSTACK_LOG(ERR, LSTACK, "hinic not support interrupt mode\n"); -+ return -1; -+ } -+ - ret = dpdk_ethdev_init(port_id); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "dpdk_ethdev_init failed, port id=%d\n", port_id); -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 37264a1..5e405ee 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -45,6 +45,7 @@ - #include "lstack_preload.h" - #include "lstack_wrap.h" - #include "lstack_flow.h" -+#include "lstack_interrupt.h" - - static void check_process_start(void) - { -@@ -289,6 +290,10 @@ __attribute__((constructor)) void gazelle_network_init(void) - LSTACK_EXIT(1, "stack_group_init failed\n"); - } - -+ if (intr_init() < 0) { -+ LSTACK_EXIT(1, "intr init failed\n"); -+ } -+ - if (!use_ltran()) { - if (init_dpdk_ethdev() != 0) { - LSTACK_EXIT(1, "init_dpdk_ethdev failed\n"); -diff --git a/src/lstack/core/lstack_interrupt.c b/src/lstack/core/lstack_interrupt.c -new file mode 100644 -index 0000000..26823cd ---- /dev/null -+++ b/src/lstack/core/lstack_interrupt.c -@@ -0,0 +1,346 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "common/dpdk_common.h" -+#include "common/gazelle_opt.h" -+#include "common/gazelle_dfx_msg.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "lstack_interrupt.h" -+ -+#define INTR_MAX_EVENT_NUM 8 -+ -+struct intr_dpdk_event { -+ int rte_epfd; -+#define INTR_PORT_NUM 2 -+#define INTR_INVALID_PORT 65535 -+ uint16_t port_id[INTR_PORT_NUM]; /* 0: nic port id, 1: virtio_user port id */ -+ uint16_t queue_id[INTR_PORT_NUM]; -+}; -+ -+struct intr_local_event { -+ bool (*get_event) (uint16_t stack_id); -+}; -+ -+struct intr_remote_event { -+ int event_fd; -+}; -+ -+struct intr_policy { -+#define INTR_LOOP_TIMES 5 -+ uint8_t no_event_cnt; -+}; -+ -+struct intr_config { -+ int epoll_fd; /* used for epoll */ -+ uint16_t stack_id; -+ bool in_wait; -+ -+ struct intr_dpdk_event dpdk_event; -+ struct intr_local_event local_event; -+ struct intr_remote_event remote_event; -+ -+ struct intr_policy policy; -+ struct interrupt_stats stats; -+}; -+ -+static struct intr_config g_intr_configs[PROTOCOL_STACK_MAX] = {0}; -+ -+static inline struct intr_config *intr_config_get(uint16_t stack_id) -+{ -+ return &g_intr_configs[stack_id]; -+} -+ -+int intr_init(void) -+{ -+ int stack_id; -+ struct cfg_params *cfg = get_global_cfg_params(); -+ if (!cfg->stack_interrupt) { -+ return 0; -+ } -+ -+ for (stack_id = 0; stack_id < cfg->num_queue; stack_id++) { -+ struct intr_config *intr_config = intr_config_get(stack_id); -+ intr_config->epoll_fd = posix_api->epoll_create_fn(1); -+ if (intr_config->epoll_fd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll create fd fialed, errno is %d\n", errno); -+ return -1; -+ } -+ -+ for (int i = 0; i < INTR_PORT_NUM; i++) { -+ intr_config->dpdk_event.port_id[i] = INTR_INVALID_PORT; -+ } -+ -+ if (intr_register(stack_id, INTR_REMOTE_EVENT, NULL) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "register intr failed\n"); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+static inline int add_fd_to_epoll(int fd, int epoll_fd) -+{ -+ struct epoll_event event ; -+ event.data.fd = fd ; -+ event.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP | EPOLLHUP ; -+ int ret = posix_api->epoll_ctl_fn(epoll_fd, EPOLL_CTL_ADD, fd, &event); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "add fd %d to epoll fd %d failed errno:%d ret=%d.\n", -+ fd, epoll_fd, errno, ret); -+ return ret; -+ } -+ -+ return ret ; -+} -+ -+static inline int intr_local_event_register(struct intr_config *config, void *priv) -+{ -+ config->local_event.get_event = priv; -+ return 0; -+} -+ -+static int intr_dpdk_event_register(struct intr_config *config, void *priv) -+{ -+ struct intr_dpdk_event_args *arg = priv; -+ int i; -+ -+ if (arg == NULL) { -+ return -1; -+ } -+ -+ if (config->dpdk_event.rte_epfd <= 0) { -+ config->dpdk_event.rte_epfd = posix_api->epoll_create_fn(1); -+ if (config->dpdk_event.rte_epfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll create fd fialed, errno is %d\n", errno); -+ return -1; -+ } -+ if (add_fd_to_epoll(config->dpdk_event.rte_epfd, config->epoll_fd) < 0) { -+ return -1; -+ } -+ } -+ -+ for (i = 0; i < INTR_PORT_NUM; i++) { -+ if (config->dpdk_event.port_id[i] == INTR_INVALID_PORT) { -+ config->dpdk_event.port_id[i] = arg->port_id; -+ break; -+ } -+ } -+ config->dpdk_event.queue_id[i] = arg->queue_id; -+ -+ int data = ((arg->port_id) << CHAR_BIT) | arg->queue_id; -+ if (rte_eth_dev_rx_intr_ctl_q(arg->port_id, arg->queue_id, config->dpdk_event.rte_epfd, -+ RTE_INTR_EVENT_ADD, (void *)((uintptr_t)data)) < 0) { -+ LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_rx_intr_ctl_q failed, port(%d), queue(%d)\n", -+ arg->port_id, arg->queue_id); -+ return -1; -+ } -+ return 0; -+} -+ -+static int intr_remote_event_register(struct intr_config *config, void *priv) -+{ -+ struct intr_remote_event *remote_event = &config->remote_event; -+ if (remote_event->event_fd > 0) { -+ return 0; -+ } -+ -+ remote_event->event_fd = posix_api->eventfd_fn(0, 0); -+ if (remote_event->event_fd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "event fd create failed\n"); -+ return -1; -+ } -+ return add_fd_to_epoll(remote_event->event_fd, config->epoll_fd); -+} -+ -+int intr_register(uint16_t stack_id, enum intr_type type, void *priv) -+{ -+ struct cfg_params *cfg = get_global_cfg_params(); -+ if (!cfg->stack_interrupt) { -+ return 0; -+ } -+ -+ struct intr_config *config = intr_config_get(stack_id); -+ switch (type) { -+ case INTR_DPDK_EVENT: -+ return intr_dpdk_event_register(config, priv); -+ case INTR_REMOTE_EVENT: -+ return intr_remote_event_register(config, priv); -+ case INTR_LOCAL_EVENT: -+ return intr_local_event_register(config, priv); -+ default: -+ return -1; -+ } -+ return 0; -+} -+ -+static inline void intr_remote_event_enable(struct intr_config *config) -+{ -+ eventfd_t eventfd_num = 1; -+ if (__atomic_load_n(&config->in_wait, __ATOMIC_ACQUIRE)) { -+ posix_api->write_fn(config->remote_event.event_fd, &eventfd_num, sizeof(eventfd_t)); -+ } -+} -+ -+static inline void intr_remote_event_disable(struct intr_config *config) -+{ -+ eventfd_t read_num; -+ posix_api->read_fn(config->remote_event.event_fd, &read_num, sizeof(eventfd_t)); -+} -+ -+static inline bool intr_local_event(struct intr_config *config) -+{ -+ return config->local_event.get_event(config->stack_id); -+} -+ -+void intr_wakeup(uint16_t stack_id, enum intr_type type) -+{ -+ if (!get_global_cfg_params()->stack_interrupt) { -+ return; -+ } -+ -+ struct intr_config *config = intr_config_get(stack_id); -+ switch (type) { -+ case INTR_REMOTE_EVENT: -+ intr_remote_event_enable(config); -+ break; -+ default: -+ break; -+ } -+} -+ -+static inline void intr_dpdk_event_enable(struct intr_config *config) -+{ -+ int i; -+ int ret = 0; -+ struct intr_dpdk_event *dpdk_event = &config->dpdk_event; -+ -+ for (i = 0; i < INTR_PORT_NUM; i++) { -+ if (dpdk_event->port_id[i] != INTR_INVALID_PORT) { -+ ret = rte_eth_dev_rx_intr_enable(dpdk_event->port_id[i], dpdk_event->queue_id[i]); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "port(%d) queue(%d) enable interrupt failed\n", -+ dpdk_event->port_id[i], dpdk_event->queue_id[i]); -+ return; -+ } -+ } -+ } -+} -+ -+static inline void intr_dpdk_event_disable(struct intr_config *config) -+{ -+ int i, n; -+ void *data; -+ uint16_t port_id; -+ uint16_t queue_id; -+ struct intr_dpdk_event *dpdk_event = &config->dpdk_event; -+ struct rte_epoll_event event[INTR_MAX_EVENT_NUM]; -+ -+ n = rte_epoll_wait(dpdk_event->rte_epfd, event, INTR_MAX_EVENT_NUM, 1); -+ for (i = 0; i < n; i++) { -+ data = event[i].epdata.data; -+ port_id = ((uintptr_t)data) >> CHAR_BIT; -+ queue_id = ((uintptr_t)data) & RTE_LEN2MASK(CHAR_BIT, uint8_t); -+ -+ rte_eth_dev_rx_intr_disable(port_id, queue_id); -+ -+ if (port_id == dpdk_event->port_id[0]) { -+ config->stats.nic_event_cnt++; -+ } else { -+ config->stats.virtio_user_event_cnt++; -+ } -+ } -+} -+ -+static inline void intr_policy_clear(struct intr_config *config) -+{ -+ config->policy.no_event_cnt = 0; -+} -+ -+static inline bool intr_policy(struct intr_config *config) -+{ -+ if (config->policy.no_event_cnt++ < INTR_LOOP_TIMES) { -+ return true; -+ } -+ config->policy.no_event_cnt = 0; -+ return false; -+} -+ -+static inline void intr_block(uint16_t stack_id, uint32_t timeout) -+{ -+ struct epoll_event events[INTR_MAX_EVENT_NUM]; -+ struct intr_config *intr_config = intr_config_get(stack_id); -+ -+ /* in_wait need in here to avoid competion problem with remote event */ -+ __atomic_store_n(&intr_config->in_wait, true, __ATOMIC_RELEASE); -+ if (intr_local_event(intr_config)) { -+ intr_config->stats.local_event_cnt++; -+ __atomic_store_n(&intr_config->in_wait, false, __ATOMIC_RELEASE); -+ return; -+ } -+ -+ intr_dpdk_event_enable(intr_config); -+ -+ int32_t event_cnt = posix_api->epoll_wait_fn(intr_config->epoll_fd, events, INTR_MAX_EVENT_NUM, timeout); -+ __atomic_store_n(&intr_config->in_wait, false, __ATOMIC_RELEASE); -+ for (int i = 0; i < event_cnt; i++) { -+ if (events[i].data.fd == intr_config->dpdk_event.rte_epfd) { -+ intr_dpdk_event_disable(intr_config); -+ } else if (events[i].data.fd == intr_config->remote_event.event_fd) { -+ intr_remote_event_disable(intr_config); -+ intr_config->stats.remote_event_cnt++; -+ } else { -+ LSTACK_LOG(ERR, LSTACK, "unknow fd have event.\n"); -+ } -+ } -+ -+ if (event_cnt < 0) { -+ intr_config->stats.timeout_event_cnt++; -+ } -+} -+ -+void intr_wait(uint16_t stack_id, uint32_t timeout) -+{ -+ struct intr_config *intr_config = intr_config_get(stack_id); -+ -+ if (intr_policy(intr_config)) { -+ return; -+ } -+ -+ intr_block(stack_id, timeout); -+ -+ intr_policy_clear(intr_config); -+} -+ -+int intr_stats_get(uint16_t stack_id, void *ptr, int len) -+{ -+ struct intr_config *config = intr_config_get(stack_id); -+ if (len < sizeof(struct interrupt_stats)) { -+ return -1; -+ } -+ -+ return memcpy_s(ptr, len, &config->stats, sizeof(struct interrupt_stats)); -+} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d03b744..e412c3b 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -34,6 +34,8 @@ - #include "lstack_virtio.h" - #include "lstack_protocol_stack.h" - -+#include "lstack_interrupt.h" -+ - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include - #endif -@@ -480,13 +482,18 @@ int stack_polling(unsigned wakeup_tick) - uint32_t rpc_number = cfg->rpc_number; - uint32_t read_connect_number = cfg->read_connect_number; - struct protocol_stack *stack = get_protocol_stack(); -+ uint32_t timeout; - - /* 2: one dfx consumes two rpc */ - rpc_poll_msg(&stack->dfx_rpc_queue, 2); - force_quit = rpc_poll_msg(&stack->rpc_queue, rpc_number); - - eth_dev_poll(); -- sys_timer_run(); -+ timeout = sys_timer_run(); -+ if (cfg->stack_interrupt) { -+ intr_wait(stack->stack_idx, timeout); -+ } -+ - if (cfg->low_power_mod != 0) { - low_power_idling(stack); - } -@@ -496,6 +503,7 @@ int stack_polling(unsigned wakeup_tick) - } - - do_lwip_read_recvlist(stack, read_connect_number); -+ - if ((wakeup_tick & 0xf) == 0) { - wakeup_stack_epoll(stack); - if (get_global_cfg_params()->send_cache_mode) { -@@ -533,6 +541,19 @@ int stack_polling(unsigned wakeup_tick) - return force_quit; - } - -+static bool stack_local_event_get(uint16_t stack_id) -+{ -+ struct protocol_stack *stack = g_stack_group.stacks[stack_id]; -+ if (!lockless_queue_empty(&stack->dfx_rpc_queue.queue) || -+ !lockless_queue_empty(&stack->rpc_queue.queue) || -+ !list_head_empty(&stack->recv_list) || -+ !list_head_empty(&stack->wakeup_list) || -+ tx_cache_count(stack->queue_id)) { -+ return true; -+ } -+ return false; -+} -+ - static void* gazelle_stack_thread(void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; -@@ -541,6 +562,7 @@ static void* gazelle_stack_thread(void *arg) - unsigned wakeup_tick = 0; - - stack = stack_thread_init(arg); -+ intr_register(stack->stack_idx, INTR_LOCAL_EVENT, stack_local_event_get); - free(arg); - if (stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id); -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index b6619f6..8efa5ab 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -325,6 +325,12 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); - } - break; -+ case GAZELLE_STAT_LSTACK_SHOW_INTR: -+ ret = intr_stats_get(stack->stack_idx, &dfx->data.intr_stats, sizeof(dfx->data.intr_stats)); -+ if (ret != EOK) { -+ LSTACK_LOG(ERR, LSTACK, "memcpy_s err ret=%d \n", ret); -+ } -+ break; - case GAZELLE_STAT_LSTACK_SHOW_VIRTIO: - ret = memcpy_s(&dfx->data.virtio, sizeof(dfx->data.virtio), virtio_instance_get(), - sizeof(*(virtio_instance_get()))); -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index b4a5953..7f77c12 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -100,7 +100,8 @@ __rte_always_inline - static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg) - { - msg->sync_flag = 0; -- lockless_queue_mpsc_push(queue, &msg->queue_node); -+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); - } - - __rte_always_inline -@@ -111,7 +112,8 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - pthread_spin_trylock(&msg->lock); - - msg->sync_flag = 1; -- lockless_queue_mpsc_push(queue, &msg->queue_node); -+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); - - // waiting stack unlock - pthread_spin_lock(&msg->lock); -@@ -123,7 +125,7 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - - int rpc_msgcnt(rpc_queue *queue) - { -- return lockless_queue_count(queue); -+ return lockless_queue_count(&queue->queue); - } - - static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) -@@ -159,7 +161,7 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - struct rpc_msg *msg; - - while (max_num--) { -- lockless_queue_node *node = lockless_queue_mpsc_pop(queue); -+ lockless_queue_node *node = lockless_queue_mpsc_pop(&queue->queue); - if (node == NULL) { - break; - } -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index fefb06d..75a23f2 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -20,6 +20,7 @@ - #include "lstack_cfg.h" - #include "lstack_log.h" - #include "lstack_port_map.h" -+#include "lstack_interrupt.h" - #include "lstack_virtio.h" - #include "securec.h" - -@@ -274,6 +275,7 @@ static int virtio_port_init(uint16_t port) - return retval; - } - -+ port_conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt; - retval = rte_eth_dev_configure(port, rx_queue_num, tx_queue_num, &port_conf); - if (retval != 0) { - LSTACK_LOG(ERR, LSTACK, "rte_eth_dev_configure failed retval=%d\n", retval); -@@ -297,6 +299,13 @@ static int virtio_port_init(uint16_t port) - LSTACK_LOG(ERR, LSTACK, "rte_eth_rx_queue_setup failed (queue %u) retval=%d \n", q, retval); - return retval; - } -+ -+ if (port_conf.intr_conf.rxq) { -+ struct intr_dpdk_event_args intr_arg; -+ intr_arg.port_id = port; -+ intr_arg.queue_id = q; -+ intr_register(q, INTR_DPDK_EVENT, &intr_arg); -+ } - } - return 0; - } -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 5e2d6fc..071492d 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -118,6 +118,7 @@ struct cfg_params { - - bool stack_mode_rtc; - bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread. -+ bool stack_interrupt; - - uint32_t read_connect_number; - uint32_t nic_read_number; -diff --git a/src/lstack/include/lstack_interrupt.h b/src/lstack/include/lstack_interrupt.h -new file mode 100644 -index 0000000..1be7d07 ---- /dev/null -+++ b/src/lstack/include/lstack_interrupt.h -@@ -0,0 +1,34 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __LSTACK_INTERRUPT_H__ -+#define __LSTACK_INTERRUPT_H__ -+ -+enum intr_type { -+ INTR_DPDK_EVENT = 0, -+ INTR_LOCAL_EVENT, -+ INTR_REMOTE_EVENT, -+}; -+ -+struct intr_dpdk_event_args { -+ uint16_t port_id; -+ uint16_t queue_id; -+}; -+ -+int intr_init(void); -+int intr_register(uint16_t stack_id, enum intr_type type, void *priv); -+void intr_wakeup(uint16_t stack_id, enum intr_type type); -+void intr_wait(uint16_t stack_id, uint32_t timeout); -+int intr_stats_get(uint16_t stack_id, void *ptr, int len); -+ -+#endif -+ -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 6f8e03e..c284d29 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -17,6 +17,7 @@ - #include - - #include "lstack_lockless_queue.h" -+#include "lstack_interrupt.h" - - #define MSG_ARG_0 (0) - #define MSG_ARG_1 (1) -@@ -25,7 +26,11 @@ - #define MSG_ARG_4 (4) - #define RPM_MSG_ARG_SIZE (5) - --typedef struct lockless_queue rpc_queue; -+typedef struct rpc_queue rpc_queue; -+struct rpc_queue { -+ struct lockless_queue queue; -+ uint16_t queue_id; -+}; - - struct rpc_stats { - uint16_t call_null; -@@ -60,9 +65,10 @@ struct rpc_msg { - lockless_queue_node queue_node; - }; - --static inline void rpc_queue_init(rpc_queue *queue) -+static inline void rpc_queue_init(rpc_queue *queue, uint16_t queue_id) - { -- lockless_queue_init(queue); -+ lockless_queue_init(&queue->queue); -+ queue->queue_id = queue_id; - } - struct rpc_stats *rpc_stats_get(void); - int rpc_msgcnt(rpc_queue *queue); -diff --git a/src/lstack/include/lstack_tx_cache.h b/src/lstack/include/lstack_tx_cache.h -index 04e9e35..ccd9c17 100644 ---- a/src/lstack/include/lstack_tx_cache.h -+++ b/src/lstack/include/lstack_tx_cache.h -@@ -15,5 +15,6 @@ - - int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops); - int tx_cache_send(uint16_t queue_id); -+int tx_cache_count(uint16_t queue_id); - - #endif /* _LSTACK_TX_CACHE_H_ */ -diff --git a/src/lstack/include/lstack_virtio.h b/src/lstack/include/lstack_virtio.h -index 5298dbe..745c86b 100644 ---- a/src/lstack/include/lstack_virtio.h -+++ b/src/lstack/include/lstack_virtio.h -@@ -50,4 +50,4 @@ int virtio_port_create(int lstack_net_port); - - struct virtio_instance* virtio_instance_get(void); - bool virtio_distribute_pkg_to_kernel(uint16_t dst_port); --#endif -\ No newline at end of file -+#endif -diff --git a/src/lstack/netif/lstack_tx_cache.c b/src/lstack/netif/lstack_tx_cache.c -index 9a48307..17d3c3b 100644 ---- a/src/lstack/netif/lstack_tx_cache.c -+++ b/src/lstack/netif/lstack_tx_cache.c -@@ -58,22 +58,40 @@ int tx_cache_init(uint16_t queue_id, void *priv, struct lstack_dev_ops *dev_ops) - return 0; - } - -+int tx_cache_count(uint16_t queue_id) -+{ -+ struct tx_cache *tx_cache = g_tx_cache[queue_id]; -+ if (tx_cache == NULL) { -+ return 0; -+ } -+ uint32_t start = tx_cache->send_start; -+ uint32_t end = tx_cache->send_end; -+ uint32_t count = (end - start) & TX_CACHE_MASK; -+ uint32_t capacity = TX_CACHE_MAX - 1; -+ -+ return (count > capacity) ? capacity : count; -+} -+ - int tx_cache_send(uint16_t queue_id) - { -+ uint32_t send_num; -+ uint32_t sent_pkts = 0; -+ uint32_t start; -+ uint32_t end; -+ - struct tx_cache *tx_cache = g_tx_cache[queue_id]; - if (tx_cache == NULL) { - LSTACK_LOG(ERR, LSTACK, "queue(%d) tx cache get failed\n", queue_id); - return 0; - } - -- uint32_t send_num = tx_cache->send_end - tx_cache->send_start; -+ send_num = tx_cache_count(queue_id); - if (send_num == 0) { - return 0; - } - -- uint32_t start = tx_cache->send_start & TX_CACHE_MASK; -- uint32_t end = tx_cache->send_end & TX_CACHE_MASK; -- uint32_t sent_pkts = 0; -+ start = tx_cache->send_start & TX_CACHE_MASK; -+ end = tx_cache->send_end & TX_CACHE_MASK; - if (start < end) { - sent_pkts = g_tx_cache_dev_ops.tx_xmit(tx_cache->priv, &tx_cache->send_pkts[start], send_num); - } else { -@@ -85,6 +103,7 @@ int tx_cache_send(uint16_t queue_id) - } - - tx_cache->send_start += sent_pkts; -+ - return sent_pkts; - } - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index e1a63a7..290046e 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -38,6 +38,8 @@ - #include "lstack_port_map.h" - #include "lstack_virtio.h" - -+#include "lstack_interrupt.h" -+ - /* INUSE_TX_PKTS_WATERMARK < VDEV_RX_QUEUE_SZ; - * USE_RX_PKTS_WATERMARK < FREE_RX_QUEUE_SZ. - * less, means more available mbuf. -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 7fa117a..f6d1148 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -138,6 +138,7 @@ static void gazelle_print_lstack_xstats(void *buf, const struct gazelle_stat_msg - static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_nic_features(void *buf, const struct gazelle_stat_msg_request *req_msg); - static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg); -+static void gazelle_print_lstack_stat_intr(void *buf, const struct gazelle_stat_msg_request *req_msg); - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - static void gazelle_print_fault_inject_set_status(void *buf, const struct gazelle_stat_msg_request *req_msg); -@@ -172,6 +173,7 @@ static struct gazelle_dfx_list g_gazelle_dfx_tbl[] = { - {GAZELLE_STAT_LSTACK_SHOW_AGGREGATE, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_aggregate}, - {GAZELLE_STAT_LSTACK_SHOW_NIC_FEATURES, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_nic_features}, - {GAZELLE_STAT_LSTACK_SHOW_PROTOCOL, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_proto}, -+ {GAZELLE_STAT_LSTACK_SHOW_INTR, sizeof(struct gazelle_stack_dfx_data), gazelle_print_lstack_stat_intr}, - - #ifdef GAZELLE_FAULT_INJECT_ENABLE - {GAZELLE_STAT_FAULT_INJECT_SET, sizeof(struct gazelle_stack_dfx_data), gazelle_print_fault_inject_set_status}, -@@ -1136,6 +1138,17 @@ static void gazelle_print_lstack_stat_proto_core(const struct gazelle_stack_dfx_ - printf("rterr: %lu\n", proto->rterr); - } - -+static void gazelle_print_lstack_stat_intr_core(const struct gazelle_stack_dfx_data *stat, -+ const struct interrupt_stats *intr_stats) -+{ -+ printf("\n------ stack tid: %6u ------\n", stat->tid); -+ printf("nic_event_cnt: %lu\n", intr_stats->nic_event_cnt); -+ printf("virtio_user_event_cnt: %lu\n", intr_stats->virtio_user_event_cnt); -+ printf("local_event_cnt: %lu\n", intr_stats->local_event_cnt); -+ printf("remote_event_cnt: %lu\n", intr_stats->remote_event_cnt); -+ printf("timeout_event_cnt: %lu\n", intr_stats->timeout_event_cnt); -+} -+ - static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - int32_t ret; -@@ -1155,6 +1168,25 @@ static void gazelle_print_lstack_stat_snmp(void *buf, const struct gazelle_stat_ - } while (true); - } - -+static void gazelle_print_lstack_stat_intr(void *buf, const struct gazelle_stat_msg_request *req_msg) -+{ -+ int32_t ret; -+ struct gazelle_stack_dfx_data *stat = (struct gazelle_stack_dfx_data *)buf; -+ struct interrupt_stats *intr_stats = &stat->data.intr_stats; -+ -+ printf("Statistics of lstack interrupt:\n"); -+ do { -+ gazelle_print_lstack_stat_intr_core(stat, intr_stats); -+ if (stat->eof != 0) { -+ break; -+ } -+ ret = dfx_stat_read_from_ltran(buf, sizeof(struct gazelle_stack_dfx_data), req_msg->stat_mode); -+ if (ret != GAZELLE_OK) { -+ return; -+ } -+ } while (true); -+} -+ - static void gazelle_print_lstack_stat_proto(void *buf, const struct gazelle_stat_msg_request *req_msg) - { - int32_t ret; -@@ -1579,6 +1611,8 @@ static int32_t parse_dfx_lstack_show_args(int32_t argc, char *argv[], struct gaz - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_MODE_MAX; - } else if (strcmp(param, "snmp") == 0 || strcmp(param, "-s") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_SNMP; -+ } else if (strcmp(param, "intr") == 0 || strcmp(param, "-I") == 0) { -+ req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_INTR; - } else if (strcmp(param, "virtio") == 0 || strcmp(param, "-v") == 0) { - req_msg[cmd_index++].stat_mode = GAZELLE_STAT_LSTACK_SHOW_VIRTIO; - } else if (strcmp(param, "connect") == 0 || strcmp(param, "-c") == 0) { --- -2.33.0 - diff --git a/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch b/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch deleted file mode 100644 index 79553f4..0000000 --- a/0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 7e6a5d97430f0d178c5e2b211c0c194fdea0c00a Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 27 Sep 2024 06:32:41 +0800 -Subject: [PATCH] af_xdp: set rlimit unlimit when gazelle init - ---- - src/lstack/core/lstack_init.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 37264a1..1d27f68 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -104,6 +105,20 @@ static int32_t check_process_conflict(void) - return 0; - } - -+/* Remove the memory resource limit of the current process. -+ * if the number of locked memory resources is exceeded, xdp_umem_create fails. -+ */ -+static int set_rlimit_unlimited(void) -+{ -+ struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; -+ -+ if (setrlimit(RLIMIT_MEMLOCK, &r) != 0) { -+ return -1; -+ } -+ -+ return 0; -+} -+ - void gazelle_exit(void) - { - wrap_api_exit(); -@@ -240,6 +255,11 @@ __attribute__((constructor)) void gazelle_network_init(void) - - wrap_api_init(); - -+ if (set_rlimit_unlimited() != 0) { -+ LSTACK_PRE_LOG(LSTACK_INFO, "set rlimit unlimited failed\n"); -+ LSTACK_EXIT(1, "set rlimit unlimited failed\n"); -+ } -+ - /* check primary process start */ - check_process_start(); - --- -2.33.0 - diff --git a/0265-fix-stack-null-when-register-interrupt.patch b/0265-fix-stack-null-when-register-interrupt.patch deleted file mode 100644 index 3e35ac7..0000000 --- a/0265-fix-stack-null-when-register-interrupt.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 14faa8f3a28490367c41c32ccb714ca4e743775d Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Mon, 30 Sep 2024 14:46:55 +0800 -Subject: [PATCH] fix stack null when register interrupt - ---- - src/lstack/core/lstack_protocol_stack.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index e412c3b..553dff3 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -562,7 +562,6 @@ static void* gazelle_stack_thread(void *arg) - unsigned wakeup_tick = 0; - - stack = stack_thread_init(arg); -- intr_register(stack->stack_idx, INTR_LOCAL_EVENT, stack_local_event_get); - free(arg); - if (stack == NULL) { - LSTACK_LOG(ERR, LSTACK, "stack_thread_init failed queue_id=%hu\n", queue_id); -@@ -577,6 +576,7 @@ static void* gazelle_stack_thread(void *arg) - return NULL; - } - -+ intr_register(stack->stack_idx, INTR_LOCAL_EVENT, stack_local_event_get); - stack_set_state(stack, RUNNING); - - while (stack_polling(wakeup_tick) == 0) { --- -2.33.0 - diff --git a/0266-rtw-fix-send-length-exceeding-send_ring_size.patch b/0266-rtw-fix-send-length-exceeding-send_ring_size.patch deleted file mode 100644 index 6f53ca8..0000000 --- a/0266-rtw-fix-send-length-exceeding-send_ring_size.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 26550111abb490691a8b774f8bcc5a11a5a1cd9a Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 30 Sep 2024 11:33:05 +0800 -Subject: [PATCH] rtw: fix send length exceeding send_ring_size - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_lwip.c | 31 +++++++++++++++++++++++++++++-- - 1 file changed, 29 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 2eb872c..cb0964b 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -538,8 +538,8 @@ static ssize_t do_lwip_udp_fill_sendring(struct lwip_sock *sock, const void *buf - 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) -+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) { -@@ -566,6 +566,10 @@ static ssize_t do_lwip_tcp_fill_sendring(struct lwip_sock *sock, const void *buf - if (sock->errevent > 0) { - GAZELLE_RETURN(ENOTCONN); - } -+ /* wait until (send_ring_size / 4) */ -+ if (write_avail > (rte_ring_get_capacity(sock->send_ring) >> 2)) { -+ break; -+ } - write_avail = gazelle_ring_readable_count(sock->send_ring); - } - -@@ -600,6 +604,29 @@ END: - return send_len; - } - -+static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags); -+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) -+{ -+ ssize_t ret, send_len = 0; -+ -+ while (true) { -+ ret = __do_lwip_tcp_fill_sendring(sock, (char *)buf + send_len, len - send_len, addr, addrlen); -+ // send = 0 : tcp peer close connection ? -+ if (unlikely(ret <= 0)) { -+ break; -+ } -+ send_len += ret; -+ if (send_len == len || netconn_is_nonblocking(sock->conn)) { -+ break; -+ } -+ -+ notice_stack_tcp_send(sock, sock->conn->callback_arg.socket, ret, 0); -+ } -+ -+ return send_len == 0 ? ret : send_len; -+} -+ - bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock) - { - bool replenish_again = false; --- -2.33.0 - diff --git a/0267-rpc-fix-rpc_sync_call-spinlock-block-when-msg-be-rec.patch b/0267-rpc-fix-rpc_sync_call-spinlock-block-when-msg-be-rec.patch deleted file mode 100644 index b32c87c..0000000 --- a/0267-rpc-fix-rpc_sync_call-spinlock-block-when-msg-be-rec.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 870caa8931a9f6a068172e56d7e401cd4b9b4086 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 8 Oct 2024 20:39:37 +0800 -Subject: [PATCH] rpc: fix rpc_sync_call spinlock block when msg be recalled - ---- - src/lstack/core/lstack_thread_rpc.c | 21 +++++++++++++-------- - 1 file changed, 13 insertions(+), 8 deletions(-) - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 7f77c12..aed792d 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -97,13 +97,19 @@ static void rpc_msg_free(struct rpc_msg *msg) - } - - __rte_always_inline --static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg) -+static void rpc_call(rpc_queue *queue, struct rpc_msg *msg) - { -- msg->sync_flag = 0; - lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); - intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); - } - -+__rte_always_inline -+static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg) -+{ -+ msg->sync_flag = 0; -+ rpc_call(queue, msg); -+} -+ - __rte_always_inline - static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - { -@@ -112,8 +118,7 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - pthread_spin_trylock(&msg->lock); - - msg->sync_flag = 1; -- lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -- intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); -+ rpc_call(queue, msg); - - // waiting stack unlock - pthread_spin_lock(&msg->lock); -@@ -209,7 +214,7 @@ static void callback_close(struct rpc_msg *msg) - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -- rpc_async_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -+ rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ - return; - } - -@@ -228,7 +233,7 @@ static void callback_shutdown(struct rpc_msg *msg) - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -- rpc_async_call(&stack->rpc_queue, msg); -+ rpc_call(&stack->rpc_queue, msg); - return; - } - -@@ -586,7 +591,7 @@ static void callback_tcp_send(struct rpc_msg *msg) - if (ret > 0 || NETCONN_IS_DATAOUT(sock)) { - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { - msg->recall_flag = 1; -- rpc_async_call(&stack->rpc_queue, msg); -+ rpc_call(&stack->rpc_queue, msg); - return; - } - } -@@ -675,7 +680,7 @@ static void callback_replenish_sendring(struct rpc_msg *msg) - msg->result = do_lwip_replenish_sendring(stack, sock); - if (msg->result == true) { - msg->recall_flag = 1; -- rpc_async_call(&stack->rpc_queue, msg); -+ rpc_call(&stack->rpc_queue, msg); - } - } - --- -2.33.0 - diff --git a/0268-bugfix-fix-gazelle-init-failed-while-setup-by-non-ro.patch b/0268-bugfix-fix-gazelle-init-failed-while-setup-by-non-ro.patch deleted file mode 100644 index b4019c1..0000000 --- a/0268-bugfix-fix-gazelle-init-failed-while-setup-by-non-ro.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 6b489d5555a2d28c37bb64f995962239f4e91624 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 8 Oct 2024 20:25:34 +0800 -Subject: [PATCH] bugfix: fix gazelle init failed while setup by non-root user - ---- - src/lstack/core/lstack_init.c | 3 +-- - src/lstack/include/lstack_log.h | 1 + - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 53e25b4..a72af84 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -257,8 +257,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - wrap_api_init(); - - if (set_rlimit_unlimited() != 0) { -- LSTACK_PRE_LOG(LSTACK_INFO, "set rlimit unlimited failed\n"); -- LSTACK_EXIT(1, "set rlimit unlimited failed\n"); -+ LSTACK_PRE_LOG(LSTACK_WARNING, "set rlimit unlimited failed. errno=%d\n", errno); - } - - /* check primary process start */ -diff --git a/src/lstack/include/lstack_log.h b/src/lstack/include/lstack_log.h -index e4bed37..a48e02f 100644 ---- a/src/lstack/include/lstack_log.h -+++ b/src/lstack/include/lstack_log.h -@@ -23,6 +23,7 @@ - - #define LSTACK_INFO LOG_INFO - #define LSTACK_ERR LOG_ERR -+#define LSTACK_WARNING LOG_WARNING - - /* before rte_eal_init */ - #define LSTACK_PRE_LOG(level, fmt, ...) \ --- -2.33.0 - diff --git a/0269-xdp-skip-checksum-temporarily-due-to-kernel-cannot-t.patch b/0269-xdp-skip-checksum-temporarily-due-to-kernel-cannot-t.patch deleted file mode 100644 index 243d7be..0000000 --- a/0269-xdp-skip-checksum-temporarily-due-to-kernel-cannot-t.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 77f34bd4406093dd47ec1fd60332ac5fd0f685a3 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 9 Oct 2024 21:05:34 +0800 -Subject: [PATCH] xdp: skip checksum temporarily due to kernel cannot transfer - offloads - ---- - src/lstack/core/lstack_dpdk.c | 10 ++++++++++ - src/lstack/include/lstack_dpdk.h | 2 ++ - src/lstack/netif/lstack_ethdev.c | 8 +++++++- - src/lstack/netif/lstack_vdev.c | 5 +++-- - 4 files changed, 22 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 530332b..33605b3 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -50,6 +50,7 @@ - - struct eth_params { - uint16_t port_id; -+ bool is_xdp; - - uint16_t nb_queues; - uint16_t nb_rx_desc; -@@ -413,6 +414,12 @@ static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *de - return rss_enable; - } - -+bool dpdk_nic_is_xdp(void) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ return stack_group->eth_params->is_xdp; -+} -+ - static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint16_t nb_queues, int *rss_enable) - { - struct rte_eth_dev_info dev_info; -@@ -442,6 +449,9 @@ static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint - eth_params->conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt; - - eth_params_checksum(ð_params->conf, &dev_info); -+ if (strcmp(dev_info.driver_name, "net_af_xdp") == 0) { -+ eth_params->is_xdp = true; -+ } - - if (!get_global_cfg_params()->tuple_filter) { - *rss_enable = eth_params_rss(ð_params->conf, &dev_info); -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 965a0cb..0210843 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -65,4 +65,6 @@ int32_t dpdk_init_lstack_kni(void); - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - -+bool dpdk_nic_is_xdp(void); -+ - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 1a721f6..315cced 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -364,7 +364,13 @@ static err_t eth_dev_init(struct netif *netif) - - netif->hwaddr_len = ETHER_ADDR_LEN; - -- netif_set_rxol_flags(netif, get_protocol_stack_group()->rx_offload); -+ if (dpdk_nic_is_xdp()) { -+ netif_set_rxol_flags(netif, RTE_ETH_RX_OFFLOAD_TCP_CKSUM | -+ RTE_ETH_RX_OFFLOAD_UDP_CKSUM | -+ RTE_ETH_RX_OFFLOAD_IPV4_CKSUM); -+ } else { -+ netif_set_rxol_flags(netif, get_protocol_stack_group()->rx_offload); -+ } - netif_set_txol_flags(netif, get_protocol_stack_group()->tx_offload); - if (get_global_cfg_params()->stack_mode_rtc) { - netif_set_rtc_mode(netif); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 290046e..b1d1a1b 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -146,8 +146,9 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - return pkt_num; - } - -- /* skip gro when tcp/ip cksum offloads disable */ -- if (get_protocol_stack_group()->rx_offload == 0 || (get_global_cfg_params()->vlan_mode >= 0 -+ if (get_protocol_stack_group()->rx_offload == 0 || /* skip gro when tcp/ip cksum offloads disable */ -+ dpdk_nic_is_xdp() || /* kernel has done GRO */ -+ (get_global_cfg_params()->vlan_mode >= 0 - && !(get_protocol_stack_group()->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP))) { - return pkt_num; - } --- -2.33.0 - diff --git a/0270-fix-dpdk_nic_is_xdp-coredump-in-ltran-mode.patch b/0270-fix-dpdk_nic_is_xdp-coredump-in-ltran-mode.patch deleted file mode 100644 index 1cea7d6..0000000 --- a/0270-fix-dpdk_nic_is_xdp-coredump-in-ltran-mode.patch +++ /dev/null @@ -1,27 +0,0 @@ -From ba4115c3e56f32fb5186cd178b36974367723df9 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 10 Oct 2024 17:55:53 +0800 -Subject: [PATCH] fix dpdk_nic_is_xdp coredump in ltran mode - ---- - src/lstack/core/lstack_dpdk.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 33605b3..9294c5b 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -417,6 +417,10 @@ static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *de - bool dpdk_nic_is_xdp(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ /* eth_params is null in ltran mode */ -+ if (stack_group->eth_params == NULL) { -+ return false; -+ } - return stack_group->eth_params->is_xdp; - } - --- -2.33.0 - diff --git a/0271-fix-the-coredump-when-gazellectl-l.patch b/0271-fix-the-coredump-when-gazellectl-l.patch deleted file mode 100644 index d427958..0000000 --- a/0271-fix-the-coredump-when-gazellectl-l.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 577698e8a9a44d5689a7608e7bfbe27ed6529a54 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 11 Oct 2024 10:48:03 +0800 -Subject: [PATCH] fix the coredump when gazellectl -l - ---- - src/lstack/core/lstack_stack_stat.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 8efa5ab..c88da8f 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -64,7 +64,7 @@ void time_stamp_record(int fd, struct pbuf *pbuf) - { - struct lwip_sock *sock = lwip_get_socket(fd); - -- if (get_protocol_stack_group()->latency_start && sock && pbuf) { -+ if (get_protocol_stack_group()->latency_start && sock && sock->stack && pbuf) { - calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); - time_stamp_into_recvmbox(sock); - } -@@ -122,6 +122,10 @@ void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const - } - - lt = &pbuf_to_private(pbuf)->lt; -+ if (lt == NULL) { -+ return; -+ } -+ - lt_type = (type / GAZELLE_LATENCY_READ_MAX) ? GAZELLE_LATENCY_WR : GAZELLE_LATENCY_RD; - if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time || lt_type != lt->type) { - return; --- -2.33.0 - diff --git a/0272-control-call-epoll_ctl-delete-fd-when-fd-close.patch b/0272-control-call-epoll_ctl-delete-fd-when-fd-close.patch deleted file mode 100644 index 2361cfe..0000000 --- a/0272-control-call-epoll_ctl-delete-fd-when-fd-close.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 2c8bf41f4adf425afc668b77c2a792abcdd98c5b Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 17 Oct 2024 19:16:55 +0800 -Subject: [PATCH] control: call epoll_ctl delete fd when fd close - ---- - src/lstack/core/lstack_control_plane.c | 8 ++++++++ - src/lstack/core/lstack_lwip.c | 4 ++++ - 2 files changed, 12 insertions(+) - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 11f5129..bf34693 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -778,6 +778,12 @@ void control_server_thread(void *arg) - } - - if ((evt_array.events & EPOLLERR) || (evt_array.events & EPOLLHUP)) { -+ /* -+ * if app call fork and child process inherits the fd, -+ * close fd cannot ensure that fd is removed from the epoll, -+ * so epoll_ctl_del need to be called. -+ */ -+ posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_DEL, evt_array.data.fd, NULL); - posix_api->close_fn(evt_array.data.fd); - continue; - } -@@ -795,6 +801,8 @@ void control_server_thread(void *arg) - } - } else { - if (handle_stat_request(evt_array.data.fd) < 0) { -+ /* same as the comment above */ -+ posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_DEL, evt_array.data.fd, NULL); - posix_api->close_fn(evt_array.data.fd); - } - } -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index cb0964b..bb261d2 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -185,6 +185,10 @@ int do_lwip_init_sock(int32_t fd) - return 0; - } - -+ if (sock->recv_ring != NULL || sock->send_ring != NULL) { -+ LSTACK_LOG(ERR, LSTACK, "socket(%d) not close but open again?\n", fd); -+ } -+ - reset_sock_data(sock); - - sock->recv_ring = gazelle_ring_create_fast("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ); --- -2.33.0 - diff --git a/0273-epoll-remove-unnecessary-judgment-code.patch b/0273-epoll-remove-unnecessary-judgment-code.patch deleted file mode 100644 index 25bede0..0000000 --- a/0273-epoll-remove-unnecessary-judgment-code.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0cecec15dad5d4baecceb343e1803eaa9c66de26 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 22 Oct 2024 10:14:58 +0800 -Subject: [PATCH] epoll: remove unnecessary judgment code - ---- - src/lstack/api/lstack_epoll.c | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index ce3d267..acbf393 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -122,17 +122,6 @@ void wakeup_stack_epoll(struct protocol_stack *stack) - struct list_node *node, *temp; - - list_for_each_node(node, temp, &stack->wakeup_list) { -- /* When temp is NULL, find the tail node in the wekeup_list and connect it to the back of the node */ -- if (unlikely(temp == NULL)) { -- struct list_node *nod = &stack->wakeup_list; -- while (nod->prev && nod->prev != node) { -- nod = nod->prev; -- } -- nod->prev = node; -- node->next = nod; -- temp = nod; -- } -- - struct wakeup_poll *wakeup = container_of_uncheck_ptr((node - stack->stack_idx), struct wakeup_poll, wakeup_list); - - if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { --- -2.33.0 - diff --git a/0274-slove-compile-err-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch b/0274-slove-compile-err-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch deleted file mode 100644 index f665305..0000000 --- a/0274-slove-compile-err-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch +++ /dev/null @@ -1,50 +0,0 @@ -From d64a161fb935b8fbfd69781a5cf891d2cebed2df Mon Sep 17 00:00:00 2001 -From: hkk -Date: Fri, 25 Oct 2024 16:55:23 +0800 -Subject: [PATCH] slove compile err when GAZELLE_TCP_REUSE_IPPORT is off - ---- - src/lstack/api/lstack_rtw_api.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 7ceff20..8765463 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -233,8 +233,9 @@ static int stack_broadcast_listen(int fd, int backlog) - } - - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+#if GAZELLE_TCP_REUSE_IPPORT - int min_conn_stk_idx = get_min_conn_stack(stack_group); -- -+#endif - for (int32_t i = 0; i < stack_group->stack_num; ++i) { - stack = stack_group->stacks[i]; - if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -@@ -249,13 +250,13 @@ static int stack_broadcast_listen(int fd, int backlog) - } else { - clone_fd = fd; - } -- -+#if GAZELLE_TCP_REUSE_IPPORT - if (min_conn_stk_idx == i) { - lwip_get_socket(clone_fd)->conn->is_master_fd = 1; - } else { - lwip_get_socket(clone_fd)->conn->is_master_fd = 0; - } -- -+#endif - ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); - if (ret < 0) { - stack_broadcast_close(fd); -@@ -546,4 +547,4 @@ void rtw_api_init(posix_api_t *api) - - api->poll_fn = rtw_poll; - api->select_fn = rtw_select; --} -\ No newline at end of file -+} --- -2.33.0 - diff --git a/0275-bugfix-start-fail-when-executing-the-popen-command-f.patch b/0275-bugfix-start-fail-when-executing-the-popen-command-f.patch deleted file mode 100644 index 61c061f..0000000 --- a/0275-bugfix-start-fail-when-executing-the-popen-command-f.patch +++ /dev/null @@ -1,25 +0,0 @@ -From e2ab6a041aa5587c6e6d021c32da2ce4d98522b2 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Wed, 30 Oct 2024 11:15:55 +0800 -Subject: [PATCH] bugfix: start fail when executing the popen command for the - second time in openGauss - ---- - src/lstack/core/lstack_init.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index a72af84..8ffc3a1 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -98,7 +98,6 @@ static int32_t check_process_conflict(void) - } - - ret = flock((fileno(fp)), LOCK_EX | LOCK_NB); -- (void)fclose(fp); - if (ret < 0) { - return -1; - } --- -2.33.0 - diff --git a/0276-Fix-annotation-errors.patch b/0276-Fix-annotation-errors.patch deleted file mode 100644 index 967c847..0000000 --- a/0276-Fix-annotation-errors.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 1005ad274d1a59d8a2d60fc280eae38f43c90dbe Mon Sep 17 00:00:00 2001 -From: lixiang -Date: Fri, 11 Oct 2024 09:58:44 +0800 -Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - ---- - examples/inc/server.h | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/examples/inc/server.h b/examples/inc/server.h -index 4631a28..35773e1 100644 ---- a/examples/inc/server.h -+++ b/examples/inc/server.h -@@ -33,7 +33,7 @@ struct ServerMumUnit - uint64_t recv_bytes; ///< total receive bytes - struct ServerIpInfo server_ip_info; - uint16_t port; ///< server port -- uint32_t pktlen; ///< the length of peckage -+ uint32_t pktlen; ///< the length of package - char* domain; ///< communication domain - char* api; ///< the type of api - bool debug; ///< if we print the debug information -@@ -65,7 +65,7 @@ struct ServerMudWorker - int32_t epfd; ///< the worker epoll file descriptor - struct epoll_event *epevs; ///< the epoll events - uint64_t recv_bytes; ///< total receive bytes -- uint32_t pktlen; ///< the length of peckage -+ uint32_t pktlen; ///< the length of package - ip_addr_t ip; ///< client ip - uint16_t port; ///< client port - char* api; ///< the type of api -@@ -88,7 +88,7 @@ struct ServerMud - struct epoll_event *epevs; ///< the epoll events - struct ServerIpInfo server_ip_info; - bool* port; ///< server port point to parameter's port -- uint32_t pktlen; ///< the length of peckage -+ uint32_t pktlen; ///< the length of package - char* domain; ///< communication domain - char* api; ///< the type of api - bool debug; ///< if we print the debug information -@@ -184,7 +184,7 @@ void *sermud_listener_create_and_run(void *arg); - int32_t sermud_create_and_run(struct ProgramParams *params); - - /** -- * @brief the multi thread, unblock, mutliplexing IO server prints informations -+ * @brief the multi thread, unblock, multiplexing IO server prints informations - * The multi thread, unblock, mutliplexing IO server prints informations. - * @param server_mum the server information - */ -@@ -199,7 +199,7 @@ void sermum_info_print(struct ServerMum *server_mum); - int32_t sersum_create_epfd_and_reg(struct ServerMumUnit *server_unit); - - /** -- * @brief the single thread, unblock, mutliplexing IO server accepts the connections -+ * @brief the single thread, unblock, multiplexing IO server accepts the connections - * The single thread, unblock, mutliplexing IO server accepts the connections. - * @param server_unit the server unit - * @param server_handler the server handler -@@ -208,7 +208,7 @@ int32_t sersum_create_epfd_and_reg(struct ServerMumUnit *server_unit); - int32_t sersum_accept_connects(struct epoll_event *cur_epev, struct ServerMumUnit *server_unit); - - /** -- * @brief the single thread, unblock, mutliplexing IO server processes the events -+ * @brief the single thread, unblock, multiplexing IO server processes the events - * The single thread, unblock, mutliplexing IO server processes the events. - * @param server_unit the server unit - * @return the result pointer --- -2.33.0 - diff --git a/0277-remove-the-unused-return-variable.patch b/0277-remove-the-unused-return-variable.patch deleted file mode 100644 index d860cec..0000000 --- a/0277-remove-the-unused-return-variable.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1494a9e8d7b461301476be05a6b9cbc170b4d51d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?= - -Date: Fri, 11 Oct 2024 14:56:06 +0800 -Subject: [PATCH] remove the unused return variable. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -因为kni_config_network_interface函数始终返回0,此提交移除了‘ret’变量,化简了函数的返回逻辑 - -Signed-off-by:zhangchujun ---- - src/common/dpdk_common.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/common/dpdk_common.c b/src/common/dpdk_common.c -index 66ad529..fafd266 100644 ---- a/src/common/dpdk_common.c -+++ b/src/common/dpdk_common.c -@@ -55,7 +55,6 @@ struct rte_kni* get_gazelle_kni(void) - - static int32_t kni_config_network_interface(uint16_t port_id, uint8_t if_up) - { -- int32_t ret = 0; - static bool g_bond_dev_started = false; - - if (port_id >= rte_eth_dev_count_avail() || port_id >= GAZELLE_MAX_ETHPORTS) { -@@ -82,7 +81,7 @@ static int32_t kni_config_network_interface(uint16_t port_id, uint8_t if_up) - } - - COMMON_INFO("Configure network interface of %hu %s \n", port_id, if_up ? "up" : "down"); -- return ret; -+ return 0; - } - - int32_t dpdk_kni_init(uint16_t port, struct rte_mempool *pool) --- -2.33.0 - diff --git a/0278-add-SO_NUMA_ID-optname-for-adapting-opneGauss.patch b/0278-add-SO_NUMA_ID-optname-for-adapting-opneGauss.patch deleted file mode 100644 index ca4903b..0000000 --- a/0278-add-SO_NUMA_ID-optname-for-adapting-opneGauss.patch +++ /dev/null @@ -1,28 +0,0 @@ -From f62692f99e2d10803a667202694b5e38fa335edb Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Thu, 31 Oct 2024 10:37:06 +0800 -Subject: [PATCH] add SO_NUMA_ID(optname) for adapting opneGauss - ---- - src/lstack/api/lstack_wrap.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8f80f98..e0e8244 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -381,7 +381,11 @@ static bool unsupport_optname(int32_t level, int32_t optname) - - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { -+#define SO_NUMA_ID 0x100c - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP && !unsupport_optname(level, optname)) { -+ if (level == IPPROTO_IP && optname == SO_NUMA_ID) { -+ return lwip_get_socket(s)->stack->socket_id; -+ } - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } - --- -2.33.0 - diff --git a/0279-xdp-support-XDP_STATISTICS-by-posix_api-getsockopt_f.patch b/0279-xdp-support-XDP_STATISTICS-by-posix_api-getsockopt_f.patch deleted file mode 100644 index 37258a5..0000000 --- a/0279-xdp-support-XDP_STATISTICS-by-posix_api-getsockopt_f.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e1cd2f3205eb6ebcf63ee931c48c54dc49417708 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Fri, 1 Nov 2024 09:12:52 +0800 -Subject: [PATCH] xdp: support XDP_STATISTICS by posix_api->getsockopt_fn - ---- - src/lstack/api/lstack_wrap.c | 29 +++++++++++++++++++---------- - 1 file changed, 19 insertions(+), 10 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8f80f98..98bb8a1 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -363,20 +364,28 @@ static bool unsupport_socket_optname(int32_t optname) - return false; - } - --static bool unsupport_optname(int32_t level, int32_t optname) -+static bool unsupport_xdp_optname(int32_t optname) - { -- if (level == SOL_IP) { -- return unsupport_ip_optname(optname); -- } -- -- if (level == SOL_TCP) { -- return unsupport_tcp_optname(optname); -+ if (optname == XDP_STATISTICS) { -+ return true; - } -+ return false; -+} - -- if (level == SOL_SOCKET) { -- return unsupport_socket_optname(optname); -+static bool unsupport_optname(int32_t level, int32_t optname) -+{ -+ switch (level) { -+ case SOL_IP: -+ return unsupport_ip_optname(optname); -+ case SOL_TCP: -+ return unsupport_tcp_optname(optname); -+ case SOL_SOCKET: -+ return unsupport_socket_optname(optname); -+ case SOL_XDP: -+ return unsupport_xdp_optname(optname); -+ default: -+ return false; - } -- return false; - } - - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) --- -2.33.0 - diff --git a/0280-interrupt-fix-timeout-events-cannot-be-counted.patch b/0280-interrupt-fix-timeout-events-cannot-be-counted.patch deleted file mode 100644 index d8f6976..0000000 --- a/0280-interrupt-fix-timeout-events-cannot-be-counted.patch +++ /dev/null @@ -1,25 +0,0 @@ -From e35d6ffd66becc2725b38115322307261dd87f07 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 2 Nov 2024 19:00:31 +0800 -Subject: [PATCH] interrupt: fix timeout events cannot be counted - ---- - src/lstack/core/lstack_interrupt.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_interrupt.c b/src/lstack/core/lstack_interrupt.c -index 26823cd..67b763c 100644 ---- a/src/lstack/core/lstack_interrupt.c -+++ b/src/lstack/core/lstack_interrupt.c -@@ -317,7 +317,7 @@ static inline void intr_block(uint16_t stack_id, uint32_t timeout) - } - } - -- if (event_cnt < 0) { -+ if (event_cnt == 0) { - intr_config->stats.timeout_event_cnt++; - } - } --- -2.33.0 - diff --git a/0281-remove-code-about-nobolck-mode-for-mysql.patch b/0281-remove-code-about-nobolck-mode-for-mysql.patch deleted file mode 100644 index 5d12828..0000000 --- a/0281-remove-code-about-nobolck-mode-for-mysql.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 84897b16c0a93606817443f792da97b5923fbdf0 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Thu, 31 Oct 2024 16:06:21 +0800 -Subject: [PATCH] remove: code about nobolck mode for mysql - ---- - src/lstack/api/lstack_rtw_api.c | 5 +---- - src/lstack/core/lstack_cfg.c | 9 --------- - src/lstack/include/lstack_cfg.h | 1 - - 3 files changed, 1 insertion(+), 14 deletions(-) - -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 8765463..eab379c 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -190,10 +190,7 @@ static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *add - - static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) - { -- if (get_global_cfg_params()->nonblock_mode) -- return stack_broadcast_accept4(fd, addr, addrlen, O_NONBLOCK); -- else -- return stack_broadcast_accept4(fd, addr, addrlen, 0); -+ return stack_broadcast_accept4(fd, addr, addrlen, 0); - } - - /* choice one stack listen */ -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index f239b60..4c8f066 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -81,7 +81,6 @@ static int32_t parse_nic_rxqueue_size(void); - static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); --static int32_t parse_defaule_nonblock_mode(void); - static int32_t parse_rpc_msg_max(void); - static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); -@@ -149,7 +148,6 @@ static struct config_vector_t g_config_tbl[] = { - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, - { "nic_vlan_mode", parse_nic_vlan_mode }, -- { "nonblock_mode", parse_defaule_nonblock_mode }, - { "rpc_msg_max", parse_rpc_msg_max }, - { "send_cache_mode", parse_send_cache_mode }, - { "flow_bifurcation", parse_flow_bifurcation}, -@@ -1358,13 +1356,6 @@ static int32_t parse_nic_vlan_mode(void) - return ret; - } - --static int32_t parse_defaule_nonblock_mode(void) --{ -- int32_t ret; -- PARSE_ARG(g_config_params.nonblock_mode, "nonblock_mode", 1, 0, 1, ret); -- return ret; --} -- - static int32_t parse_rpc_msg_max(void) - { - int32_t ret; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 071492d..876423d 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -136,7 +136,6 @@ struct cfg_params { - struct { // deprecated - char unix_socket_filename[NAME_MAX]; - bool use_ltran; // false:lstack read from nic. true:lstack read form ltran process. -- bool nonblock_mode; - bool udp_enable; - bool kni_switch; - }; --- -2.33.0 - diff --git a/0282-LOG-Optimize-some-log-displays.patch b/0282-LOG-Optimize-some-log-displays.patch deleted file mode 100644 index b0d408d..0000000 --- a/0282-LOG-Optimize-some-log-displays.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c33bfd14030ee84d4da1a5083fe47271f4cb27bb Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 5 Nov 2024 19:55:52 +0800 -Subject: [PATCH] LOG: Optimize some log displays - ---- - src/lstack/core/lstack_init.c | 2 +- - src/lstack/core/lstack_thread_rpc.c | 3 --- - 2 files changed, 1 insertion(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 8ffc3a1..276cdf8 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -264,7 +264,7 @@ __attribute__((constructor)) void gazelle_network_init(void) - - /* check conflict */ - if (check_process_conflict() < 0) { -- LSTACK_PRE_LOG(LSTACK_INFO, "Have another same primary process. WARNING: Posix API will use kernel mode!\n"); -+ LSTACK_PRE_LOG(LSTACK_INFO, "Main process has been initialized, this process will use kernel mode!\n"); - return; - } - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index aed792d..26bd16a 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -470,9 +470,6 @@ int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, sock - static void callback_getpeername(struct rpc_msg *msg) - { - msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -- } - } - - static void callback_getsockname(struct rpc_msg *msg) --- -2.33.0 - diff --git a/0283-xdp-support-bind-no-cpu-mode.patch b/0283-xdp-support-bind-no-cpu-mode.patch deleted file mode 100644 index 708f4f8..0000000 --- a/0283-xdp-support-bind-no-cpu-mode.patch +++ /dev/null @@ -1,967 +0,0 @@ -From 10eb6041c9a3e632b9fc2e769d7e726fbf7c9dd8 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Sat, 2 Nov 2024 16:03:54 +0800 -Subject: [PATCH] xdp: support bind no cpu mode - ---- - src/common/gazelle_base_func.h | 8 + - src/common/gazelle_reg_msg.h | 21 +- - src/lstack/api/lstack_rtw_api.c | 3 - - src/lstack/api/lstack_wrap.c | 2 +- - src/lstack/core/lstack_cfg.c | 303 +++++++++++---------- - src/lstack/core/lstack_dpdk.c | 64 ++++- - src/lstack/core/lstack_protocol_stack.c | 113 +++----- - src/lstack/include/lstack_cfg.h | 10 +- - src/lstack/include/lstack_dpdk.h | 2 + - src/lstack/include/lstack_protocol_stack.h | 3 +- - src/lstack/include/lstack_thread_rpc.h | 2 + - src/lstack/netif/lstack_flow.c | 6 +- - 12 files changed, 289 insertions(+), 248 deletions(-) - -diff --git a/src/common/gazelle_base_func.h b/src/common/gazelle_base_func.h -index be87ccd..a579cd4 100644 ---- a/src/common/gazelle_base_func.h -+++ b/src/common/gazelle_base_func.h -@@ -13,6 +13,8 @@ - #ifndef __GAZELLE_BASE_FUNC_H__ - #define __GAZELLE_BASE_FUNC_H__ - -+#include -+ - #define GAZELLE_FREE(p) do { \ - if (p) { \ - free(p); \ -@@ -28,6 +30,12 @@ - #define NODE_ENTRY(node, type, member) \ - ((type*)((char*)(node) - (size_t)&((type*)0)->member)) - -+#define MB_IN_BYTES (1024 * 1024) -+static inline int bytes_to_mb(uint32_t bytes) -+{ -+ return ceil((double)bytes / MB_IN_BYTES); -+} -+ - int32_t separate_str_to_array(char *args, uint32_t *array, int32_t array_size, int32_t max_value); - - int32_t check_and_set_run_dir(void); -diff --git a/src/common/gazelle_reg_msg.h b/src/common/gazelle_reg_msg.h -index d849cea..f9de32c 100644 ---- a/src/common/gazelle_reg_msg.h -+++ b/src/common/gazelle_reg_msg.h -@@ -17,19 +17,22 @@ - - #include "gazelle_opt.h" - --#define NULL_CLIENT_IP UINT32_MAX --#define NULL_CLIENT_PORT UINT16_MAX -+#define NULL_CLIENT_IP UINT32_MAX -+#define NULL_CLIENT_PORT UINT16_MAX - --#define GAZELLE_MAX_REG_ARGS 32 -+#define GAZELLE_MAX_REG_ARGS 32 - - #define ENQUEUE_RING_RETRY_TIMEOUT 10 // ms - --#define OPT_BASE_VIRTADDR "--base-virtaddr" --#define OPT_FILE_PREFIX "--file-prefix" --#define OPT_SOCKET_MEM "--socket-mem" --#define OPT_LEGACY_MEM "--legacy-mem" --#define OPT_HUGE_DIR "--huge-dir" --#define OPT_BIND_CORELIST "-l" -+#define OPT_BASE_VIRTADDR "--base-virtaddr" -+#define OPT_FILE_PREFIX "--file-prefix" -+#define OPT_SOCKET_MEM "--socket-mem" -+#define OPT_LEGACY_MEM "--legacy-mem" -+#define OPT_HUGE_DIR "--huge-dir" -+#define OPT_BIND_CORELIST "-l" -+ -+#define GAZELLE_MAX_NUMA_NODES 4 -+#define SOCKET_MEM_STRLEN (GAZELLE_MAX_NUMA_NODES * 10) - - /* types for msg from lstack to ltran */ - enum response_type { -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index eab379c..1b02e2a 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -235,9 +235,6 @@ static int stack_broadcast_listen(int fd, int backlog) - #endif - for (int32_t i = 0; i < stack_group->stack_num; ++i) { - stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -- continue; -- } - if (stack != cur_stack) { - clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, (struct sockaddr *)&addr, addr_len); - if (clone_fd < 0) { -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 66cea51..c228cab 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -393,7 +393,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v - #define SO_NUMA_ID 0x100c - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP && !unsupport_optname(level, optname)) { - if (level == IPPROTO_IP && optname == SO_NUMA_ID) { -- return lwip_get_socket(s)->stack->socket_id; -+ return lwip_get_socket(s)->stack->numa_id; - } - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 4c8f066..43482af 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -22,14 +22,18 @@ - #include - #include - #include -+#include - - #include -+#include -+#include - #include - #include - - #include "common/gazelle_reg_msg.h" - #include "common/gazelle_base_func.h" - #include "lstack_log.h" -+#include "lstack_dpdk.h" - #include "lstack_cfg.h" - - #define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" -@@ -70,7 +74,6 @@ static int32_t parse_recv_ring_size(void); - static int32_t parse_num_process(void); - static int32_t parse_process_numa(void); - static int32_t parse_process_index(void); --static int32_t parse_seperate_sendrecv_args(void); - static int32_t parse_tuple_filter(void); - static int32_t parse_bond_mode(void); - static int32_t parse_bond_miimon(void); -@@ -85,6 +88,7 @@ static int32_t parse_rpc_msg_max(void); - static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); -+static int32_t parse_stack_num(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -118,9 +122,16 @@ static struct config_vector_t g_config_tbl[] = { - { "mask_addr", parse_mask_addr }, - { "use_ltran", parse_use_ltran }, - { "devices", parse_devices }, -- { "dpdk_args", parse_dpdk_args }, -- { "seperate_send_recv", parse_seperate_sendrecv_args }, -+ { "tcp_conn_count", parse_tcp_conn_count }, -+ { "mbuf_count_per_conn", parse_mbuf_count_per_conn }, -+ { "nic_rxqueue_size", parse_nic_rxqueue_size}, -+ { "nic_txqueue_size", parse_nic_txqueue_size}, -+ { "send_ring_size", parse_send_ring_size }, -+ { "recv_ring_size", parse_recv_ring_size }, -+ { "rpc_msg_max", parse_rpc_msg_max }, -+ { "stack_num", parse_stack_num }, - { "num_cpus", parse_stack_cpu_number }, -+ { "dpdk_args", parse_dpdk_args }, - { "low_power_mode", parse_low_power_mode }, - { "kni_switch", parse_kni_switch }, - { "listen_shadow", parse_listen_shadow }, -@@ -128,13 +139,9 @@ static struct config_vector_t g_config_tbl[] = { - { "app_exclude_cpus", parse_app_exclude_cpus }, - { "main_thread_affinity", parse_main_thread_affinity }, - { "unix_prefix", parse_unix_prefix }, -- { "tcp_conn_count", parse_tcp_conn_count }, -- { "mbuf_count_per_conn", parse_mbuf_count_per_conn }, - { "read_connect_number", parse_read_connect_number }, - { "rpc_number", parse_rpc_number }, - { "nic_read_number", parse_nic_read_number }, -- { "send_ring_size", parse_send_ring_size }, -- { "recv_ring_size", parse_recv_ring_size }, - { "num_process", parse_num_process }, - { "process_numa", parse_process_numa }, - { "process_idx", parse_process_index }, -@@ -144,11 +151,8 @@ static struct config_vector_t g_config_tbl[] = { - { "bond_slave_mac", parse_bond_slave_mac }, - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, -- { "nic_rxqueue_size", parse_nic_rxqueue_size}, -- { "nic_txqueue_size", parse_nic_txqueue_size}, - { "stack_thread_mode", parse_stack_thread_mode }, - { "nic_vlan_mode", parse_nic_vlan_mode }, -- { "rpc_msg_max", parse_rpc_msg_max }, - { "send_cache_mode", parse_send_cache_mode }, - { "flow_bifurcation", parse_flow_bifurcation}, - { "stack_interrupt", parse_stack_interrupt}, -@@ -354,135 +358,80 @@ static int32_t get_param_idx(int32_t argc, char **argv, const char *param) - return -1; - } - --static bool have_corelist_arg(int32_t argc, char **argv) -+static int32_t stack_bind_no_cpu(void) - { -- for (uint32_t i = 0; i < argc; i++) { -- if (strncmp(argv[i], OPT_BIND_CORELIST, strlen(OPT_BIND_CORELIST)) == 0) { -- return true; -- } -+ uint16_t numa_id = 0; -+ -+ /* launch a lstack thread when neither num_cpus nor stack_num is specified */ -+ if (g_config_params.stack_num == 0) { -+ g_config_params.stack_num = 1; -+ } - -- if (strncmp(argv[i], "--lcores", strlen("--lcores")) == 0) { -- return true; -- } -- -- if (strncmp(argv[i], "-c", strlen("-c")) == 0) { -- return true; -- } -+ numa_id = numa_node_of_cpu(sched_getcpu()); -+ if (numa_id < 0) { -+ return -EINVAL; -+ } - -- if (strncmp(argv[i], "-s", strlen("-s")) == 0) { -- return true; -- } -+ g_config_params.numa_id = numa_id; -+ g_config_params.num_cpu = g_config_params.stack_num; -+ g_config_params.num_queue = g_config_params.num_cpu; -+ g_config_params.tot_queue_num = g_config_params.num_queue; - -- if (strncmp(argv[i], "-S", strlen("-S")) == 0) { -- return true; -- } -- } -+ LSTACK_PRE_LOG(LSTACK_INFO, "NUMA node: %d\n", g_config_params.numa_id); - -- return false; -+ return 0; - } - --static int32_t parse_stack_cpu_number(void) -+ -+static int32_t stack_bind_cpus(void) - { -- const config_setting_t *num_cpus = NULL; -+ int cnt = 0; -+ char *tmp_arg = NULL; - const char *args = NULL; -+ const config_setting_t *num_cpus = NULL; - -- if (!g_config_params.seperate_send_recv) { -- num_cpus = config_lookup(&g_config, "num_cpus"); -- if (num_cpus == NULL) { -- return -EINVAL; -- } -- -- args = config_setting_get_string(num_cpus); -- if (args == NULL) { -- return -EINVAL; -- } -- -- if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { -- int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); -- if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); -- g_config_params.dpdk_argc++; -- -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); -- g_config_params.dpdk_argc++; -- } -- } -- -- char *tmp_arg = strdup_assert_return(args); -- int32_t cnt = separate_str_to_array(tmp_arg, g_config_params.cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); -- free(tmp_arg); -- if (cnt <= 0 || cnt > CFG_MAX_CPUS) { -- return -EINVAL; -- } -- -- g_config_params.num_cpu = cnt; -- g_config_params.num_queue = (uint16_t)cnt; -- g_config_params.tot_queue_num = g_config_params.num_queue; -- } else { -- // send_num_cpus -- num_cpus = config_lookup(&g_config, "send_num_cpus"); -- if (num_cpus == NULL) { -- return -EINVAL; -- } -- -- args = config_setting_get_string(num_cpus); -- if (args == NULL) { -- return -EINVAL; -- } -- -- if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { -- int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); -- if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); -- g_config_params.dpdk_argc++; -- -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); -- g_config_params.dpdk_argc++; -- } -- } -- -- char *tmp_arg_send = strdup_assert_return(args); -- int32_t send_cpu_cnt = separate_str_to_array(tmp_arg_send, g_config_params.send_cpus, -- CFG_MAX_CPUS, CFG_MAX_CPUS); -- free(tmp_arg_send); -- -- // recv_num_cpus -- num_cpus = config_lookup(&g_config, "recv_num_cpus"); -- if (num_cpus == NULL) { -- return -EINVAL; -- } -+ num_cpus = config_lookup(&g_config, "num_cpus"); -+ if (num_cpus == NULL) { -+ return stack_bind_no_cpu(); -+ } - -- args = config_setting_get_string(num_cpus); -- if (args == NULL) { -- return -EINVAL; -- } -+ args = config_setting_get_string(num_cpus); -+ if (args == NULL) { -+ return -EINVAL; -+ } - -- if (!have_corelist_arg(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { -- int32_t idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_BIND_CORELIST); -- if (idx < 0) { -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(OPT_BIND_CORELIST); -- g_config_params.dpdk_argc++; -+ strcpy(g_config_params.lcores, args); - -- g_config_params.dpdk_argv[g_config_params.dpdk_argc] = strdup_assert_return(args); -- g_config_params.dpdk_argc++; -- } -- } -+ tmp_arg = strdup_assert_return(args); -+ cnt = separate_str_to_array(tmp_arg, g_config_params.cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); -+ free(tmp_arg); -+ if (cnt <= 0) { -+ return stack_bind_no_cpu(); -+ } else if (cnt > CFG_MAX_CPUS) { -+ return -EINVAL; -+ } - -- char *tmp_arg_recv = strdup_assert_return(args); -- int32_t recv_cpu_cnt = separate_str_to_array(tmp_arg_recv, g_config_params.recv_cpus, -- CFG_MAX_CPUS, CFG_MAX_CPUS); -- free(tmp_arg_recv); -+ g_config_params.num_cpu = cnt; -+ g_config_params.num_queue = (uint16_t)cnt; -+ g_config_params.tot_queue_num = g_config_params.num_queue; - -- if (send_cpu_cnt <= 0 || send_cpu_cnt > CFG_MAX_CPUS / 2 || send_cpu_cnt != recv_cpu_cnt) { -- return -EINVAL; -- } -+ return 0; -+} - -- g_config_params.num_cpu = send_cpu_cnt; -- g_config_params.num_queue = (uint16_t)send_cpu_cnt * 2; -- g_config_params.tot_queue_num = g_config_params.num_queue; -+static int32_t parse_stack_cpu_number(void) -+{ -+ if (g_config_params.stack_num > 0) { -+ return stack_bind_no_cpu(); - } - -- return 0; -+ return stack_bind_cpus(); -+} -+ -+static int32_t parse_stack_num(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.stack_num, "stack_num", 0, 0, 320, ret); -+ return ret; - } - - static int32_t parse_app_bind_numa(void) -@@ -525,12 +474,12 @@ static int32_t parse_app_exclude_cpus(void) - return 0; - } - --static int32_t numa_to_cpusnum(unsigned socket_id, uint32_t *cpulist, int32_t num) -+static int32_t numa_to_cpusnum(unsigned numa_id, uint32_t *cpulist, int32_t num) - { - char path[PATH_MAX] = {0}; - char strbuf[PATH_MAX] = {0}; - -- int32_t ret = snprintf_s(path, sizeof(path), PATH_MAX - 1, NUMA_CPULIST_PATH, socket_id); -+ int32_t ret = snprintf_s(path, sizeof(path), PATH_MAX - 1, NUMA_CPULIST_PATH, numa_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "snprintf numa_cpulist failed\n"); - return -1; -@@ -557,7 +506,7 @@ static int32_t stack_idle_cpuset(struct protocol_stack *stack, cpu_set_t *exclud - { - uint32_t cpulist[CPUS_MAX_NUM]; - -- int32_t cpunum = numa_to_cpusnum(stack->socket_id, cpulist, CPUS_MAX_NUM); -+ int32_t cpunum = numa_to_cpusnum(stack->numa_id, cpulist, CPUS_MAX_NUM); - if (cpunum <= 0) { - LSTACK_LOG(ERR, LSTACK, "numa_to_cpusnum failed\n"); - return -1; -@@ -584,12 +533,7 @@ int32_t init_stack_numa_cpuset(struct protocol_stack *stack) - cpu_set_t stack_cpuset; - CPU_ZERO(&stack_cpuset); - for (int32_t idx = 0; idx < cfg->num_cpu; ++idx) { -- if (!cfg->seperate_send_recv) { -- CPU_SET(cfg->cpus[idx], &stack_cpuset); -- } else { -- CPU_SET(cfg->send_cpus[idx], &stack_cpuset); -- CPU_SET(cfg->recv_cpus[idx], &stack_cpuset); -- } -+ CPU_SET(cfg->cpus[idx], &stack_cpuset); - } - - for (int32_t idx = 0; idx < cfg->app_exclude_num_cpu; ++idx) { -@@ -831,6 +775,94 @@ int32_t gazelle_param_init(int32_t *argc, char **argv) - return 0; - } - -+static bool dpdk_have_corelist(int32_t argc, char **argv) -+{ -+ for (uint32_t i = 0; i < argc; i++) { -+ if (strncmp(argv[i], OPT_BIND_CORELIST, strlen(OPT_BIND_CORELIST)) == 0) { -+ return true; -+ } -+ -+ if (strncmp(argv[i], "--lcores", strlen("--lcores")) == 0) { -+ return true; -+ } -+ -+ if (strncmp(argv[i], "-c", strlen("-c")) == 0) { -+ return true; -+ } -+ -+ if (strncmp(argv[i], "-s", strlen("-s")) == 0) { -+ return true; -+ } -+ -+ if (strncmp(argv[i], "-S", strlen("-S")) == 0) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static bool dpdk_have_socket_mem(int32_t argc, char **argv) -+{ -+ for (uint32_t i = 0; i < argc; i++) { -+ if (strncmp(argv[i], OPT_SOCKET_MEM, strlen(OPT_SOCKET_MEM)) == 0) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static void dpdk_fill_socket_mem(void) -+{ -+ uint32_t socket_mem_size = dpdk_total_socket_memory(); -+ -+ for (uint32_t i = 0; i < GAZELLE_MAX_NUMA_NODES; i++) { -+ if (i == g_config_params.numa_id) { -+ snprintf(g_config_params.socket_mem + strlen(g_config_params.socket_mem), -+ SOCKET_MEM_STRLEN - strlen(g_config_params.socket_mem), "%d", socket_mem_size); -+ } else { -+ snprintf(g_config_params.socket_mem + strlen(g_config_params.socket_mem), -+ SOCKET_MEM_STRLEN - strlen(g_config_params.socket_mem), "%d", 0); -+ } -+ if (i < (GAZELLE_MAX_NUMA_NODES - 1)) { -+ snprintf(g_config_params.socket_mem + strlen(g_config_params.socket_mem), -+ SOCKET_MEM_STRLEN - strlen(g_config_params.socket_mem), "%s", ","); -+ } -+ } -+} -+ -+static void dpdk_add_args(void) -+{ -+ int idx; -+ uint16_t lcore_id; -+ -+ if (!dpdk_have_corelist(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { -+ if (g_config_params.stack_num > 0) { -+ RTE_LCORE_FOREACH(lcore_id) { -+ if (numa_node_of_cpu(lcore_id) == g_config_params.numa_id && rte_lcore_is_enabled(lcore_id)) { -+ snprintf_s(g_config_params.lcores, sizeof(g_config_params.lcores), -+ sizeof(g_config_params.lcores) - 1, "%d", lcore_id); -+ break; -+ } -+ } -+ } -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(OPT_BIND_CORELIST); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(g_config_params.lcores); -+ } -+ -+ if (g_config_params.stack_num > 0) { -+ dpdk_fill_socket_mem(); -+ if (!dpdk_have_socket_mem(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(OPT_SOCKET_MEM); -+ g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(g_config_params.socket_mem); -+ } else { -+ idx = get_param_idx(g_config_params.dpdk_argc, g_config_params.dpdk_argv, OPT_SOCKET_MEM); -+ strcpy(g_config_params.dpdk_argv[idx + 1], g_config_params.socket_mem); -+ } -+ } -+} -+ - static int32_t parse_dpdk_args(void) - { - int32_t i; -@@ -880,8 +912,10 @@ static int32_t parse_dpdk_args(void) - (void)fprintf(stderr, "%s ", g_config_params.dpdk_argv[start_index + i]); - } - (void)fprintf(stderr, "\n"); -- - g_config_params.dpdk_argc++; -+ -+ dpdk_add_args(); -+ - if (turn_args_to_config(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) - goto free_dpdk_args; - -@@ -1106,13 +1140,6 @@ static int32_t parse_unix_prefix(void) - return 0; - } - --static int32_t parse_seperate_sendrecv_args(void) --{ -- int32_t ret; -- PARSE_ARG(g_config_params.seperate_send_recv, "seperate_send_recv", 0, 0, 1, ret); -- return ret; --} -- - static int32_t parse_num_process(void) - { - if (g_config_params.use_ltran) { -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 9294c5b..5141c3a 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -42,6 +42,8 @@ - - #include "lstack_log.h" - #include "common/dpdk_common.h" -+#include "common/gazelle_base_func.h" -+#include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" - #include "lstack_lwip.h" - #include "lstack_cfg.h" -@@ -107,6 +109,10 @@ int32_t thread_affinity_init(int32_t cpu_id) - int32_t ret; - cpu_set_t cpuset; - -+ if (get_global_cfg_params()->stack_num > 0) { -+ return 0; -+ } -+ - CPU_ZERO(&cpuset); - CPU_SET(cpu_id, &cpuset); - -@@ -546,9 +552,6 @@ int32_t dpdk_ethdev_init(int port_id) - int ret; - int32_t rss_enable = 0; - uint16_t nb_queues = get_global_cfg_params()->num_cpu; -- if (get_global_cfg_params()->seperate_send_recv) { -- nb_queues = get_global_cfg_params()->num_cpu * 2; -- } - - if (!use_ltran()) { - nb_queues = get_global_cfg_params()->tot_queue_num; -@@ -616,24 +619,23 @@ int32_t dpdk_ethdev_init(int port_id) - static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t idx) - { - int32_t ret; -- -+ uint16_t numa_id = 0; -+ struct cfg_params *cfg = get_global_cfg_params(); - struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx]; - -- uint16_t socket_id = 0; -- struct cfg_params *cfg = get_global_cfg_params(); - if (!cfg->use_ltran && cfg->num_process == 1) { -- socket_id = numa_node_of_cpu(cfg->cpus[idx]); -+ numa_id = (cfg->stack_num > 0) ? cfg->numa_id : numa_node_of_cpu(cfg->cpus[idx]); - } else { -- socket_id = cfg->process_numa[idx]; -+ numa_id = cfg->process_numa[idx]; - } -- ret = rte_eth_rx_queue_setup(eth_params->port_id, idx, eth_params->nb_rx_desc, socket_id, -+ ret = rte_eth_rx_queue_setup(eth_params->port_id, idx, eth_params->nb_rx_desc, numa_id, - ð_params->rx_conf, rxtx_mbuf_pool); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot setup rx_queue %hu: %s\n", idx, rte_strerror(-ret)); - return -1; - } - -- ret = rte_eth_tx_queue_setup(eth_params->port_id, idx, eth_params->nb_tx_desc, socket_id, -+ ret = rte_eth_tx_queue_setup(eth_params->port_id, idx, eth_params->nb_tx_desc, numa_id, - ð_params->tx_conf); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "cannot setup tx_queue %hu: %s\n", idx, rte_strerror(-ret)); -@@ -1034,3 +1036,45 @@ void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id) - dfx->data.nic_features.rx_offload = dev_conf.rxmode.offloads; - return; - } -+ -+uint32_t dpdk_pktmbuf_mempool_num(void) -+{ -+ struct cfg_params *cfg = get_global_cfg_params(); -+ -+ return (MBUFPOOL_RESERVE_NUM + cfg->rxqueue_size + cfg->txqueue_size + -+ (cfg->tcp_conn_count * cfg->mbuf_count_per_conn) / cfg->num_queue); -+} -+ -+uint32_t dpdk_total_socket_memory(void) -+{ -+ uint32_t elt_size = 0; -+ uint32_t per_pktmbuf_mempool_size = 0; -+ uint32_t per_rpc_mempool_size = 0; -+ uint32_t per_conn_ring_size = 0; -+ /* the actual fixed memory is about 50M, and 100M is reserved here. -+ * including all hugepages memory used by lwip. -+ */ -+ uint32_t fixed_mem = 100; -+ uint32_t total_socket_memory = 0; -+ struct cfg_params *cfg = get_global_cfg_params(); -+ -+ /* calculate the memory(bytes) of rxtx_mempool */ -+ elt_size = sizeof(struct rte_mbuf) + MBUF_SZ + RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); -+ per_pktmbuf_mempool_size = rte_mempool_calc_obj_size(elt_size, 0, NULL); -+ -+ /* calculate the memory(bytes) of rpc_mempool, reserved num is (app threads + lstack threads + listen thread) */ -+ elt_size = sizeof(struct rpc_msg); -+ per_rpc_mempool_size = rte_mempool_calc_obj_size(elt_size, 0, NULL); -+ -+ /* calculate the memory(bytes) of rings, reserved num is GAZELLE_LSTACK_MAX_CONN. */ -+ per_conn_ring_size = rte_ring_get_memsize(cfg->send_ring_size) + -+ rte_ring_get_memsize(cfg->recv_ring_size) + -+ rte_ring_get_memsize(DEFAULT_ACCEPTMBOX_SIZE); -+ -+ total_socket_memory = fixed_mem + bytes_to_mb( -+ (per_pktmbuf_mempool_size * dpdk_pktmbuf_mempool_num()) * cfg->num_queue + -+ per_rpc_mempool_size * cfg->rpc_msg_max * (RPC_MEMPOOL_THREAD_NUM + cfg->num_queue + 1) + -+ per_conn_ring_size * GAZELLE_LSTACK_MAX_CONN); -+ -+ return total_socket_memory; -+} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 553dff3..9cfd54f 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -126,16 +126,9 @@ struct protocol_stack *get_bind_protocol_stack(void) - pthread_spin_lock(&stack_group->socket_lock); - for (uint16_t i = 0; i < stack_group->stack_num; i++) { - struct protocol_stack* stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv) { -- if (stack->is_send_thread && stack->conn_num < min_conn_num) { -- index = i; -- min_conn_num = stack->conn_num; -- } -- } else { -- if (stack->conn_num < min_conn_num) { -- index = i; -- min_conn_num = stack->conn_num; -- } -+ if (stack->conn_num < min_conn_num) { -+ index = i; -+ min_conn_num = stack->conn_num; - } - } - } -@@ -154,16 +147,9 @@ int get_min_conn_stack(struct protocol_stack_group *stack_group) - - for (int i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv) { -- if (!stack->is_send_thread && stack->conn_num < min_conn_num) { -- min_conn_stk_idx = i; -- min_conn_num = stack->conn_num; -- } -- } else { -- if (stack->conn_num < min_conn_num) { -- min_conn_stk_idx = i; -- min_conn_num = stack->conn_num; -- } -+ if (stack->conn_num < min_conn_num) { -+ min_conn_stk_idx = i; -+ min_conn_num = stack->conn_num; - } - } - return min_conn_stk_idx; -@@ -174,6 +160,10 @@ void bind_to_stack_numa(struct protocol_stack *stack) - int32_t ret; - pthread_t tid = pthread_self(); - -+ if (get_global_cfg_params()->stack_num > 0) { -+ return; -+ } -+ - ret = pthread_setaffinity_np(tid, sizeof(stack->idle_cpuset), &stack->idle_cpuset); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "thread %d setaffinity to stack %hu failed\n", rte_gettid(), stack->queue_id); -@@ -268,18 +258,10 @@ static int32_t create_thread(void *arg, char *thread_name, stack_thread_func fun - return -1; - } - -- if (get_global_cfg_params()->seperate_send_recv) { -- ret = sprintf_s(name, sizeof(name), "%s", thread_name); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "set name failed\n"); -- return -1; -- } -- } else { -- ret = sprintf_s(name, sizeof(name), "%s%02hu", thread_name, t_params->queue_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "set name failed\n"); -- return -1; -- } -+ ret = sprintf_s(name, sizeof(name), "%s%02hu", thread_name, t_params->queue_id); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "set name failed\n"); -+ return -1; - } - - ret = pthread_create(&tid, NULL, func, arg); -@@ -343,6 +325,7 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ struct cfg_params *cfg_params = get_global_cfg_params(); - - stack->tid = rte_gettid(); - stack->queue_id = t_params->queue_id; -@@ -363,24 +346,15 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - return -1; - } - -- int idx = t_params->idx; -- if (get_global_cfg_params()->seperate_send_recv) { -- // 2: idx is even, stack is recv thread, idx is odd, stack is send thread -- if (idx % 2 == 0) { -- stack->cpu_id = get_global_cfg_params()->recv_cpus[idx / 2]; -- stack->is_send_thread = 0; -- } else { -- stack->cpu_id = get_global_cfg_params()->send_cpus[idx / 2]; -- stack->is_send_thread = 1; -- } -+ if (cfg_params->stack_num > 0) { -+ stack->numa_id = cfg_params->numa_id; - } else { -- stack->cpu_id = get_global_cfg_params()->cpus[idx]; -- } -- -- stack->socket_id = numa_node_of_cpu(stack->cpu_id); -- if (stack->socket_id < 0) { -- LSTACK_LOG(ERR, LSTACK, "numa_node_of_cpu failed\n"); -- return -1; -+ stack->cpu_id = cfg_params->cpus[t_params->idx]; -+ stack->numa_id = numa_node_of_cpu(stack->cpu_id); -+ if (stack->numa_id < 0) { -+ LSTACK_LOG(ERR, LSTACK, "numa_node_of_cpu failed\n"); -+ return -1; -+ } - } - - if (pktmbuf_pool_init(stack) != 0) { -@@ -441,7 +415,10 @@ static struct protocol_stack *stack_thread_init(void *arg) - if (thread_affinity_init(stack->cpu_id) != 0) { - goto END; - } -- RTE_PER_LCORE(_lcore_id) = stack->cpu_id; -+ -+ if (get_global_cfg_params()->stack_num == 0) { -+ RTE_PER_LCORE(_lcore_id) = stack->cpu_id; -+ } - - lwip_init(); - /* Using errno to return lwip_init() result. */ -@@ -591,9 +568,7 @@ static void* gazelle_stack_thread(void *arg) - static int stack_group_init_mempool(void) - { - struct cfg_params *cfg_params = get_global_cfg_params(); -- uint32_t total_mbufs = 0; -- uint32_t total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; -- uint32_t total_nic_mbufs = cfg_params->rxqueue_size + cfg_params->txqueue_size; -+ uint32_t total_mbufs = dpdk_pktmbuf_mempool_num(); - struct rte_mempool *rxtx_mbuf = NULL; - uint32_t cpu_id = 0; - unsigned numa_id = 0; -@@ -603,8 +578,12 @@ static int stack_group_init_mempool(void) - "config::num_cpu=%d num_process=%d \n", cfg_params->num_cpu, cfg_params->num_process); - - for (int cpu_idx = 0; cpu_idx < cfg_params->num_queue; cpu_idx++) { -- cpu_id = cfg_params->cpus[cpu_idx]; -- numa_id = numa_node_of_cpu(cpu_id); -+ if (cfg_params->stack_num > 0) { -+ numa_id = cfg_params->numa_id; -+ } else { -+ cpu_id = cfg_params->cpus[cpu_idx]; -+ numa_id = numa_node_of_cpu(cpu_id); -+ } - - for (int process_idx = 0; process_idx < cfg_params->num_process; process_idx++) { - queue_id = cpu_idx * cfg_params->num_process + process_idx; -@@ -613,11 +592,9 @@ static int stack_group_init_mempool(void) - return -1; - } - -- total_mbufs = (total_conn_mbufs / cfg_params->num_queue) + total_nic_mbufs + MBUFPOOL_RESERVE_NUM; - rxtx_mbuf = create_pktmbuf_mempool("rxtx_mbuf", total_mbufs, RXTX_CACHE_SZ, queue_id, numa_id); - if (rxtx_mbuf == NULL) { -- LSTACK_LOG(ERR, LSTACK, "cpuid=%u, numid=%d , rxtx_mbuf idx= %d create_pktmbuf_mempool fail\n", -- cpu_id, numa_id, queue_id); -+ LSTACK_LOG(ERR, LSTACK, "numid=%d, rxtx_mbuf idx=%d, create_pktmbuf_mempool fail\n", numa_id, queue_id); - return -1; - } - -@@ -696,23 +673,9 @@ int stack_setup_thread(void) - } - } - for (i = 0; i < queue_num; i++) { -- if (get_global_cfg_params()->seperate_send_recv) { -- if (i % 2 == 0) { -- ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_RECV_THREAD_NAME, process_index, i / 2); -- if (ret < 0) { -- goto OUT1; -- } -- } else { -- ret = sprintf_s(name, sizeof(name), "%s_%d_%d", LSTACK_SEND_THREAD_NAME, process_index, i / 2); -- if (ret < 0) { -- goto OUT1; -- } -- } -- } else { -- ret = sprintf_s(name, sizeof(name), "%s", LSTACK_THREAD_NAME); -- if (ret < 0) { -- goto OUT1; -- } -+ ret = sprintf_s(name, sizeof(name), "%s", LSTACK_THREAD_NAME); -+ if (ret < 0) { -+ goto OUT1; - } - - t_params[i]->idx = i; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 876423d..073aab6 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -20,6 +20,7 @@ - #include - - #include "lstack_protocol_stack.h" -+#include "common/gazelle_reg_msg.h" - #include "common/gazelle_opt.h" - - #define BASE_BIN_SCALE 2 -@@ -36,7 +37,6 @@ - #define ARP_MAX_ENTRIES 1024 - #define LOG_DIR_PATH PATH_MAX - #define LOG_LEVEL_LEN 16 --#define GAZELLE_MAX_NUMA_NODES 8 - #define MAX_PROCESS_NUM 32 - - /* Default value of low power mode parameters */ -@@ -77,6 +77,8 @@ struct cfg_params { - uintptr_t base_virtaddr; - char file_prefix[PATH_MAX]; - } sec_attach_arg; -+ char socket_mem[SOCKET_MEM_STRLEN]; -+ char lcores[RTE_MAX_LCORE]; - }; - - struct { // eth -@@ -109,6 +111,8 @@ struct cfg_params { - - struct { // stack - uint16_t num_cpu; -+ uint16_t numa_id; -+ uint16_t stack_num; - uint32_t cpus[CFG_MAX_CPUS]; - - bool main_thread_affinity; -@@ -147,10 +151,6 @@ struct cfg_params { - uint32_t process_numa[PROTOCOL_STACK_MAX]; - bool tuple_filter; - bool use_sockmap; -- -- bool seperate_send_recv; -- uint32_t send_cpus[CFG_MAX_CPUS]; -- uint32_t recv_cpus[CFG_MAX_CPUS]; - }; - }; - -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 0210843..87219c2 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -66,5 +66,7 @@ void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - - bool dpdk_nic_is_xdp(void); -+uint32_t dpdk_pktmbuf_mempool_num(void); -+uint32_t dpdk_total_socket_memory(void); - - #endif /* GAZELLE_DPDK_H */ -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 4d10ac2..068e9d2 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -40,7 +40,7 @@ struct protocol_stack { - uint32_t tid; - uint16_t queue_id; - uint16_t port_id; -- uint16_t socket_id; -+ uint16_t numa_id; - uint16_t cpu_id; - uint32_t stack_idx; - cpu_set_t idle_cpuset; /* idle cpu in numa of stack, app thread bind to it */ -@@ -56,7 +56,6 @@ struct protocol_stack { - uint32_t reg_head; - - volatile bool low_power; -- bool is_send_thread; - - char pad1 __rte_cache_aligned; - rpc_queue dfx_rpc_queue; -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index c284d29..c74981f 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -26,6 +26,8 @@ - #define MSG_ARG_4 (4) - #define RPM_MSG_ARG_SIZE (5) - -+#define RPC_MEMPOOL_THREAD_NUM 64 -+ - typedef struct rpc_queue rpc_queue; - struct rpc_queue { - struct lockless_queue queue; -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index 1ca3314..ec09e45 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -639,11 +639,7 @@ int distribute_pakages(struct rte_mbuf *mbuf) - return TRANSFER_KERNEL; - } - -- if (get_global_cfg_params()->seperate_send_recv) { -- queue_id = user_process_idx * each_process_queue_num + (index / 2) * 2; -- } else { -- queue_id = user_process_idx * each_process_queue_num + index; -- } -+ queue_id = user_process_idx * each_process_queue_num + index; - if (queue_id != 0) { - if (user_process_idx == 0) { - transfer_tcp_to_thread(mbuf, queue_id); --- -2.33.0 - diff --git a/0284-support-auto-set-xdp-addr.patch b/0284-support-auto-set-xdp-addr.patch deleted file mode 100644 index f5f0081..0000000 --- a/0284-support-auto-set-xdp-addr.patch +++ /dev/null @@ -1,391 +0,0 @@ -From fa5060a255109d089f98c9c498d7119e96bd39fd Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 11 Nov 2024 22:45:54 +0800 -Subject: [PATCH] support auto set xdp addr - ---- - src/common/gazelle_reg_msg.h | 2 + - src/lstack/core/lstack_cfg.c | 207 ++++++++++++++++++++++++------- - src/lstack/core/lstack_preload.c | 2 +- - src/lstack/include/lstack_cfg.h | 5 + - 4 files changed, 171 insertions(+), 45 deletions(-) - -diff --git a/src/common/gazelle_reg_msg.h b/src/common/gazelle_reg_msg.h -index f9de32c..2ba47cc 100644 ---- a/src/common/gazelle_reg_msg.h -+++ b/src/common/gazelle_reg_msg.h -@@ -30,6 +30,8 @@ - #define OPT_LEGACY_MEM "--legacy-mem" - #define OPT_HUGE_DIR "--huge-dir" - #define OPT_BIND_CORELIST "-l" -+#define OPT_VDEV "--vdev" -+#define VDEV_ARG_IFACE "iface" - - #define GAZELLE_MAX_NUMA_NODES 4 - #define SOCKET_MEM_STRLEN (GAZELLE_MAX_NUMA_NODES * 10) -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 43482af..2a3f1af 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -23,12 +22,15 @@ - #include - #include - #include -+#include -+#include -+#include -+#include - - #include - #include - #include - #include --#include - - #include "common/gazelle_reg_msg.h" - #include "common/gazelle_base_func.h" -@@ -36,14 +38,14 @@ - #include "lstack_dpdk.h" - #include "lstack_cfg.h" - --#define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" --#define LSTACK_CONF_ENV "LSTACK_CONF_PATH" --#define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist" --#define DEV_MAC_LEN 17 --#define DEV_PCI_ADDR_LEN 12 --#define CPUS_MAX_NUM 256 --#define BOND_MIIMON_MIN 1 --#define BOND_MIIMON_MAX INT_MAX -+#define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" -+#define LSTACK_CONF_ENV "LSTACK_CONF_PATH" -+#define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist" -+#define DEV_MAC_LEN 17 -+#define DEV_PCI_ADDR_LEN 12 -+#define CPUS_MAX_NUM 256 -+#define BOND_MIIMON_MIN 1 -+#define BOND_MIIMON_MAX INT_MAX - - static struct cfg_params g_config_params; - -@@ -89,6 +91,7 @@ static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); - static int32_t parse_stack_num(void); -+static int32_t parse_xdp_eth_name(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -116,12 +119,7 @@ struct config_vector_t { - }; - - static struct config_vector_t g_config_tbl[] = { -- { "host_addr", parse_host_addr }, -- { "host_addr6", parse_host_addr6 }, -- { "gateway_addr", parse_gateway_addr }, -- { "mask_addr", parse_mask_addr }, - { "use_ltran", parse_use_ltran }, -- { "devices", parse_devices }, - { "tcp_conn_count", parse_tcp_conn_count }, - { "mbuf_count_per_conn", parse_mbuf_count_per_conn }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, -@@ -132,6 +130,12 @@ static struct config_vector_t g_config_tbl[] = { - { "stack_num", parse_stack_num }, - { "num_cpus", parse_stack_cpu_number }, - { "dpdk_args", parse_dpdk_args }, -+ { "xdp_eth_name", parse_xdp_eth_name}, -+ { "host_addr", parse_host_addr }, -+ { "host_addr6", parse_host_addr6 }, -+ { "mask_addr", parse_mask_addr }, -+ { "gateway_addr", parse_gateway_addr }, -+ { "devices", parse_devices }, - { "low_power_mode", parse_low_power_mode }, - { "kni_switch", parse_kni_switch }, - { "listen_shadow", parse_listen_shadow }, -@@ -211,18 +215,25 @@ static int32_t str_to_dev_addr(const char *src, struct dev_addr *dst) - - static int32_t parse_gateway_addr(void) - { -- char *value; - bool ok; -+ char *value; -+ const char *first_addr = "0.0.0.1"; - - if (ip4_addr_isany_val(g_config_params.host_addr)) { - return 0; - } - -- ok = config_lookup_string(&g_config, "gateway_addr", (const char **)&value); -- if (!ok) { -- return -EINVAL; -+ if (strlen(g_config_params.xdp_eth_name) == 0) { -+ ok = config_lookup_string(&g_config, "gateway_addr", (const char **)&value); -+ if (!ok) { -+ return -EINVAL; -+ } -+ g_config_params.gateway_addr.addr = inet_addr(value); -+ } else { -+ g_config_params.gateway_addr.addr = -+ (g_config_params.host_addr.addr & g_config_params.netmask.addr) | inet_addr(first_addr); - } -- g_config_params.gateway_addr.addr = inet_addr(value); -+ - if (g_config_params.gateway_addr.addr == INADDR_NONE) { - return -EINVAL; - } -@@ -231,19 +242,40 @@ static int32_t parse_gateway_addr(void) - - static int32_t parse_mask_addr(void) - { -- char *value = NULL; -+ int32_t ret; - uint32_t mask; -- bool ok; -+ char *mask_addr; -+ struct ifaddrs *ifaddr; -+ struct ifaddrs *ifa; - - if (ip4_addr_isany_val(g_config_params.host_addr)) { - return 0; - } - -- ok = config_lookup_string(&g_config, "mask_addr", (const char **)&value); -- if (!ok) { -- return -EINVAL; -+ if (strlen(g_config_params.xdp_eth_name) == 0) { -+ ret = config_lookup_string(&g_config, "mask_addr", (const char **)&mask_addr); -+ if (!ret) { -+ return -EINVAL; -+ } -+ g_config_params.netmask.addr = inet_addr(mask_addr); -+ } else { -+ if (getifaddrs(&ifaddr) == -1) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "getifaddrs failed\n"); -+ return -1; -+ } -+ -+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { -+ if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET || -+ strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ continue; -+ } -+ g_config_params.netmask.addr = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr; -+ } -+ -+ freeifaddrs(ifaddr); -+ freeifaddrs(ifa); - } -- g_config_params.netmask.addr = inet_addr(value); -+ - if (g_config_params.netmask.addr == INADDR_NONE) { - return -EINVAL; - } -@@ -257,21 +289,41 @@ static int32_t parse_mask_addr(void) - - static int32_t parse_host_addr(void) - { -- char *value = NULL; -- bool ok; -+ int32_t ret; -+ char *host_addr; -+ struct ifaddrs *ifaddr; -+ struct ifaddrs *ifa; - -- ok = config_lookup_string(&g_config, "host_addr", (const char **)&value); -- if (!ok) { -- return 0; -+ if (strlen(g_config_params.xdp_eth_name) == 0) { -+ ret = config_lookup_string(&g_config, "host_addr", (const char **)&host_addr); -+ if (!ret) { -+ return 0; -+ } -+ g_config_params.host_addr.addr = inet_addr(host_addr); -+ } else { -+ if (getifaddrs(&ifaddr) == -1) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "getifaddrs failed\n"); -+ return -1; -+ } -+ -+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { -+ if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET || -+ strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ continue; -+ } -+ g_config_params.host_addr.addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; -+ } -+ -+ freeifaddrs(ifaddr); -+ freeifaddrs(ifa); - } - -- g_config_params.host_addr.addr = inet_addr(value); - if (g_config_params.host_addr.addr == INADDR_NONE) { - return -EINVAL; - } - - if (IN_MULTICAST(ntohl(g_config_params.host_addr.addr))) { -- LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr:%s should not be a multicast IP.", value); -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr:%s should not be a multicast IP.", host_addr); - return -EINVAL; - } - return 0; -@@ -284,7 +336,7 @@ static int32_t parse_host_addr6(void) - - ok = config_lookup_string(&g_config, "host_addr6", (const char **)&value); - if (!ok) { -- if (ip4_addr_isany_val(g_config_params.host_addr)) { -+ if (ip4_addr_isany_val(g_config_params.host_addr) && (strlen(g_config_params.xdp_eth_name) == 0)) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr and host_addr6 must have a valid one."); - return -EINVAL; - } else { -@@ -322,16 +374,37 @@ int32_t match_host_addr(ip_addr_t *addr) - static int32_t parse_devices(void) - { - int32_t ret; -- const char *dev = NULL; -- const config_setting_t *devs = NULL; -+ char *dev = NULL; -+ struct ifaddrs *ifa; -+ struct ifaddrs *ifaddr; -+ char temp_dev[DEV_MAC_LEN + 1] = {0}; -+ -+ if (strlen(g_config_params.xdp_eth_name) == 0) { -+ ret = config_lookup_string(&g_config, "devices", (const char **)&dev); -+ if (!ret) { -+ return -EINVAL; -+ } -+ } else { -+ if (getifaddrs(&ifaddr) == -1) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "getifaddrs failed\n"); -+ return -1; -+ } - -- devs = config_lookup(&g_config, "devices"); -- if (devs == NULL) { -- return -EINVAL; -- } -- dev = config_setting_get_string(devs); -- if (dev == NULL) { -- return 0; -+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { -+ if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_PACKET || -+ strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ continue; -+ } -+ -+ for (uint32_t i = 0; i < ETHER_ADDR_LEN; i++) { -+ sprintf(temp_dev + strlen(temp_dev), "%02x%s", -+ ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr[i], i < (ETHER_ADDR_LEN - 1) ? ":" : ""); -+ } -+ dev = strdup_assert_return(temp_dev); -+ } -+ -+ freeifaddrs(ifaddr); -+ freeifaddrs(ifa); - } - - /* add dev */ -@@ -1294,7 +1367,7 @@ static int32_t parse_bond_slave_mac(void) - char *bond_slave_mac_tmp = strdup_assert_return(bond_slave_mac); - char *tmp = NULL; - const char *delim = ";"; -- -+ - char *mac_addr = strtok_s(bond_slave_mac_tmp, delim, &tmp); - while (mac_addr != NULL) { - if (k >= GAZELLE_MAX_BOND_NUM) { -@@ -1426,3 +1499,49 @@ static int32_t parse_stack_interrupt(void) - - return ret; - } -+ -+static void dpdk_dev_get_iface_name(char *vdev_str) -+{ -+ char *token = NULL; -+ char *iface_value = NULL; -+ char *next_token = NULL; -+ char vdev_str_cp[strlen(vdev_str) + 1]; -+ -+ /* To prevent the original string from being modified, use a copied string. */ -+ if (strcpy_s(vdev_str_cp, sizeof(vdev_str_cp), vdev_str) != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "vdev_str strcpy_s fail \n"); -+ return; -+ } -+ -+ token = strtok_s(vdev_str_cp, ",", &next_token); -+ while (token != NULL) { -+ if (strncmp(token, VDEV_ARG_IFACE, strlen(VDEV_ARG_IFACE)) == 0) { -+ iface_value = token + strlen(VDEV_ARG_IFACE) + 1; -+ break; -+ } -+ token = strtok_s(NULL, ",", &next_token); -+ } -+ -+ if (iface_value) { -+ strncpy_s(g_config_params.xdp_eth_name, IFNAMSIZ, iface_value, IFNAMSIZ - 1); -+ } -+} -+ -+static int32_t parse_xdp_eth_name(void) -+{ -+ int32_t ret; -+ -+ ret = memset_s(g_config_params.xdp_eth_name, IFNAMSIZ, 0, IFNAMSIZ); -+ if (ret != 0) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "memset_s failed \n"); -+ return ret; -+ } -+ -+ for (uint32_t i = 0; i < g_config_params.dpdk_argc; i++) { -+ if (!strncmp(g_config_params.dpdk_argv[i], OPT_VDEV, strlen(OPT_VDEV))) { -+ dpdk_dev_get_iface_name(g_config_params.dpdk_argv[i + 1]); -+ } -+ } -+ -+ return 0; -+} -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index 0a1df7d..bdb61e9 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -193,6 +193,6 @@ int preload_info_init(void) - } - - g_preload_info.preload_switch = 1; -- LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); -+ - return preload_check_bind_proc(); - } -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 073aab6..0fd5323 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -14,6 +14,10 @@ - #define _GAZELLE_NET_CFG_H_ - #include - -+#ifndef IFNAMSIZ -+#include -+#endif -+ - #include - #include - #include -@@ -86,6 +90,7 @@ struct cfg_params { - ip6_addr_t host_addr6; - ip4_addr_t netmask; - ip4_addr_t gateway_addr; -+ char xdp_eth_name[IFNAMSIZ]; - uint8_t mac_addr[ETHER_ADDR_LEN]; - int8_t bond_mode; - int32_t bond_miimon; --- -2.33.0 - diff --git a/0285-suport-kernel-accept-for-openGauss.patch b/0285-suport-kernel-accept-for-openGauss.patch deleted file mode 100644 index 80b80ed..0000000 --- a/0285-suport-kernel-accept-for-openGauss.patch +++ /dev/null @@ -1,82 +0,0 @@ -From be28f36adfebb0e5f7f2340638120a19f5b2eaa6 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Thu, 14 Nov 2024 20:16:14 +0800 -Subject: [PATCH] suport kernel accept for openGauss - ---- - src/lstack/api/lstack_wrap.c | 34 ++++++++++++++++++++++++++++++---- - 1 file changed, 30 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 66cea51..6ab31f6 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -102,14 +103,22 @@ static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *add - return posix_api->accept_fn(s, addr, addrlen); - } - -- int32_t fd = g_wrap_api->accept_fn(s, addr, addrlen); -+ int fd = 0; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ fd = posix_api->accept4_fn(s, addr, addrlen, SOCK_NONBLOCK); -+ if (fd >= 0) { -+ return fd; -+ } -+ } -+ -+ fd = g_wrap_api->accept_fn(s, addr, addrlen); - if (fd >= 0) { -- struct lwip_sock *sock = lwip_get_socket(fd); -+ sock = lwip_get_socket(fd); - POSIX_SET_TYPE(sock, POSIX_LWIP); -- return fd; - } - -- return posix_api->accept_fn(s, addr, addrlen); -+ return fd; - } - - static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, int32_t flags) -@@ -132,6 +141,22 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - -+static inline int sock_set_nonblocking(int fd) -+{ -+ int flags = posix_api->fcntl_fn(fd, F_GETFL, 0); -+ if (flags == -1) { -+ LSTACK_LOG(ERR, LSTACK, " get block status faild errno %d.\n", errno); -+ return -1; -+ } -+ // set nonblock -+ flags |= O_NONBLOCK; -+ if (posix_api->fcntl_fn(fd, F_SETFL, flags) == -1) { -+ LSTACK_LOG(ERR, LSTACK, " set non_block status faild errno %d.\n", errno); -+ return -1; -+ } -+ return 0; -+} -+ - static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t namelen) - { - struct lwip_sock *sock = lwip_get_socket(s); -@@ -165,6 +190,7 @@ static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t - ((struct sockaddr_in *)name)->sin_port = kerneladdr.sin_port; - } - /* not sure POSIX_LWIP or POSIX_KERNEL */ -+ sock_set_nonblocking(s); - } else { - POSIX_SET_TYPE(sock, POSIX_LWIP); - LSTACK_LOG(ERR, LSTACK, "kernel bind failed ret %d errno %d sa_family %u times %u\n", --- -2.33.0 - diff --git a/0286-openGauss-support-kernel-accept4.patch b/0286-openGauss-support-kernel-accept4.patch deleted file mode 100644 index 2db330e..0000000 --- a/0286-openGauss-support-kernel-accept4.patch +++ /dev/null @@ -1,43 +0,0 @@ -From e09613994ea3fee2c5468c48d24d8a6dfb96f8b4 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Mon, 18 Nov 2024 09:18:42 +0800 -Subject: [PATCH] openGauss: support kernel accept4 - ---- - src/lstack/api/lstack_wrap.c | 16 ++++++++++++---- - 1 file changed, 12 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 7d32ef1..7e724cd 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -131,14 +131,22 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen, - return posix_api->accept4_fn(s, addr, addrlen, flags); - } - -- int32_t fd = g_wrap_api->accept4_fn(s, addr, addrlen, flags); -+ int fd = 0; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ fd = posix_api->accept4_fn(s, addr, addrlen, flags); -+ if (fd >= 0) { -+ return fd; -+ } -+ } -+ -+ fd = g_wrap_api->accept4_fn(s, addr, addrlen, flags); - if (fd >= 0) { -- struct lwip_sock *sock = lwip_get_socket(fd); -+ sock = lwip_get_socket(fd); - POSIX_SET_TYPE(sock, POSIX_LWIP); -- return fd; - } - -- return posix_api->accept4_fn(s, addr, addrlen, flags); -+ return fd; - } - - static inline int sock_set_nonblocking(int fd) --- -2.33.0 - diff --git a/0287-socket-init-wakeup-in-blocking-socket.patch b/0287-socket-init-wakeup-in-blocking-socket.patch deleted file mode 100644 index 9e98a01..0000000 --- a/0287-socket-init-wakeup-in-blocking-socket.patch +++ /dev/null @@ -1,125 +0,0 @@ -From a735fd09aa59df805865331b3cbda5e0458c9fac Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 19 Nov 2024 19:36:26 +0800 -Subject: [PATCH] socket: init wakeup in blocking socket - ---- - src/lstack/api/lstack_epoll.c | 16 ++++++++++++---- - src/lstack/api/lstack_rtw_api.c | 9 +++++++++ - src/lstack/core/lstack_lwip.c | 15 ++++++++++++++- - src/lstack/include/lstack_epoll.h | 2 ++ - 4 files changed, 37 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index acbf393..ff9cccf 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -872,21 +872,30 @@ static int poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfds - return 0; - } - --int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) -+struct wakeup_poll* poll_construct_wakeup(void) - { - static PER_THREAD struct wakeup_poll *wakeup = NULL; - if (wakeup == NULL) { - wakeup = calloc(1, sizeof(struct wakeup_poll)); - if (wakeup == NULL) { - LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -- GAZELLE_RETURN(EINVAL); -+ return NULL; - } - - if (init_poll_wakeup_data(wakeup) < 0) { - free(wakeup); -- GAZELLE_RETURN(EINVAL); -+ return NULL; - } - } -+ return wakeup; -+} -+ -+int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) -+{ -+ struct wakeup_poll *wakeup = poll_construct_wakeup(); -+ if (wakeup == NULL) { -+ GAZELLE_RETURN(EINVAL); -+ } - - if (poll_init(wakeup, fds, nfds) < 0) { - free(wakeup); -@@ -1015,4 +1024,3 @@ int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfd - - return event_num; - } -- -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 1b02e2a..6d0bd05 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -136,6 +136,15 @@ static struct lwip_sock *get_min_accept_sock(int fd) - struct lwip_sock *min_sock = NULL; - - while (sock) { -+ if (!netconn_is_nonblocking(sock->conn)) { -+ if (sock->wakeup == NULL) { -+ sock->wakeup = poll_construct_wakeup(); -+ if (sock->wakeup == NULL) { -+ return NULL; -+ } -+ sock->epoll_events = POLLIN | POLLERR; -+ } -+ } - if (!NETCONN_IS_ACCEPTIN(sock)) { - sock = sock->listen_next; - continue; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index bb261d2..65acae2 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -993,6 +993,7 @@ static bool recv_break_for_err(struct lwip_sock *sock) - static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf **pbuf) - { - int32_t expect = 1; // only get one pbuf -+ int ret = 0; - uint64_t time_stamp = sys_now_us(); - - if (sock->recv_lastdata != NULL) { -@@ -1008,8 +1009,20 @@ static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf * - if (recv_break_for_err(sock)) { - return -1; - } -- if (lstack_block_wait(sock->wakeup, sock->conn->recv_timeout) == ETIMEDOUT) { -+ if (unlikely(sock->wakeup == NULL)) { -+ sock->wakeup = poll_construct_wakeup(); -+ if (sock->wakeup == NULL) { -+ return -1; -+ } -+ sock->epoll_events = POLLIN | POLLERR; -+ } -+ -+ ret = lstack_block_wait(sock->wakeup, sock->conn->recv_timeout); -+ if (ret == ETIMEDOUT) { - noblock = true; -+ } else if (ret != 0 && errno == EINTR) { -+ /* SIGALRM signal may interrupt blocking */ -+ return ret; - } - } - -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index e7ae26b..cad9aed 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -76,6 +76,8 @@ int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfd - - int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout); - -+struct wakeup_poll* poll_construct_wakeup(void); -+ - static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) - { - if (wakeup && __atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { --- -2.33.0 - diff --git a/0288-fix-socket-of-control-thread-is-overwirtten-due-to-a.patch b/0288-fix-socket-of-control-thread-is-overwirtten-due-to-a.patch deleted file mode 100644 index 17443d3..0000000 --- a/0288-fix-socket-of-control-thread-is-overwirtten-due-to-a.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0f3a61700b17bed0ed39c7c5433952b72dc82b84 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 20 Nov 2024 11:26:55 +0800 -Subject: [PATCH] fix socket of control thread is overwirtten due to another - primary process start - ---- - src/lstack/core/lstack_init.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c -index 276cdf8..29796ee 100644 ---- a/src/lstack/core/lstack_init.c -+++ b/src/lstack/core/lstack_init.c -@@ -166,14 +166,14 @@ static void create_control_thread(void) - LSTACK_EXIT(1, "pthread_create failed ret=%d errno=%d\n", ret, errno); - } - } else { -- ret = pthread_create(&tid, NULL, (void *(*)(void *))control_server_thread, NULL); -- if (ret != 0) { -- LSTACK_EXIT(1, "pthread_create failed ret=%d errno=%d\n", ret, errno); -- } - ret = dpdk_eal_init(); - if (ret < 0) { - LSTACK_EXIT(1, "dpdk_eal_init failed ret=%d errno=%d\n", ret, errno); - } -+ ret = pthread_create(&tid, NULL, (void *(*)(void *))control_server_thread, NULL); -+ if (ret != 0) { -+ LSTACK_EXIT(1, "pthread_create failed ret=%d errno=%d\n", ret, errno); -+ } - } - - if (pthread_setname_np(tid, CONTROL_THREAD_NAME) != 0) { --- -2.33.0 - diff --git a/0289-LWIP-adjust-position-of-shutdown-in-callback-of-conn.patch b/0289-LWIP-adjust-position-of-shutdown-in-callback-of-conn.patch deleted file mode 100644 index b067e0e..0000000 --- a/0289-LWIP-adjust-position-of-shutdown-in-callback-of-conn.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 1d4bdf6a14afe7459d2fa9d2da19a36c45ae91f5 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 20 Nov 2024 16:32:28 +0800 -Subject: [PATCH] LWIP: adjust position of shutdown in callback of connect - ---- - src/lstack/core/lstack_lwip.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 65acae2..648da58 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1273,10 +1273,10 @@ void do_lwip_connected_callback(struct netconn *conn) - posix_api->epoll_ctl_fn(sock->wakeup->epollfd, EPOLL_CTL_DEL, fd, NULL); - } - -- posix_api->shutdown_fn(fd, SHUT_RDWR); -- - POSIX_SET_TYPE(sock, POSIX_LWIP); - -+ posix_api->shutdown_fn(fd, SHUT_RDWR); -+ - add_sock_event(sock, EPOLLOUT); - } - --- -2.33.0 - diff --git a/0290-Fix-the-wrong-spelling-description-in-the-notes-and-.patch b/0290-Fix-the-wrong-spelling-description-in-the-notes-and-.patch deleted file mode 100644 index f25cb9d..0000000 --- a/0290-Fix-the-wrong-spelling-description-in-the-notes-and-.patch +++ /dev/null @@ -1,154 +0,0 @@ -From e5aa9e48521b3096ba9acb888d293eefeaf677da Mon Sep 17 00:00:00 2001 -From: Caohongtao -Date: Wed, 9 Oct 2024 02:55:56 +0000 -Subject: [PATCH] Fix the wrong spelling description in the notes and logs - -Signed-off-by: Caohongtao ---- - src/ltran/ltran_forward.c | 6 +++--- - src/ltran/main.c | 4 ++-- - tools/gazelle_common.sh | 8 ++++---- - tools/gazelle_setup.sh | 4 ++-- - tools/sync-gazelle-src.sh | 4 ++-- - 5 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index 0de9c1c..aef5e46 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -58,7 +58,7 @@ static void calculate_ltran_latency(struct gazelle_stack *stack, const struct rt - uint64_t latency; - - lt = &mbuf_to_private(mbuf)->lt; -- // vaild check -+ // valid check - if (lt->stamp != ~(lt->check)) { - return; - } -@@ -221,7 +221,7 @@ static __rte_always_inline void flush_rx_ring(struct gazelle_stack *stack) - } - - uint32_t flush_cnt = pkt_bufs_enque_rx_ring(stack); -- /* cant't flush mbuf into backup */ -+ /* can't flush mbuf into backup */ - if (unlikely(flush_cnt < stack->pkt_cnt)) { - pktbufs_move_to_backup_bufs(stack, &(stack->pkt_buf[flush_cnt]), stack->pkt_cnt - flush_cnt); - } -@@ -475,7 +475,7 @@ static __rte_always_inline void tcp_hash_table_add_conn(struct gazelle_stack *st - tcp_conn->conn_timeout = -1; - return; - } else { -- /* del old invaild conn */ -+ /* del old invalid conn */ - gazelle_conn_del_by_quintuple(conn_htable, transfer_qtuple); - } - } -diff --git a/src/ltran/main.c b/src/ltran/main.c -index 3d2310b..0320b29 100644 ---- a/src/ltran/main.c -+++ b/src/ltran/main.c -@@ -117,7 +117,7 @@ static int32_t ltran_core_init(int32_t argc, char *argv[]) - - ret = ltran_ethdev_init(); - if (ret != GAZELLE_OK) { -- syslog(LOG_ERR, "ltran ethdev init faild. ret=%d.\n", ret); -+ syslog(LOG_ERR, "ltran ethdev init failed. ret=%d.\n", ret); - closelog(); - return ret; - } -@@ -211,7 +211,7 @@ int32_t main(int32_t argc, char *argv[]) - } - - /* create multi thread to receive and send packet for multi bond port */ -- LTRAN_INFO("Runing Process forward\n"); -+ LTRAN_INFO("Running Process forward\n"); - /* main thread is for port 0 receive packet */ - index = 0; - upstream_forward((const void *)&index); -diff --git a/tools/gazelle_common.sh b/tools/gazelle_common.sh -index fac0d68..8febd16 100644 ---- a/tools/gazelle_common.sh -+++ b/tools/gazelle_common.sh -@@ -25,7 +25,7 @@ g_subnet_len="" - g_gateway="" - g_premask="" - --# globla varibles initialized when run -+# global variables initialized when run - g_netcard_mac="" - g_kni_mac="" - g_default_route="$(sudo ip route | grep default)" -@@ -148,7 +148,7 @@ load_vfio_module() { - msg_show "Loading vfio module" - sudo /sbin/modprobe vfio enable_unsafe_noiommu_mode=1 - else -- msg_err "the vfio mudule is not exist" -+ msg_err "the vfio module is not exist" - return 1 - fi - sudo modinfo vfio-pci > /dev/null -@@ -156,7 +156,7 @@ load_vfio_module() { - msg_show "Loading vfio-pci module" - sudo /sbin/modprobe vfio-pci - else -- msg_err "the vfio-pci mudule is not exist" -+ msg_err "the vfio-pci module is not exist" - return 1 - fi - fi -@@ -393,7 +393,7 @@ configure_nic() { - fi - - if [ $1 = "usr" ]; then -- msg_show "use vitual kni card" -+ msg_show "use virtual kni card" - net_card=$g_conn_if_kni - default_route="$(echo $g_default_route | grep $g_conn_if)" - fi -diff --git a/tools/gazelle_setup.sh b/tools/gazelle_setup.sh -index c3ad830..8185e19 100644 ---- a/tools/gazelle_setup.sh -+++ b/tools/gazelle_setup.sh -@@ -117,7 +117,7 @@ check_nic_name() { - - check_numa_pages() { - numa_num=$(lscpu | grep "NUMA node(s)" | awk '{print $3}') -- # todo : check the maxmum and minmum of the page numbers, make sure the system available mem support -+ # todo : check the maxmum and minimum of the page numbers, make sure the system available mem support - g_hugepages=${g_hugepages:-1024} - msg_show "make sure the huge mem is large enough & not extend the maximum of system mem!" - myPage=(${g_hugepages//\,/ }) -@@ -511,7 +511,7 @@ XDG_RUNTIME_DIR=/tmp nohup /usr/bin/ltran --config-file=$CONF_DIR/ltran.conf > / - - check_ltran 120 - if [ $? -ne 0 ]; then -- msg_err "ltran start faild! Please check ltran's log for the reason of the problem." -+ msg_err "ltran start failed! Please check ltran's log for the reason of the problem." - nic_recover - exit 1 - else -diff --git a/tools/sync-gazelle-src.sh b/tools/sync-gazelle-src.sh -index ccfa8eb..326119b 100644 ---- a/tools/sync-gazelle-src.sh -+++ b/tools/sync-gazelle-src.sh -@@ -8,7 +8,7 @@ - # 2. COMMIT_ID is a committrf hash record from openeuler/gazelle (this repository). - # Multiple committrf hash records should be separated by spaces; - # 3. TARGET_BRANCH is a branch from src-openeuler/gazelle; --# 4. USER/EMAIL will be autimatically obtailed from the git configuration; -+# 4. USER/EMAIL will be automatically obtailed from the git configuration; - - # Example Usage: - # > COMMIT_ID="123456789" TARGET_BRANCH="openEuler-20.03-LTS-SP1" bash tools/sync-gazelle-src.sh -@@ -39,7 +39,7 @@ for commitid in ${COMMIT_ID};do - cd ${workdir} - patchname=$(git format-patch -1 ${commitid} | tail -n1) - if [ $? -ne 0 ];then -- echo "invaild commitid $commitid" -+ echo "invalid commitid $commitid" - exit 1 - fi - gitmsg=$(git log --pretty=format:"%s" -1 $commitid | sed -e 's/^![0-9]* //g') --- -2.33.0 - diff --git a/0291-update-test-unitest-ltran-ltran_param_test.c.patch b/0291-update-test-unitest-ltran-ltran_param_test.c.patch deleted file mode 100644 index d9b6367..0000000 --- a/0291-update-test-unitest-ltran-ltran_param_test.c.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 6da24dc0e77efa68f7b8c7d9986634918ef6097e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E8=8F=A0=E8=90=9D=E6=9C=89=E7=82=B9=E9=85=B8?= - -Date: Wed, 9 Oct 2024 07:55:56 +0000 -Subject: [PATCH] update test/unitest/ltran/ltran_param_test.c. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: 菠萝有点酸 ---- - test/unitest/ltran/ltran_param_test.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/test/unitest/ltran/ltran_param_test.c b/test/unitest/ltran/ltran_param_test.c -index 3b2a24d..d43d20f 100644 ---- a/test/unitest/ltran/ltran_param_test.c -+++ b/test/unitest/ltran/ltran_param_test.c -@@ -74,7 +74,7 @@ void test_ltran_bad_params_clients(void) - CU_ASSERT(ltran_bad_param("s/dispatch_max_clients = 32/dispatch_max_clients = 0/") != 0); - CU_ASSERT(gazelle_get_errno() == GAZELLE_ERANGE); - -- /* ltran start 999 clinet */ -+ /* ltran start 999 client */ - CU_ASSERT(ltran_bad_param("s/dispatch_max_clients = 32/dispatch_max_clients = 999/") != 0); - CU_ASSERT(gazelle_get_errno() == GAZELLE_ERANGE); - --- -2.33.0 - diff --git a/0292-fix-free-null-pointer-when-no-matching-device-is-fou.patch b/0292-fix-free-null-pointer-when-no-matching-device-is-fou.patch deleted file mode 100644 index 3b2e6fd..0000000 --- a/0292-fix-free-null-pointer-when-no-matching-device-is-fou.patch +++ /dev/null @@ -1,87 +0,0 @@ -From cd82f46b54e14898087ea1b051bce51eb50adef7 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 20 Nov 2024 14:17:09 +0800 -Subject: [PATCH] fix free null pointer when no matching device is found - ---- - src/lstack/core/lstack_cfg.c | 15 ++++++--------- - 1 file changed, 6 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 2a3f1af..0ca838d 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -179,7 +179,7 @@ struct cfg_params *get_global_cfg_params(void) - - static int32_t str_to_eth_addr(const char *src, unsigned char *dst) - { -- if (strlen(src) > DEV_MAC_LEN) { -+ if (src == NULL || strlen(src) > DEV_MAC_LEN) { - return -EINVAL; - } - -@@ -273,7 +273,6 @@ static int32_t parse_mask_addr(void) - } - - freeifaddrs(ifaddr); -- freeifaddrs(ifa); - } - - if (g_config_params.netmask.addr == INADDR_NONE) { -@@ -315,7 +314,6 @@ static int32_t parse_host_addr(void) - } - - freeifaddrs(ifaddr); -- freeifaddrs(ifa); - } - - if (g_config_params.host_addr.addr == INADDR_NONE) { -@@ -404,7 +402,6 @@ static int32_t parse_devices(void) - } - - freeifaddrs(ifaddr); -- freeifaddrs(ifa); - } - - /* add dev */ -@@ -1048,7 +1045,7 @@ static int32_t parse_mbuf_count_per_conn(void) - { - int32_t ret; - PARSE_ARG(g_config_params.mbuf_count_per_conn, "mbuf_count_per_conn", -- MBUF_COUNT_PER_CONN, 1, INT32_MAX, ret); -+ MBUF_COUNT_PER_CONN, 1, INT32_MAX, ret); - return ret; - } - -@@ -1173,13 +1170,13 @@ static int32_t parse_unix_prefix(void) - int32_t ret = 0; - - ret = memset_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -- 0, sizeof(g_config_params.unix_socket_filename)); -+ 0, sizeof(g_config_params.unix_socket_filename)); - if (ret != EOK) { - return ret; - } - - ret = strncpy_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -- GAZELLE_RUN_DIR, strlen(GAZELLE_RUN_DIR) + 1); -+ GAZELLE_RUN_DIR, strlen(GAZELLE_RUN_DIR) + 1); - if (ret != EOK) { - return ret; - } -@@ -1200,10 +1197,10 @@ static int32_t parse_unix_prefix(void) - - if (g_config_params.use_ltran) { - ret = strncat_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -- LTRAN_REG_SOCK_FILENAME, strlen(LTRAN_REG_SOCK_FILENAME) + 1); -+ LTRAN_REG_SOCK_FILENAME, strlen(LTRAN_REG_SOCK_FILENAME) + 1); - } else { - ret = strncat_s(g_config_params.unix_socket_filename, sizeof(g_config_params.unix_socket_filename), -- LSTACK_DFX_SOCK_FILENAME, strlen(LSTACK_DFX_SOCK_FILENAME) + 1); -+ LSTACK_DFX_SOCK_FILENAME, strlen(LSTACK_DFX_SOCK_FILENAME) + 1); - } - - if (ret != EOK) { --- -2.33.0 - diff --git a/0293-cfg-show-dpdk-args-after-dpdk_adjust_args.patch b/0293-cfg-show-dpdk-args-after-dpdk_adjust_args.patch deleted file mode 100644 index 732509a..0000000 --- a/0293-cfg-show-dpdk-args-after-dpdk_adjust_args.patch +++ /dev/null @@ -1,66 +0,0 @@ -From f05ce4c32a5c4121f41a69fa8b78c0a6a69e29d8 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 20 Nov 2024 11:42:00 +0800 -Subject: [PATCH] cfg: show dpdk args after dpdk_adjust_args - ---- - src/lstack/core/lstack_cfg.c | 19 ++++++++++++------- - 1 file changed, 12 insertions(+), 7 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 2a3f1af..72dbb18 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -905,7 +905,7 @@ static void dpdk_fill_socket_mem(void) - } - } - --static void dpdk_add_args(void) -+static void dpdk_adjust_args(void) - { - int idx; - uint16_t lcore_id; -@@ -936,6 +936,15 @@ static void dpdk_add_args(void) - } - } - -+static void dpdk_show_args(void) -+{ -+ (void)fprintf(stderr, "dpdk argv: "); -+ for (uint32_t i = 1; i < g_config_params.dpdk_argc; i++) { -+ (void)fprintf(stderr, "%s ", g_config_params.dpdk_argv[i]); -+ } -+ (void)fprintf(stderr, "\n"); -+} -+ - static int32_t parse_dpdk_args(void) - { - int32_t i; -@@ -957,8 +966,6 @@ static int32_t parse_dpdk_args(void) - if (!g_config_params.dpdk_argv) - return -EINVAL; - -- (void)fprintf(stderr, "dpdk argv: "); -- - g_config_params.dpdk_argv[0] = strdup("lstack"); - if (!g_config_params.dpdk_argv[0]) { - goto free_dpdk_args; -@@ -981,13 +988,11 @@ static int32_t parse_dpdk_args(void) - if (strcmp(p, secondary) == 0) { - global_params->is_primary = 0; - } -- -- (void)fprintf(stderr, "%s ", g_config_params.dpdk_argv[start_index + i]); - } -- (void)fprintf(stderr, "\n"); - g_config_params.dpdk_argc++; - -- dpdk_add_args(); -+ dpdk_adjust_args(); -+ dpdk_show_args(); - - if (turn_args_to_config(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) - goto free_dpdk_args; --- -2.33.0 - diff --git a/0294-fix-build-error-in-2003SP4.patch b/0294-fix-build-error-in-2003SP4.patch deleted file mode 100644 index fa6a004..0000000 --- a/0294-fix-build-error-in-2003SP4.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 83b65f8da77f586cc58278944f840016817ba9f7 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Sat, 23 Nov 2024 16:14:25 +0800 -Subject: [PATCH] fix build error in 2003SP4 - ---- - src/lstack/api/lstack_wrap.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 7e724cd..d22847a 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -31,6 +31,10 @@ - #include "lstack_rtw_api.h" - #include "lstack_dummy_api.h" - -+#ifndef SOL_XDP -+#define SOL_XDP 283 /* same as define in bits/socket.h */ -+#endif -+ - static posix_api_t g_wrap_api_value; - static posix_api_t *g_wrap_api; - --- -2.33.0 - diff --git a/0295-CFG-fix-xdp-iface-check-error.patch b/0295-CFG-fix-xdp-iface-check-error.patch deleted file mode 100644 index adfb22d..0000000 --- a/0295-CFG-fix-xdp-iface-check-error.patch +++ /dev/null @@ -1,166 +0,0 @@ -From fb7be13ec41f31261fb32741cab2f9903b05d246 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 22 Nov 2024 16:04:14 +0800 -Subject: [PATCH] CFG: fix xdp iface check error - ---- - src/lstack/core/lstack_cfg.c | 47 ++++++++++++++++++++++++++---------- - 1 file changed, 34 insertions(+), 13 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0ca838d..45c695e 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -92,6 +92,7 @@ static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); - static int32_t parse_stack_num(void); - static int32_t parse_xdp_eth_name(void); -+static bool xdp_eth_enabled(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -223,7 +224,7 @@ static int32_t parse_gateway_addr(void) - return 0; - } - -- if (strlen(g_config_params.xdp_eth_name) == 0) { -+ if (!xdp_eth_enabled()) { - ok = config_lookup_string(&g_config, "gateway_addr", (const char **)&value); - if (!ok) { - return -EINVAL; -@@ -252,7 +253,7 @@ static int32_t parse_mask_addr(void) - return 0; - } - -- if (strlen(g_config_params.xdp_eth_name) == 0) { -+ if (!xdp_eth_enabled()) { - ret = config_lookup_string(&g_config, "mask_addr", (const char **)&mask_addr); - if (!ret) { - return -EINVAL; -@@ -266,7 +267,7 @@ static int32_t parse_mask_addr(void) - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET || -- strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ strcmp(ifa->ifa_name, g_config_params.xdp_eth_name)) { - continue; - } - g_config_params.netmask.addr = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr; -@@ -293,7 +294,7 @@ static int32_t parse_host_addr(void) - struct ifaddrs *ifaddr; - struct ifaddrs *ifa; - -- if (strlen(g_config_params.xdp_eth_name) == 0) { -+ if (!xdp_eth_enabled()) { - ret = config_lookup_string(&g_config, "host_addr", (const char **)&host_addr); - if (!ret) { - return 0; -@@ -307,7 +308,7 @@ static int32_t parse_host_addr(void) - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET || -- strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ strcmp(ifa->ifa_name, g_config_params.xdp_eth_name)) { - continue; - } - g_config_params.host_addr.addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; -@@ -334,7 +335,7 @@ static int32_t parse_host_addr6(void) - - ok = config_lookup_string(&g_config, "host_addr6", (const char **)&value); - if (!ok) { -- if (ip4_addr_isany_val(g_config_params.host_addr) && (strlen(g_config_params.xdp_eth_name) == 0)) { -+ if (ip4_addr_isany_val(g_config_params.host_addr) && (!xdp_eth_enabled())) { - LSTACK_PRE_LOG(LSTACK_ERR, "cfg: host_addr and host_addr6 must have a valid one."); - return -EINVAL; - } else { -@@ -377,7 +378,7 @@ static int32_t parse_devices(void) - struct ifaddrs *ifaddr; - char temp_dev[DEV_MAC_LEN + 1] = {0}; - -- if (strlen(g_config_params.xdp_eth_name) == 0) { -+ if (!xdp_eth_enabled()) { - ret = config_lookup_string(&g_config, "devices", (const char **)&dev); - if (!ret) { - return -EINVAL; -@@ -390,7 +391,7 @@ static int32_t parse_devices(void) - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_PACKET || -- strncmp(ifa->ifa_name, g_config_params.xdp_eth_name, strlen(g_config_params.xdp_eth_name))) { -+ strcmp(ifa->ifa_name, g_config_params.xdp_eth_name)) { - continue; - } - -@@ -399,9 +400,16 @@ static int32_t parse_devices(void) - ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr[i], i < (ETHER_ADDR_LEN - 1) ? ":" : ""); - } - dev = strdup_assert_return(temp_dev); -+ break; - } - - freeifaddrs(ifaddr); -+ -+ if (dev == NULL) { -+ LSTACK_PRE_LOG(LSTACK_ERR, "cfg: can not find the iface \"%s\" specified in dpdk_args." -+ " devices parsing exit!\n", g_config_params.xdp_eth_name); -+ return -EINVAL; -+ } - } - - /* add dev */ -@@ -1497,7 +1505,7 @@ static int32_t parse_stack_interrupt(void) - return ret; - } - --static void dpdk_dev_get_iface_name(char *vdev_str) -+static int dpdk_dev_get_iface_name(char *vdev_str) - { - char *token = NULL; - char *iface_value = NULL; -@@ -1507,7 +1515,7 @@ static void dpdk_dev_get_iface_name(char *vdev_str) - /* To prevent the original string from being modified, use a copied string. */ - if (strcpy_s(vdev_str_cp, sizeof(vdev_str_cp), vdev_str) != 0) { - LSTACK_PRE_LOG(LSTACK_ERR, "vdev_str strcpy_s fail \n"); -- return; -+ return -1; - } - - token = strtok_s(vdev_str_cp, ",", &next_token); -@@ -1519,8 +1527,12 @@ static void dpdk_dev_get_iface_name(char *vdev_str) - token = strtok_s(NULL, ",", &next_token); - } - -- if (iface_value) { -+ if (iface_value && strlen(iface_value) > 0) { - strncpy_s(g_config_params.xdp_eth_name, IFNAMSIZ, iface_value, IFNAMSIZ - 1); -+ return 0; -+ } else { -+ LSTACK_PRE_LOG(LSTACK_ERR, "xdp iface name bas not been specified in dpdk_args.\n"); -+ return -1; - } - } - -@@ -1536,9 +1548,18 @@ static int32_t parse_xdp_eth_name(void) - - for (uint32_t i = 0; i < g_config_params.dpdk_argc; i++) { - if (!strncmp(g_config_params.dpdk_argv[i], OPT_VDEV, strlen(OPT_VDEV))) { -- dpdk_dev_get_iface_name(g_config_params.dpdk_argv[i + 1]); -+ ret = dpdk_dev_get_iface_name(g_config_params.dpdk_argv[i + 1]); -+ break; - } - } - -- return 0; -+ return ret; -+} -+ -+static bool xdp_eth_enabled(void) -+{ -+ if (strlen(g_config_params.xdp_eth_name)) { -+ return true; -+ } -+ return false; - } --- -2.33.0 - diff --git a/0296-xdp-support-stack-bind-numa.patch b/0296-xdp-support-stack-bind-numa.patch deleted file mode 100644 index 6af3c82..0000000 --- a/0296-xdp-support-stack-bind-numa.patch +++ /dev/null @@ -1,425 +0,0 @@ -From 4b5ead09ab19b08a46a9ffba7cbc5e42e361dcc1 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Sat, 23 Nov 2024 18:04:55 +0800 -Subject: [PATCH] xdp: support stack bind numa - ---- - src/common/gazelle_opt.h | 5 +- - src/lstack/core/lstack_cfg.c | 101 ++++++++---------------- - src/lstack/core/lstack_dpdk.c | 20 ----- - src/lstack/core/lstack_protocol_stack.c | 82 +++++++++++++++++-- - src/lstack/include/lstack_cfg.h | 11 +-- - src/lstack/include/lstack_dpdk.h | 1 - - 6 files changed, 119 insertions(+), 101 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 6d787b9..98f1afd 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -105,8 +105,11 @@ - - #define LSTACK_SEND_THREAD_NAME "lstack_send" - #define LSTACK_RECV_THREAD_NAME "lstack_recv" --#define LSTACK_THREAD_NAME "gazellelstack" -+#define LSTACK_THREAD_NAME "gazellelstack" - - #define SLEEP_US_BEFORE_LINK_UP 10000 - -+#define CPUS_MAX_NUM 640 -+#define GAZELLE_MAX_NUMA_NODES 4 -+ - #endif /* _GAZELLE_OPT_H_ */ -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 0ca838d..c8ce5c3 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -43,7 +43,6 @@ - #define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist" - #define DEV_MAC_LEN 17 - #define DEV_PCI_ADDR_LEN 12 --#define CPUS_MAX_NUM 256 - #define BOND_MIIMON_MIN 1 - #define BOND_MIIMON_MAX INT_MAX - -@@ -127,6 +126,7 @@ static struct config_vector_t g_config_tbl[] = { - { "send_ring_size", parse_send_ring_size }, - { "recv_ring_size", parse_recv_ring_size }, - { "rpc_msg_max", parse_rpc_msg_max }, -+ { "app_bind_numa", parse_app_bind_numa }, - { "stack_num", parse_stack_num }, - { "num_cpus", parse_stack_cpu_number }, - { "dpdk_args", parse_dpdk_args }, -@@ -139,7 +139,6 @@ static struct config_vector_t g_config_tbl[] = { - { "low_power_mode", parse_low_power_mode }, - { "kni_switch", parse_kni_switch }, - { "listen_shadow", parse_listen_shadow }, -- { "app_bind_numa", parse_app_bind_numa }, - { "app_exclude_cpus", parse_app_exclude_cpus }, - { "main_thread_affinity", parse_main_thread_affinity }, - { "unix_prefix", parse_unix_prefix }, -@@ -446,6 +445,7 @@ static int32_t stack_bind_no_cpu(void) - g_config_params.num_cpu = g_config_params.stack_num; - g_config_params.num_queue = g_config_params.num_cpu; - g_config_params.tot_queue_num = g_config_params.num_queue; -+ g_config_params.app_bind_numa = true; - - LSTACK_PRE_LOG(LSTACK_INFO, "NUMA node: %d\n", g_config_params.numa_id); - -@@ -473,11 +473,11 @@ static int32_t stack_bind_cpus(void) - strcpy(g_config_params.lcores, args); - - tmp_arg = strdup_assert_return(args); -- cnt = separate_str_to_array(tmp_arg, g_config_params.cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); -+ cnt = separate_str_to_array(tmp_arg, g_config_params.cpus, CPUS_MAX_NUM, CPUS_MAX_NUM); - free(tmp_arg); - if (cnt <= 0) { - return stack_bind_no_cpu(); -- } else if (cnt > CFG_MAX_CPUS) { -+ } else if (cnt > CPUS_MAX_NUM) { - return -EINVAL; - } - -@@ -534,9 +534,9 @@ static int32_t parse_app_exclude_cpus(void) - } - - tmp_arg = strdup_assert_return(args); -- cnt = separate_str_to_array(tmp_arg, g_config_params.app_exclude_cpus, CFG_MAX_CPUS, CFG_MAX_CPUS); -+ cnt = separate_str_to_array(tmp_arg, g_config_params.app_exclude_cpus, CPUS_MAX_NUM, CPUS_MAX_NUM); - free(tmp_arg); -- if (cnt <= 0 || cnt > CFG_MAX_CPUS) { -+ if (cnt <= 0 || cnt > CPUS_MAX_NUM) { - return -EINVAL; - } - -@@ -544,18 +544,20 @@ static int32_t parse_app_exclude_cpus(void) - return 0; - } - --static int32_t numa_to_cpusnum(unsigned numa_id, uint32_t *cpulist, int32_t num) -+int numa_to_cpusnum(uint16_t numa_id, uint32_t *cpulist, int num) - { -+ int ret; -+ int fd; - char path[PATH_MAX] = {0}; - char strbuf[PATH_MAX] = {0}; - -- int32_t ret = snprintf_s(path, sizeof(path), PATH_MAX - 1, NUMA_CPULIST_PATH, numa_id); -+ ret = snprintf_s(path, sizeof(path), PATH_MAX - 1, NUMA_CPULIST_PATH, numa_id); - if (ret < 0) { - LSTACK_LOG(ERR, LSTACK, "snprintf numa_cpulist failed\n"); - return -1; - } - -- int32_t fd = open(path, O_RDONLY); -+ fd = open(path, O_RDONLY); - if (fd < 0) { - LSTACK_LOG(ERR, LSTACK, "open %s failed\n", path); - return -1; -@@ -568,55 +570,7 @@ static int32_t numa_to_cpusnum(unsigned numa_id, uint32_t *cpulist, int32_t num) - return -1; - } - -- int32_t count = separate_str_to_array(strbuf, cpulist, num, CFG_MAX_CPUS); -- return count; --} -- --static int32_t stack_idle_cpuset(struct protocol_stack *stack, cpu_set_t *exclude) --{ -- uint32_t cpulist[CPUS_MAX_NUM]; -- -- int32_t cpunum = numa_to_cpusnum(stack->numa_id, cpulist, CPUS_MAX_NUM); -- if (cpunum <= 0) { -- LSTACK_LOG(ERR, LSTACK, "numa_to_cpusnum failed\n"); -- return -1; -- } -- -- CPU_ZERO(&stack->idle_cpuset); -- for (int32_t i = 0; i < cpunum; i++) { -- /* skip stack cpu */ -- if (CPU_ISSET(cpulist[i], exclude)) { -- continue; -- } -- -- CPU_SET(cpulist[i], &stack->idle_cpuset); -- } -- -- return 0; --} -- --int32_t init_stack_numa_cpuset(struct protocol_stack *stack) --{ -- int32_t ret; -- struct cfg_params *cfg = get_global_cfg_params(); -- -- cpu_set_t stack_cpuset; -- CPU_ZERO(&stack_cpuset); -- for (int32_t idx = 0; idx < cfg->num_cpu; ++idx) { -- CPU_SET(cfg->cpus[idx], &stack_cpuset); -- } -- -- for (int32_t idx = 0; idx < cfg->app_exclude_num_cpu; ++idx) { -- CPU_SET(cfg->app_exclude_cpus[idx], &stack_cpuset); -- } -- -- ret = stack_idle_cpuset(stack, &stack_cpuset); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "thread_get_cpuset stack(%u) failed\n", stack->tid); -- return -1; -- } -- -- return 0; -+ return separate_str_to_array(strbuf, cpulist, num, CPUS_MAX_NUM); - } - - static int32_t gazelle_parse_base_virtaddr(const char *arg, uintptr_t *base_vaddr) -@@ -883,6 +837,28 @@ static bool dpdk_have_socket_mem(int32_t argc, char **argv) - return false; - } - -+static void dpdk_fill_lcore(void) -+{ -+ uint16_t lcore_id; -+ cpu_set_t cpuset; -+ -+ CPU_ZERO(&cpuset); -+ if (sched_getaffinity(0, sizeof(cpu_set_t), &cpuset) == -1) { -+ LSTACK_LOG(ERR, LSTACK, "sched_getaffinity failed\n"); -+ return; -+ } -+ -+ for (lcore_id = 0; lcore_id < CPU_SETSIZE; lcore_id++) { -+ if (CPU_ISSET(lcore_id, &cpuset) && -+ numa_node_of_cpu(lcore_id) == g_config_params.numa_id && -+ rte_lcore_is_enabled(lcore_id)) { -+ snprintf_s(g_config_params.lcores, sizeof(g_config_params.lcores), -+ sizeof(g_config_params.lcores) - 1, "%d", lcore_id); -+ break; -+ } -+ } -+} -+ - static void dpdk_fill_socket_mem(void) - { - uint32_t socket_mem_size = dpdk_total_socket_memory(); -@@ -905,17 +881,10 @@ static void dpdk_fill_socket_mem(void) - static void dpdk_adjust_args(void) - { - int idx; -- uint16_t lcore_id; - - if (!dpdk_have_corelist(g_config_params.dpdk_argc, g_config_params.dpdk_argv)) { - if (g_config_params.stack_num > 0) { -- RTE_LCORE_FOREACH(lcore_id) { -- if (numa_node_of_cpu(lcore_id) == g_config_params.numa_id && rte_lcore_is_enabled(lcore_id)) { -- snprintf_s(g_config_params.lcores, sizeof(g_config_params.lcores), -- sizeof(g_config_params.lcores) - 1, "%d", lcore_id); -- break; -- } -- } -+ dpdk_fill_lcore(); - } - g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(OPT_BIND_CORELIST); - g_config_params.dpdk_argv[g_config_params.dpdk_argc++] = strdup_assert_return(g_config_params.lcores); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 5141c3a..3023a6c 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -104,26 +104,6 @@ int32_t thread_affinity_default(void) - return 0; - } - --int32_t thread_affinity_init(int32_t cpu_id) --{ -- int32_t ret; -- cpu_set_t cpuset; -- -- if (get_global_cfg_params()->stack_num > 0) { -- return 0; -- } -- -- CPU_ZERO(&cpuset); -- CPU_SET(cpu_id, &cpuset); -- -- ret = rte_thread_set_affinity(&cpuset); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "thread %d pthread_setaffinity_np failed ret=%d\n", rte_gettid(), ret); -- } -- -- return 0; --} -- - int32_t dpdk_eal_init(void) - { - int32_t ret; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 9cfd54f..2c60a49 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -32,9 +32,8 @@ - #include "lstack_epoll.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" --#include "lstack_protocol_stack.h" -- - #include "lstack_interrupt.h" -+#include "lstack_protocol_stack.h" - - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -@@ -161,6 +160,7 @@ void bind_to_stack_numa(struct protocol_stack *stack) - pthread_t tid = pthread_self(); - - if (get_global_cfg_params()->stack_num > 0) { -+ numa_run_on_node(stack->numa_id); - return; - } - -@@ -187,6 +187,75 @@ void thread_bind_stack(struct protocol_stack *stack) - } - } - -+static int stack_affinity_cpu(int cpu_id) -+{ -+ int32_t ret; -+ cpu_set_t cpuset; -+ -+ CPU_ZERO(&cpuset); -+ CPU_SET(cpu_id, &cpuset); -+ -+ ret = rte_thread_set_affinity(&cpuset); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "thread %d pthread_setaffinity_np failed ret=%d\n", rte_gettid(), ret); -+ } -+ -+ return ret; -+} -+ -+static void stack_affinity_numa(int numa_id) -+{ -+ numa_run_on_node(numa_id); -+} -+ -+static int32_t stack_idle_cpuset(struct protocol_stack *stack, cpu_set_t *exclude) -+{ -+ int32_t cpunum; -+ uint32_t cpulist[CPUS_MAX_NUM]; -+ -+ cpunum = numa_to_cpusnum(stack->numa_id, cpulist, CPUS_MAX_NUM); -+ if (cpunum <= 0) { -+ LSTACK_LOG(ERR, LSTACK, "numa_to_cpusnum failed\n"); -+ return -1; -+ } -+ -+ CPU_ZERO(&stack->idle_cpuset); -+ for (uint32_t i = 0; i < cpunum; i++) { -+ /* skip stack cpu */ -+ if (CPU_ISSET(cpulist[i], exclude)) { -+ continue; -+ } -+ -+ CPU_SET(cpulist[i], &stack->idle_cpuset); -+ } -+ -+ return 0; -+} -+ -+static int32_t init_stack_numa_cpuset(struct protocol_stack *stack) -+{ -+ int32_t ret; -+ struct cfg_params *cfg = get_global_cfg_params(); -+ -+ cpu_set_t stack_cpuset; -+ CPU_ZERO(&stack_cpuset); -+ for (int32_t idx = 0; idx < cfg->num_cpu; ++idx) { -+ CPU_SET(cfg->cpus[idx], &stack_cpuset); -+ } -+ -+ for (int32_t idx = 0; idx < cfg->app_exclude_num_cpu; ++idx) { -+ CPU_SET(cfg->app_exclude_cpus[idx], &stack_cpuset); -+ } -+ -+ ret = stack_idle_cpuset(stack, &stack_cpuset); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "thread_get_cpuset stack(%u) failed\n", stack->tid); -+ return -1; -+ } -+ -+ return 0; -+} -+ - static uint32_t get_protocol_traffic(struct protocol_stack *stack) - { - if (use_ltran()) { -@@ -412,12 +481,13 @@ static struct protocol_stack *stack_thread_init(void *arg) - goto END; - } - -- if (thread_affinity_init(stack->cpu_id) != 0) { -- goto END; -- } -- - if (get_global_cfg_params()->stack_num == 0) { -+ if (stack_affinity_cpu(stack->cpu_id) != 0) { -+ goto END; -+ } - RTE_PER_LCORE(_lcore_id) = stack->cpu_id; -+ } else { -+ stack_affinity_numa(stack->numa_id); - } - - lwip_init(); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 0fd5323..07a97cb 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -36,7 +36,6 @@ - #define RX_RING_NAME 64 - #define MBUF_POOL_NAME 64 - --#define CFG_MAX_CPUS 512 - #define CFG_MAX_PORTS UINT8_MAX - #define ARP_MAX_ENTRIES 1024 - #define LOG_DIR_PATH PATH_MAX -@@ -118,12 +117,12 @@ struct cfg_params { - uint16_t num_cpu; - uint16_t numa_id; - uint16_t stack_num; -- uint32_t cpus[CFG_MAX_CPUS]; -+ uint32_t cpus[CPUS_MAX_NUM]; - - bool main_thread_affinity; - bool app_bind_numa; - uint16_t app_exclude_num_cpu; -- uint32_t app_exclude_cpus[CFG_MAX_CPUS]; -+ uint32_t app_exclude_cpus[CPUS_MAX_NUM]; - - bool stack_mode_rtc; - bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread. -@@ -168,10 +167,8 @@ static inline uint8_t use_ltran(void) - - int cfg_init(void); - int gazelle_param_init(int *argc, char **argv); --int gazelle_copy_param(const char *param, bool is_double, -- int *argc, char argv[][PATH_MAX]); -- -+int gazelle_copy_param(const char *param, bool is_double, int *argc, char argv[][PATH_MAX]); - int match_host_addr(ip_addr_t *addr); --int32_t init_stack_numa_cpuset(struct protocol_stack *stack); -+int numa_to_cpusnum(uint16_t numa_id, uint32_t *cpulist, int num); - - #endif /* GAZELLE_NET_CFG_H */ -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 87219c2..c2142d6 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -45,7 +45,6 @@ int dpdk_ethdev_start(void); - int init_dpdk_ethdev(void); - - int thread_affinity_default(void); --int thread_affinity_init(int cpu_id); - - int32_t create_shared_ring(struct protocol_stack *stack); - int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num); --- -2.33.0 - diff --git a/0297-openGauss-support-kernel-connnect.patch b/0297-openGauss-support-kernel-connnect.patch deleted file mode 100644 index 0acbe91..0000000 --- a/0297-openGauss-support-kernel-connnect.patch +++ /dev/null @@ -1,125 +0,0 @@ -From b29d2ce72651ac91728278cb9b31029b397c6ea5 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Wed, 27 Nov 2024 09:50:08 +0800 -Subject: [PATCH] openGauss: support kernel connnect - -Signed-off-by: hankangkang ---- - src/lstack/api/lstack_wrap.c | 71 ++++++++++++++++++++++++++++-------- - 1 file changed, 56 insertions(+), 15 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index d22847a..4416bd8 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -250,7 +250,7 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - return g_wrap_api->bind_fn(s, name, namelen); - } - --static bool is_dst_ip_localhost(const struct sockaddr *addr) -+static bool kernel_ip_route(const struct sockaddr *addr) - { - struct ifaddrs *ifap; - struct ifaddrs *ifa; -@@ -292,43 +292,84 @@ static bool is_dst_ip_localhost(const struct sockaddr *addr) - freeifaddrs(ifap); - return false; - } -+static bool is_relatived_kernel_ip(const struct sockaddr *dst_addr) -+{ -+ struct ifaddrs *ifap; -+ struct ifaddrs *ifa; -+ uint32_t local_ip; -+ uint32_t local_mask; -+ uint32_t dst_ip; -+ bool ret = false; -+ -+ if (getifaddrs(&ifap) == -1) { -+ LSTACK_LOG(ERR, LSTACK, "get interface IP address failed\n"); -+ return false; -+ } - --static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t namelen) -+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { -+ if (ifa->ifa_addr == NULL) { -+ continue; -+ } -+ -+ if (ifa->ifa_addr->sa_family == AF_INET) { -+ struct sockaddr_in *if_addr = (struct sockaddr_in *)ifa->ifa_addr; -+ if (get_global_cfg_params()->host_addr.addr == if_addr->sin_addr.s_addr) { -+ continue; -+ } -+ } -+ -+ if (ifa->ifa_addr->sa_family == AF_INET && dst_addr->sa_family == AF_INET) { -+ struct sockaddr_in *if_addr = (struct sockaddr_in *)ifa->ifa_addr; -+ struct sockaddr_in *ifa_netmask = (struct sockaddr_in *)ifa->ifa_netmask; -+ local_ip = if_addr->sin_addr.s_addr; -+ local_mask = ifa_netmask->sin_addr.s_addr; -+ dst_ip = ((struct sockaddr_in *)dst_addr) ->sin_addr.s_addr; -+ if ((local_ip & local_mask) == (dst_ip & local_mask)) { -+ ret = true; -+ break; -+ } -+ } -+ } -+ freeifaddrs(ifap); -+ return ret; -+} -+static int32_t do_connect(int32_t s, const struct sockaddr *addr, socklen_t addrlen) - { -- if (name == NULL) { -+ if (addr == NULL) { - GAZELLE_RETURN(EINVAL); - } - - struct lwip_sock *sock = lwip_get_socket(s); - if (select_sock_posix_path(sock) == POSIX_KERNEL) { -- return posix_api->connect_fn(s, name, namelen); -+ return posix_api->connect_fn(s, addr, addrlen); - } - - int32_t ret = 0; - int32_t remote_port; -- bool is_local = is_dst_ip_localhost(name); -+ bool is_kernel = kernel_ip_route(addr); -+ bool is_to_kernel_connect = is_relatived_kernel_ip(addr); - -- remote_port = htons(((struct sockaddr_in *)name)->sin_port); -+ remote_port = htons(((struct sockaddr_in *)addr)->sin_port); - - char listen_ring_name[RING_NAME_LEN]; - snprintf_s(listen_ring_name, sizeof(listen_ring_name), sizeof(listen_ring_name) - 1, - "listen_rx_ring_%d", remote_port); -- if (is_local && rte_ring_lookup(listen_ring_name) == NULL) { -- ret = posix_api->connect_fn(s, name, namelen); -+ -+ if ((is_kernel && rte_ring_lookup(listen_ring_name) == NULL) || is_to_kernel_connect) { -+ ret = posix_api->connect_fn(s, addr, addrlen); - POSIX_SET_TYPE(sock, POSIX_KERNEL); - } 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); -+ ret = g_wrap_api->connect_fn(s, addr, addrlen); - if (ret == 0 || (ret != 0 && errno == EINPROGRESS)) { - POSIX_SET_TYPE(sock, POSIX_LWIP); -- } else { -- ret = posix_api->connect_fn(s, name, namelen); -+ } else { -+ ret = posix_api->connect_fn(s, addr, addrlen); - if (ret == 0) { -- POSIX_SET_TYPE(sock, POSIX_KERNEL); -- } -- } -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); -+ } -+ } - } -- - return ret; - } - --- -2.33.0 - diff --git a/0298-DUMP-gazelle-supports-dump-lstack.patch b/0298-DUMP-gazelle-supports-dump-lstack.patch deleted file mode 100644 index db6afc6..0000000 --- a/0298-DUMP-gazelle-supports-dump-lstack.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 71fee80519b321b565cdec74d9e7fae25f9bc750 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 30 Nov 2024 16:05:02 +0800 -Subject: [PATCH] DUMP: gazelle supports dump lstack - ---- - src/lstack/api/lstack_unistd.c | 36 +++----- - src/lstack/core/lstack_dump.c | 144 +++++++++++++++++++++++++++++++ - src/lstack/include/lstack_dump.h | 19 ++++ - 3 files changed, 176 insertions(+), 23 deletions(-) - create mode 100644 src/lstack/core/lstack_dump.c - create mode 100644 src/lstack/include/lstack_dump.h - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index 1f78626..8fd6490 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -11,7 +11,6 @@ - */ - - #include --#include - #include - - #include -@@ -22,28 +21,11 @@ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "lstack_control_plane.h" -+#include "lstack_dump.h" - - static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGKILL}; - #define HIJACK_SIGNAL_COUNT (sizeof(g_hijack_signal) / sizeof(g_hijack_signal[0])) --#define BACKTRACE_SIZE 64 - --static void dump_stack(void) --{ -- char **stack_trace = NULL; -- void *stack_array[BACKTRACE_SIZE]; -- int stack_num = backtrace(stack_array, BACKTRACE_SIZE); -- -- stack_trace = (char**)backtrace_symbols(stack_array, stack_num); -- if (stack_trace == NULL) { -- perror("backtrace_symbols"); -- return; -- } -- -- for (int i = 0; i < stack_num; i++) { -- LSTACK_LOG(ERR, LSTACK, "%s\n", stack_trace[i]); -- } -- free(stack_trace); --} - static inline bool match_hijack_signal(int sig) - { - unsigned int i; -@@ -58,14 +40,22 @@ static inline bool match_hijack_signal(int sig) - static void lstack_sig_default_handler(int sig) - { - LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); -- if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { -- delete_primary_path(); -- } -- control_fd_close(); -+ - /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ - if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { -+ /* dump stack info */ - dump_stack(); -+ -+ /* dump internal information of lstack */ -+ dump_lstack(); - } -+ -+ if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { -+ delete_primary_path(); -+ } -+ -+ control_fd_close(); -+ - lwip_exit(); - gazelle_exit(); - (void)kill(getpid(), sig); -diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c -new file mode 100644 -index 0000000..d415ddc ---- /dev/null -+++ b/src/lstack/core/lstack_dump.c -@@ -0,0 +1,144 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+ -+#include "lstack_cfg.h" -+#include "lstack_log.h" -+ -+#define DUMP_COMMAND_TIMEOUT_MS 2000 -+#define DUMP_COMMAND_INTERVAL_MS 1 -+#define DUMP_BUF_SZ 1024 -+#define DUMP_BACKTRACE_SIZE 64 -+ -+static const char *dump_command[] = { -+ "gazellectl lstack show 1", -+ "gazellectl lstack show 1 -s", -+ "gazellectl lstack show 1 -x", -+ "gazellectl lstack show 1 -p UDP", -+ "gazellectl lstack show 1 -p TCP", -+ "gazellectl lstack show 1 -p ICMP", -+ "gazellectl lstack show 1 -p IP", -+ "gazellectl lstack show 1 -p ETHARP", -+ "gazellectl lstack show 1 -c" -+}; -+ -+static int dump_lstack_check(void) -+{ -+ /* In ltran mode, dump commands maybe illegal */ -+ if (use_ltran()) { -+ LSTACK_LOG(ERR, LSTACK, "ltran mode doesn't support lstack info dump.\n"); -+ return -1; -+ } -+ -+ LSTACK_LOG(INFO, LSTACK, "Dump lstack check passed. Dumping information:\n"); -+ return 0; -+} -+ -+#define US_PER_MS (MS_PER_S) -+static long timeval_diff_ms(struct timeval *end, struct timeval *begin) -+{ -+ struct timeval result; -+ long result_ms; -+ -+ result.tv_sec = end->tv_sec - begin->tv_sec; -+ result.tv_usec = end->tv_usec - begin->tv_usec; -+ -+ result_ms = result.tv_sec * MS_PER_S + result.tv_usec / US_PER_MS; -+ return result_ms; -+} -+ -+static int dump_command_excute(const char *command) -+{ -+ FILE *fp; -+ int flags, fd; -+ char buffer[DUMP_BUF_SZ]; -+ struct timeval start, now; -+ long elapsed; -+ -+ if ((fp = popen(command, "r")) == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "popen() failed, command \"%s\" didn't excute.\n", command); -+ return -1; -+ } -+ -+ fd = fileno(fp); -+ flags = fcntl(fd, F_GETFL, 0); -+ fcntl(fd, F_SETFL, flags | O_NONBLOCK); -+ -+ gettimeofday(&start, NULL); -+ -+ /* Loop to print command output while checking for timeout. */ -+ while (1) { -+ gettimeofday(&now, NULL); -+ elapsed = timeval_diff_ms(&now, &start); -+ -+ /* check timeout */ -+ if (elapsed > DUMP_COMMAND_TIMEOUT_MS) { -+ LSTACK_LOG(ERR, LSTACK, "Command timeout: %s\n", command); -+ pclose(fp); -+ return -1; -+ } -+ -+ /* get and print command output */ -+ if (fgets(buffer, sizeof(buffer), fp) != NULL) { -+ LSTACK_LOG(INFO, LSTACK, "\r %s", buffer); -+ } else if (feof(fp)) { -+ break; -+ } else { -+ usleep(DUMP_COMMAND_INTERVAL_MS * US_PER_MS); // 1ms -+ } -+ } -+ -+ pclose(fp); -+ return 0; -+} -+ -+void dump_lstack(void) -+{ -+ int ret, command_count; -+ -+ ret = dump_lstack_check(); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "lstack dump check failed, dump process exited!\n"); -+ return; -+ } -+ -+ command_count = sizeof(dump_command) / sizeof(dump_command[0]); -+ for (int i = 0; i < command_count; ++i) { -+ LSTACK_LOG(INFO, LSTACK, "Dump command: \"%s\"\n", dump_command[i]); -+ -+ ret = dump_command_excute(dump_command[i]); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "Dump command: \"%s\" excute failed.\n", dump_command[i]); -+ } -+ } -+} -+ -+void dump_stack(void) -+{ -+ char **stack_trace = NULL; -+ void *stack_array[DUMP_BACKTRACE_SIZE]; -+ int stack_num = backtrace(stack_array, DUMP_BACKTRACE_SIZE); -+ -+ stack_trace = (char**)backtrace_symbols(stack_array, stack_num); -+ if (stack_trace == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "Error in backtrace_symbols, errno %d\n", errno); -+ return; -+ } -+ -+ for (int i = 0; i < stack_num; i++) { -+ LSTACK_LOG(ERR, LSTACK, "%s\n", stack_trace[i]); -+ } -+ free(stack_trace); -+} -diff --git a/src/lstack/include/lstack_dump.h b/src/lstack/include/lstack_dump.h -new file mode 100644 -index 0000000..83f2fd9 ---- /dev/null -+++ b/src/lstack/include/lstack_dump.h -@@ -0,0 +1,19 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _GAZELLE_DUMP_H_ -+#define _GAZELLE_DUMP_H_ -+ -+void dump_stack(void); -+void dump_lstack(void); -+ -+#endif /* _GAZELLE_DUMP_H_ */ --- -2.33.0 - diff --git a/0299-openGauss-fix-gs_ctl-switchover-failed.patch b/0299-openGauss-fix-gs_ctl-switchover-failed.patch deleted file mode 100644 index 89cb302..0000000 --- a/0299-openGauss-fix-gs_ctl-switchover-failed.patch +++ /dev/null @@ -1,59 +0,0 @@ -From ac8f22827e961148a8e469e964d58fe248ba03ce Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 4 Dec 2024 18:00:26 +0800 -Subject: [PATCH] openGauss: fix gs_ctl switchover failed - ---- - src/lstack/api/lstack_unistd.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index 1f78626..e61b0a4 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -71,6 +71,24 @@ static void lstack_sig_default_handler(int sig) - (void)kill(getpid(), sig); - } - -+static void pthread_block_sig(int sig) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, sig); -+ pthread_sigmask(SIG_BLOCK, &mask, NULL); -+} -+ -+static void pthread_unblock_sig(int sig) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, sig); -+ pthread_sigmask(SIG_UNBLOCK, &mask, NULL); -+} -+ - int lstack_signal_init(void) - { - unsigned int i; -@@ -80,6 +98,8 @@ int lstack_signal_init(void) - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { - return -1; - } -+ pthread_block_sig(SIGUSR1); -+ pthread_block_sig(SIGUSR2); - - sigemptyset(&action.sa_mask); - action.sa_flags = (int)(SA_NODEFER | SA_RESETHAND); -@@ -119,6 +139,8 @@ pid_t lstack_fork(void) - pid = posix_api->fork_fn(); - /* child not support lwip */ - if (pid == 0) { -+ pthread_unblock_sig(SIGUSR1); -+ pthread_unblock_sig(SIGUSR2); - posix_api->use_kernel = 1; - } - return pid; --- -2.33.0 - diff --git a/0300-openGauss-fix-connection-attempt-failed.patch b/0300-openGauss-fix-connection-attempt-failed.patch deleted file mode 100644 index c86518d..0000000 --- a/0300-openGauss-fix-connection-attempt-failed.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 1627afea1cb97f85ffe0877daa3691acb2c67dae Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 11 Dec 2024 10:04:40 +0800 -Subject: [PATCH] openGauss: fix connection attempt failed - ---- - src/lstack/api/lstack_wrap.c | 7 +------ - 1 file changed, 1 insertion(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 4416bd8..4b57e60 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -174,12 +174,7 @@ static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t - struct lwip_sock *sock = lwip_get_socket(s); - int times = 10; - int ret = 0; -- /* lstack not sense if ltran enable kni, so only checks use_ltran. */ -- if (!get_global_cfg_params()->use_ltran && !get_global_cfg_params()->kni_switch && -- !get_global_cfg_params()->flow_bifurcation) { -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- 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) { --- -2.33.0 - diff --git a/0301-remove-app_bind_numa-check-from-exclude_cpus.patch b/0301-remove-app_bind_numa-check-from-exclude_cpus.patch deleted file mode 100644 index c9dff59..0000000 --- a/0301-remove-app_bind_numa-check-from-exclude_cpus.patch +++ /dev/null @@ -1,26 +0,0 @@ -From d51c2a23a52d2a2db501abe8cf75c6c2e4fe6bf3 Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Wed, 11 Dec 2024 03:06:17 +0000 -Subject: [PATCH] remove app_bind_numa check from exclude_cpus - ---- - src/lstack/core/lstack_cfg.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 7545726..6a544b4 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -527,9 +527,6 @@ static int32_t parse_app_exclude_cpus(void) - int32_t cnt; - - g_config_params.app_exclude_num_cpu = 0; -- if (!g_config_params.app_bind_numa) { -- return 0; -- } - - num_cpus = config_lookup(&g_config, "app_exclude_cpus"); - if (num_cpus == NULL) { --- -2.33.0 - diff --git a/0302-fix-rpc-pool-leak-when-thread-exits.patch b/0302-fix-rpc-pool-leak-when-thread-exits.patch deleted file mode 100644 index 55517df..0000000 --- a/0302-fix-rpc-pool-leak-when-thread-exits.patch +++ /dev/null @@ -1,99 +0,0 @@ -From f132c0c51e362909081cf0b156ebe093000aa82b Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 10 Dec 2024 17:12:18 +0800 -Subject: [PATCH] fix rpc pool leak, when thread exits - ---- - src/lstack/core/lstack_thread_rpc.c | 56 +++++++++++++++++++++++------ - 1 file changed, 45 insertions(+), 11 deletions(-) - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 26bd16a..d342af4 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -24,6 +24,15 @@ - #include "lstack_epoll.h" - #include "lstack_lwip.h" - -+struct rpc_pool_array { -+#define RPC_POOL_MAX_COUNT 1024 -+ struct rpc_msg_pool *array[RPC_POOL_MAX_COUNT]; -+ pthread_mutex_t lock; -+ int cur_count; -+}; -+ -+static struct rpc_pool_array g_rpc_pool_array; -+ - static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; - static struct rpc_stats g_rpc_stats; - -@@ -32,6 +41,13 @@ struct rpc_stats *rpc_stats_get(void) - return &g_rpc_stats; - } - -+static inline void rpc_pool_array_add(struct rpc_msg_pool *pool) -+{ -+ pthread_mutex_lock(&g_rpc_pool_array.lock); -+ g_rpc_pool_array.array[g_rpc_pool_array.cur_count++] = pool; -+ pthread_mutex_unlock(&g_rpc_pool_array.lock); -+} -+ - __rte_always_inline - static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) - { -@@ -54,23 +70,41 @@ static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func, struct rpc_msg_po - pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); - } - -+static struct rpc_msg_pool *rpc_msg_pool_init(void) -+{ -+ struct rpc_msg_pool *rpc_pool; -+ if (g_rpc_pool_array.cur_count >= RPC_POOL_MAX_COUNT) { -+ return g_rpc_pool_array.array[rte_gettid() % RPC_POOL_MAX_COUNT]; -+ } -+ -+ rpc_pool = calloc(1, sizeof(struct rpc_msg_pool)); -+ if (rpc_pool == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); -+ goto END; -+ } -+ rpc_pool->mempool = -+ create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), 0, rte_gettid()); -+ if (rpc_pool->mempool == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); -+ free(rpc_pool); -+ goto END; -+ } -+ -+ rpc_pool_array_add(rpc_pool); -+ return rpc_pool; -+END: -+ g_rpc_stats.call_alloc_fail++; -+ return NULL; -+} -+ -+ - static struct rpc_msg *rpc_msg_alloc(rpc_func_t func) - { - struct rpc_msg *msg; - - if (unlikely(g_rpc_pool == NULL)) { -- g_rpc_pool = calloc(1, sizeof(struct rpc_msg_pool)); -+ g_rpc_pool = rpc_msg_pool_init(); - if (g_rpc_pool == NULL) { -- LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); -- g_rpc_stats.call_alloc_fail++; -- exit(-1); -- } -- -- g_rpc_pool->mempool = -- create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), 0, rte_gettid()); -- if (g_rpc_pool->mempool == NULL) { -- LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); -- g_rpc_stats.call_alloc_fail++; - exit(-1); - } - } --- -2.33.0 - diff --git a/0303-fix-epoll-and-recv-threads-blocked-on-the-same-semap.patch b/0303-fix-epoll-and-recv-threads-blocked-on-the-same-semap.patch deleted file mode 100644 index 2decded..0000000 --- a/0303-fix-epoll-and-recv-threads-blocked-on-the-same-semap.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 2d8ea9ed99116bf034e447307f8360dd24e9449c Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Tue, 10 Dec 2024 16:35:44 +0800 -Subject: [PATCH] fix epoll and recv threads blocked on the same semaphore. - data cannot be read in recv thread. - ---- - src/lstack/api/lstack_epoll.c | 24 +++++++++++++---- - src/lstack/core/lstack_lwip.c | 43 ++++++++++++++++++++----------- - src/lstack/include/lstack_epoll.h | 1 + - 3 files changed, 48 insertions(+), 20 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index ff9cccf..644efc0 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -73,11 +73,18 @@ void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - return; - } - --void add_sock_event(struct lwip_sock *sock, uint32_t event) -+static void _add_sock_event(struct lwip_sock *sock, struct wakeup_poll *wakeup, uint32_t event) - { -- struct wakeup_poll *wakeup = sock->wakeup; - struct protocol_stack *stack = sock->stack; -- if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE || (event & sock->epoll_events) == 0) { -+ if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE) { -+ return; -+ } -+ -+ if (wakeup->type == WAKEUP_BLOCK) { -+ if (!(event & (EPOLLIN | EPOLLERR))) { -+ return; -+ } -+ } else if (!(event & sock->epoll_events)) { - return; - } - -@@ -91,6 +98,12 @@ void add_sock_event(struct lwip_sock *sock, uint32_t event) - return; - } - -+void add_sock_event(struct lwip_sock *sock, uint32_t event) -+{ -+ _add_sock_event(sock, sock->wakeup, event); -+ _add_sock_event(sock, sock->recv_block, event); -+} -+ - void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - { - if (get_global_cfg_params()->stack_mode_rtc) { -@@ -99,7 +112,7 @@ void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) - if ((event & EPOLLOUT) && !NETCONN_IS_OUTIDLE(sock)) { - sock->events &= ~EPOLLOUT; - } -- if ((event & EPOLLIN) && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { -+ if ((event & EPOLLIN) && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { - sock->events &= ~EPOLLIN; - } - } -@@ -212,7 +225,8 @@ static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *s - if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && - list_node_null(&sock->event_list)) { - list_add_node(&sock->event_list, &wakeup->event_list); -- sem_post(&wakeup->wait); -+ rte_mb(); -+ sem_post(&wakeup->wait); - } - } - pthread_spin_unlock(&wakeup->event_list_lock); -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 648da58..c1338aa 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1002,30 +1002,43 @@ static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf * - return 0; - } - -- while (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) != expect) { -- if (noblock) { -+ if (noblock) { -+ if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) != expect) { - GAZELLE_RETURN(EAGAIN); - } -+ goto END; -+ } -+ -+ if (sock->recv_block == NULL) { -+ sock->recv_block = poll_construct_wakeup(); -+ if (sock->recv_block == NULL) { -+ GAZELLE_RETURN(ENOMEM); -+ } -+ sock->recv_block->type = WAKEUP_BLOCK; -+ } -+ -+ do { -+ __atomic_store_n(&sock->recv_block->in_wait, true, __ATOMIC_RELEASE); -+ if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) == expect) { -+ break; -+ } - if (recv_break_for_err(sock)) { -+ sock->recv_block = NULL; - return -1; - } -- if (unlikely(sock->wakeup == NULL)) { -- sock->wakeup = poll_construct_wakeup(); -- if (sock->wakeup == NULL) { -- return -1; -+ ret = lstack_block_wait(sock->recv_block, sock->conn->recv_timeout); -+ if (ret != 0) { -+ if (errno = ETIMEDOUT) { -+ errno = EAGAIN; - } -- sock->epoll_events = POLLIN | POLLERR; -- } -- -- ret = lstack_block_wait(sock->wakeup, sock->conn->recv_timeout); -- if (ret == ETIMEDOUT) { -- noblock = true; -- } else if (ret != 0 && errno == EINTR) { -- /* SIGALRM signal may interrupt blocking */ -+ sock->recv_block = NULL; - return ret; - } -- } -+ } while (1); -+ __atomic_store_n(&sock->recv_block->in_wait, false, __ATOMIC_RELEASE); -+ sock->recv_block = NULL; - -+END: - if (get_protocol_stack_group()->latency_start) { - calculate_lstack_latency(&sock->stack->latency, *pbuf, GAZELLE_LATENCY_READ_APP_CALL, time_stamp); - } -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index cad9aed..83eace7 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -28,6 +28,7 @@ enum wakeup_type { - WAKEUP_EPOLL = 0, - WAKEUP_POLL, - WAKEUP_CLOSE, -+ WAKEUP_BLOCK, - }; - - struct protocol_stack; --- -2.33.0 - diff --git a/0304-fix-errno-ETIMEFOUT.patch b/0304-fix-errno-ETIMEFOUT.patch deleted file mode 100644 index 7908aee..0000000 --- a/0304-fix-errno-ETIMEFOUT.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4de27f4f182bec258313d736d423b3b0ab4ff057 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Wed, 11 Dec 2024 15:31:15 +0800 -Subject: [PATCH] fix errno == ETIMEFOUT - ---- - src/lstack/core/lstack_lwip.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index c1338aa..1bff5ca 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -1028,7 +1028,7 @@ static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf * - } - ret = lstack_block_wait(sock->recv_block, sock->conn->recv_timeout); - if (ret != 0) { -- if (errno = ETIMEDOUT) { -+ if (errno == ETIMEDOUT) { - errno = EAGAIN; - } - sock->recv_block = NULL; --- -2.33.0 - diff --git a/0305-cfg-notify-that-it-s-unsupported-when-stack_num-1.patch b/0305-cfg-notify-that-it-s-unsupported-when-stack_num-1.patch deleted file mode 100644 index 4d2e203..0000000 --- a/0305-cfg-notify-that-it-s-unsupported-when-stack_num-1.patch +++ /dev/null @@ -1,32 +0,0 @@ -From e03be16e5deab1f8cdaf1ec6b6097184c643063d Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Wed, 11 Dec 2024 10:50:39 +0800 -Subject: [PATCH] cfg: notify that it's unsupported, when stack_num > 1 - ---- - src/lstack/core/lstack_cfg.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 7545726..48408d1 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -509,6 +509,15 @@ static int32_t parse_stack_num(void) - { - int32_t ret; - PARSE_ARG(g_config_params.stack_num, "stack_num", 0, 0, 320, ret); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ if (g_config_params.stack_num > 1) { -+ LSTACK_LOG(ERR, LSTACK, "Multi stacks bound to numa are not supported currently. Please set stack_num <= 1.\n"); -+ return -EINVAL; -+ } -+ - return ret; - } - --- -2.33.0 - diff --git a/0306-fix-a-contention-issue-when-rpc-pools-are-added-to-r.patch b/0306-fix-a-contention-issue-when-rpc-pools-are-added-to-r.patch deleted file mode 100644 index 9738bcf..0000000 --- a/0306-fix-a-contention-issue-when-rpc-pools-are-added-to-r.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 6dce1a0ac071e365cb96551b04f555dec3658d85 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Thu, 12 Dec 2024 16:39:48 +0800 -Subject: [PATCH] fix a contention issue when rpc pools are added to - rpc_pool_array - ---- - src/lstack/core/lstack_thread_rpc.c | 17 ++++++++--------- - 1 file changed, 8 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index d342af4..050594e 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -31,7 +31,9 @@ struct rpc_pool_array { - int cur_count; - }; - --static struct rpc_pool_array g_rpc_pool_array; -+static struct rpc_pool_array g_rpc_pool_array = { -+ .lock = PTHREAD_MUTEX_INITIALIZER, -+}; - - static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; - static struct rpc_stats g_rpc_stats; -@@ -41,13 +43,6 @@ struct rpc_stats *rpc_stats_get(void) - return &g_rpc_stats; - } - --static inline void rpc_pool_array_add(struct rpc_msg_pool *pool) --{ -- pthread_mutex_lock(&g_rpc_pool_array.lock); -- g_rpc_pool_array.array[g_rpc_pool_array.cur_count++] = pool; -- pthread_mutex_unlock(&g_rpc_pool_array.lock); --} -- - __rte_always_inline - static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) - { -@@ -73,7 +68,9 @@ static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func, struct rpc_msg_po - static struct rpc_msg_pool *rpc_msg_pool_init(void) - { - struct rpc_msg_pool *rpc_pool; -+ pthread_mutex_lock(&g_rpc_pool_array.lock); - if (g_rpc_pool_array.cur_count >= RPC_POOL_MAX_COUNT) { -+ pthread_mutex_unlock(&g_rpc_pool_array.lock); - return g_rpc_pool_array.array[rte_gettid() % RPC_POOL_MAX_COUNT]; - } - -@@ -90,9 +87,11 @@ static struct rpc_msg_pool *rpc_msg_pool_init(void) - goto END; - } - -- rpc_pool_array_add(rpc_pool); -+ g_rpc_pool_array.array[g_rpc_pool_array.cur_count++] = rpc_pool; -+ pthread_mutex_unlock(&g_rpc_pool_array.lock); - return rpc_pool; - END: -+ pthread_mutex_unlock(&g_rpc_pool_array.lock); - g_rpc_stats.call_alloc_fail++; - return NULL; - } --- -2.33.0 - diff --git a/0307-openGauss-unsupport_tcp_optname.patch b/0307-openGauss-unsupport_tcp_optname.patch deleted file mode 100644 index de3546f..0000000 --- a/0307-openGauss-unsupport_tcp_optname.patch +++ /dev/null @@ -1,24 +0,0 @@ -From fd8004b7b7e78d08a7ad59a4561a3b539e806f06 Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Thu, 12 Dec 2024 09:14:25 +0800 -Subject: [PATCH] openGauss unsupport_tcp_optname - ---- - src/lstack/api/lstack_wrap.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 4416bd8..95e77b6 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -426,6 +426,7 @@ static bool unsupport_tcp_optname(int32_t optname) - if ((optname == TCP_QUICKACK) || - (optname == TCP_INFO) || - (optname == TCP_MAXSEG) || -+ (optname == TCP_USER_TIMEOUT) || - (optname == TCP_CONGESTION)) { - return true; - } --- -2.33.0 - diff --git a/0308-kernerl-bind-add-ipv6-add-check.patch b/0308-kernerl-bind-add-ipv6-add-check.patch deleted file mode 100644 index 29f7a48..0000000 --- a/0308-kernerl-bind-add-ipv6-add-check.patch +++ /dev/null @@ -1,48 +0,0 @@ -From bf5bf036eed0f7c15e7441c0c4ddbd5d7e48b3dd Mon Sep 17 00:00:00 2001 -From: hankangkang -Date: Thu, 12 Dec 2024 11:40:09 +0800 -Subject: [PATCH] kernerl bind: add ipv6 add check - ---- - src/lstack/api/lstack_wrap.c | 23 +++++++++++++++++------ - 1 file changed, 17 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 4b57e60..05fa6ef 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -174,14 +174,25 @@ static int kernel_bind_process(int32_t s, const struct sockaddr *name, socklen_t - struct lwip_sock *sock = lwip_get_socket(s); - int times = 10; - int ret = 0; -+ bool share_ip = true; -+ -+ /* lwip and kernel share IP, and exchange mbuf through virtual-NIC. -+ * lstack not sense if ltran enable kni, so only checks use_ltran. */ -+ -+ if (!get_global_cfg_params()->use_ltran && !get_global_cfg_params()->kni_switch && -+ !get_global_cfg_params()->flow_bifurcation) { -+ share_ip = false; -+ } - - 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 && errno == EADDRNOTAVAIL) { -+ /* ipv6 addr of virtual-NIC maybe is tentative, need to wait a few seconds */ -+ if (name->sa_family == AF_INET6 && share_ip) { -+ 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); -+ } - } - } - --- -2.33.0 - diff --git a/0309-Connect-execute-lwip-connect-if-dst_ip-and-host_ip-a.patch b/0309-Connect-execute-lwip-connect-if-dst_ip-and-host_ip-a.patch deleted file mode 100644 index 885171b..0000000 --- a/0309-Connect-execute-lwip-connect-if-dst_ip-and-host_ip-a.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 434a2509c25f265adb5d7b9398cb3bf8e379b387 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 14 Dec 2024 16:55:18 +0800 -Subject: [PATCH] Connect: execute lwip connect if dst_ip and host_ip are in - the same network. - ---- - src/lstack/api/lstack_wrap.c | 82 ++++++++++++++++++++++++++---------- - 1 file changed, 59 insertions(+), 23 deletions(-) - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8077753..97e927a 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -256,7 +256,7 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen - return g_wrap_api->bind_fn(s, name, namelen); - } - --static bool kernel_ip_route(const struct sockaddr *addr) -+static bool kernel_ip_match(const struct sockaddr *addr) - { - struct ifaddrs *ifap; - struct ifaddrs *ifa; -@@ -298,7 +298,27 @@ static bool kernel_ip_route(const struct sockaddr *addr) - freeifaddrs(ifap); - return false; - } --static bool is_relatived_kernel_ip(const struct sockaddr *dst_addr) -+ -+static bool lwip_ip_route(const struct sockaddr *dst_addr) -+{ -+ uint32_t host_ip; -+ uint32_t host_mask; -+ uint32_t dst_ip; -+ -+ host_ip = get_global_cfg_params()->host_addr.addr; -+ host_mask = get_global_cfg_params()->netmask.addr; -+ if (dst_addr->sa_family == AF_INET) { -+ dst_ip = ((struct sockaddr_in *)dst_addr) ->sin_addr.s_addr; -+ /* if dst_addr and host_addr are in the same network, return ture. */ -+ if ((host_ip & host_mask) == (dst_ip & host_mask)) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static bool kernel_ip_route(const struct sockaddr *dst_addr) - { - struct ifaddrs *ifap; - struct ifaddrs *ifa; -@@ -339,8 +359,34 @@ static bool is_relatived_kernel_ip(const struct sockaddr *dst_addr) - freeifaddrs(ifap); - return ret; - } -+ -+static bool should_enter_kernel_connect(const struct sockaddr *addr) -+{ -+ int32_t remote_port; -+ char listen_ring_name[RING_NAME_LEN]; -+ -+ remote_port = htons(((struct sockaddr_in *)addr)->sin_port); -+ snprintf_s(listen_ring_name, sizeof(listen_ring_name), sizeof(listen_ring_name) - 1, -+ "listen_rx_ring_%d", remote_port); -+ if (kernel_ip_match(addr) && rte_ring_lookup(listen_ring_name) == NULL) { -+ return true; -+ } -+ -+ if (lwip_ip_route(addr)) { -+ return false; -+ } -+ -+ if (kernel_ip_route(addr)) { -+ return true; -+ } -+ -+ return false; -+} -+ - static int32_t do_connect(int32_t s, const struct sockaddr *addr, socklen_t addrlen) - { -+ int32_t ret = 0; -+ - if (addr == NULL) { - GAZELLE_RETURN(EINVAL); - } -@@ -350,30 +396,20 @@ static int32_t do_connect(int32_t s, const struct sockaddr *addr, socklen_t addr - return posix_api->connect_fn(s, addr, addrlen); - } - -- int32_t ret = 0; -- int32_t remote_port; -- bool is_kernel = kernel_ip_route(addr); -- bool is_to_kernel_connect = is_relatived_kernel_ip(addr); -- -- remote_port = htons(((struct sockaddr_in *)addr)->sin_port); -- -- char listen_ring_name[RING_NAME_LEN]; -- snprintf_s(listen_ring_name, sizeof(listen_ring_name), sizeof(listen_ring_name) - 1, -- "listen_rx_ring_%d", remote_port); -- -- if ((is_kernel && rte_ring_lookup(listen_ring_name) == NULL) || is_to_kernel_connect) { -+ if (should_enter_kernel_connect(addr)) { - ret = posix_api->connect_fn(s, addr, addrlen); - POSIX_SET_TYPE(sock, POSIX_KERNEL); -+ return ret; -+ } -+ -+ /* When the socket is POSIX_LWIP_OR_KERNEL, connect to lwip first and then connect to kernel. */ -+ ret = g_wrap_api->connect_fn(s, addr, addrlen); -+ if (ret == 0 || (ret != 0 && errno == EINPROGRESS)) { -+ POSIX_SET_TYPE(sock, POSIX_LWIP); - } 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, addr, addrlen); -- if (ret == 0 || (ret != 0 && errno == EINPROGRESS)) { -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- } else { -- ret = posix_api->connect_fn(s, addr, addrlen); -- if (ret == 0) { -- POSIX_SET_TYPE(sock, POSIX_KERNEL); -- } -+ ret = posix_api->connect_fn(s, addr, addrlen); -+ if (ret == 0) { -+ POSIX_SET_TYPE(sock, POSIX_KERNEL); - } - } - return ret; --- -2.33.0 - diff --git a/0310-DUMP-fix-build-error-of-oe2003-because-of-micro-is-n.patch b/0310-DUMP-fix-build-error-of-oe2003-because-of-micro-is-n.patch deleted file mode 100644 index f78853c..0000000 --- a/0310-DUMP-fix-build-error-of-oe2003-because-of-micro-is-n.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2def683d0139084f48dc15d118af1d78e687e1f0 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 18 Dec 2024 19:54:29 +0800 -Subject: [PATCH] DUMP: fix build error of oe2003 because of micro is not - defined. - ---- - src/lstack/core/lstack_dump.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c -index d415ddc..969ca2b 100644 ---- a/src/lstack/core/lstack_dump.c -+++ b/src/lstack/core/lstack_dump.c -@@ -14,6 +14,8 @@ - #include - #include - -+#include -+ - #include "lstack_cfg.h" - #include "lstack_log.h" - --- -2.33.0 - diff --git a/0311-SIGNAL-Adjust-sigaction-function-to-keep-lstack-sign.patch b/0311-SIGNAL-Adjust-sigaction-function-to-keep-lstack-sign.patch deleted file mode 100644 index 098403b..0000000 --- a/0311-SIGNAL-Adjust-sigaction-function-to-keep-lstack-sign.patch +++ /dev/null @@ -1,310 +0,0 @@ -From bfc5d283ad9558d169bdb70e6b43876f5aa0062c Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 31 Dec 2024 14:45:58 +0800 -Subject: [PATCH] SIGNAL: Adjust sigaction function to keep lstack signal - function executed successfully. - ---- - src/lstack/api/lstack_unistd.c | 91 ++++++++++++++++++---- - src/lstack/core/lstack_dump.c | 4 +- - src/lstack/core/lstack_protocol_stack.c | 23 +++++- - src/lstack/core/lstack_stack_stat.c | 24 +++--- - src/lstack/core/lstack_thread_rpc.c | 1 + - src/lstack/include/lstack_protocol_stack.h | 3 + - 6 files changed, 117 insertions(+), 29 deletions(-) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index 47d80ec..90e603e 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -26,23 +26,54 @@ - static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGKILL}; - #define HIJACK_SIGNAL_COUNT (sizeof(g_hijack_signal) / sizeof(g_hijack_signal[0])) - -+static struct sigaction g_register_sigactions[NSIG]; // NSIG is the signal counts of system, normally equal 65 in Linux. -+static void lstack_sig_default_handler(int sig); -+ -+static bool sig_is_registered(int sig) -+{ -+ if (g_register_sigactions[sig].sa_handler != NULL && -+ g_register_sigactions[sig].sa_handler != (void *) lstack_sig_default_handler) { -+ return true; -+ } -+ return false; -+} -+ - static inline bool match_hijack_signal(int sig) - { - unsigned int i; - for (i = 0; i < HIJACK_SIGNAL_COUNT; i++) { - if (sig == g_hijack_signal[i]) { -- return 1; -+ return true; - } - } -- return 0; -+ return false; - } - --static void lstack_sig_default_handler(int sig) -+/* When operations such as pressing Ctrl+C or Kill are executed, we don't need to dump the stack. */ -+bool sig_need_dump(int sig) - { -+ if (sig == SIGINT || sig == SIGTERM || sig == SIGKILL) { -+ return false; -+ } -+ return true; -+} -+ -+static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *context) -+{ -+ static bool skip_process_exit = false; -+ -+ /* avoiding sig function being executed twice. */ -+ if (!skip_process_exit) { -+ skip_process_exit = true; -+ } else { -+ return; -+ } -+ - LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); - -- /* When operations such as pressing Ctrl+C or Kill, the call stack exit is not displayed. */ -- if (sig != SIGINT && sig != SIGTERM && sig != SIGKILL) { -+ stack_stop(); -+ -+ if (sig_need_dump(sig)) { - /* dump stack info */ - dump_stack(); - -@@ -50,17 +81,31 @@ static void lstack_sig_default_handler(int sig) - dump_lstack(); - } - -+ if (sig_is_registered(sig)) { -+ if (g_register_sigactions[sig].sa_flags & SA_SIGINFO) { -+ g_register_sigactions[sig].sa_sigaction(sig, info, context); -+ } else { -+ g_register_sigactions[sig].sa_handler(sig); -+ } -+ } -+ - if (get_global_cfg_params() && get_global_cfg_params()->is_primary) { - delete_primary_path(); - } - - control_fd_close(); - -+ stack_exit(); - lwip_exit(); - gazelle_exit(); - (void)kill(getpid(), sig); - } - -+static void lstack_sig_default_handler(int sig) -+{ -+ lstack_sigaction_default_handler(sig, NULL, NULL); -+} -+ - static void pthread_block_sig(int sig) - { - sigset_t mask; -@@ -105,18 +150,34 @@ int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigacti - { - struct sigaction new_action; - -- if ((match_hijack_signal(sig_num) != 0) && (action && action->sa_handler == SIG_DFL)) { -+ if (match_hijack_signal(sig_num) && action != NULL) { - new_action = *action; -- new_action.sa_flags |= SA_RESETHAND; -- new_action.sa_handler = lstack_sig_default_handler; -- return posix_api->sigaction_fn(sig_num, &new_action, old_action); -- } - -- /* SA_INTERRUPT is deprecated, use SA_RESETHAND instead. */ -- if ((match_hijack_signal(sig_num) != 0) && (action && action->sa_flags == SA_INTERRUPT)) { -- new_action = *action; -- new_action.sa_flags |= SA_RESETHAND; -- return posix_api->sigaction_fn(sig_num, &new_action, old_action); -+ if (action->sa_handler == SIG_DFL) { -+ new_action = *action; -+ new_action.sa_flags |= SA_RESETHAND; -+ new_action.sa_handler = lstack_sig_default_handler; -+ return posix_api->sigaction_fn(sig_num, &new_action, old_action); -+ } -+ -+ /* SA_INTERRUPT is deprecated, use SA_RESETHAND instead. */ -+ if (action->sa_flags == SA_INTERRUPT) { -+ new_action = *action; -+ new_action.sa_flags |= SA_RESETHAND; -+ return posix_api->sigaction_fn(sig_num, &new_action, old_action); -+ } -+ -+ if (sig_need_dump(sig_num)) { -+ g_register_sigactions[sig_num] = new_action; -+ -+ /* If SA_SIGINFO is setted, we use sa_sigaction. */ -+ if (action->sa_flags & SA_SIGINFO) { -+ new_action.sa_sigaction = lstack_sigaction_default_handler; -+ } else { -+ new_action.sa_handler = lstack_sig_default_handler; -+ } -+ return posix_api->sigaction_fn(sig_num, &new_action, old_action); -+ } - } - - return posix_api->sigaction_fn(sig_num, action, old_action); -diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c -index d415ddc..2a4477d 100644 ---- a/src/lstack/core/lstack_dump.c -+++ b/src/lstack/core/lstack_dump.c -@@ -23,14 +23,16 @@ - #define DUMP_BACKTRACE_SIZE 64 - - static const char *dump_command[] = { -- "gazellectl lstack show 1", - "gazellectl lstack show 1 -s", - "gazellectl lstack show 1 -x", -+ "gazellectl lstack show 1 -v", -+ "gazellectl lstack show 1 -I", - "gazellectl lstack show 1 -p UDP", - "gazellectl lstack show 1 -p TCP", - "gazellectl lstack show 1 -p ICMP", - "gazellectl lstack show 1 -p IP", - "gazellectl lstack show 1 -p ETHARP", -+ "gazellectl lstack show 1", - "gazellectl lstack show 1 -c" - }; - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 2c60a49..1eebac4 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -51,7 +51,7 @@ static void stack_set_state(struct protocol_stack *stack, enum rte_lcore_state_t - __atomic_store_n(&stack->state, state, __ATOMIC_RELEASE); - } - --static enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) -+enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) - { - return __atomic_load_n(&stack->state, __ATOMIC_ACQUIRE); - } -@@ -777,17 +777,32 @@ OUT2: - return -1; - } - --void stack_exit(void) -+static void stack_all_fds_close(struct protocol_stack *stack) - { -- /* close all fd */ - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { - struct lwip_sock *sock = lwip_get_socket(i); -- if (!POSIX_IS_CLOSED(sock) && sock->stack == get_protocol_stack()) { -+ if (!POSIX_IS_CLOSED(sock) && sock->stack == stack) { - lwip_close(i); - } - } - } - -+void stack_exit(void) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ if (stack != NULL) { -+ stack_all_fds_close(stack); -+ } -+} -+ -+void stack_stop(void) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ if (stack != NULL) { -+ stack_set_state(stack, WAIT); -+ } -+} -+ - void stack_group_exit(void) - { - int i; -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index c88da8f..b1eb60e 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -30,6 +30,7 @@ - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" -+#include "lstack_dump.h" - - void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) - { -@@ -263,11 +264,13 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - int32_t rpc_call_result = rpc_msgcnt(&stack->rpc_queue); - dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); -- dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ if (stack_get_state(stack) == RUNNING) { -+ rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); -+ dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); -- dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); -+ dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ } - - dfx->data.pkts.conn_num = stack->conn_num; - } -@@ -343,11 +346,14 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - } - break; - case GAZELLE_STAT_LSTACK_SHOW_CONN: -- rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, -- GAZELLE_LSTACK_MAX_CONN); -- dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -- rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); -- dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ if (stack_get_state(stack) == RUNNING) { -+ rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, -+ GAZELLE_LSTACK_MAX_CONN); -+ dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); -+ dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -+ } -+ - break; - case GAZELLE_STAT_LSTACK_SHOW_LATENCY: - ret = memcpy_s(&dfx->data.latency, sizeof(dfx->data.latency), &stack->latency, sizeof(stack->latency)); -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 26bd16a..9f871af 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -146,6 +146,7 @@ static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) - - static void stack_exit_by_rpc(struct rpc_msg *msg) - { -+ stack_stop(); - stack_exit(); - } - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 068e9d2..c7c7efe 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -120,10 +120,13 @@ void thread_bind_stack(struct protocol_stack *stack); - int stack_group_init(void); - void stack_group_exit(void); - void stack_exit(void); -+void stack_stop(void); - - int stack_setup_thread(void); - int stack_setup_app_thread(void); - - int stack_polling(unsigned wakeup_tick); - -+enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack); -+ - #endif --- -2.33.0 - diff --git a/0312-SIGNAL-Adjust-hijack-sigal-table-to-hijack-SIGABRT-S.patch b/0312-SIGNAL-Adjust-hijack-sigal-table-to-hijack-SIGABRT-S.patch deleted file mode 100644 index 1489236..0000000 --- a/0312-SIGNAL-Adjust-hijack-sigal-table-to-hijack-SIGABRT-S.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 036485b74b382574f1b88b10b5cfed5a0efb2562 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Thu, 2 Jan 2025 17:47:13 +0800 -Subject: [PATCH] SIGNAL: Adjust hijack sigal table to hijack SIGABRT SIGQUIT - and delet SIGKILL - ---- - src/lstack/api/lstack_unistd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index 90e603e..0837a6b 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -23,7 +23,7 @@ - #include "lstack_control_plane.h" - #include "lstack_dump.h" - --static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGKILL}; -+static int g_hijack_signal[] = { SIGTERM, SIGINT, SIGSEGV, SIGBUS, SIGFPE, SIGILL, SIGABRT, SIGQUIT}; - #define HIJACK_SIGNAL_COUNT (sizeof(g_hijack_signal) / sizeof(g_hijack_signal[0])) - - static struct sigaction g_register_sigactions[NSIG]; // NSIG is the signal counts of system, normally equal 65 in Linux. -@@ -52,7 +52,7 @@ static inline bool match_hijack_signal(int sig) - /* When operations such as pressing Ctrl+C or Kill are executed, we don't need to dump the stack. */ - bool sig_need_dump(int sig) - { -- if (sig == SIGINT || sig == SIGTERM || sig == SIGKILL) { -+ if (sig == SIGINT || sig == SIGTERM || sig == SIGQUIT) { - return false; - } - return true; --- -2.33.0 - diff --git a/0313-DUMP-fix-abnomal-printing-in-the-dump-process.patch b/0313-DUMP-fix-abnomal-printing-in-the-dump-process.patch deleted file mode 100644 index 4c0fa4c..0000000 --- a/0313-DUMP-fix-abnomal-printing-in-the-dump-process.patch +++ /dev/null @@ -1,25 +0,0 @@ -From b514eab8bb012067d6f40f3d6a7ec925e9b2093e Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 10 Jan 2025 14:04:44 +0800 -Subject: [PATCH] DUMP: fix abnomal printing in the dump process. - ---- - src/lstack/core/lstack_dump.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c -index 2a4477d..56eb305 100644 ---- a/src/lstack/core/lstack_dump.c -+++ b/src/lstack/core/lstack_dump.c -@@ -94,7 +94,7 @@ static int dump_command_excute(const char *command) - - /* get and print command output */ - if (fgets(buffer, sizeof(buffer), fp) != NULL) { -- LSTACK_LOG(INFO, LSTACK, "\r %s", buffer); -+ LSTACK_LOG(INFO, LSTACK, "\r\033[K %s", buffer); - } else if (feof(fp)) { - break; - } else { --- -2.33.0 - diff --git a/0314-fix-the-memory-leak-when-using-strdup.patch b/0314-fix-the-memory-leak-when-using-strdup.patch deleted file mode 100644 index d314181..0000000 --- a/0314-fix-the-memory-leak-when-using-strdup.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ff847f26a675fe7a1eca24cda2aad5904435ea74 Mon Sep 17 00:00:00 2001 -From: yangchen -Date: Mon, 13 Jan 2025 14:19:47 +0800 -Subject: [PATCH] fix the memory leak when using strdup - ---- - src/lstack/core/lstack_cfg.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 9a935f1..3d49cc3 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -398,7 +398,7 @@ static int32_t parse_devices(void) - sprintf(temp_dev + strlen(temp_dev), "%02x%s", - ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr[i], i < (ETHER_ADDR_LEN - 1) ? ":" : ""); - } -- dev = strdup_assert_return(temp_dev); -+ dev = temp_dev; - break; - } - --- -2.33.0 - diff --git a/0315-Stack-unset-stack_stop-while-stacks-exit-by-rpc-mess.patch b/0315-Stack-unset-stack_stop-while-stacks-exit-by-rpc-mess.patch deleted file mode 100644 index 9daafed..0000000 --- a/0315-Stack-unset-stack_stop-while-stacks-exit-by-rpc-mess.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 51e3c4f57dfcd6400df17bbebe18f544b90e134f Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 14 Jan 2025 10:19:27 +0800 -Subject: [PATCH] Stack: unset stack_stop, while stacks exit by rpc message. - ---- - src/lstack/api/lstack_unistd.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 3 ++- - src/lstack/core/lstack_thread_rpc.c | 1 - - src/lstack/include/lstack_protocol_stack.h | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index 0837a6b..d8b5d8e 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -71,7 +71,7 @@ static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *con - - LSTACK_LOG(ERR, LSTACK, "lstack dumped, caught signal: %d\n", sig); - -- stack_stop(); -+ stack_wait(); - - if (sig_need_dump(sig)) { - /* dump stack info */ -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 1eebac4..fcc0ad7 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -795,7 +795,7 @@ void stack_exit(void) - } - } - --void stack_stop(void) -+void stack_wait(void) - { - struct protocol_stack *stack = get_protocol_stack(); - if (stack != NULL) { -@@ -824,6 +824,7 @@ void stack_group_exit(void) - stack_exit(); - } - -+ /* Waiting all stacks' status transfer to WAIT, which means stacks are ready to exit. */ - for (i = 0; i < stack_group->stack_num; i++) { - if (stack_group->stacks[i] == NULL || stack == stack_group->stacks[i]) { - continue; -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 9f871af..26bd16a 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -146,7 +146,6 @@ static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) - - static void stack_exit_by_rpc(struct rpc_msg *msg) - { -- stack_stop(); - stack_exit(); - } - -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index c7c7efe..c9c50c9 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -120,7 +120,7 @@ void thread_bind_stack(struct protocol_stack *stack); - int stack_group_init(void); - void stack_group_exit(void); - void stack_exit(void); --void stack_stop(void); -+void stack_wait(void); - - int stack_setup_thread(void); - int stack_setup_app_thread(void); --- -2.33.0 - diff --git a/0316-SIGNAL-block-SIGSEGV-during-exit-process.patch b/0316-SIGNAL-block-SIGSEGV-during-exit-process.patch deleted file mode 100644 index a339ff5..0000000 --- a/0316-SIGNAL-block-SIGSEGV-during-exit-process.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 5d7e406a138567a9959c994af4fb574f7f075bed Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Wed, 15 Jan 2025 11:16:43 +0800 -Subject: [PATCH] SIGNAL: block SIGSEGV during exit process - ---- - src/lstack/api/lstack_unistd.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index d8b5d8e..e3b9b1f 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -58,6 +58,15 @@ bool sig_need_dump(int sig) - return true; - } - -+static void pthread_block_sig(int sig) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, sig); -+ pthread_sigmask(SIG_BLOCK, &mask, NULL); -+} -+ - static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *context) - { - static bool skip_process_exit = false; -@@ -81,6 +90,9 @@ static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *con - dump_lstack(); - } - -+ /* App sig_handler may access invalid memory address in gazelle threads, -+ * so we block this signal avoiding getting stuck during exit. */ -+ pthread_block_sig(SIGSEGV); - if (sig_is_registered(sig)) { - if (g_register_sigactions[sig].sa_flags & SA_SIGINFO) { - g_register_sigactions[sig].sa_sigaction(sig, info, context); -@@ -106,15 +118,6 @@ static void lstack_sig_default_handler(int sig) - lstack_sigaction_default_handler(sig, NULL, NULL); - } - --static void pthread_block_sig(int sig) --{ -- sigset_t mask; -- -- sigemptyset(&mask); -- sigaddset(&mask, sig); -- pthread_sigmask(SIG_BLOCK, &mask, NULL); --} -- - static void pthread_unblock_sig(int sig) - { - sigset_t mask; --- -2.33.0 - diff --git a/0317-add-xdp-tx-checksum-tso-offload.patch b/0317-add-xdp-tx-checksum-tso-offload.patch deleted file mode 100644 index 8edb75d..0000000 --- a/0317-add-xdp-tx-checksum-tso-offload.patch +++ /dev/null @@ -1,191 +0,0 @@ -From a237d1d8515d602e152546f182b1769fd31fa8b7 Mon Sep 17 00:00:00 2001 -From: jiangheng -Date: Sat, 18 Jan 2025 21:32:23 +0800 -Subject: [PATCH] add xdp tx checksum/tso offload - ---- - src/lstack/core/lstack_cfg.c | 20 ++++++++++---------- - src/lstack/core/lstack_dpdk.c | 21 ++++++--------------- - src/lstack/include/lstack_cfg.h | 8 ++++++++ - src/lstack/include/lstack_dpdk.h | 1 - - src/lstack/netif/lstack_ethdev.c | 11 +++++++++-- - src/lstack/netif/lstack_vdev.c | 2 +- - 6 files changed, 34 insertions(+), 29 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 3d49cc3..04ceb89 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -91,7 +91,6 @@ static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); - static int32_t parse_stack_num(void); - static int32_t parse_xdp_eth_name(void); --static bool xdp_eth_enabled(void); - - #define PARSE_ARG(_arg, _arg_string, _default_val, _min_val, _max_val, _ret) \ - do { \ -@@ -1491,6 +1490,7 @@ static int dpdk_dev_get_iface_name(char *vdev_str) - char *iface_value = NULL; - char *next_token = NULL; - char vdev_str_cp[strlen(vdev_str) + 1]; -+ int idx = 0; - - /* To prevent the original string from being modified, use a copied string. */ - if (strcpy_s(vdev_str_cp, sizeof(vdev_str_cp), vdev_str) != 0) { -@@ -1498,7 +1498,15 @@ static int dpdk_dev_get_iface_name(char *vdev_str) - return -1; - } - -- token = strtok_s(vdev_str_cp, ",", &next_token); -+ while (vdev_str_cp[idx] == ' ') { -+ idx++; -+ } -+ -+ if (strncmp(&vdev_str_cp[idx], "net_af_xdp", strlen("net_af_xdp")) != 0) { -+ return 0; -+ } -+ -+ token = strtok_s(&vdev_str_cp[idx], ",", &next_token); - while (token != NULL) { - if (strncmp(token, VDEV_ARG_IFACE, strlen(VDEV_ARG_IFACE)) == 0) { - iface_value = token + strlen(VDEV_ARG_IFACE) + 1; -@@ -1535,11 +1543,3 @@ static int32_t parse_xdp_eth_name(void) - - return ret; - } -- --static bool xdp_eth_enabled(void) --{ -- if (strlen(g_config_params.xdp_eth_name)) { -- return true; -- } -- return false; --} -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 3023a6c..fcb78ca 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -52,7 +52,6 @@ - - struct eth_params { - uint16_t port_id; -- bool is_xdp; - - uint16_t nb_queues; - uint16_t nb_rx_desc; -@@ -155,7 +154,12 @@ struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, - } - - /* time stamp before pbuf_custom as priv_data */ -- uint16_t private_size = RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); -+ uint16_t private_size = sizeof(struct mbuf_private); -+ if (xdp_eth_enabled()) { -+ /* reserved for xdp metadata, see struct xsk_tx_metadata in /usr/include/linux/if_xdp.h */ -+ private_size += 24; -+ } -+ private_size = RTE_ALIGN(private_size, RTE_CACHE_LINE_SIZE); - pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf, mbuf_cache_size, private_size, MBUF_SZ, numa_id); - if (pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "cannot create %s pool rte_err=%d\n", pool_name, rte_errno); -@@ -400,16 +404,6 @@ static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *de - return rss_enable; - } - --bool dpdk_nic_is_xdp(void) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- /* eth_params is null in ltran mode */ -- if (stack_group->eth_params == NULL) { -- return false; -- } -- return stack_group->eth_params->is_xdp; --} -- - static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint16_t nb_queues, int *rss_enable) - { - struct rte_eth_dev_info dev_info; -@@ -439,9 +433,6 @@ static int eth_params_init(struct eth_params *eth_params, uint16_t port_id, uint - eth_params->conf.intr_conf.rxq = get_global_cfg_params()->stack_interrupt; - - eth_params_checksum(ð_params->conf, &dev_info); -- if (strcmp(dev_info.driver_name, "net_af_xdp") == 0) { -- eth_params->is_xdp = true; -- } - - if (!get_global_cfg_params()->tuple_filter) { - *rss_enable = eth_params_rss(ð_params->conf, &dev_info); -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 07a97cb..d59407b 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -165,6 +165,14 @@ static inline uint8_t use_ltran(void) - return get_global_cfg_params()->use_ltran; - } - -+static inline bool xdp_eth_enabled(void) -+{ -+ if (strlen(get_global_cfg_params()->xdp_eth_name)) { -+ return true; -+ } -+ return false; -+} -+ - int cfg_init(void); - int gazelle_param_init(int *argc, char **argv); - int gazelle_copy_param(const char *param, bool is_double, int *argc, char argv[][PATH_MAX]); -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index c2142d6..6251be7 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -64,7 +64,6 @@ int32_t dpdk_init_lstack_kni(void); - void dpdk_nic_xstats_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - void dpdk_nic_features_get(struct gazelle_stack_dfx_data *dfx, uint16_t port_id); - --bool dpdk_nic_is_xdp(void); - uint32_t dpdk_pktmbuf_mempool_num(void); - uint32_t dpdk_total_socket_memory(void); - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 315cced..3b859d2 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -364,14 +364,21 @@ static err_t eth_dev_init(struct netif *netif) - - netif->hwaddr_len = ETHER_ADDR_LEN; - -- if (dpdk_nic_is_xdp()) { -+ if (xdp_eth_enabled()) { - netif_set_rxol_flags(netif, RTE_ETH_RX_OFFLOAD_TCP_CKSUM | - RTE_ETH_RX_OFFLOAD_UDP_CKSUM | - RTE_ETH_RX_OFFLOAD_IPV4_CKSUM); -+ netif_set_txol_flags(netif, RTE_ETH_TX_OFFLOAD_TCP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_TSO); -+ /* 16: see kernel MAX_SKB_FRAGS define in skbuff.h */ -+ netif_set_max_pbuf_frags(netif, 16); - } else { - netif_set_rxol_flags(netif, get_protocol_stack_group()->rx_offload); -+ netif_set_txol_flags(netif, get_protocol_stack_group()->tx_offload); -+ /* 40: dpdk pmd support 40 max segs */ -+ netif_set_max_pbuf_frags(netif, 40); - } -- netif_set_txol_flags(netif, get_protocol_stack_group()->tx_offload); -+ netif_set_min_tso_seglen(netif, 256); -+ - if (get_global_cfg_params()->stack_mode_rtc) { - netif_set_rtc_mode(netif); - } -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index b1d1a1b..2eaeb1f 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -147,7 +147,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - } - - if (get_protocol_stack_group()->rx_offload == 0 || /* skip gro when tcp/ip cksum offloads disable */ -- dpdk_nic_is_xdp() || /* kernel has done GRO */ -+ xdp_eth_enabled() || /* kernel has done GRO */ - (get_global_cfg_params()->vlan_mode >= 0 - && !(get_protocol_stack_group()->rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP))) { - return pkt_num; --- -2.33.0 - diff --git a/0318-RTC-mode-fix-gazellectl-can-t-print-connenct-info.patch b/0318-RTC-mode-fix-gazellectl-can-t-print-connenct-info.patch deleted file mode 100644 index 2b57b57..0000000 --- a/0318-RTC-mode-fix-gazellectl-can-t-print-connenct-info.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 4ad01c9c13f3f0837d19194463d6493ee5f1c243 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 21 Jan 2025 11:43:02 +0800 -Subject: [PATCH] RTC-mode: fix gazellectl can't print connenct info - ---- - src/lstack/core/lstack_protocol_stack.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index fcc0ad7..cb1b2b8 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -704,6 +704,7 @@ int stack_setup_app_thread(void) - { - static PER_THREAD int first_flags = 1; - static _Atomic uint32_t queue_id = 0; -+ struct protocol_stack *stack; - - if (likely(first_flags == 0)) { - return 0; -@@ -723,6 +724,10 @@ int stack_setup_app_thread(void) - free(t_params); - return -1; - } -+ -+ stack = get_protocol_stack(); -+ stack_set_state(stack, RUNNING); -+ - atomic_fetch_add(&g_stack_group.stack_num, 1); - free(t_params); - return 0; --- -2.33.0 - diff --git a/0319-Connect-fix-benchmark_dws-connect-failed.patch b/0319-Connect-fix-benchmark_dws-connect-failed.patch deleted file mode 100644 index 8b88bb6..0000000 --- a/0319-Connect-fix-benchmark_dws-connect-failed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 76c84f12bbcaf36f367252adc0a6da1bfee05de1 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Sat, 15 Feb 2025 16:41:13 +0800 -Subject: [PATCH] Connect: fix benchmark_dws connect failed - ---- - 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 97e927a..e90c523 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -404,7 +404,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *addr, socklen_t addr - - /* When the socket is POSIX_LWIP_OR_KERNEL, connect to lwip first and then connect to kernel. */ - ret = g_wrap_api->connect_fn(s, addr, addrlen); -- if (ret == 0 || (ret != 0 && errno == EINPROGRESS)) { -+ if (ret == 0 || (ret != 0 && (errno == EINPROGRESS || errno == EISCONN))) { - POSIX_SET_TYPE(sock, POSIX_LWIP); - } else { - ret = posix_api->connect_fn(s, addr, addrlen); --- -2.33.0 - diff --git a/0320-Protocal-fixing-deathlock-between-protocol-threads-a.patch b/0320-Protocal-fixing-deathlock-between-protocol-threads-a.patch deleted file mode 100644 index c9ae9b9..0000000 --- a/0320-Protocal-fixing-deathlock-between-protocol-threads-a.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 3619605574d0c624513a10ecd543cc2bc1608f7b Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Fri, 24 Jan 2025 14:18:26 +0800 -Subject: [PATCH] Protocal: fixing deathlock between protocol threads and app - thread - ---- - src/lstack/core/lstack_lwip.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 648da58..3bb943f 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -267,7 +267,14 @@ struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type typ - - static inline bool pbuf_allow_append(struct pbuf *pbuf, uint16_t remain_size) - { -- pthread_spin_lock(&pbuf->pbuf_lock); -+ int ret; -+ -+ /* Using pthread_spin_trylock to avoid deadlock between app thread and lstack threads */ -+ ret = pthread_spin_trylock(&pbuf->pbuf_lock); -+ if (ret != 0) { -+ return false; -+ } -+ - if (pbuf->tot_len > remain_size) { - pthread_spin_unlock(&pbuf->pbuf_lock); - return false; --- -2.33.0 - diff --git a/0321-update-gazelle-max-numa-nodes-8.patch b/0321-update-gazelle-max-numa-nodes-8.patch deleted file mode 100644 index 0552c4b..0000000 --- a/0321-update-gazelle-max-numa-nodes-8.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 9e8c4da250bb57f0ba6d59a98d0f601a853d4f7e Mon Sep 17 00:00:00 2001 -From: compile_success <980965867@qq.com> -Date: Tue, 4 Mar 2025 08:14:18 +0000 -Subject: [PATCH] update gazelle max numa nodes 8 - ---- - src/common/gazelle_opt.h | 2 +- - src/common/gazelle_reg_msg.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 98f1afd..d6b1c44 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -110,6 +110,6 @@ - #define SLEEP_US_BEFORE_LINK_UP 10000 - - #define CPUS_MAX_NUM 640 --#define GAZELLE_MAX_NUMA_NODES 4 -+#define GAZELLE_MAX_NUMA_NODES 8 - - #endif /* _GAZELLE_OPT_H_ */ -diff --git a/src/common/gazelle_reg_msg.h b/src/common/gazelle_reg_msg.h -index 2ba47cc..ecd1e35 100644 ---- a/src/common/gazelle_reg_msg.h -+++ b/src/common/gazelle_reg_msg.h -@@ -33,7 +33,7 @@ - #define OPT_VDEV "--vdev" - #define VDEV_ARG_IFACE "iface" - --#define GAZELLE_MAX_NUMA_NODES 4 -+#define GAZELLE_MAX_NUMA_NODES 8 - #define SOCKET_MEM_STRLEN (GAZELLE_MAX_NUMA_NODES * 10) - - /* types for msg from lstack to ltran */ --- -2.33.0 - diff --git a/0322-RTC-fixing-program-stuck-while-gazelle-exit-in-multi.patch b/0322-RTC-fixing-program-stuck-while-gazelle-exit-in-multi.patch deleted file mode 100644 index 1706f31..0000000 --- a/0322-RTC-fixing-program-stuck-while-gazelle-exit-in-multi.patch +++ /dev/null @@ -1,134 +0,0 @@ -From e09eda4fb531f63836f0b2c2ed4bfd4f769a67e3 Mon Sep 17 00:00:00 2001 -From: yinbin -Date: Tue, 3 Jun 2025 21:05:13 +0800 -Subject: [PATCH] RTC: fixing program stuck while gazelle exit in multi-threads - envirement - ---- - src/common/gazelle_base_func.h | 2 ++ - src/lstack/api/lstack_dummy_api.c | 35 +++++++++++++++++++++---- - src/lstack/core/lstack_dump.c | 2 +- - src/lstack/core/lstack_protocol_stack.c | 12 +++++++-- - 4 files changed, 43 insertions(+), 8 deletions(-) - -diff --git a/src/common/gazelle_base_func.h b/src/common/gazelle_base_func.h -index a579cd4..0ccb34b 100644 ---- a/src/common/gazelle_base_func.h -+++ b/src/common/gazelle_base_func.h -@@ -15,6 +15,8 @@ - - #include - -+#define US_PER_MS 1000 -+ - #define GAZELLE_FREE(p) do { \ - if (p) { \ - free(p); \ -diff --git a/src/lstack/api/lstack_dummy_api.c b/src/lstack/api/lstack_dummy_api.c -index 3a867b3..004a3aa 100644 ---- a/src/lstack/api/lstack_dummy_api.c -+++ b/src/lstack/api/lstack_dummy_api.c -@@ -17,18 +17,45 @@ - #include - #include - --#define DUMMY_SLEEP_S 5 -+#include "lstack_log.h" -+#include "lstack_protocol_stack.h" -+#include "common/gazelle_base_func.h" -+ -+#define DUMMY_WAIT_TIMEOUT_MS 5000 -+static void waiting_exit_msg(void) -+{ -+ int time = 0; -+ int sleep_interval = 10; -+ -+ while (time < DUMMY_WAIT_TIMEOUT_MS) { -+ time += sleep_interval; -+ usleep(sleep_interval * US_PER_MS); -+ /* Must be in a secure context before close sockets */ -+ if (get_protocol_stack() && stack_polling(0) != 0) { -+ /* Means stack has closed all fds */ -+ stack_wait(); -+ break; -+ } -+ } -+ -+ if (time >= DUMMY_WAIT_TIMEOUT_MS) { -+ LSTACK_LOG(ERR, LSTACK, "APP thread doesn't recv 'stack_exit' message, will force quit within 5 seconds.\n"); -+ stack_wait(); -+ } -+ -+ usleep(DUMMY_WAIT_TIMEOUT_MS * US_PER_MS); -+} - - static inline ssize_t dummy_exit(void) - { -- sleep(DUMMY_SLEEP_S); -+ waiting_exit_msg(); - errno = ENOTCONN; - return -1; - } - - static int dummy_socket(int domain, int type, int protocol) - { -- sleep(DUMMY_SLEEP_S); -+ waiting_exit_msg(); - return -1; - } - -@@ -68,6 +95,4 @@ void dummy_api_init(posix_api_t *api) - api->sendto_fn = dummy_sendto; - - rte_wmb(); -- /* 1: wait until app thread call send functio complete */ -- sleep(1); - } -diff --git a/src/lstack/core/lstack_dump.c b/src/lstack/core/lstack_dump.c -index da9da28..7092871 100644 ---- a/src/lstack/core/lstack_dump.c -+++ b/src/lstack/core/lstack_dump.c -@@ -18,6 +18,7 @@ - - #include "lstack_cfg.h" - #include "lstack_log.h" -+#include "common/gazelle_base_func.h" - - #define DUMP_COMMAND_TIMEOUT_MS 2000 - #define DUMP_COMMAND_INTERVAL_MS 1 -@@ -50,7 +51,6 @@ static int dump_lstack_check(void) - return 0; - } - --#define US_PER_MS (MS_PER_S) - static long timeval_diff_ms(struct timeval *end, struct timeval *begin) - { - struct timeval result; -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index cb1b2b8..ed36890 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -56,10 +56,18 @@ enum rte_lcore_state_t stack_get_state(struct protocol_stack *stack) - return __atomic_load_n(&stack->state, __ATOMIC_ACQUIRE); - } - -+#define STACK_WAIT_TIMEOUT_MS 5000 - static void stack_wait_quit(struct protocol_stack *stack) - { -- while (__atomic_load_n(&stack->state, __ATOMIC_ACQUIRE) != WAIT) { -- rte_pause(); -+ int timeout = 0; -+ int sleep_interval = 10; -+ while (stack_get_state(stack) != WAIT && timeout < STACK_WAIT_TIMEOUT_MS) { -+ timeout += sleep_interval; -+ usleep(sleep_interval * US_PER_MS); -+ } -+ -+ if (timeout >= STACK_WAIT_TIMEOUT_MS) { -+ LSTACK_LOG(ERR, LSTACK, "stack %p exits time out!\n", stack); - } - } - --- -2.33.0 - diff --git a/0323-cleancode-add-GAZELLE_SAME_NODE.patch b/0323-cleancode-add-GAZELLE_SAME_NODE.patch deleted file mode 100644 index 650b5e5..0000000 --- a/0323-cleancode-add-GAZELLE_SAME_NODE.patch +++ /dev/null @@ -1,958 +0,0 @@ -From ff922a7e3085c37ed70add038a306ef519983a06 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 11 Mar 2025 14:30:02 +0800 -Subject: [PATCH] cleancode: add GAZELLE_SAME_NODE - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_wrap.c | 2 + - src/lstack/core/lstack_lwip.c | 363 +------------------- - src/lstack/core/lstack_protocol_stack.c | 4 + - src/lstack/core/same_node.c | 376 +++++++++++++++++++++ - src/lstack/include/lstack_ethdev.h | 2 - - src/lstack/include/lstack_lwip.h | 6 +- - src/lstack/include/lstack_protocol_stack.h | 2 + - src/lstack/include/same_node.h | 35 ++ - 8 files changed, 427 insertions(+), 363 deletions(-) - create mode 100644 src/lstack/core/same_node.c - create mode 100644 src/lstack/include/same_node.h - -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index e90c523..8a88c47 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -362,6 +362,7 @@ static bool kernel_ip_route(const struct sockaddr *dst_addr) - - static bool should_enter_kernel_connect(const struct sockaddr *addr) - { -+#if GAZELLE_SAME_NODE - int32_t remote_port; - char listen_ring_name[RING_NAME_LEN]; - -@@ -371,6 +372,7 @@ static bool should_enter_kernel_connect(const struct sockaddr *addr) - if (kernel_ip_match(addr) && rte_ring_lookup(listen_ring_name) == NULL) { - return true; - } -+#endif /* GAZELLE_SAME_NODE */ - - if (lwip_ip_route(addr)) { - return false; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index 4f5c4cc..d0e51b2 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -814,76 +814,6 @@ static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t - } - } - --/* process on same node use ring to recv data */ --ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) --{ -- unsigned long long cur_begin = sock->same_node_rx_ring->sndbegin; -- unsigned long long cur_end; -- unsigned long long index = cur_begin + 1; -- size_t act_len = 0; -- -- cur_end = __atomic_load_n(&sock->same_node_rx_ring->sndend, __ATOMIC_ACQUIRE); -- if (cur_begin == cur_end) { -- errno = EAGAIN; -- act_len = -1; -- goto END; -- } -- act_len = cur_end - index + 1; -- act_len = RTE_MIN(act_len, len); -- if ((index & SAME_NODE_RING_MASK) + act_len > SAME_NODE_RING_LEN) { -- size_t act_len1 = SAME_NODE_RING_LEN - (index & SAME_NODE_RING_MASK); -- size_t act_len2 = act_len - act_len1; -- rte_memcpy((char *)buf, (char *)sock->same_node_rx_ring->mz->addr + (index & SAME_NODE_RING_MASK), act_len1); -- rte_memcpy((char *)buf + act_len1, (char *)sock->same_node_rx_ring->mz->addr, act_len2); -- } else { -- rte_memcpy((char *)buf, (char *)sock->same_node_rx_ring->mz->addr + (index & SAME_NODE_RING_MASK), act_len); -- } -- -- index += act_len; -- __atomic_store_n(&sock->same_node_rx_ring->sndbegin, index - 1, __ATOMIC_RELEASE); -- --END: -- /* 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); -- } -- return act_len; --} -- --/* processes on same node use ring to send data */ --ssize_t gazelle_same_node_ring_send(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) --{ -- unsigned long long cur_begin = __atomic_load_n(&sock->same_node_tx_ring->sndbegin, __ATOMIC_ACQUIRE); -- unsigned long long cur_end = sock->same_node_tx_ring->sndend; -- if (cur_end >= cur_begin + SAME_NODE_RING_LEN) { -- errno = EAGAIN; -- return -1; -- } -- -- unsigned long long index = cur_end + 1; -- size_t act_len = SAME_NODE_RING_LEN - (cur_end - cur_begin); -- act_len = RTE_MIN(act_len, len); -- -- if ((index & SAME_NODE_RING_MASK) + act_len > SAME_NODE_RING_LEN) { -- size_t act_len1 = SAME_NODE_RING_LEN - (index & SAME_NODE_RING_MASK); -- size_t act_len2 = act_len - act_len1; -- rte_memcpy((char *)sock->same_node_tx_ring->mz->addr + (index & SAME_NODE_RING_MASK), buf, act_len1); -- rte_memcpy((char *)sock->same_node_tx_ring->mz->addr, (char *)buf + act_len1, act_len2); -- } else { -- rte_memcpy((char *)sock->same_node_tx_ring->mz->addr + (index & SAME_NODE_RING_MASK), buf, act_len); -- } -- -- index += act_len; -- __atomic_store_n(&sock->same_node_tx_ring->sndend, index - 1, __ATOMIC_RELEASE); -- if (act_len == 0) { -- errno = EAGAIN; -- return -1; -- } -- -- return act_len; --} -- - 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) - { -@@ -903,9 +833,11 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - sock->already_bind_numa = 1; - } - -+#if GAZELLE_SAME_NODE - if (sock->same_node_tx_ring != NULL) { - return gazelle_same_node_ring_send(sock, buf, len, flags); - } -+#endif /* GAZELLE_SAME_NODE */ - if (sock->errevent > 0 || sock->stack == NULL) { - GAZELLE_RETURN(ENOTCONN); - } -@@ -1186,10 +1118,11 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - sock->already_bind_numa = 1; - } - -+#if GAZELLE_SAME_NODE - if (sock->same_node_rx_ring != NULL) { -- return gazelle_same_node_ring_recv(sock, buf, len, flags); -- } -- -+ recvd = gazelle_same_node_ring_recv(sock, buf, len, flags); -+ } else -+#endif /* GAZELLE_SAME_NODE */ - if (NETCONN_IS_UDP(sock)) { - recvd = recv_ring_udp_read(sock, buf, len, noblock, addr, addrlen); - } else { -@@ -1220,21 +1153,6 @@ void do_lwip_add_recvlist(int32_t fd) - } - } - --void read_same_node_recv_list(struct protocol_stack *stack) --{ -- struct list_node *list = &(stack->same_node_recv_list); -- struct list_node *node, *temp; -- struct lwip_sock *sock; -- -- list_for_each_node(node, temp, list) { -- sock = list_entry(node, struct lwip_sock, recv_list); -- -- if (sock->same_node_rx_ring != NULL && same_node_ring_count(sock)) { -- add_sock_event(sock, EPOLLIN); -- } -- } --} -- - void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - { - struct list_node *list = &(stack->recv_list); -@@ -1417,272 +1335,3 @@ uint32_t do_lwip_get_connnum(void) - return conn_num; - } - --void netif_poll(struct netif *netif) --{ -- struct tcp_pcb *pcb = NULL; -- struct tcp_pcb_listen *pcbl = NULL; -- -- for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { --#define NETIF_POLL_READ_COUNT 32 -- struct pbuf *pbufs[NETIF_POLL_READ_COUNT]; -- int ret; -- -- if (pcb->client_rx_ring != NULL) { -- ret = rte_ring_sc_dequeue_burst(pcb->client_rx_ring, (void **)pbufs, NETIF_POLL_READ_COUNT, NULL); -- for (int i = 0; i < ret; i++) { -- if (ip_input(pbufs[i], netif) != 0) { -- LSTACK_LOG(INFO, LSTACK, "ip_input return err\n"); -- pbuf_free(pbufs[i]); -- } -- } -- } -- } -- for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { -- if (pcbl->listen_rx_ring != NULL) { -- struct pbuf *pbuf; -- if (rte_ring_sc_dequeue(pcbl->listen_rx_ring, (void **)&pbuf) == 0) { -- if (ip_input(pbuf, netif) != ERR_OK) { -- pbuf_free(pbuf); -- } -- } -- } -- } --} -- --/* processes on same node handshake packet use this function */ --err_t netif_loop_output(struct netif *netif, struct pbuf *p) --{ -- if (!p) { -- return ERR_ARG; -- } -- const struct ip_hdr *iphdr; -- iphdr = (const struct ip_hdr *)p->payload; -- if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { -- return udp_netif_loop_output(netif, p); -- } -- -- struct tcp_pcb *pcb = p->pcb; -- struct pbuf *head = NULL; -- -- if (pcb == NULL || pcb->client_tx_ring == NULL) { -- LSTACK_LOG(ERR, LSTACK, "pcb is null\n"); -- return ERR_ARG; -- } -- -- if (p->next != NULL) { -- LSTACK_LOG(ERR, LSTACK, "netif_loop_output: not support chained pbuf\n"); -- return ERR_ARG; -- } -- -- struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)((char *)p->payload + sizeof(struct ip_hdr)); -- uint8_t flags = TCPH_FLAGS(tcp_hdr); -- -- head = pbuf_alloc(0, p->len, PBUF_RAM); -- if (head == NULL) { -- LSTACK_LOG(ERR, LSTACK, "netif_loop_output: pbuf_alloc failed\n"); -- return ERR_MEM; -- } -- memcpy_s(head->payload, head->len, p->payload, p->len); -- -- if ((flags & TCP_SYN) && !(flags & TCP_ACK)) { -- /* SYN packet, send to listen_ring */ -- char ring_name[RING_NAME_LEN] = {0}; -- snprintf_s(ring_name, sizeof(ring_name), sizeof(ring_name) - 1, "listen_rx_ring_%d", pcb->remote_port); -- struct rte_ring *ring = rte_ring_lookup(ring_name); -- if (ring == NULL) { -- LSTACK_LOG(INFO, LSTACK, "netif_loop_output: cant find listen_rx_ring %d\n", pcb->remote_port); -- pbuf_free(head); -- } else { -- if (rte_ring_mp_enqueue(ring, head) != 0) { -- LSTACK_LOG(INFO, LSTACK, "enqueue sync packet failed\n"); -- pbuf_free(head); -- } -- } -- } else { -- /* send other type packet to tx_ring */ -- if (rte_ring_sp_enqueue(pcb->client_tx_ring, head) != 0) { -- LSTACK_LOG(INFO, LSTACK, "client tx ring full\n"); -- pbuf_free(head); -- } -- } -- -- return ERR_OK; --} -- --err_t find_same_node_memzone(struct tcp_pcb *pcb, struct lwip_sock *nsock) --{ -- char name[RING_NAME_LEN]; -- snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_rx_%u", pcb->remote_port); -- if ((nsock->same_node_tx_ring_mz = rte_memzone_lookup(name)) == NULL) { -- LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -- return -1; -- } else { -- LSTACK_LOG(INFO, LSTACK, "lookup %s success\n", name); -- } -- nsock->same_node_tx_ring = (struct same_node_ring *)nsock->same_node_tx_ring_mz->addr; -- -- snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_buf_rx_%u", pcb->remote_port); -- if ((nsock->same_node_tx_ring->mz = rte_memzone_lookup(name)) == NULL) { -- LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -- return -1; -- } -- -- snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_tx_%u", pcb->remote_port); -- if ((nsock->same_node_rx_ring_mz = rte_memzone_lookup(name)) == NULL) { -- LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -- return -1; -- } else { -- LSTACK_LOG(INFO, LSTACK, "lookup %s success\n", name); -- } -- nsock->same_node_rx_ring = (struct same_node_ring *)nsock->same_node_rx_ring_mz->addr; -- -- snprintf_s(name, sizeof(name), sizeof(name) - 1,"rte_mz_buf_tx_%u", pcb->remote_port); -- if ((nsock->same_node_rx_ring->mz = rte_memzone_lookup(name)) == NULL) { -- LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -- return -1; -- } -- -- /* rcvlink init in alloc_socket() */ -- /* remove from g_rcv_process_list in free_socket */ -- list_add_node(&nsock->recv_list, &nsock->stack->same_node_recv_list); -- return 0; --} -- --err_t same_node_memzone_create(const struct rte_memzone **zone, int size, int port, char *name, char *rx) --{ -- char mem_name[RING_NAME_LEN] = {0}; -- snprintf_s(mem_name, sizeof(mem_name), sizeof(mem_name) - 1, "%s_%s_%d", name, rx, port); -- -- *zone = rte_memzone_reserve_aligned(mem_name, size, rte_socket_id(), 0, RTE_CACHE_LINE_SIZE); -- if (*zone == NULL) { -- LSTACK_LOG(ERR, LSTACK, "cannot reserve memzone:%s, errno is %d\n", mem_name, rte_errno); -- return ERR_MEM; -- } -- -- LSTACK_LOG(INFO, LSTACK, "lstack id %d, reserve %s(%p) success, addr is %p, size is %u\n", -- rte_socket_id(), mem_name, *zone, (*zone)->addr, size); -- -- return ERR_OK; --} -- --err_t same_node_ring_create(struct rte_ring **ring, int size, int port, char *name, char *rx) --{ -- if (!get_global_cfg_params()->use_sockmap) { -- *ring = NULL; -- return -1; -- } -- -- unsigned flags; -- char ring_name[RING_NAME_LEN] = {0}; -- if (strcmp(name, "listen") == 0) { -- flags = RING_F_SC_DEQ; -- } else { -- flags = RING_F_SP_ENQ | RING_F_SC_DEQ; -- } -- -- snprintf_s(ring_name, sizeof(ring_name), sizeof(ring_name) - 1, "%s_%s_ring_%d", name, rx, port); -- *ring = rte_ring_create(ring_name, size, rte_socket_id(), flags); -- if (*ring == NULL) { -- LSTACK_LOG(ERR, LSTACK, "cannot create rte_ring %s, errno is %d\n", ring_name, rte_errno); -- return ERR_MEM; -- } -- LSTACK_LOG(INFO, LSTACK, "lstack socket id:%d, create %s(%p) success\n", rte_socket_id(), ring_name, *ring); -- return ERR_OK; --} -- --static void init_same_node_ring(struct tcp_pcb *pcb) --{ -- struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -- -- pcb->client_rx_ring = NULL; -- pcb->client_tx_ring = NULL; -- pcb->free_ring = 0; -- sock->same_node_rx_ring = NULL; -- sock->same_node_rx_ring_mz = NULL; -- sock->same_node_tx_ring = NULL; -- sock->same_node_tx_ring_mz = NULL; --} -- --#define CLIENT_RING_SIZE 512 --err_t create_same_node_ring(struct tcp_pcb *pcb) --{ -- struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -- -- if (same_node_ring_create(&pcb->client_rx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "rx") != 0) { -- goto END; -- } -- if (same_node_ring_create(&pcb->client_tx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "tx") != 0) { -- goto END; -- } -- pcb->free_ring = 1; -- -- if (same_node_memzone_create(&sock->same_node_rx_ring_mz, sizeof(struct same_node_ring), -- pcb->local_port, "rte_mz", "rx") != 0) { -- goto END; -- } -- sock->same_node_rx_ring = (struct same_node_ring*)sock->same_node_rx_ring_mz->addr; -- -- if (same_node_memzone_create(&sock->same_node_rx_ring->mz, SAME_NODE_RING_LEN, -- pcb->local_port, "rte_mz_buf", "rx") != 0) { -- goto END; -- } -- -- sock->same_node_rx_ring->sndbegin = 0; -- sock->same_node_rx_ring->sndend = 0; -- -- if (same_node_memzone_create(&sock->same_node_tx_ring_mz, sizeof(struct same_node_ring), -- pcb->local_port, "rte_mz", "tx") != 0) { -- goto END; -- } -- sock->same_node_tx_ring = (struct same_node_ring*)sock->same_node_tx_ring_mz->addr; -- -- if (same_node_memzone_create(&sock->same_node_tx_ring->mz, SAME_NODE_RING_LEN, -- pcb->local_port, "rte_mz_buf", "tx") != 0) { -- goto END; -- } -- -- sock->same_node_tx_ring->sndbegin = 0; -- sock->same_node_tx_ring->sndend = 0; -- -- return 0; --END: -- rte_ring_free(pcb->client_rx_ring); -- rte_ring_free(pcb->client_tx_ring); -- rte_memzone_free(sock->same_node_rx_ring->mz); -- rte_memzone_free(sock->same_node_rx_ring_mz); -- rte_memzone_free(sock->same_node_tx_ring->mz); -- rte_memzone_free(sock->same_node_tx_ring_mz); -- init_same_node_ring(pcb); -- return ERR_BUF; --} -- --err_t find_same_node_ring(struct tcp_pcb *npcb) --{ -- char name[RING_NAME_LEN] = {0}; -- snprintf_s(name, sizeof(name), sizeof(name) - 1, "client_tx_ring_%u", npcb->remote_port); -- npcb->client_rx_ring = rte_ring_lookup(name); -- memset_s(name, sizeof(name), 0, sizeof(name)); -- snprintf_s(name, sizeof(name), sizeof(name) - 1, "client_rx_ring_%u", npcb->remote_port); -- npcb->client_tx_ring = rte_ring_lookup(name); -- npcb->free_ring = 0; -- if (npcb->client_tx_ring == NULL || -- npcb->client_rx_ring == NULL) { -- LSTACK_LOG(INFO, LSTACK, "lookup client rxtx ring failed, port is %d\n", npcb->remote_port); -- tcp_abandon(npcb, 0); -- return ERR_CONN; -- } else { -- LSTACK_LOG(INFO, LSTACK, "find client_tx_ring_%u and client_rx_ring_%u\n", -- npcb->remote_port, npcb->remote_port); -- } -- return 0; --} -- --unsigned same_node_ring_count(struct lwip_sock *sock) --{ -- const unsigned long long cur_begin = __atomic_load_n(&sock->same_node_rx_ring->sndbegin, __ATOMIC_RELAXED); -- const unsigned long long cur_end = __atomic_load_n(&sock->same_node_rx_ring->sndend, __ATOMIC_RELAXED); -- -- return cur_end - cur_begin; --} -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index ed36890..b4fb2fd 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -146,6 +146,7 @@ struct protocol_stack *get_bind_protocol_stack(void) - return stack_group->stacks[index]; - } - -+#if GAZELLE_TCP_REUSE_IPPORT - int get_min_conn_stack(struct protocol_stack_group *stack_group) - { - struct protocol_stack* stack; -@@ -161,6 +162,7 @@ int get_min_conn_stack(struct protocol_stack_group *stack_group) - } - return min_conn_stk_idx; - } -+#endif /* GAZELLE_TCP_REUSE_IPPORT */ - - void bind_to_stack_numa(struct protocol_stack *stack) - { -@@ -566,6 +568,7 @@ int stack_polling(unsigned wakeup_tick) - } - } - -+#if GAZELLE_SAME_NODE - /* run to completion mode currently does not support sockmap */ - if (use_sockmap) { - netif_poll(&stack->netif); -@@ -574,6 +577,7 @@ int stack_polling(unsigned wakeup_tick) - read_same_node_recv_list(stack); - } - } -+#endif /* GAZELLE_SAME_NODE */ - - if (cfg->udp_enable) { - udp_netif_poll(&stack->netif); -diff --git a/src/lstack/core/same_node.c b/src/lstack/core/same_node.c -new file mode 100644 -index 0000000..0fe0fa8 ---- /dev/null -+++ b/src/lstack/core/same_node.c -@@ -0,0 +1,376 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+ -+#include -+ -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_stack_stat.h" -+#include "same_node.h" -+#include "lstack_epoll.h" -+#include "lstack_lwip.h" -+ -+#if GAZELLE_SAME_NODE -+void read_same_node_recv_list(struct protocol_stack *stack) -+{ -+ struct list_node *list = &(stack->same_node_recv_list); -+ struct list_node *node, *temp; -+ struct lwip_sock *sock; -+ -+ list_for_each_node(node, temp, list) { -+ sock = list_entry(node, struct lwip_sock, recv_list); -+ -+ if (sock->same_node_rx_ring != NULL && same_node_ring_count(sock)) { -+ add_sock_event(sock, EPOLLIN); -+ } -+ } -+} -+ -+/* process on same node use ring to recv data */ -+ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) -+{ -+ unsigned long long cur_begin = sock->same_node_rx_ring->sndbegin; -+ unsigned long long cur_end; -+ unsigned long long index = cur_begin + 1; -+ size_t act_len = 0; -+ -+ cur_end = __atomic_load_n(&sock->same_node_rx_ring->sndend, __ATOMIC_ACQUIRE); -+ if (cur_begin == cur_end) { -+ errno = EAGAIN; -+ act_len = -1; -+ goto END; -+ } -+ act_len = cur_end - index + 1; -+ act_len = RTE_MIN(act_len, len); -+ if ((index & SAME_NODE_RING_MASK) + act_len > SAME_NODE_RING_LEN) { -+ size_t act_len1 = SAME_NODE_RING_LEN - (index & SAME_NODE_RING_MASK); -+ size_t act_len2 = act_len - act_len1; -+ rte_memcpy((char *)buf, (char *)sock->same_node_rx_ring->mz->addr + (index & SAME_NODE_RING_MASK), act_len1); -+ rte_memcpy((char *)buf + act_len1, (char *)sock->same_node_rx_ring->mz->addr, act_len2); -+ } else { -+ rte_memcpy((char *)buf, (char *)sock->same_node_rx_ring->mz->addr + (index & SAME_NODE_RING_MASK), act_len); -+ } -+ -+ index += act_len; -+ __atomic_store_n(&sock->same_node_rx_ring->sndbegin, index - 1, __ATOMIC_RELEASE); -+ -+END: -+ return act_len; -+} -+ -+/* processes on same node use ring to send data */ -+ssize_t gazelle_same_node_ring_send(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) -+{ -+ unsigned long long cur_begin = __atomic_load_n(&sock->same_node_tx_ring->sndbegin, __ATOMIC_ACQUIRE); -+ unsigned long long cur_end = sock->same_node_tx_ring->sndend; -+ if (cur_end >= cur_begin + SAME_NODE_RING_LEN) { -+ errno = EAGAIN; -+ return -1; -+ } -+ -+ unsigned long long index = cur_end + 1; -+ size_t act_len = SAME_NODE_RING_LEN - (cur_end - cur_begin); -+ act_len = RTE_MIN(act_len, len); -+ -+ if ((index & SAME_NODE_RING_MASK) + act_len > SAME_NODE_RING_LEN) { -+ size_t act_len1 = SAME_NODE_RING_LEN - (index & SAME_NODE_RING_MASK); -+ size_t act_len2 = act_len - act_len1; -+ rte_memcpy((char *)sock->same_node_tx_ring->mz->addr + (index & SAME_NODE_RING_MASK), buf, act_len1); -+ rte_memcpy((char *)sock->same_node_tx_ring->mz->addr, (char *)buf + act_len1, act_len2); -+ } else { -+ rte_memcpy((char *)sock->same_node_tx_ring->mz->addr + (index & SAME_NODE_RING_MASK), buf, act_len); -+ } -+ -+ index += act_len; -+ __atomic_store_n(&sock->same_node_tx_ring->sndend, index - 1, __ATOMIC_RELEASE); -+ if (act_len == 0) { -+ errno = EAGAIN; -+ return -1; -+ } -+ -+ return act_len; -+} -+ -+void netif_poll(struct netif *netif) -+{ -+ struct tcp_pcb *pcb = NULL; -+ struct tcp_pcb_listen *pcbl = NULL; -+ -+ for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { -+#define NETIF_POLL_READ_COUNT 32 -+ struct pbuf *pbufs[NETIF_POLL_READ_COUNT]; -+ int ret; -+ -+ if (pcb->client_rx_ring != NULL) { -+ ret = rte_ring_sc_dequeue_burst(pcb->client_rx_ring, (void **)pbufs, NETIF_POLL_READ_COUNT, NULL); -+ for (int i = 0; i < ret; i++) { -+ if (ip_input(pbufs[i], netif) != 0) { -+ LSTACK_LOG(INFO, LSTACK, "ip_input return err\n"); -+ pbuf_free(pbufs[i]); -+ } -+ } -+ } -+ } -+ for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { -+ if (pcbl->listen_rx_ring != NULL) { -+ struct pbuf *pbuf; -+ if (rte_ring_sc_dequeue(pcbl->listen_rx_ring, (void **)&pbuf) == 0) { -+ if (ip_input(pbuf, netif) != ERR_OK) { -+ pbuf_free(pbuf); -+ } -+ } -+ } -+ } -+} -+ -+/* processes on same node handshake packet use this function */ -+err_t netif_loop_output(struct netif *netif, struct pbuf *p) -+{ -+ if (!p) { -+ return ERR_ARG; -+ } -+ const struct ip_hdr *iphdr; -+ iphdr = (const struct ip_hdr *)p->payload; -+ if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { -+ return udp_netif_loop_output(netif, p); -+ } -+ -+ struct tcp_pcb *pcb = p->pcb; -+ struct pbuf *head = NULL; -+ -+ if (pcb == NULL || pcb->client_tx_ring == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "pcb is null\n"); -+ return ERR_ARG; -+ } -+ -+ if (p->next != NULL) { -+ LSTACK_LOG(ERR, LSTACK, "netif_loop_output: not support chained pbuf\n"); -+ return ERR_ARG; -+ } -+ -+ struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)((char *)p->payload + sizeof(struct ip_hdr)); -+ uint8_t flags = TCPH_FLAGS(tcp_hdr); -+ -+ head = pbuf_alloc(0, p->len, PBUF_RAM); -+ if (head == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "netif_loop_output: pbuf_alloc failed\n"); -+ return ERR_MEM; -+ } -+ memcpy_s(head->payload, head->len, p->payload, p->len); -+ -+ if ((flags & TCP_SYN) && !(flags & TCP_ACK)) { -+ /* SYN packet, send to listen_ring */ -+ char ring_name[RING_NAME_LEN] = {0}; -+ snprintf_s(ring_name, sizeof(ring_name), sizeof(ring_name) - 1, "listen_rx_ring_%d", pcb->remote_port); -+ struct rte_ring *ring = rte_ring_lookup(ring_name); -+ if (ring == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "netif_loop_output: cant find listen_rx_ring %d\n", pcb->remote_port); -+ pbuf_free(head); -+ } else { -+ if (rte_ring_mp_enqueue(ring, head) != 0) { -+ LSTACK_LOG(INFO, LSTACK, "enqueue sync packet failed\n"); -+ pbuf_free(head); -+ } -+ } -+ } else { -+ /* send other type packet to tx_ring */ -+ if (rte_ring_sp_enqueue(pcb->client_tx_ring, head) != 0) { -+ LSTACK_LOG(INFO, LSTACK, "client tx ring full\n"); -+ pbuf_free(head); -+ } -+ } -+ -+ return ERR_OK; -+} -+ -+err_t find_same_node_memzone(struct tcp_pcb *pcb, struct lwip_sock *nsock) -+{ -+ char name[RING_NAME_LEN]; -+ snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_rx_%u", pcb->remote_port); -+ if ((nsock->same_node_tx_ring_mz = rte_memzone_lookup(name)) == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -+ return -1; -+ } else { -+ LSTACK_LOG(INFO, LSTACK, "lookup %s success\n", name); -+ } -+ nsock->same_node_tx_ring = (struct same_node_ring *)nsock->same_node_tx_ring_mz->addr; -+ -+ snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_buf_rx_%u", pcb->remote_port); -+ if ((nsock->same_node_tx_ring->mz = rte_memzone_lookup(name)) == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -+ return -1; -+ } -+ -+ snprintf_s(name, sizeof(name), sizeof(name) - 1, "rte_mz_tx_%u", pcb->remote_port); -+ if ((nsock->same_node_rx_ring_mz = rte_memzone_lookup(name)) == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -+ return -1; -+ } else { -+ LSTACK_LOG(INFO, LSTACK, "lookup %s success\n", name); -+ } -+ nsock->same_node_rx_ring = (struct same_node_ring *)nsock->same_node_rx_ring_mz->addr; -+ -+ snprintf_s(name, sizeof(name), sizeof(name) - 1,"rte_mz_buf_tx_%u", pcb->remote_port); -+ if ((nsock->same_node_rx_ring->mz = rte_memzone_lookup(name)) == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "lwip_accept: can't find %s\n",name); -+ return -1; -+ } -+ -+ /* rcvlink init in alloc_socket() */ -+ /* remove from g_rcv_process_list in free_socket */ -+ list_add_node(&nsock->recv_list, &nsock->stack->same_node_recv_list); -+ return 0; -+} -+ -+err_t same_node_memzone_create(const struct rte_memzone **zone, int size, int port, char *name, char *rx) -+{ -+ char mem_name[RING_NAME_LEN] = {0}; -+ snprintf_s(mem_name, sizeof(mem_name), sizeof(mem_name) - 1, "%s_%s_%d", name, rx, port); -+ -+ *zone = rte_memzone_reserve_aligned(mem_name, size, rte_socket_id(), 0, RTE_CACHE_LINE_SIZE); -+ if (*zone == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "cannot reserve memzone:%s, errno is %d\n", mem_name, rte_errno); -+ return ERR_MEM; -+ } -+ -+ LSTACK_LOG(INFO, LSTACK, "lstack id %d, reserve %s(%p) success, addr is %p, size is %u\n", -+ rte_socket_id(), mem_name, *zone, (*zone)->addr, size); -+ -+ return ERR_OK; -+} -+ -+err_t same_node_ring_create(struct rte_ring **ring, int size, int port, char *name, char *rx) -+{ -+ if (!get_global_cfg_params()->use_sockmap) { -+ *ring = NULL; -+ return -1; -+ } -+ -+ unsigned flags; -+ char ring_name[RING_NAME_LEN] = {0}; -+ if (strcmp(name, "listen") == 0) { -+ flags = RING_F_SC_DEQ; -+ } else { -+ flags = RING_F_SP_ENQ | RING_F_SC_DEQ; -+ } -+ -+ snprintf_s(ring_name, sizeof(ring_name), sizeof(ring_name) - 1, "%s_%s_ring_%d", name, rx, port); -+ *ring = rte_ring_create(ring_name, size, rte_socket_id(), flags); -+ if (*ring == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "cannot create rte_ring %s, errno is %d\n", ring_name, rte_errno); -+ return ERR_MEM; -+ } -+ LSTACK_LOG(INFO, LSTACK, "lstack socket id:%d, create %s(%p) success\n", rte_socket_id(), ring_name, *ring); -+ return ERR_OK; -+} -+ -+static void init_same_node_ring(struct tcp_pcb *pcb) -+{ -+ struct netconn *netconn = (struct netconn *)pcb->callback_arg; -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -+ -+ pcb->client_rx_ring = NULL; -+ pcb->client_tx_ring = NULL; -+ pcb->free_ring = 0; -+ sock->same_node_rx_ring = NULL; -+ sock->same_node_rx_ring_mz = NULL; -+ sock->same_node_tx_ring = NULL; -+ sock->same_node_tx_ring_mz = NULL; -+} -+ -+#define CLIENT_RING_SIZE 512 -+err_t create_same_node_ring(struct tcp_pcb *pcb) -+{ -+ struct netconn *netconn = (struct netconn *)pcb->callback_arg; -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -+ -+ if (same_node_ring_create(&pcb->client_rx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "rx") != 0) { -+ goto END; -+ } -+ if (same_node_ring_create(&pcb->client_tx_ring, CLIENT_RING_SIZE, pcb->local_port, "client", "tx") != 0) { -+ goto END; -+ } -+ pcb->free_ring = 1; -+ -+ if (same_node_memzone_create(&sock->same_node_rx_ring_mz, sizeof(struct same_node_ring), -+ pcb->local_port, "rte_mz", "rx") != 0) { -+ goto END; -+ } -+ sock->same_node_rx_ring = (struct same_node_ring*)sock->same_node_rx_ring_mz->addr; -+ -+ if (same_node_memzone_create(&sock->same_node_rx_ring->mz, SAME_NODE_RING_LEN, -+ pcb->local_port, "rte_mz_buf", "rx") != 0) { -+ goto END; -+ } -+ -+ sock->same_node_rx_ring->sndbegin = 0; -+ sock->same_node_rx_ring->sndend = 0; -+ -+ if (same_node_memzone_create(&sock->same_node_tx_ring_mz, sizeof(struct same_node_ring), -+ pcb->local_port, "rte_mz", "tx") != 0) { -+ goto END; -+ } -+ sock->same_node_tx_ring = (struct same_node_ring*)sock->same_node_tx_ring_mz->addr; -+ -+ if (same_node_memzone_create(&sock->same_node_tx_ring->mz, SAME_NODE_RING_LEN, -+ pcb->local_port, "rte_mz_buf", "tx") != 0) { -+ goto END; -+ } -+ -+ sock->same_node_tx_ring->sndbegin = 0; -+ sock->same_node_tx_ring->sndend = 0; -+ -+ return 0; -+END: -+ rte_ring_free(pcb->client_rx_ring); -+ rte_ring_free(pcb->client_tx_ring); -+ rte_memzone_free(sock->same_node_rx_ring->mz); -+ rte_memzone_free(sock->same_node_rx_ring_mz); -+ rte_memzone_free(sock->same_node_tx_ring->mz); -+ rte_memzone_free(sock->same_node_tx_ring_mz); -+ init_same_node_ring(pcb); -+ return ERR_BUF; -+} -+ -+err_t find_same_node_ring(struct tcp_pcb *npcb) -+{ -+ char name[RING_NAME_LEN] = {0}; -+ snprintf_s(name, sizeof(name), sizeof(name) - 1, "client_tx_ring_%u", npcb->remote_port); -+ npcb->client_rx_ring = rte_ring_lookup(name); -+ memset_s(name, sizeof(name), 0, sizeof(name)); -+ snprintf_s(name, sizeof(name), sizeof(name) - 1, "client_rx_ring_%u", npcb->remote_port); -+ npcb->client_tx_ring = rte_ring_lookup(name); -+ npcb->free_ring = 0; -+ if (npcb->client_tx_ring == NULL || -+ npcb->client_rx_ring == NULL) { -+ LSTACK_LOG(INFO, LSTACK, "lookup client rxtx ring failed, port is %d\n", npcb->remote_port); -+ tcp_abandon(npcb, 0); -+ return ERR_CONN; -+ } else { -+ LSTACK_LOG(INFO, LSTACK, "find client_tx_ring_%u and client_rx_ring_%u\n", -+ npcb->remote_port, npcb->remote_port); -+ } -+ return 0; -+} -+ -+unsigned same_node_ring_count(const struct lwip_sock *sock) -+{ -+ const unsigned long long cur_begin = __atomic_load_n(&sock->same_node_rx_ring->sndbegin, __ATOMIC_RELAXED); -+ const unsigned long long cur_end = __atomic_load_n(&sock->same_node_rx_ring->sndend, __ATOMIC_RELAXED); -+ -+ return cur_end - cur_begin; -+} -+#endif /* GAZELLE_SAME_NODE */ -diff --git a/src/lstack/include/lstack_ethdev.h b/src/lstack/include/lstack_ethdev.h -index 0c3d906..5aeb80d 100644 ---- a/src/lstack/include/lstack_ethdev.h -+++ b/src/lstack/include/lstack_ethdev.h -@@ -32,6 +32,4 @@ void kni_handle_rx(uint16_t port_id); - void kni_handle_tx(struct rte_mbuf *mbuf); - #endif - --void netif_poll(struct netif *netif); -- - #endif /* __GAZELLE_ETHDEV_H__ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index dcb7dac..f2524e4 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -16,15 +16,15 @@ - - #include "common/gazelle_dfx_msg.h" - #include "common/dpdk_common.h" -+#include "same_node.h" - - struct lwip_sock; - struct rpc_msg; - struct protocol_stack; - --unsigned same_node_ring_count(struct lwip_sock *sock); - - #define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) --#define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || (sock->same_node_rx_ring != NULL && same_node_ring_count(sock))) -+#define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || NETCONN_NEED_SAME_NODE(sock)) - #define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_pre_del) - #define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) -@@ -63,6 +63,4 @@ void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_soc - uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint32_t max_num); - uint32_t do_lwip_get_connnum(void); - --void read_same_node_recv_list(struct protocol_stack *stack); -- - #endif -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index c9c50c9..a278d7a 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -113,7 +113,9 @@ struct protocol_stack *get_protocol_stack_by_fd(int fd); - struct protocol_stack *get_bind_protocol_stack(void); - struct protocol_stack_group *get_protocol_stack_group(void); - -+#if GAZELLE_TCP_REUSE_IPPORT - int get_min_conn_stack(struct protocol_stack_group *stack_group); -+#endif /* GAZELLE_TCP_REUSE_IPPORT */ - void bind_to_stack_numa(struct protocol_stack *stack); - void thread_bind_stack(struct protocol_stack *stack); - -diff --git a/src/lstack/include/same_node.h b/src/lstack/include/same_node.h -new file mode 100644 -index 0000000..90a5b76 ---- /dev/null -+++ b/src/lstack/include/same_node.h -@@ -0,0 +1,35 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __GAZELLE_SAME_NODE_H__ -+#define __GAZELLE_SAME_NODE_H__ -+ -+#include -+ -+#if GAZELLE_SAME_NODE -+ -+unsigned same_node_ring_count(const struct lwip_sock *sock); -+ -+void read_same_node_recv_list(struct protocol_stack *stack); -+ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags); -+ssize_t gazelle_same_node_ring_send(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags); -+ -+#define NETCONN_NEED_SAME_NODE(sock) \ -+ ( (sock->same_node_rx_ring && same_node_ring_count(sock)) ) -+ -+#else /* GAZELLE_SAME_NODE */ -+ -+#define NETCONN_NEED_SAME_NODE(sock) false -+ -+#endif /* GAZELLE_SAME_NODE */ -+ -+#endif /* __GAZELLE_SAME_NODE_H__ */ --- -2.33.0 - diff --git a/0324-cleancode-remove-gazelle_light_ring.patch b/0324-cleancode-remove-gazelle_light_ring.patch deleted file mode 100644 index abaa10d..0000000 --- a/0324-cleancode-remove-gazelle_light_ring.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 791872dcb02eacc2bc0e43deb97ecb9cf3cd9711 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 11 Mar 2025 15:06:10 +0800 -Subject: [PATCH] cleancode: remove gazelle_light_ring - -Signed-off-by: Lemmy Huang ---- - src/common/dpdk_common.h | 60 ++++++---------------------------------- - 1 file changed, 8 insertions(+), 52 deletions(-) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index 7a05342..8609216 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -123,49 +123,6 @@ struct rte_eth_conf; - struct rte_eth_dev_info; - void eth_params_checksum(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info); - --/* -- gazelle custom rte ring interface -- lightweight ring reduce atomic and smp_mb. -- only surpport single-consumers or the single-consumer. -- */ --static __rte_always_inline uint32_t gazelle_light_ring_enqueue_busrt(struct rte_ring *r, void **obj_table, uint32_t n) --{ -- uint32_t cons = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE); -- uint32_t prod = r->prod.tail; -- uint32_t free_entries = r->capacity + cons - prod; -- -- if (n > free_entries) { -- return 0; -- } -- -- __rte_ring_enqueue_elems(r, prod, obj_table, sizeof(void *), n); -- -- __atomic_store_n(&r->prod.tail, prod + n, __ATOMIC_RELEASE); -- -- return n; --} -- --static __rte_always_inline uint32_t gazelle_light_ring_dequeue_burst(struct rte_ring *r, void **obj_table, uint32_t n) --{ -- uint32_t prod = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE); -- uint32_t cons = r->cons.tail; -- uint32_t entries = prod - cons; -- -- if (n > entries) { -- n = entries; -- } -- -- if (n == 0) { -- return 0; -- } -- -- __rte_ring_dequeue_elems(r, cons, obj_table, sizeof(void *), n); -- -- __atomic_store_n(&r->cons.tail, cons + n, __ATOMIC_RELEASE); -- -- return n; --} -- - /* - gazelle custom rte ring interface - one thread enqueue and dequeue, other thread read object use and object still in queue. -@@ -177,15 +134,16 @@ static __rte_always_inline uint32_t gazelle_light_ring_dequeue_burst(struct rte_ - gazelle_ring_read: prod.head-->> cons.head, read object, prod.head = prod.tail + N - gazelle_ring_read_over: prod.tail = prod.head, update prod.tail - */ --static __rte_always_inline uint32_t gazelle_ring_sp_enqueue(struct rte_ring *r, void **obj_table, uint32_t n) -+static __rte_always_inline uint32_t gazelle_ring_sp_enqueue(struct rte_ring *r, void *const *obj_table, uint32_t n) - { - uint32_t head = __atomic_load_n(&r->cons.head, __ATOMIC_ACQUIRE); - uint32_t tail = r->cons.tail; - -- uint32_t entries = r->capacity + tail - head; -- if (n > entries) { -+ uint32_t free_entries = r->capacity + tail - head; -+ if (unlikely(free_entries == 0)) - return 0; -- } -+ if (n > free_entries) -+ n = free_entries; - - __rte_ring_enqueue_elems(r, head, obj_table, sizeof(void *), n); - -@@ -200,12 +158,10 @@ static __rte_always_inline uint32_t gazelle_ring_sc_dequeue(struct rte_ring *r, - uint32_t cons = r->cons.tail; - - uint32_t entries = prod - cons; -- if (n > entries) { -- n = entries; -- } -- if (unlikely(n == 0)) { -+ if (unlikely(entries == 0)) - return 0; -- } -+ if (n > entries) -+ n = entries; - - __rte_ring_dequeue_elems(r, cons, obj_table, sizeof(void *), n); - --- -2.33.0 - diff --git a/0325-cleancode-remove-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch b/0325-cleancode-remove-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch deleted file mode 100644 index 29914c6..0000000 --- a/0325-cleancode-remove-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch +++ /dev/null @@ -1,292 +0,0 @@ -From 33b786bd43e769351f89e9500f78819c3550949b Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 11 Mar 2025 15:09:56 +0800 -Subject: [PATCH] cleancode: remove get_stack_tid DPDK_PKT_BURST_SIZE - PACKET_READ_SIZE - -Signed-off-by: Lemmy Huang ---- - src/common/gazelle_base_func.h | 3 --- - src/common/gazelle_opt.h | 10 ++++------ - src/lstack/api/lstack_rtw_api.c | 4 ++-- - src/lstack/core/lstack_protocol_stack.c | 11 ----------- - src/lstack/core/lstack_thread_rpc.c | 16 ++++++++-------- - src/lstack/core/lstack_virtio.c | 3 ++- - src/lstack/include/lstack_protocol_stack.h | 2 -- - src/lstack/netif/lstack_ethdev.c | 5 ++--- - src/lstack/netif/lstack_vdev.c | 8 ++++---- - 9 files changed, 22 insertions(+), 40 deletions(-) - -diff --git a/src/common/gazelle_base_func.h b/src/common/gazelle_base_func.h -index 0ccb34b..29534a7 100644 ---- a/src/common/gazelle_base_func.h -+++ b/src/common/gazelle_base_func.h -@@ -29,9 +29,6 @@ - return -1; \ - } while (0) - --#define NODE_ENTRY(node, type, member) \ -- ((type*)((char*)(node) - (size_t)&((type*)0)->member)) -- - #define MB_IN_BYTES (1024 * 1024) - static inline int bytes_to_mb(uint32_t bytes) - { -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index d6b1c44..4406831 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -23,6 +23,9 @@ - #define GAZELLE_TRUE 1 - #define GAZELLE_FALSE 0 - -+#define CPUS_MAX_NUM 640 -+#define GAZELLE_MAX_NUMA_NODES 8 -+ - #define PROTOCOL_STACK_MAX 32 - #define KERNEL_EPOLL_MAX 512 - -@@ -41,7 +44,7 @@ - #define VDEV_IDLE_QUEUE_SZ DEFAULT_RING_SIZE - - #define VDEV_TX_QUEUE_SZ DEFAULT_RING_SIZE --#define FREE_RX_QUEUE_SZ DPDK_PKT_BURST_SIZE -+#define FREE_RX_QUEUE_SZ DEFAULT_RING_SIZE - - #define NIC_QUEUE_SIZE_MAX 8192 - #define NIC_QUEUE_SIZE_MIN 512 -@@ -58,8 +61,6 @@ - #define IPV6_EXTRA_HEAD_LEN 20 - #define MBUF_MAX_DATA_LEN (MTU_DEFAULT_DATA_LEN - VLAN_HEAD_LEN - IPV6_EXTRA_HEAD_LEN) - --#define DPDK_PKT_BURST_SIZE 512 -- - #define GAZELLE_UDP_PKGLEN_MAX (65535 - IP_HLEN - UDP_HLEN) - - /* total:33 client, index 32 is invaild client */ -@@ -109,7 +110,4 @@ - - #define SLEEP_US_BEFORE_LINK_UP 10000 - --#define CPUS_MAX_NUM 640 --#define GAZELLE_MAX_NUMA_NODES 8 -- - #endif /* _GAZELLE_OPT_H_ */ -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 6d0bd05..35439bc 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -92,7 +92,7 @@ static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t n - - struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || cur_stack == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); - GAZELLE_RETURN(EBADF); - } - -@@ -229,7 +229,7 @@ static int stack_broadcast_listen(int fd, int backlog) - - struct lwip_sock *sock = lwip_get_socket(fd); - if (sock == NULL || cur_stack == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %d get sock null or stack null\n", get_stack_tid(), fd); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); - GAZELLE_RETURN(EBADF); - } - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index b4fb2fd..3bb1eeb 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -76,17 +76,6 @@ static inline void set_stack_idx(uint16_t idx) - g_stack_p = g_stack_group.stacks[idx]; - } - --long get_stack_tid(void) --{ -- static PER_THREAD int32_t g_stack_tid = 0; -- -- if (g_stack_tid == 0) { -- g_stack_tid = rte_gettid(); -- } -- -- return g_stack_tid; --} -- - struct protocol_stack_group *get_protocol_stack_group(void) - { - return &g_stack_group; -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 050594e..26ae501 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -235,7 +235,7 @@ static void callback_socket(struct rpc_msg *msg) - { - msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); - if (msg->result < 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, %ld socket failed\n", get_stack_tid(), msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %ld socket failed\n", rte_gettid(), msg->result); - } - } - -@@ -253,7 +253,7 @@ static void callback_close(struct rpc_msg *msg) - - msg->result = lwip_close(fd); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); - } - } - -@@ -272,7 +272,7 @@ static void callback_shutdown(struct rpc_msg *msg) - - msg->result = lwip_shutdown(fd, how); - if (msg->result != 0 && errno != ENOTCONN) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), fd, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), fd, msg->result); - } - - posix_api->shutdown_fn(fd, how); -@@ -282,7 +282,7 @@ static void callback_bind(struct rpc_msg *msg) - { - msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].u); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); - } - } - -@@ -300,7 +300,7 @@ static void callback_listen(struct rpc_msg *msg) - /* new listen add to stack listen list */ - msg->result = lwip_listen(fd, backlog); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d failed %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); - } - } - -@@ -509,7 +509,7 @@ static void callback_getsockname(struct rpc_msg *msg) - { - msg->result = lwip_getsockname(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d fail %ld\n", get_stack_tid(), msg->args[MSG_ARG_0].i, msg->result); -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); - } - } - -@@ -518,7 +518,7 @@ static void callback_getsockopt(struct rpc_msg *msg) - msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, - msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), - msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); - } - } -@@ -528,7 +528,7 @@ static void callback_setsockopt(struct rpc_msg *msg) - msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, - msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].u); - if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %ld, fd %d, level %d, optname %d, fail %ld\n", get_stack_tid(), -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), - msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); - } - } -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index 75a23f2..f6855d1 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -17,12 +17,13 @@ - #include - #include - #include -+#include -+ - #include "lstack_cfg.h" - #include "lstack_log.h" - #include "lstack_port_map.h" - #include "lstack_interrupt.h" - #include "lstack_virtio.h" --#include "securec.h" - - #define VIRTIO_USER_NAME "virtio_user" - #define VIRTIO_DPDK_PARA_LEN 256 -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index a278d7a..3f6e3d3e 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -106,8 +106,6 @@ struct protocol_stack_group { - pthread_spinlock_t socket_lock; - }; - --long get_stack_tid(void); -- - struct protocol_stack *get_protocol_stack(void); - struct protocol_stack *get_protocol_stack_by_fd(int fd); - struct protocol_stack *get_bind_protocol_stack(void); -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index 3b859d2..a370714 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -41,7 +41,6 @@ - - /* FRAME_MTU + 14byte header */ - #define MBUF_MAX_LEN 1514 --#define PACKET_READ_SIZE 32 - - /* any protocol stack thread receives arp packet and sync it to other threads, - * so that it can have the arp table */ -@@ -150,11 +149,11 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void kni_handle_rx(uint16_t port_id) - { -- struct rte_mbuf *pkts_burst[PACKET_READ_SIZE]; -+ struct rte_mbuf *pkts_burst[GAZELLE_PACKET_READ_SIZE]; - struct rte_kni* kni = get_gazelle_kni(); - uint32_t nb_kni_rx = 0; - if (kni) { -- nb_kni_rx = rte_kni_rx_burst(kni, pkts_burst, PACKET_READ_SIZE); -+ nb_kni_rx = rte_kni_rx_burst(kni, pkts_burst, GAZELLE_PACKET_READ_SIZE); - } - if (nb_kni_rx > 0) { - uint16_t nb_rx = rte_eth_tx_burst(port_id, 0, pkts_burst, nb_kni_rx); -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 2eaeb1f..14d8cc6 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -57,13 +57,13 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - { - uint32_t rcvd_pkts; - uint32_t nr_pkts; -- struct rte_mbuf *free_buf[DPDK_PKT_BURST_SIZE]; -+ struct rte_mbuf *free_buf[VDEV_RX_QUEUE_SZ]; - - rcvd_pkts = gazelle_ring_sc_dequeue(stack->rx_ring, (void **)pkts, max_mbuf); - - stack->rx_ring_used += rcvd_pkts; - if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) { -- uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(DPDK_PKT_BURST_SIZE)); -+ uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(VDEV_RX_QUEUE_SZ)); - int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)free_buf, free_cnt, true); - if (likely(ret == 0)) { - nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt); -@@ -161,7 +161,7 @@ static uint32_t vdev_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pkt - static uint32_t ltran_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pkts, uint32_t nr_pkts) - { - uint32_t sent_pkts = 0; -- struct rte_mbuf *free_buf[DPDK_PKT_BURST_SIZE]; -+ struct rte_mbuf *free_buf[VDEV_TX_QUEUE_SZ]; - const uint32_t tbegin = sys_now(); - - do { -@@ -292,7 +292,7 @@ int32_t vdev_reg_xmit(enum reg_ring_type type, struct gazelle_quintuple *qtuple) - - tmp_buf = &stack->reg_buf[reg_index]; - tmp_buf->type = type; -- tmp_buf->tid = get_stack_tid(); -+ tmp_buf->tid = rte_gettid(); - ret = memcpy_s(&tmp_buf->qtuple, sizeof(*qtuple), qtuple, sizeof(struct gazelle_quintuple)); - if (ret != EOK) { - LSTACK_LOG(ERR, LSTACK, "memcpy_s failed ret=%d.\n", ret); --- -2.33.0 - diff --git a/0326-socket-refactor-sock_event.patch b/0326-socket-refactor-sock_event.patch deleted file mode 100644 index 007cbc9..0000000 --- a/0326-socket-refactor-sock_event.patch +++ /dev/null @@ -1,1613 +0,0 @@ -From 2168db467896885c571dafb98ed03a90101c98d2 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 21 Mar 2025 16:42:43 +0800 -Subject: [PATCH] socket: refactor sock_event - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 846 ++++++++++++++++++++++++++++++ - src/lstack/core/lstack_wait.c | 550 +++++++++++++++++++ - src/lstack/include/lstack_epoll.h | 18 + - src/lstack/include/lstack_wait.h | 138 +++++ - 4 files changed, 1552 insertions(+) - create mode 100644 src/lstack/core/lstack_wait.c - create mode 100644 src/lstack/include/lstack_wait.h - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 644efc0..a110aa1 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -10,6 +10,8 @@ - * See the Mulan PSL v2 for more details. - */ - -+#if !SOCK_EVENT_V2 -+ - #include - #include - #include -@@ -1038,3 +1040,847 @@ int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfd - - return event_num; - } -+ -+#else /* SOCK_EVENT_V2 */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "lstack_epoll.h" -+#include "common/dpdk_common.h" -+#include "common/gazelle_base_func.h" -+#include "lstack_preload.h" -+#include "lstack_cfg.h" -+#include "lstack_log.h" -+#include "lstack_protocol_stack.h" -+ -+#define POLL_MAX_EVENTS 32 -+ -+static PER_THREAD struct sock_wait *g_sk_wait = NULL; -+ -+ -+static int rtc_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint32_t start) -+{ -+ stack_polling(0); -+ -+ if (timeout > 0 && timeout <= (int)(sys_now() - start)) { -+ timeout = 0; -+ } -+ return timeout; -+} -+ -+static int rtw_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint32_t start) -+{ -+ return sys_mutex_timedlock_internal(&sk_wait->mutex, timeout); -+} -+ -+static void rtc_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id) -+{ -+ sk_event->pending |= pending; -+ if (list_node_null(&sk_event->event_node)) { -+ list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ } -+} -+ -+static void rtc_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+{ -+ sk_event->pending &= ~pending; -+ if (sk_event->pending == 0) { -+ list_del_node(&sk_event->event_node); -+ } -+} -+ -+static void rtw_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id) -+{ -+#if SOCK_WAIT_BATCH_NOTIFY -+ if (likely(stack_id >= 0)) { -+ lwip_wait_add_notify(sk_wait, sk_event, pending, stack_id); -+ return; -+ } -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ -+ rte_spinlock_lock(&sk_wait->epcb.lock); -+ sk_event->pending |= pending; -+ if (list_node_null(&sk_event->event_node)) { -+ list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ } -+ rte_spinlock_unlock(&sk_wait->epcb.lock); -+ -+ sys_mutex_unlock_internal(&sk_wait->mutex); -+} -+ -+static void rtw_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+{ -+ rte_spinlock_lock(&sk_wait->epcb.lock); -+ sk_event->pending &= ~pending; -+ if (sk_event->pending == 0) { -+ list_del_node(&sk_event->event_node); -+ } -+ rte_spinlock_unlock(&sk_wait->epcb.lock); -+} -+ -+static void rtc_poll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id) -+{ -+} -+static void rtc_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+{ -+} -+static void rtw_poll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id) -+{ -+#if SOCK_WAIT_BATCH_NOTIFY -+ if (likely(stack_id >= 0)) { -+ lwip_wait_add_notify(sk_wait, NULL, 0, stack_id); -+ return; -+ } -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ sys_mutex_unlock_internal(&sk_wait->mutex); -+} -+static void rtw_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+{ -+} -+ -+/* Cannot support the same sock being waited by both epoll/poll/select or multiple epollfd. */ -+static void sock_wait_check_change(struct sock_wait *new_sk_wait, struct sock_wait *old_sk_wait) -+{ -+ if (old_sk_wait == NULL || new_sk_wait == old_sk_wait || -+ old_sk_wait->type == WAIT_CLOSE) { -+ return; -+ } -+ -+ if (new_sk_wait->type & WAIT_EPOLL) { -+ if (old_sk_wait->type & WAIT_EPOLL) { -+ LSTACK_LOG(ERR, LSTACK, "Cannot support the same sock being waited by multiple epollfd! \n"); -+ } else { -+ LSTACK_LOG(ERR, LSTACK, "Cannot support the same sock being waited by both epoll/poll/select! \n"); -+ } -+ } -+} -+ -+ -+static int epoll_cb_init(struct epoll_cb *epcb) -+{ -+ list_init_head(&epcb->event_list); -+ rte_spinlock_init(&epcb->lock); -+ return 0; -+} -+ -+static void epoll_cb_free(struct epoll_cb *epcb) -+{ -+ struct list_node *node, *temp; -+ struct sock_event *sk_event; -+ -+ rte_spinlock_lock(&epcb->lock); -+ -+ list_for_each_node(node, temp, &epcb->event_list) { -+ sk_event = list_entry(node, struct sock_event, event_node); -+ list_del_node(&sk_event->event_node); -+ } -+ -+ rte_spinlock_unlock(&epcb->lock); -+} -+ -+static int epoll_create_internal(int epfd) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -+ struct sock_wait *sk_wait; -+ struct lwip_sock *epsock; -+ -+ epsock = lwip_get_socket(epfd); -+ if (epsock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "epfd=%d sock is NULL errno=%d\n", epfd, errno); -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ /* calloc will memset to zero */ -+ sk_wait = calloc(1, sizeof(struct sock_wait)); -+ if (sk_wait == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "calloc null\n"); -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ sk_wait->type = WAIT_EPOLL; -+ sock_wait_common_init(sk_wait); -+ sock_wait_kernel_init(sk_wait, epfd, stack_group->stack_num); -+ epoll_cb_init(&sk_wait->epcb); -+ -+ if (rtc_mode) { -+ sk_wait->timedwait_fn = rtc_sock_wait_timedwait; -+ sk_wait->notify_fn = rtc_epoll_notify_event; -+ sk_wait->remove_fn = rtc_epoll_remove_event; -+ } else { -+ sk_wait->timedwait_fn = rtw_sock_wait_timedwait; -+ sk_wait->notify_fn = rtw_epoll_notify_event; -+ sk_wait->remove_fn = rtw_epoll_remove_event; -+ } -+ -+ epsock->sk_wait = sk_wait; -+ return 0; -+} -+ -+static int epoll_close_internal(int epfd) -+{ -+ struct sock_wait *sk_wait; -+ struct lwip_sock *epsock; -+ -+ epsock = lwip_get_socket(epfd); -+ if (epsock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "epfd=%d sock is NULL errno=%d\n", epfd, errno); -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ sk_wait = epsock->sk_wait; -+ if (sk_wait == NULL) { -+ return 0; -+ } -+ -+ sk_wait->type = WAIT_CLOSE; -+ epoll_cb_free(&sk_wait->epcb); -+ -+ posix_api->close_fn(sk_wait->epfd); -+ sock_wait_kernel_free(sk_wait); -+ sock_wait_common_free(sk_wait); -+ -+ sk_wait->timedwait_fn = NULL; -+ sk_wait->notify_fn = NULL; -+ sk_wait->remove_fn = NULL; -+ -+ /* FIXME: set all 'sock->sk_wait = NULL' before free. */ -+ free(sk_wait); -+ epsock->sk_wait = NULL; -+ -+ return 0; -+} -+ -+int lstack_epoll_create1(int flags) -+{ -+ int epfd = posix_api->epoll_create1_fn(flags); -+ if (epfd != -1) { -+ if (epoll_create_internal(epfd) != 0) { -+ posix_api->close_fn(epfd); -+ epfd = -1; -+ } -+ } -+ return epfd; -+} -+ -+int lstack_epoll_create(int size) -+{ -+ /* Since Linux 2.6.8, the size argument is ignored, -+ * but must be greater than zero. */ -+ return size <= 0 ? -1 : lstack_epoll_create1(0); -+} -+ -+int lstack_epoll_close(int epfd) -+{ -+ epoll_close_internal(epfd); -+ return posix_api->close_fn(epfd); -+} -+ -+int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) -+{ -+ int ret; -+ struct lwip_sock *epsock = lwip_get_socket(epfd); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ struct sock_wait *sk_wait = epsock->sk_wait; -+ struct sock_event *sk_event; -+ unsigned pending; -+ -+ if (epfd < 0 || fd < 0 || epfd == fd || \ -+ (event == NULL && op != EPOLL_CTL_DEL)) { -+ LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d\n", fd, epfd, op); -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(epfd=%d, op=%d, fd=%d, event=%p)\n", -+ __FUNCTION__, epfd, op, fd, event)); -+ -+ enum posix_type sk_type = select_sock_posix_path(sock); -+ /* has POSIX_LWIP */ -+ if (sk_type != POSIX_LWIP) { -+ ret = posix_api->epoll_ctl_fn(epfd, op, fd, event); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn failed, fd=%d epfd=%d op=%d\n", fd, epfd, op); -+ return ret; -+ } -+ if (op == EPOLL_CTL_ADD) { -+ sk_wait->kernel_nfds++; -+ } else if (op == EPOLL_CTL_DEL) { -+ sk_wait->kernel_nfds--; -+ } -+ } -+ /* is POSIX_KERNEL */ -+ if (sk_type == POSIX_KERNEL) -+ return ret; -+ -+ for (; sock != NULL; sock = sock->listen_next) { -+ sk_event = &sock->sk_event; -+ -+ switch (op) { -+ case EPOLL_CTL_ADD: -+ sock_wait_check_change(sk_wait, sock->sk_wait); -+ sock->sk_wait = sk_wait; -+ /* fall through */ -+ case EPOLL_CTL_MOD: -+ sk_event->events = event->events | EPOLLERR | EPOLLHUP; -+ sk_event->ep_data = event->data; -+ -+ pending = sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_RCVPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_SENDPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_ERROR, 0); -+ sk_wait->notify_fn(sk_wait, sk_event, pending, -1); -+ -+ sk_wait->lwip_nfds++; -+ sk_wait->affinity.stack_nfds[sock->stack_id]++; -+ break; -+ case EPOLL_CTL_DEL: -+ sk_event->events = 0; -+ -+ pending = sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_RCVMINUS, 0) | -+ sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_SENDMINUS, 0) | -+ sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_ERROR, 0); -+ sk_wait->remove_fn(sk_wait, sk_event, pending); -+ -+ sk_wait->lwip_nfds--; -+ sk_wait->affinity.stack_nfds[sock->stack_id]--; -+ break; -+ default: -+ GAZELLE_RETURN(EINVAL); -+ } -+ } -+ -+ if (get_global_cfg_params()->app_bind_numa) { -+ affinity_update_max_stack(&sk_wait->affinity); -+ } -+ return 0; -+} -+ -+static int epoll_scan_lwip_event(struct epoll_cb *epcb, struct epoll_event *events, int maxevents) -+{ -+ bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -+ struct list_node *node, *temp; -+ struct sock_event *sk_event; -+ int num = 0; -+ -+ if (!rtc_mode) -+ rte_spinlock_lock(&epcb->lock); -+ -+ list_for_each_node(node, temp, &epcb->event_list) { -+ sk_event = list_entry(node, struct sock_event, event_node); -+ if (num >= maxevents) { -+ /* move list head after the current node, -+ * and start traversing from this node next time */ -+ list_del_node(&epcb->event_list); -+ list_add_node(&epcb->event_list, node); -+ break; -+ } -+ -+ if ((sk_event->events & sk_event->pending) == 0) { -+ // LSTACK_LOG(WARNING, LSTACK, "get empty event\n"); -+ list_del_node(node); -+ continue; -+ } -+ -+ events[num].events = sk_event->pending; -+ events[num].data = sk_event->ep_data; -+ num++; -+ -+ if (sk_event->events & EPOLLET) { -+ sk_event->pending = 0; -+ list_del_node(node); -+ } -+ -+ /* EPOLLONESHOT: generate event after epoll_ctl add/mod event again, -+ * epoll_event set 0 avoid generating event util epoll_ctl reset epoll_event */ -+ if (sk_event->events & EPOLLONESHOT) { -+ sk_event->events = 0; -+ list_del_node(node); -+ } -+ } -+ -+ if (!rtc_mode) -+ rte_spinlock_unlock(&epcb->lock); -+ -+ return num; -+} -+ -+int lstack_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+{ -+ bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -+ struct lwip_sock *epsock = lwip_get_socket(epfd); -+ struct sock_wait *sk_wait = epsock->sk_wait; -+ int kernel_num = 0; -+ int lwip_num = 0; -+ int lwip_maxevents; -+ uint32_t start; -+ -+ if (unlikely(epfd < 0)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ if (unlikely(events == NULL || maxevents <= 0 || timeout < -1)) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ if (get_global_cfg_params()->app_bind_numa) { -+ affinity_bind_stack(sk_wait, &sk_wait->affinity); -+ } -+ -+ /* avoid RTC app process events for a long time */ -+ if (rtc_mode && maxevents > POLL_MAX_EVENTS) { -+ maxevents = POLL_MAX_EVENTS; -+ } -+ /* avoid the starvation of poll events from both kernel and lwip */ -+ lwip_maxevents = (maxevents >> 1) + 1; -+ -+ start = sys_now(); -+ -+ /* RTC try to recv polling. */ -+ sk_wait->timedwait_fn(sk_wait, 0, start); -+ do { -+ if (likely(sk_wait->lwip_nfds > 0)) { -+ lwip_num = epoll_scan_lwip_event(&sk_wait->epcb, events, lwip_maxevents); -+ } -+ -+ if (sk_wait->kernel_nfds > 0 && rte_atomic16_read(&sk_wait->kernel_pending)) { -+ kernel_num = posix_api->epoll_wait_fn( -+ sk_wait->epfd, &events[lwip_num], maxevents - lwip_num, 0); -+ if (unlikely(kernel_num == 0) && errno != EINTR && errno != EAGAIN) { -+ rte_atomic16_set(&sk_wait->kernel_pending, false); -+ } -+ } -+ -+ if (lwip_num + kernel_num > 0) { -+ break; -+ } -+ -+ timeout = sk_wait->timedwait_fn(sk_wait, timeout, start); -+ } while (timeout != 0); -+ -+ sk_wait->stat.app_events += lwip_num; -+ sk_wait->stat.kernel_events += kernel_num; -+ -+ return lwip_num + kernel_num; -+} -+ -+static void poll_cb_free(struct poll_cb *pcb) -+{ -+ if (pcb->lwip_p_fds != NULL) { -+ free(pcb->lwip_p_fds); -+ pcb->lwip_p_fds = NULL; -+ } -+ if (pcb->kernel_fds != NULL) { -+ free(pcb->kernel_fds); -+ pcb->kernel_fds = NULL; -+ } -+} -+ -+static int poll_cb_init(struct poll_cb *pcb, int nfds) -+{ -+ if (nfds <= 0) -+ return 0; -+ -+ pcb->lwip_p_fds = calloc(1, sizeof(*pcb->lwip_p_fds) * nfds); -+ pcb->kernel_fds = calloc(1, sizeof(*pcb->kernel_fds) * nfds); -+ -+ if (pcb->lwip_p_fds == NULL || pcb->kernel_fds == NULL) { -+ poll_cb_free(pcb); -+ return -1; -+ } -+ -+ pcb->max_nfds = nfds; -+ return 0; -+} -+ -+static int poll_init_wait(struct sock_wait *sk_wait, int nfds) -+{ -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -+ int epfd; -+ -+ epfd = posix_api->epoll_create_fn(POLL_MAX_EVENTS); -+ if (epfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_create failed, errno %d\n", errno); -+ return -1; -+ } -+ -+ sk_wait->type = WAIT_POLL; -+ sock_wait_common_init(sk_wait); -+ sock_wait_kernel_init(sk_wait, epfd, stack_group->stack_num); -+ -+ if (rtc_mode) { -+ sk_wait->timedwait_fn = rtc_sock_wait_timedwait; -+ sk_wait->notify_fn = rtc_poll_notify_event; -+ sk_wait->remove_fn = rtc_poll_remove_event; -+ } else { -+ sk_wait->timedwait_fn = rtw_sock_wait_timedwait; -+ sk_wait->notify_fn = rtw_poll_notify_event; -+ sk_wait->remove_fn = rtw_poll_remove_event; -+ } -+ -+ return poll_cb_init(&sk_wait->pcb, nfds); -+} -+ -+static void poll_free_wait(struct sock_wait *sk_wait) -+{ -+ sk_wait->type = WAIT_CLOSE; -+ poll_cb_free(&sk_wait->pcb); -+ -+ posix_api->close_fn(sk_wait->epfd); -+ sock_wait_kernel_free(sk_wait); -+ sock_wait_common_free(sk_wait); -+ -+ sk_wait->timedwait_fn = NULL; -+ sk_wait->notify_fn = NULL; -+ sk_wait->remove_fn = NULL; -+} -+ -+void poll_destruct_wait(void) -+{ -+ if (unlikely(g_sk_wait == NULL)) { -+ return; -+ } -+ -+ poll_free_wait(g_sk_wait); -+ -+ /* FIXME: set all 'sock->sk_wait = NULL' before free. */ -+ free(g_sk_wait); -+ g_sk_wait = NULL; -+} -+ -+struct sock_wait *poll_construct_wait(int nfds) -+{ -+ if (unlikely(g_sk_wait == NULL)) { -+ g_sk_wait = calloc(1, sizeof(struct sock_wait)); -+ if (g_sk_wait == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -+ return NULL; -+ } -+ -+ if (poll_init_wait(g_sk_wait, nfds) < 0) { -+ free(g_sk_wait); -+ return NULL; -+ } -+ } -+ -+ /* resize poll_cb */ -+ if (g_sk_wait->pcb.max_nfds < nfds) { -+ poll_cb_free(&g_sk_wait->pcb); -+ if (poll_cb_init(&g_sk_wait->pcb, nfds) != 0) { -+ return NULL; -+ } -+ } -+ -+ return g_sk_wait; -+} -+ -+static bool poll_ctl_kernel_event(int epfd, int fds_id, -+ const struct pollfd *new_fds, const struct pollfd *old_fds) -+{ -+ int ret; -+ struct epoll_event epevent; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(epfd=%d, old_fd=%d, new_fd=%d)\n", -+ __FUNCTION__, epfd, old_fds->fd, new_fds->fd)); -+ -+ epevent.data.fd = fds_id; -+ epevent.events = new_fds->events; -+ -+ /* EPOLL_CTL_MOD may not be any events, but why? */ -+ if (old_fds->fd == 0) { -+ ret = posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_ADD, new_fds->fd, &epevent); -+ } else { -+ ret = posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_DEL, old_fds->fd, NULL); -+ ret |= posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_ADD, new_fds->fd, &epevent); -+ } -+ -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d, new_fd %d, old_fd %d\n", -+ errno, new_fds->fd, old_fds->fd); -+ } -+ return true; -+} -+ -+static int poll_wait_kernel_event(int epfd, struct pollfd *fds, int maxevents) -+{ -+ struct epoll_event epevents[POLL_MAX_EVENTS]; -+ int num = 0; -+ int i, fds_id; -+ -+ num = posix_api->epoll_wait_fn(epfd, epevents, maxevents, 0); -+ for (i = 0; i < num; ++i) { -+ fds_id = epevents[i].data.fd; -+ fds[fds_id].revents = epevents[i].events; -+ } -+ -+ return num; -+} -+ -+static void poll_prepare_wait(struct sock_wait *sk_wait, struct pollfd *fds, nfds_t nfds) -+{ -+ struct poll_cb *pcb = &sk_wait->pcb; -+ struct lwip_sock *sock; -+ enum posix_type sk_type; -+ int fd, i; -+ -+ sk_wait->lwip_nfds = 0; -+ sk_wait->kernel_nfds = 0; -+ memset_s(&sk_wait->affinity.stack_nfds, sizeof(sk_wait->affinity.stack_nfds), -+ 0, sizeof(sk_wait->affinity.stack_nfds)); -+ -+ for (i = 0; i < nfds; ++i) { -+ fd = fds[i].fd; -+ sock = lwip_get_socket(fd); -+ sk_type = select_sock_posix_path(sock); -+ -+ if (sk_type & POSIX_KERNEL) { -+ poll_ctl_kernel_event(sk_wait->epfd, i, &fds[i], -+ &pcb->kernel_fds[sk_wait->kernel_nfds]); -+ pcb->kernel_fds[sk_wait->kernel_nfds] = fds[i]; -+ sk_wait->kernel_nfds++; -+ } -+ -+ if (sk_type & POSIX_LWIP) { -+ pcb->lwip_p_fds[sk_wait->lwip_nfds] = &fds[i]; -+ sk_wait->lwip_nfds++; -+ -+ for (; sock != NULL; sock = sock->listen_next) { -+ sock->sk_event.events = fds[i].events | POLLERR; -+ sock_wait_check_change(sk_wait, sock->sk_wait); -+ sock->sk_wait = sk_wait; -+ sk_wait->affinity.stack_nfds[sock->stack_id]++; -+ } -+ } -+ } -+ -+ if (get_global_cfg_params()->app_bind_numa) { -+ affinity_update_max_stack(&sk_wait->affinity); -+ affinity_bind_stack(sk_wait, &sk_wait->affinity); -+ } -+ -+ return; -+} -+ -+static int poll_scan_lwip_event(struct poll_cb *pcb, int nfds, int maxevents) -+{ -+ struct lwip_sock *sock; -+ struct pollfd *fds; -+ int num = 0; -+ int i; -+ -+ for (i = 0; i < nfds && num < maxevents; ++i) { -+ fds = pcb->lwip_p_fds[i]; -+ sock = lwip_get_socket(fds->fd); -+ -+ for (; !POSIX_IS_CLOSED(sock); sock = sock->listen_next) { -+ fds->revents = sock_event_hold_pending(sock, WAIT_POLL, NETCONN_EVT_RCVPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_POLL, NETCONN_EVT_SENDPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_POLL, NETCONN_EVT_ERROR, 0); -+ if (fds->revents != 0) { -+ num++; -+ break; -+ } -+ } -+ } -+ -+ return num; -+} -+ -+int lstack_poll(struct pollfd *fds, nfds_t nfds, int timeout) -+{ -+ struct sock_wait *sk_wait; -+ int kernel_num = 0; -+ int lwip_num = 0; -+ uint32_t start; -+ -+ if (unlikely(fds == NULL || nfds == 0 || timeout < -1)) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ -+ sk_wait = poll_construct_wait(nfds); -+ if (unlikely(sk_wait == NULL)) { -+ return -1; -+ } -+ poll_prepare_wait(sk_wait, fds, nfds); -+ -+ if (sk_wait->lwip_nfds == 0 && sk_wait->kernel_nfds > 0) { -+ return posix_api->poll_fn(fds, nfds, timeout); -+ } -+ -+ start = sys_now(); -+ -+ /* RTC try to recv polling. */ -+ sk_wait->timedwait_fn(sk_wait, 0, start); -+ do { -+ if (sk_wait->lwip_nfds > 0) { -+ lwip_num = poll_scan_lwip_event(&sk_wait->pcb, sk_wait->lwip_nfds, nfds); -+ } -+ -+ if (sk_wait->kernel_nfds > 0 && rte_atomic16_read(&sk_wait->kernel_pending)) { -+ kernel_num = poll_wait_kernel_event(sk_wait->epfd, fds, sk_wait->kernel_nfds); -+ if (kernel_num == 0 && errno != EINTR && errno != EAGAIN) { -+ rte_atomic16_set(&sk_wait->kernel_pending, false); -+ } -+ } -+ -+ if (lwip_num + kernel_num > 0) { -+ break; -+ } -+ -+ timeout = sk_wait->timedwait_fn(sk_wait, timeout, start); -+ } while (timeout != 0); -+ -+ sk_wait->stat.app_events += lwip_num; -+ sk_wait->stat.kernel_events += kernel_num; -+ -+ return lwip_num + kernel_num; -+} -+ -+/* refer to linux kernel */ -+#define POLLIN_SET (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | EPOLLHUP | EPOLLERR) -+#define POLLOUT_SET (EPOLLWRBAND | EPOLLWRNORM | EPOLLOUT | EPOLLERR) -+#define POLLEX_SET (EPOLLPRI) -+ -+static int fds_select2poll(struct pollfd *fds, int maxfd, -+ fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -+{ -+ int nfds = 0; -+ -+ for (int i = 0; i < maxfd; i++) { -+ if (readfds && FD_ISSET(i, readfds)) { -+ fds[nfds].events = POLLIN_SET; -+ } -+ if (writefds && FD_ISSET(i, writefds)) { -+ fds[nfds].events |= POLLOUT_SET; -+ } -+ if (exceptfds && FD_ISSET(i, exceptfds)) { -+ fds[nfds].events |= POLLEX_SET; -+ } -+ if (fds[nfds].events > 0) { -+ fds[nfds].fd = i; -+ nfds++; -+ } -+ } -+ -+ return nfds; -+} -+ -+static void fds_poll2select(const struct pollfd *fds, int nfds, -+ fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -+{ -+ if (readfds) -+ FD_ZERO(readfds); -+ if (writefds) -+ FD_ZERO(writefds); -+ if (exceptfds) -+ FD_ZERO(exceptfds); -+ -+ for (int i = 0; i < nfds; ++i) { -+ if (readfds && fds[i].revents & POLLIN_SET) { -+ FD_SET(fds[i].fd, readfds); -+ } -+ if (writefds && fds[i].revents & POLLOUT_SET) { -+ FD_SET(fds[i].fd, writefds); -+ } -+ if (exceptfds && fds[i].revents & POLLEX_SET) { -+ FD_SET(fds[i].fd, exceptfds); -+ } -+ } -+} -+ -+static inline int timeval2ms(struct timeval *timeval) -+{ -+ if (timeval == NULL) { -+ return -1; -+ } -+ return timeval->tv_sec * MS_PER_S + timeval->tv_usec / (US_PER_S / MS_PER_S); -+} -+ -+int lstack_select(int nfds, fd_set *readfds, fd_set *writefds, -+ fd_set *exceptfds, struct timeval *timeout) -+{ -+ struct pollfd poll_fds[FD_SETSIZE] = {0}; -+ int poll_nfds, num; -+ int time_ms; -+ -+ if (unlikely(nfds < 0 || nfds > FD_SETSIZE)) { -+ LSTACK_LOG(ERR, LSTACK, "select invalid args, nfds=%d\n", nfds); -+ GAZELLE_RETURN(EINVAL); -+ } -+ if (timeout != NULL && unlikely(timeout->tv_sec < 0 || timeout->tv_usec < 0)) { -+ LSTACK_LOG(ERR, LSTACK, "select invalid args, timeout\n"); -+ GAZELLE_RETURN(EINVAL); -+ } -+ /* empty fds, just timeout */ -+ if (!readfds && !writefds && !exceptfds) { -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ } -+ -+ time_ms = timeval2ms(timeout); -+ -+ poll_nfds = fds_select2poll(poll_fds, nfds, readfds, writefds, exceptfds); -+ num = lstack_poll(poll_fds, poll_nfds, time_ms); -+ fds_poll2select(poll_fds, poll_nfds, readfds, writefds, exceptfds); -+ -+ return num; -+} -+ -+void epoll_api_init(posix_api_t *api) -+{ -+ api->epoll_create1_fn = lstack_epoll_create1; -+ api->epoll_create_fn = lstack_epoll_create; -+ api->epoll_ctl_fn = lstack_epoll_ctl; -+ api->epoll_wait_fn = lstack_epoll_wait; -+ -+ api->poll_fn = lstack_poll; -+ api->select_fn = lstack_select; -+} -+ -+bool sock_event_wait(struct lwip_sock *sock, bool noblocking) -+{ -+ bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -+ uint32_t start; -+ int timeout; -+ unsigned pending; -+ -+ if (!rtc_mode && noblocking) -+ return false; -+ -+ if (unlikely(sock->sk_wait == NULL) || sock->sk_wait->type == WAIT_CLOSE) { -+ sock->sk_wait = poll_construct_wait(0); -+ } -+ if (!(sock->sk_wait->type & WAIT_BLOCK)) { -+ sock->sk_wait->type |= WAIT_BLOCK; -+ } -+ -+ if (rtc_mode) { -+ /* RTC try to recv polling. */ -+ sock->sk_wait->timedwait_fn(sock->sk_wait, 0, 0); -+ return true; -+ } -+ -+ timeout = sock->conn->recv_timeout == 0 ? -1 : sock->conn->recv_timeout; -+ start = sys_now(); -+ do { -+ pending = sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0); -+ if (pending) { -+ return true; -+ } -+ timeout = sock->sk_wait->timedwait_fn(sock->sk_wait, timeout, start); -+ } while (timeout != 0); -+ -+ return false; -+} -+#endif /* SOCK_EVENT_V2 */ -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -new file mode 100644 -index 0000000..c67df93 ---- /dev/null -+++ b/src/lstack/core/lstack_wait.c -@@ -0,0 +1,550 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "common/gazelle_base_func.h" -+#include "lstack_wait.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "same_node.h" -+#include "mbox_ring.h" -+ -+#define KERNEL_EVENT_WAIT_US 10 -+#define LWIP_EVENT_WAIT_US 10 -+ -+struct kernel_wait { -+ int epfd; -+}; -+ -+struct lwip_wait { -+#if SOCK_WAIT_BATCH_NOTIFY -+ struct list_node stk_notify_list; -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+} __rte_cache_aligned; -+ -+struct sock_wait_group { -+ struct kernel_wait kwaits[PROTOCOL_STACK_MAX]; -+ struct lwip_wait lwaits[PROTOCOL_STACK_MAX]; -+ -+ _Atomic uint16_t affinity_tick; -+ -+ /* new cache line */ -+ char pad0 __rte_cache_aligned; -+ -+ /* dfx stat */ -+ struct list_node group_list; -+ rte_spinlock_t group_list_lock; -+}; -+static struct sock_wait_group g_wait_group = {0}; -+ -+static inline struct kernel_wait *kernel_wait_get(int stack_id) -+{ -+ if (unlikely(stack_id < 0 || stack_id >= PROTOCOL_STACK_MAX)) { -+ return NULL; -+ } -+ return &g_wait_group.kwaits[stack_id]; -+} -+ -+static inline struct lwip_wait *lwip_wait_get(int stack_id) -+{ -+ if (unlikely(stack_id < 0 || stack_id >= PROTOCOL_STACK_MAX)) { -+ return NULL; -+ } -+ return &g_wait_group.lwaits[stack_id]; -+} -+ -+static int lwip_wait_init(int stack_id) -+{ -+ struct lwip_wait *lwait = lwip_wait_get(stack_id); -+ LWIP_UNUSED_ARG(lwait); -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+ list_init_head(&lwait->stk_notify_list); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ return 0; -+} -+ -+static int kernel_wait_init(int stack_id) -+{ -+ struct kernel_wait *kwait = kernel_wait_get(stack_id); -+ -+ kwait->epfd = posix_api->epoll_create_fn(GAZELLE_LSTACK_MAX_CONN); -+ if (kwait->epfd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_create failed, errno %d\n", errno); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int sock_wait_group_init(void) -+{ -+ list_init_head(&g_wait_group.group_list); -+ rte_spinlock_init(&g_wait_group.group_list_lock); -+ return 0; -+} -+ -+static inline void sock_wait_group_add(struct sock_wait *sk_wait) -+{ -+ list_init_node(&sk_wait->group_node); -+ -+ rte_spinlock_lock(&g_wait_group.group_list_lock); -+ list_add_node(&sk_wait->group_node, &g_wait_group.group_list); -+ rte_spinlock_unlock(&g_wait_group.group_list_lock); -+} -+ -+static inline void sock_wait_group_del(struct sock_wait *sk_wait) -+{ -+ rte_spinlock_lock(&g_wait_group.group_list_lock); -+ list_del_node(&sk_wait->group_node); -+ rte_spinlock_unlock(&g_wait_group.group_list_lock); -+} -+ -+void sock_wait_group_stat(int stack_id, struct gazelle_wakeup_stat *stat) -+{ -+ struct sock_wait *sk_wait; -+ struct list_node *node, *next; -+ -+ rte_spinlock_lock(&g_wait_group.group_list_lock); -+ -+ list_for_each_node(node, next, &g_wait_group.group_list) { -+ sk_wait = list_entry(node, struct sock_wait, group_node); -+ -+ if (sk_wait->affinity.bind_stack_id == stack_id) { -+ memcpy_s(stat, sizeof(struct gazelle_wakeup_stat), -+ &sk_wait->stat, sizeof(struct gazelle_wakeup_stat)); -+ } -+ } -+ -+ rte_spinlock_unlock(&g_wait_group.group_list_lock); -+} -+ -+int kernel_wait_ctl(struct sock_wait *sk_wait, int new_stack_id, int old_stack_id) -+{ -+ int ret; -+ struct kernel_wait *old_kwait = kernel_wait_get(old_stack_id); -+ struct kernel_wait *new_kwait = kernel_wait_get(new_stack_id); -+ struct epoll_event epevent; -+ -+ /* not change */ -+ if (old_kwait != NULL && old_kwait == new_kwait) { -+ return 0; -+ } -+ -+ if (old_kwait) { -+ ret = posix_api->epoll_ctl_fn(old_kwait->epfd, EPOLL_CTL_DEL, sk_wait->epfd, NULL); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d\n", errno); -+ return -1; -+ } -+ } -+ -+ if (new_kwait) { -+ epevent.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET; -+ epevent.data.ptr = sk_wait; -+ ret = posix_api->epoll_ctl_fn(new_kwait->epfd, EPOLL_CTL_ADD, sk_wait->epfd, &epevent); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d\n", errno); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+void* kernel_wait_thread(void *arg) -+{ -+ struct thread_params *t_params = (struct thread_params*) arg; -+ unsigned stack_id = t_params->idx; -+ struct epoll_event kernel_events[KERNEL_EPOLL_MAX]; -+ int num, i; -+ struct kernel_wait *kwait; -+ struct sock_wait *sk_wait; -+ -+ bind_to_stack_numa(stack_id); -+ free(arg); -+ sem_post(&get_protocol_stack_group()->sem_stack_setup); -+ -+ lwip_wait_init(stack_id); -+ kernel_wait_init(stack_id); -+ kwait = kernel_wait_get(stack_id); -+ -+ LSTACK_LOG(INFO, LSTACK, "kernelevent_%02hu start\n", stack_id); -+ -+ for (;;) { -+ num = posix_api->epoll_wait_fn(kwait->epfd, kernel_events, KERNEL_EPOLL_MAX, -1); -+ if (num < 0 && errno != EINTR && errno != EAGAIN) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_wait faild, errno %d\n", errno); -+ } -+ -+ for (i = 0; i < num; ++i) { -+ sk_wait = kernel_events[i].data.ptr; -+ if (sk_wait->type == WAIT_CLOSE) -+ continue; -+ rte_atomic16_set(&sk_wait->kernel_pending, true); -+ sys_mutex_unlock_internal(&sk_wait->mutex); -+ } -+ usleep(KERNEL_EVENT_WAIT_US); -+ } -+ -+ return NULL; -+} -+ -+static unsigned affinity_choice_stack(int stack_num) -+{ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ return get_protocol_stack()->stack_idx; -+ } -+ return atomic_fetch_add(&g_wait_group.affinity_tick, 1) % stack_num; -+} -+ -+static void affinity_find_max_stack(struct wait_affinity *affinity, int stack_num) -+{ -+ int max_stack_id = affinity->max_stack_id; -+ -+ for (int i = 0; i < stack_num; i++) { -+ if (affinity->stack_nfds[i] > affinity->stack_nfds[max_stack_id]) { -+ max_stack_id = i; -+ } -+ } -+ affinity->max_stack_id = max_stack_id; -+} -+ -+void affinity_update_max_stack(struct wait_affinity *affinity) -+{ -+ struct protocol_stack_group *stack_group; -+ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ affinity->max_stack_id = get_protocol_stack()->stack_idx; -+ } else { -+ stack_group = get_protocol_stack_group(); -+ affinity_find_max_stack(affinity, stack_group->stack_num); -+ } -+} -+ -+void affinity_bind_stack(struct sock_wait *sk_wait, struct wait_affinity *affinity) -+{ -+ if (affinity->max_stack_id != affinity->bind_stack_id) { -+ bind_to_stack_numa(affinity->max_stack_id); -+ kernel_wait_ctl(sk_wait, affinity->max_stack_id, affinity->bind_stack_id); -+ affinity->bind_stack_id = affinity->max_stack_id; -+ } -+} -+ -+int sock_event_init(struct sock_event *sk_event) -+{ -+ memset_s(sk_event, sizeof(struct sock_event), 0, sizeof(struct sock_event)); -+ -+ list_init_node(&sk_event->event_node); -+#if SOCK_WAIT_BATCH_NOTIFY -+ list_init_node(&sk_event->stk_event_node); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ return 0; -+} -+ -+void sock_event_free(struct sock_event *sk_event, struct sock_wait *sk_wait) -+{ -+ if (sk_wait && sk_wait->type & WAIT_EPOLL) { -+ rte_spinlock_lock(&sk_wait->epcb.lock); -+ list_del_node(&sk_event->event_node); -+ rte_spinlock_unlock(&sk_wait->epcb.lock); -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+ list_del_node(&sk_event->stk_event_node); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ } -+} -+ -+int sock_wait_common_init(struct sock_wait *sk_wait) -+{ -+ sk_wait->lwip_nfds = 0; -+ sk_wait->kernel_nfds = 0; -+ sys_mutex_new_internal(&sk_wait->mutex); -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+ for (int i = 0; i < PROTOCOL_STACK_MAX; ++i) { -+ list_init_node(&sk_wait->stk_notify_node[i]); -+ list_init_head(&sk_wait->stk_event_list[i]); -+ } -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ sock_wait_group_add(sk_wait); -+ -+ return 0; -+} -+ -+void sock_wait_common_free(struct sock_wait *sk_wait) -+{ -+#if SOCK_WAIT_BATCH_NOTIFY -+ bool wait_stack; -+ -+ /* wait lwip_wait_foreach_notify() finish. */ -+ do { -+ wait_stack = false; -+ for (int i = 0; i < PROTOCOL_STACK_MAX; ++i) { -+ rte_mb(); -+ if (!list_node_null(&sk_wait->stk_notify_node[i])) { -+ wait_stack = true; -+ usleep(LWIP_EVENT_WAIT_US); -+ break; -+ } -+ } -+ } while (wait_stack); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ -+ sock_wait_group_del(sk_wait); -+ sys_mutex_free_internal(&sk_wait->mutex); -+} -+ -+int sock_wait_kernel_init(struct sock_wait *sk_wait, int epfd, int stack_num) -+{ -+ sk_wait->epfd = epfd; -+ sk_wait->affinity.max_stack_id = affinity_choice_stack(stack_num); -+ kernel_wait_ctl(sk_wait, sk_wait->affinity.max_stack_id, -1); -+ sk_wait->affinity.bind_stack_id = sk_wait->affinity.max_stack_id; -+ -+ rte_atomic16_init(&sk_wait->kernel_pending); -+ rte_atomic16_set(&sk_wait->kernel_pending, true); -+ return 0; -+} -+ -+void sock_wait_kernel_free(struct sock_wait *sk_wait) -+{ -+ kernel_wait_ctl(sk_wait, -1, sk_wait->affinity.bind_stack_id); -+ sk_wait->epfd = -1; -+ sk_wait->affinity.bind_stack_id = -1; -+ sk_wait->affinity.max_stack_id = -1; -+ -+ rte_atomic16_clear(&sk_wait->kernel_pending); -+} -+ -+ -+static inline bool NETCONN_NEED_ACCEPT(const struct lwip_sock *sock) -+{ -+ if (sys_mbox_valid(&sock->conn->acceptmbox)) { -+ const struct mbox_ring *mr = &sock->conn->acceptmbox->mring; -+ return mr->ops->count(mr) > 0; -+ } -+ return false; -+} -+ -+static inline bool NETCONN_NEED_RECV(const struct lwip_sock *sock) -+{ -+ if (sock->lastdata.pbuf != NULL) -+ return true; -+ if (sys_mbox_valid(&sock->conn->recvmbox)) { -+ const struct mbox_ring *mr = &sock->conn->recvmbox->mring; -+ return mr->ops->recv_count(mr) > 0; -+ } -+ return false; -+} -+ -+static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) -+{ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ if (NETCONN_TYPE(sock->conn) == NETCONN_TCP) -+ return lwip_tcp_allow_send(sock->conn->pcb.tcp); -+ return false; -+ } -+ if (sys_mbox_valid(&sock->conn->sendmbox)) { -+ const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ return mr->ops->free_count(mr) > 0; -+ } -+ return false; -+} -+ -+static unsigned sock_event_lose_pending(const struct lwip_sock *sock, enum netconn_evt evt, unsigned len) -+{ -+ unsigned event = 0; -+ -+ switch (evt) { -+ case NETCONN_EVT_RCVMINUS: -+ if (sock->sk_event.events & EPOLLIN) { -+ if (!NETCONN_NEED_RECV(sock) && -+ !NETCONN_NEED_ACCEPT(sock)) { -+ event = EPOLLIN; -+ } -+ } -+ break; -+ case NETCONN_EVT_SENDMINUS: -+ if (sock->sk_event.events & EPOLLOUT) { -+ if (!NETCONN_ALLOW_SEND(sock)) { -+ event = EPOLLOUT; -+ } -+ } -+ break; -+ default: -+ break; -+ } -+ -+ return event; -+} -+ -+unsigned sock_event_hold_pending(const struct lwip_sock *sock, -+ enum sock_wait_type type, enum netconn_evt evt, unsigned len) -+{ -+ unsigned event = 0; -+ -+ switch (evt) { -+ case NETCONN_EVT_RCVPLUS: -+ if (sock->sk_event.events & EPOLLIN || type & WAIT_BLOCK) { -+ if (len > 0 || -+ NETCONN_NEED_RECV(sock) || -+ NETCONN_NEED_ACCEPT(sock)) { -+ event = EPOLLIN; -+ } -+ } -+ break; -+ case NETCONN_EVT_SENDPLUS: -+ if (sock->sk_event.events & EPOLLOUT) { -+ if (len > 0 || -+ NETCONN_ALLOW_SEND(sock)) { -+ event = EPOLLOUT; -+ } -+ } -+ break; -+ case NETCONN_EVT_ERROR: -+ if (sock->errevent) { -+ event = EPOLLERR | EPOLLHUP | EPOLLIN; -+ } -+ break; -+ default: -+ break; -+ } -+ -+ return event; -+} -+ -+void sock_event_remove_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len) -+{ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, sk_wait=%p, evt=%d, len=%u)\n", -+ __FUNCTION__, sock, sock->sk_wait, evt, len)); -+ -+ if (sock->sk_wait == NULL) { -+ return; -+ } -+ if (unlikely(sock->sk_wait->type == WAIT_CLOSE)) { -+ sock->sk_wait = NULL; -+ return; -+ } -+ -+ unsigned pending = sock_event_lose_pending(sock, evt, 0); -+ if (pending) { -+ sock->sk_wait->remove_fn(sock->sk_wait, &sock->sk_event, pending); -+ } -+} -+ -+void sock_event_notify_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len) -+{ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, sk_wait=%p, evt=%d, len=%u)\n", -+ __FUNCTION__, sock, sock->sk_wait, evt, len)); -+ -+ if (sock->sk_wait == NULL) { -+ return; -+ } -+ if (unlikely(sock->sk_wait->type == WAIT_CLOSE)) { -+ sock->sk_wait = NULL; -+ return; -+ } -+ -+ unsigned pending = sock_event_hold_pending(sock, sock->sk_wait->type, evt, len); -+ if (pending) { -+ sock->sk_wait->notify_fn(sock->sk_wait, &sock->sk_event, pending, sock->stack_id); -+ } -+} -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+/* Only allow stack call */ -+void lwip_wait_add_notify(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id) -+{ -+ struct lwip_wait *lwait = lwip_wait_get(stack_id); -+ -+ if (sk_event != NULL) { -+ sk_event->stk_pending |= pending; -+ if (list_node_null(&sk_event->stk_event_node)) { -+ list_add_node(&sk_event->stk_event_node, &sk_wait->stk_event_list[stack_id]); -+ } -+ } -+ -+ if (list_node_null(&sk_wait->stk_notify_node[stack_id])) { -+ list_add_node(&sk_wait->stk_notify_node[stack_id], &lwait->stk_notify_list); -+ } -+} -+ -+static inline -+unsigned sock_wait_foreach_event(struct sock_wait *sk_wait, int stack_id) -+{ -+ struct list_node *node, *next; -+ struct sock_event *sk_event; -+ unsigned count = 0; -+ -+ /* only rtw epoll need */ -+ if (list_head_empty(&sk_wait->stk_event_list[stack_id])) -+ return 0; -+ -+ rte_spinlock_lock(&sk_wait->epcb.lock); -+ -+ list_for_each_node(node, next, &sk_wait->stk_event_list[stack_id]) { -+ list_del_node(node); -+ sk_event = container_of(node, struct sock_event, stk_event_node); -+ -+ /* see rtw_epoll_notify_event() */ -+ sk_event->pending |= sk_event->stk_pending; -+ if (list_node_null(&sk_event->event_node)) { -+ list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ } -+ -+ sk_event->stk_pending = 0; -+ count++; -+ } -+ -+ rte_spinlock_unlock(&sk_wait->epcb.lock); -+ -+ return count; -+} -+ -+/* Only allow stack call */ -+unsigned lwip_wait_foreach_notify(int stack_id) -+{ -+ struct lwip_wait *lwait = lwip_wait_get(stack_id); -+ struct sock_wait *sk_wait; -+ struct list_node *node, *next; -+ unsigned count = 0; -+ -+ list_for_each_node(node, next, &lwait->stk_notify_list) { -+ list_del_node(node); -+ sk_wait = container_of_uncheck_ptr((node - stack_id), struct sock_wait, stk_notify_node); -+ -+ sock_wait_foreach_event(sk_wait, stack_id); -+ -+ sys_mutex_unlock_internal(&sk_wait->mutex); -+ count++; -+ } -+ return count; -+} -+ -+bool lwip_wait_notify_empty(int stack_id) -+{ -+ struct lwip_wait *lwait = lwip_wait_get(stack_id); -+ return list_head_empty(&lwait->stk_notify_list); -+} -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 83eace7..9a5d15a 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -13,6 +13,8 @@ - #ifndef _GAZELLE_EPOLL_H_ - #define _GAZELLE_EPOLL_H_ - -+#if /* SOCK_EVENT_V2 */ -+ - #include - #include - #include -@@ -88,4 +90,20 @@ static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) - } - } - -+#else /* SOCK_EVENT_V2 */ -+ -+#include -+#include -+ -+#include "lstack_wait.h" -+ -+struct sock_wait *poll_construct_wait(int nfds); -+void poll_destruct_wait(void); -+ -+int lstack_epoll_close(int epfd); -+void epoll_api_init(posix_api_t *api); -+bool sock_event_wait(struct lwip_sock *sock, bool noblocking); -+ -+#endif /* SOCK_EVENT_V2 */ -+ - #endif /* _GAZELLE_EPOLL_H_ */ -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -new file mode 100644 -index 0000000..ed154b4 ---- /dev/null -+++ b/src/lstack/include/lstack_wait.h -@@ -0,0 +1,138 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_WAIT_H_ -+#define _LSTACK_WAIT_H_ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "common/gazelle_dfx_msg.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_cfg.h" -+ -+ -+#define NETCONN_TYPE(conn) NETCONNTYPE_GROUP(netconn_type((conn))) -+ -+enum sock_wait_type { -+ WAIT_CLOSE = 0x00, -+ WAIT_POLL = 0x01, -+ WAIT_EPOLL = 0x02, -+ WAIT_BLOCK = 0x04, -+ WAIT_MAX = 0x08, -+}; -+ -+struct wait_affinity { -+ int bind_stack_id; -+ int max_stack_id; -+ unsigned stack_nfds[PROTOCOL_STACK_MAX]; -+}; -+ -+/* epoll control block */ -+struct epoll_cb { -+ struct list_node event_list; -+ rte_spinlock_t lock; -+}; -+ -+/* poll control block */ -+struct poll_cb { -+ int max_nfds; -+ struct pollfd **lwip_p_fds; -+ struct pollfd *kernel_fds; -+}; -+ -+struct sock_wait { -+ enum sock_wait_type type; -+ -+ /* blocking and return 0 on timeout */ -+ int (*timedwait_fn)(struct sock_wait *sk_wait, int timeout, uint32_t start); -+ /* trigger event */ -+ void (*notify_fn)(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id); -+ /* remove event */ -+ void (*remove_fn)(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending); -+ -+ /* dfx stat */ -+ struct list_node group_node; -+ struct gazelle_wakeup_stat stat; -+ -+ /* epoll kernel fd */ -+ int epfd; -+ -+ /* socket count */ -+ unsigned lwip_nfds; -+ unsigned kernel_nfds; -+ struct wait_affinity affinity; -+ -+ char pad0 __rte_cache_aligned; /* new cache line */ -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+ /* lwip event foreach notify list */ -+ struct list_node __rte_cache_aligned stk_notify_node[PROTOCOL_STACK_MAX]; -+ struct list_node __rte_cache_aligned stk_event_list[PROTOCOL_STACK_MAX]; -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ -+ char pad1 __rte_cache_aligned; /* new cache line */ -+ -+ /* kernel event flag */ -+ rte_atomic16_t kernel_pending; -+ /* run-to-wakeup blocking lock */ -+ struct sys_mutex mutex; -+ -+ union { -+ struct epoll_cb epcb; -+ struct poll_cb pcb; -+ }; -+}; -+ -+ -+int sock_wait_group_init(void); -+void sock_wait_group_stat(int stack_id, struct gazelle_wakeup_stat *stat); -+ -+void* kernel_wait_thread(void *arg); -+int kernel_wait_ctl(struct sock_wait *sk_wait, int new_stack_id, int old_stack_id); -+ -+#if SOCK_WAIT_BATCH_NOTIFY -+void lwip_wait_add_notify(struct sock_wait *sk_wait, struct sock_event *sk_event, -+ unsigned pending, int stack_id); -+unsigned lwip_wait_foreach_notify(int stack_id); -+bool lwip_wait_notify_empty(int stack_id); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ -+ -+unsigned sock_event_hold_pending(const struct lwip_sock *sock, -+ enum sock_wait_type type, enum netconn_evt evt, unsigned len); -+void sock_event_notify_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len); -+void sock_event_remove_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len); -+ -+int sock_event_init(struct sock_event *sk_event); -+void sock_event_free(struct sock_event *sk_event, struct sock_wait *sk_wait); -+ -+int sock_wait_common_init(struct sock_wait *sk_wait); -+void sock_wait_common_free(struct sock_wait *sk_wait); -+ -+int sock_wait_kernel_init(struct sock_wait *sk_wait, int epfd, int stack_num); -+void sock_wait_kernel_free(struct sock_wait *sk_wait); -+ -+void affinity_update_max_stack(struct wait_affinity *affinity); -+void affinity_bind_stack(struct sock_wait *sk_wait, struct wait_affinity *affinity); -+ -+#endif /* _LSTACK_WAIT_H_ */ --- -2.33.0 - diff --git a/0327-socket-adapt-to-sock_event.patch b/0327-socket-adapt-to-sock_event.patch deleted file mode 100644 index c025539..0000000 --- a/0327-socket-adapt-to-sock_event.patch +++ /dev/null @@ -1,2955 +0,0 @@ -From 9098cb36f9a28fcc64b90168c71dfa4910c607ec Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 21 Mar 2025 16:53:37 +0800 -Subject: [PATCH] socket: adapt to sock_event - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 1034 -------------------- - src/lstack/api/lstack_rtc_api.c | 79 +- - src/lstack/api/lstack_rtw_api.c | 189 ++-- - src/lstack/api/lstack_wrap.c | 153 +-- - src/lstack/core/lstack_lwip.c | 217 ++-- - src/lstack/core/lstack_protocol_stack.c | 116 +-- - src/lstack/core/lstack_stack_stat.c | 32 +- - src/lstack/core/lstack_thread_rpc.c | 29 +- - src/lstack/core/lstack_wait.c | 26 +- - src/lstack/core/same_node.c | 5 +- - src/lstack/include/lstack_epoll.h | 81 -- - src/lstack/include/lstack_lwip.h | 4 - - src/lstack/include/lstack_protocol_stack.h | 52 +- - src/lstack/include/lstack_thread_rpc.h | 1 - - 14 files changed, 312 insertions(+), 1706 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index a110aa1..3940f43 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -10,1039 +10,6 @@ - * See the Mulan PSL v2 for more details. - */ - --#if !SOCK_EVENT_V2 -- --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include -- --#include "lstack_stack_stat.h" --#include "lstack_cfg.h" --#include "lstack_log.h" --#include "common/dpdk_common.h" --#include "common/gazelle_base_func.h" --#include "lstack_lwip.h" --#include "lstack_protocol_stack.h" --#include "lstack_epoll.h" -- --#define EPOLL_KERNEL_INTERVAL 10 /* ms */ --#define SEC_TO_NSEC 1000000000 --#define SEC_TO_MSEC 1000 --#define MSEC_TO_NSEC 1000000 --#define POLL_KERNEL_EVENTS 32 -- --static void update_epoll_max_stack(struct wakeup_poll *wakeup); --static void change_epollfd_kernel_thread(struct wakeup_poll *wakeup, struct protocol_stack *old_stack, -- struct protocol_stack *new_stack); -- --static inline void add_wakeup_to_stack_wakeuplist(struct wakeup_poll *wakeup, struct protocol_stack *stack) --{ -- if (list_node_null(&wakeup->wakeup_list[stack->stack_idx])) { -- list_add_node(&wakeup->wakeup_list[stack->stack_idx], &stack->wakeup_list); -- } --} -- --void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event) --{ -- struct wakeup_poll *wakeup = sock->wakeup; -- -- if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE || (event & sock->epoll_events) == 0) { -- return; -- } -- -- if (!get_global_cfg_params()->stack_mode_rtc) { -- if (event == EPOLLIN && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { -- return; -- } -- -- if (event == EPOLLOUT && !NETCONN_IS_OUTIDLE(sock)) { -- return; -- } -- } -- -- sock->events |= (event == EPOLLERR) ? (EPOLLIN | EPOLLERR) : (event & sock->epoll_events); -- if (list_node_null(&sock->event_list)) { -- list_add_node(&sock->event_list, &wakeup->event_list); -- } -- return; --} -- --static void _add_sock_event(struct lwip_sock *sock, struct wakeup_poll *wakeup, uint32_t event) --{ -- struct protocol_stack *stack = sock->stack; -- if (wakeup == NULL || wakeup->type == WAKEUP_CLOSE) { -- return; -- } -- -- if (wakeup->type == WAKEUP_BLOCK) { -- if (!(event & (EPOLLIN | EPOLLERR))) { -- return; -- } -- } else if (!(event & sock->epoll_events)) { -- return; -- } -- -- if (wakeup->type == WAKEUP_EPOLL) { -- pthread_spin_lock(&wakeup->event_list_lock); -- add_sock_event_nolock(sock, event); -- pthread_spin_unlock(&wakeup->event_list_lock); -- } -- -- add_wakeup_to_stack_wakeuplist(wakeup, stack); -- return; --} -- --void add_sock_event(struct lwip_sock *sock, uint32_t event) --{ -- _add_sock_event(sock, sock->wakeup, event); -- _add_sock_event(sock, sock->recv_block, event); --} -- --void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event) --{ -- if (get_global_cfg_params()->stack_mode_rtc) { -- sock->events &= ~event; -- } else { -- if ((event & EPOLLOUT) && !NETCONN_IS_OUTIDLE(sock)) { -- sock->events &= ~EPOLLOUT; -- } -- if ((event & EPOLLIN) && !NETCONN_IS_DATAIN(sock) && !NETCONN_IS_ACCEPTIN(sock)) { -- sock->events &= ~EPOLLIN; -- } -- } -- -- if (sock->events == 0) { -- list_del_node(&sock->event_list); -- } -- return; --} -- --void del_sock_event(struct lwip_sock *sock, uint32_t event) --{ -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- del_sock_event_nolock(sock, event); -- pthread_spin_unlock(&sock->wakeup->event_list_lock); --} -- --void wakeup_stack_epoll(struct protocol_stack *stack) --{ -- struct list_node *node, *temp; -- -- list_for_each_node(node, temp, &stack->wakeup_list) { -- struct wakeup_poll *wakeup = container_of_uncheck_ptr((node - stack->stack_idx), struct wakeup_poll, wakeup_list); -- -- if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- rte_mb(); -- sem_post(&wakeup->wait); -- stack->stats.wakeup_events++; -- } -- -- list_del_node(&wakeup->wakeup_list[stack->stack_idx]); -- } --} -- --static uint32_t update_events(struct lwip_sock *sock) --{ -- uint32_t event = 0; -- -- if (sock->epoll_events & EPOLLIN) { -- if (NETCONN_IS_DATAIN(sock) || NETCONN_IS_ACCEPTIN(sock)) { -- event |= EPOLLIN; -- } -- } -- -- if ((sock->epoll_events & EPOLLOUT) && NETCONN_IS_OUTIDLE(sock)) { -- /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -- event |= EPOLLOUT; -- } -- } -- -- if (sock->errevent > 0) { -- event |= EPOLLERR | EPOLLIN; -- } -- -- return event; --} -- --static void rtc_raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *sock) --{ -- uint32_t event = 0; -- -- if (sock->rcvevent) { -- event |= EPOLLIN; -- } -- -- if (sock->errevent > 0) { -- event |= EPOLLERR | EPOLLIN; -- } -- -- if (sock->sendevent) { -- /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -- event |= EPOLLOUT; -- } -- } -- -- if (event) { -- sock->events = event; -- if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && -- list_node_null(&sock->event_list)) { -- list_add_node(&sock->event_list, &wakeup->event_list); -- } -- } --} -- --static void raise_pending_events(struct wakeup_poll *wakeup, struct lwip_sock *sock) --{ -- uint32_t event = 0; -- -- pthread_spin_lock(&wakeup->event_list_lock); -- if (NETCONN_IS_DATAIN(sock) || NETCONN_IS_ACCEPTIN(sock)) { -- event |= EPOLLIN; -- } -- -- if (sock->errevent > 0) { -- event |= EPOLLERR | EPOLLIN; -- } -- -- if (NETCONN_IS_OUTIDLE(sock)) { -- /* lwip_netconn_do_connected set LIBOS FLAGS when connected */ -- if (!POSIX_IS_CLOSED(sock) && POSIX_IS_TYPE(sock, POSIX_LWIP)) { -- event |= EPOLLOUT; -- } -- } -- -- if (event) { -- sock->events = event; -- if (wakeup->type == WAKEUP_EPOLL && (sock->events & sock->epoll_events) && -- list_node_null(&sock->event_list)) { -- list_add_node(&sock->event_list, &wakeup->event_list); -- rte_mb(); -- sem_post(&wakeup->wait); -- } -- } -- pthread_spin_unlock(&wakeup->event_list_lock); --} -- --int32_t lstack_do_epoll_create(int32_t fd) --{ -- if (fd < 0) { -- return fd; -- } -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "fd=%d sock is NULL errno=%d\n", fd, errno); -- posix_api->close_fn(fd); -- GAZELLE_RETURN(EINVAL); -- } -- -- struct wakeup_poll *wakeup = calloc(1, sizeof(struct wakeup_poll)); -- if (wakeup == NULL) { -- LSTACK_LOG(ERR, LSTACK, "calloc null\n"); -- posix_api->close_fn(fd); -- GAZELLE_RETURN(EINVAL); -- } -- -- for (uint32_t i = 0; i < PROTOCOL_STACK_MAX; i++) { -- list_init_node(&wakeup->wakeup_list[i]); -- } -- -- if (sem_init(&wakeup->wait, 0, 0) != 0) { -- posix_api->close_fn(fd); -- free(wakeup); -- GAZELLE_RETURN(EINVAL); -- } -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- list_init_node(&wakeup->poll_list); -- pthread_spin_lock(&stack_group->poll_list_lock); -- list_add_node(&wakeup->poll_list, &stack_group->poll_list); -- pthread_spin_unlock(&stack_group->poll_list_lock); -- -- list_init_head(&wakeup->event_list); -- pthread_spin_init(&wakeup->event_list_lock, PTHREAD_PROCESS_PRIVATE); -- -- wakeup->type = WAKEUP_EPOLL; -- wakeup->epollfd = fd; -- sock->wakeup = wakeup; -- -- if (!get_global_cfg_params()->stack_mode_rtc) { -- update_epoll_max_stack(wakeup); -- change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, wakeup->max_stack); -- wakeup->bind_stack = wakeup->max_stack; -- if (get_global_cfg_params()->app_bind_numa) { -- bind_to_stack_numa(wakeup->bind_stack); -- } -- } else { -- wakeup->bind_stack = wakeup->max_stack = get_protocol_stack(); -- change_epollfd_kernel_thread(wakeup, NULL, wakeup->max_stack); -- } -- -- return fd; --} -- --int32_t lstack_epoll_create1(int32_t flags) --{ -- int32_t fd = posix_api->epoll_create1_fn(flags); -- return lstack_do_epoll_create(fd); --} -- --int32_t lstack_epoll_create(int32_t flags) --{ -- int32_t fd = posix_api->epoll_create_fn(flags); -- return lstack_do_epoll_create(fd); --} -- --static void stack_broadcast_clean_epoll(struct wakeup_poll *wakeup) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- struct protocol_stack *stack = NULL; -- -- for (int32_t i = 0; i < stack_group->stack_num; i++) { -- stack = stack_group->stacks[i]; -- rpc_call_clean_epoll(&stack->rpc_queue, wakeup); -- } --} -- --int32_t lstack_epoll_close(int32_t fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "fd=%d sock is NULL errno=%d\n", fd, errno); -- GAZELLE_RETURN(EINVAL); -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- struct wakeup_poll *wakeup = sock->wakeup; -- if (wakeup == NULL) { -- return 0; -- } -- -- wakeup->type = WAKEUP_CLOSE; -- -- if (!get_global_cfg_params()->stack_mode_rtc) { -- stack_broadcast_clean_epoll(wakeup); -- } -- -- struct list_node *node, *temp; -- pthread_spin_lock(&wakeup->event_list_lock); -- list_for_each_node(node, temp, &wakeup->event_list) { -- struct lwip_sock *sock = list_entry(node, struct lwip_sock, event_list); -- list_del_node(&sock->event_list); -- } -- pthread_spin_unlock(&wakeup->event_list_lock); -- pthread_spin_destroy(&wakeup->event_list_lock); -- -- pthread_spin_lock(&stack_group->poll_list_lock); -- list_del_node(&wakeup->poll_list); -- pthread_spin_unlock(&stack_group->poll_list_lock); -- -- sem_destroy(&wakeup->wait); -- -- free(wakeup); -- sock->wakeup = NULL; -- -- posix_api->close_fn(fd); -- return 0; --} -- --static uint16_t find_max_cnt_stack(int32_t *stack_count, uint16_t stack_num, struct protocol_stack *last_stack) --{ -- uint16_t max_index = 0; -- bool all_same_cnt = true; -- -- for (uint16_t i = 1; i < stack_num; i++) { -- if (stack_count[i] != stack_count[0]) { -- all_same_cnt = false; -- } -- -- if (stack_count[i] > stack_count[max_index]) { -- max_index = i; -- } -- } -- -- /* all stack same, don't change */ -- if (all_same_cnt && last_stack) { -- return last_stack->stack_idx; -- } -- -- /* first bind and all stack same. choice tick as queue_id, avoid all bind to statck_0. */ -- static _Atomic uint16_t tick = 0; -- if (all_same_cnt && stack_num) { -- max_index = atomic_fetch_add(&tick, 1) % stack_num; -- } -- -- return max_index; --} -- --static void update_epoll_max_stack(struct wakeup_poll *wakeup) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- uint16_t bind_id = find_max_cnt_stack(wakeup->stack_fd_cnt, stack_group->stack_num, wakeup->max_stack); -- -- wakeup->max_stack = stack_group->stacks[bind_id]; --} -- --int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event) --{ -- if (epfd < 0 || fd < 0 || epfd == fd || (event == NULL && op != EPOLL_CTL_DEL)) { -- LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d\n", fd, epfd, op); -- GAZELLE_RETURN(EINVAL); -- } -- -- struct lwip_sock *epoll_sock = lwip_get_socket(epfd); -- if (epoll_sock == NULL || epoll_sock->wakeup == NULL) { -- return posix_api->epoll_ctl_fn(epfd, op, fd, event); -- } -- -- struct wakeup_poll *wakeup = epoll_sock->wakeup; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- return posix_api->epoll_ctl_fn(epfd, op, fd, event); -- } -- -- switch (op) { -- case EPOLL_CTL_ADD: -- sock->wakeup = wakeup; -- /* fall through */ -- case EPOLL_CTL_MOD: -- sock->epoll_events = event->events | EPOLLERR | EPOLLHUP; -- sock->ep_data = event->data; -- rtc_raise_pending_events(wakeup, sock); -- break; -- case EPOLL_CTL_DEL: -- sock->epoll_events = 0; -- list_del_node(&sock->event_list); -- break; -- default: -- GAZELLE_RETURN(EINVAL); -- } -- -- return 0; --} -- --int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event) --{ -- LSTACK_LOG(DEBUG, LSTACK, "op=%d events: fd: %d\n", op, fd); -- -- if (epfd < 0 || fd < 0 || epfd == fd || (event == NULL && op != EPOLL_CTL_DEL)) { -- LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d\n", fd, epfd, op); -- GAZELLE_RETURN(EINVAL); -- } -- -- struct lwip_sock *epoll_sock = lwip_get_socket(epfd); -- if (epoll_sock == NULL || epoll_sock->wakeup == NULL) { -- return posix_api->epoll_ctl_fn(epfd, op, fd, event); -- } -- -- struct wakeup_poll *wakeup = epoll_sock->wakeup; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock) || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { -- return posix_api->epoll_ctl_fn(epfd, op, fd, event); -- } -- -- if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -- int32_t ret = posix_api->epoll_ctl_fn(epfd, op, fd, event); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "fd=%d epfd=%d op=%d errno=%d\n", fd, epfd, op, errno); -- } -- } -- -- do { -- switch (op) { -- case EPOLL_CTL_ADD: -- sock->wakeup = wakeup; -- wakeup->stack_fd_cnt[sock->stack->stack_idx]++; -- /* fall through */ -- case EPOLL_CTL_MOD: -- sock->epoll_events = event->events | EPOLLERR | EPOLLHUP; -- sock->ep_data = event->data; -- raise_pending_events(wakeup, sock); -- break; -- case EPOLL_CTL_DEL: -- sock->epoll_events = 0; -- wakeup->stack_fd_cnt[sock->stack->stack_idx]--; -- pthread_spin_lock(&wakeup->event_list_lock); -- list_del_node(&sock->event_list); -- pthread_spin_unlock(&wakeup->event_list_lock); -- break; -- default: -- GAZELLE_RETURN(EINVAL); -- } -- sock = sock->listen_next; -- } while (sock != NULL); -- -- update_epoll_max_stack(wakeup); -- return 0; --} -- --int32_t epoll_lwip_event_nolock(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents) --{ -- int32_t event_num = 0; -- struct list_node *node, *temp; -- -- list_for_each_node(node, temp, &wakeup->event_list) { -- struct lwip_sock *sock = list_entry(node, struct lwip_sock, event_list); -- -- if ((sock->epoll_events & sock->events) == 0) { -- list_del_node(node); -- continue; -- } -- -- if (event_num >= maxevents) { -- /* move list head after the current node, and start traversing from this node next time */ -- list_del_node(&wakeup->event_list); -- list_add_node(&wakeup->event_list, node); -- break; -- } -- -- events[event_num].events = sock->events & sock->epoll_events; -- events[event_num].data = sock->ep_data; -- event_num++; -- -- if (sock->epoll_events & EPOLLET) { -- list_del_node(node); -- sock->events = 0; -- } -- -- /* EPOLLONESHOT: generate event after epoll_ctl add/mod event again -- epoll_event set 0 avoid generating event util epoll_ctl reset epoll_event */ -- if (sock->epoll_events & EPOLLONESHOT) { -- list_del_node(node); -- sock->epoll_events = 0; -- } -- } -- -- return event_num; --} -- --static int32_t epoll_lwip_event(struct wakeup_poll *wakeup, struct epoll_event *events, uint32_t maxevents) --{ -- int32_t event_num; -- -- pthread_spin_lock(&wakeup->event_list_lock); -- event_num = epoll_lwip_event_nolock(wakeup, events, maxevents); -- pthread_spin_unlock(&wakeup->event_list_lock); -- -- return event_num; --} -- --static int32_t poll_lwip_event(struct pollfd *fds, nfds_t nfds) --{ -- int32_t event_num = 0; -- -- for (uint32_t i = 0; i < nfds; i++) { -- /* sock->listen_next pointerto next stack listen */ -- int32_t fd = fds[i].fd; -- struct lwip_sock *sock = lwip_get_socket(fd); -- while (!POSIX_IS_CLOSED(sock)) { -- uint32_t events = update_events(sock); -- if (events) { -- fds[i].revents = events; -- event_num++; -- break; -- } -- -- sock = sock->listen_next; -- } -- } -- -- return event_num; --} -- --static void change_epollfd_kernel_thread(struct wakeup_poll *wakeup, struct protocol_stack *old_stack, -- struct protocol_stack *new_stack) --{ -- if (old_stack) { -- if (posix_api->epoll_ctl_fn(old_stack->epollfd, EPOLL_CTL_DEL, wakeup->epollfd, NULL) != 0) { -- LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn errno=%d\n", errno); -- } -- } -- -- /* avoid kernel thread post too much, use EPOLLET */ -- struct epoll_event event; -- event.data.ptr = wakeup; -- event.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLET; -- if (posix_api->epoll_ctl_fn(new_stack->epollfd, EPOLL_CTL_ADD, wakeup->epollfd, &event) != 0) { -- LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn errno=%d\n", errno); -- } --} -- --static void epoll_bind_statck(struct wakeup_poll *wakeup) --{ -- if (wakeup->bind_stack != wakeup->max_stack && wakeup->max_stack) { -- bind_to_stack_numa(wakeup->max_stack); -- change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, wakeup->max_stack); -- wakeup->bind_stack = wakeup->max_stack; -- } --} -- --static void ms_to_timespec(struct timespec *timespec, int32_t timeout) --{ -- clock_gettime(CLOCK_REALTIME, timespec); -- timespec->tv_sec += timeout / SEC_TO_MSEC; -- timespec->tv_nsec += (timeout % SEC_TO_MSEC) * MSEC_TO_NSEC; -- timespec->tv_sec += timespec->tv_nsec / SEC_TO_NSEC; -- timespec->tv_nsec = timespec->tv_nsec % SEC_TO_NSEC; --} -- --/** -- * Block lstack thread -- * -- * @param wakeup -- * The pointer to the wakeup_poll. -- * @param timeout -- * The time to wait, if 'timeout <= 0' will block until unlock -- * -- * @return -- * - return '0' on unlock -- * - return 'ETIMEDOUT' on timeout -- */ --int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout) --{ -- int ret = 0; -- if (wakeup == NULL) { -- return ret; -- } -- -- __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -- if (timeout > 0) { -- struct timespec timespec; -- ms_to_timespec(×pec, timeout); -- ret = sem_timedwait(&wakeup->wait, ×pec); -- } else { -- ret = sem_wait(&wakeup->wait); -- } -- -- if (__atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- } -- -- return ret; --} -- --int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) --{ -- struct lwip_sock *sock = lwip_get_socket(epfd); -- -- if (sock == NULL || sock->wakeup == NULL) { -- return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -- } -- -- struct wakeup_poll *wakeup = sock->wakeup; -- int32_t lwip_num = 0; -- /* 16: avoid app process events for a long time */ -- int32_t tmpmaxevents = 16; -- /* avoid the starvation of epoll events from both netstack */ -- int host_maxevents = tmpmaxevents / 2; -- uint32_t poll_ts = sys_now(); -- bool loop_flag; -- int32_t kernel_num = 0; -- int32_t tmptimeout = timeout; -- -- do { -- stack_polling(0); -- if (__atomic_load_n(&wakeup->have_kernel_event, __ATOMIC_ACQUIRE)) { -- kernel_num = posix_api->epoll_wait_fn(epfd, events, host_maxevents, 0); -- if (!kernel_num) { -- __atomic_store_n(&wakeup->have_kernel_event, false, __ATOMIC_RELEASE); -- } -- } -- if (tmptimeout > 0) { -- if (tmptimeout <= sys_now() - poll_ts) { -- tmptimeout = 0; -- } -- } -- -- loop_flag = false; -- if (!kernel_num && list_head_empty(&wakeup->event_list) && tmptimeout != 0) { -- loop_flag = true; -- } -- } while (loop_flag); -- -- if (kernel_num < 0) { -- LSTACK_LOG(ERR, LSTACK, "lstack_rtc_epoll_wait: kernel event failed\n"); -- return kernel_num; -- } -- -- lwip_num = epoll_lwip_event_nolock(wakeup, &events[kernel_num], tmpmaxevents - kernel_num); -- wakeup->stat.app_events += lwip_num; -- wakeup->stat.kernel_events += kernel_num; -- -- return lwip_num + kernel_num; --} -- --int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) --{ -- struct lwip_sock *sock = lwip_get_socket(epfd); -- if (sock == NULL || sock->wakeup == NULL) { -- return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -- } -- -- struct wakeup_poll *wakeup = sock->wakeup; -- int32_t kernel_num = 0; -- int32_t lwip_num = 0; -- -- if (get_global_cfg_params()->app_bind_numa) { -- epoll_bind_statck(sock->wakeup); -- } -- -- do { -- __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -- lwip_num = epoll_lwip_event(wakeup, events, maxevents); -- -- if (__atomic_load_n(&wakeup->have_kernel_event, __ATOMIC_ACQUIRE)) { -- kernel_num = posix_api->epoll_wait_fn(epfd, &events[lwip_num], maxevents - lwip_num, 0); -- if (!kernel_num) { -- __atomic_store_n(&wakeup->have_kernel_event, false, __ATOMIC_RELEASE); -- } -- } -- -- if (lwip_num + kernel_num > 0) { -- break; -- } -- -- if (timeout == 0) { -- break; -- } -- } while (lstack_block_wait(wakeup, timeout) == 0); -- -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- wakeup->stat.app_events += lwip_num; -- wakeup->stat.kernel_events += kernel_num; -- -- return lwip_num + kernel_num; --} -- --static int32_t init_poll_wakeup_data(struct wakeup_poll *wakeup) --{ -- if (sem_init(&wakeup->wait, 0, 0) != 0) { -- GAZELLE_RETURN(EINVAL); -- } -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- -- for (uint32_t i = 0; i < PROTOCOL_STACK_MAX; i++) { -- list_init_node(&wakeup->wakeup_list[i]); -- } -- -- wakeup->epollfd = posix_api->epoll_create_fn(POLL_KERNEL_EVENTS); -- if (wakeup->epollfd < 0) { -- GAZELLE_RETURN(EINVAL); -- } -- -- wakeup->type = WAKEUP_POLL; -- -- wakeup->last_fds = calloc(POLL_KERNEL_EVENTS, sizeof(struct pollfd)); -- if (wakeup->last_fds == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- wakeup->last_max_nfds = POLL_KERNEL_EVENTS; -- -- wakeup->events = calloc(POLL_KERNEL_EVENTS, sizeof(struct epoll_event)); -- if (wakeup->events == NULL) { -- free(wakeup->last_fds); -- wakeup->last_fds = NULL; -- GAZELLE_RETURN(EINVAL); -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- list_init_node(&wakeup->poll_list); -- pthread_spin_lock(&stack_group->poll_list_lock); -- list_add_node(&wakeup->poll_list, &stack_group->poll_list); -- pthread_spin_unlock(&stack_group->poll_list_lock); -- -- int32_t stack_count[PROTOCOL_STACK_MAX] = {0}; -- uint16_t bind_id = find_max_cnt_stack(stack_count, stack_group->stack_num, wakeup->bind_stack); -- change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, stack_group->stacks[bind_id]); -- wakeup->bind_stack = stack_group->stacks[bind_id]; -- if (get_global_cfg_params()->app_bind_numa) { -- bind_to_stack_numa(wakeup->bind_stack); -- } -- -- return 0; --} -- --static int resize_kernel_poll(struct wakeup_poll *wakeup, nfds_t nfds) --{ -- if (wakeup->last_fds) { -- free(wakeup->last_fds); -- } -- wakeup->last_fds = calloc(nfds, sizeof(struct pollfd)); -- if (wakeup->last_fds == NULL) { -- LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -- return -1; -- } -- -- if (wakeup->events) { -- free(wakeup->events); -- } -- wakeup->events = calloc(nfds, sizeof(struct epoll_event)); -- if (wakeup->events == NULL) { -- LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -- free(wakeup->last_fds); -- wakeup->last_fds = NULL; -- return -1; -- } -- -- wakeup->last_max_nfds = nfds; -- return 0; --} -- --static void poll_bind_statck(struct wakeup_poll *wakeup, int32_t *stack_count) --{ -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- -- uint16_t bind_id = find_max_cnt_stack(stack_count, stack_group->stack_num, wakeup->bind_stack); -- if (wakeup->bind_stack && wakeup->bind_stack->queue_id == bind_id) { -- return; -- } -- -- change_epollfd_kernel_thread(wakeup, wakeup->bind_stack, stack_group->stacks[bind_id]); -- bind_to_stack_numa(stack_group->stacks[bind_id]); -- wakeup->bind_stack = stack_group->stacks[bind_id]; --} -- --static void update_kernel_poll(struct wakeup_poll *wakeup, uint32_t index, struct pollfd *new_fd) --{ -- posix_api->epoll_ctl_fn(wakeup->epollfd, EPOLL_CTL_DEL, wakeup->last_fds[index].fd, NULL); -- -- if (new_fd == NULL) { -- return; -- } -- -- struct epoll_event event; -- event.data.u32 = index; -- event.events = new_fd->events; -- if (posix_api->epoll_ctl_fn(wakeup->epollfd, EPOLL_CTL_ADD, new_fd->fd, &event) != 0) { -- LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn errno=%d\n", errno); -- } --} -- --static int poll_init(struct wakeup_poll *wakeup, struct pollfd *fds, nfds_t nfds) --{ -- int32_t stack_count[PROTOCOL_STACK_MAX] = {0}; -- int32_t poll_change = 0; -- int ret = 0; -- -- /* poll fds num more, recalloc fds size */ -- if (nfds > wakeup->last_max_nfds) { -- ret = resize_kernel_poll(wakeup, nfds); -- if (ret < 0) { -- return -1; -- } -- poll_change = 1; -- } -- -- if (nfds < wakeup->last_nfds) { -- poll_change = 1; -- } -- -- for (uint32_t i = 0; i < nfds; i++) { -- int32_t fd = fds[i].fd; -- fds[i].revents = 0; -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- if (fd == wakeup->last_fds[i].fd && fds[i].events == wakeup->last_fds[i].events) { -- /* fd close then socket may get same fd. */ -- if (sock == NULL || sock->wakeup != NULL) { -- continue; -- } -- } -- -- if (POSIX_IS_CLOSED(sock) || POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -- update_kernel_poll(wakeup, i, fds + i); -- } -- -- wakeup->last_fds[i].fd = fd; -- wakeup->last_fds[i].events = fds[i].events; -- poll_change = 1; -- -- while (!POSIX_IS_CLOSED(sock)) { -- sock->epoll_events = fds[i].events | POLLERR; -- sock->wakeup = wakeup; -- stack_count[sock->stack->stack_idx]++; -- sock = sock->listen_next; -- } -- } -- -- if (poll_change == 0) { -- return 0; -- } -- wakeup->last_nfds = nfds; -- -- if (get_global_cfg_params()->app_bind_numa) { -- poll_bind_statck(wakeup, stack_count); -- } -- return 0; --} -- --struct wakeup_poll* poll_construct_wakeup(void) --{ -- static PER_THREAD struct wakeup_poll *wakeup = NULL; -- if (wakeup == NULL) { -- wakeup = calloc(1, sizeof(struct wakeup_poll)); -- if (wakeup == NULL) { -- LSTACK_LOG(ERR, LSTACK, "calloc failed errno=%d\n", errno); -- return NULL; -- } -- -- if (init_poll_wakeup_data(wakeup) < 0) { -- free(wakeup); -- return NULL; -- } -- } -- return wakeup; --} -- --int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) --{ -- struct wakeup_poll *wakeup = poll_construct_wakeup(); -- if (wakeup == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- -- if (poll_init(wakeup, fds, nfds) < 0) { -- free(wakeup); -- GAZELLE_RETURN(EINVAL); -- } -- -- int32_t kernel_num = 0; -- int32_t lwip_num = 0; -- -- do { -- __atomic_store_n(&wakeup->in_wait, true, __ATOMIC_RELEASE); -- lwip_num = poll_lwip_event(fds, nfds); -- -- if (__atomic_load_n(&wakeup->have_kernel_event, __ATOMIC_ACQUIRE)) { -- kernel_num = posix_api->epoll_wait_fn(wakeup->epollfd, wakeup->events, nfds, 0); -- for (int32_t i = 0; i < kernel_num; i++) { -- uint32_t index = wakeup->events[i].data.u32; -- fds[index].revents = wakeup->events[i].events; -- } -- if (!kernel_num) { -- __atomic_store_n(&wakeup->have_kernel_event, false, __ATOMIC_RELEASE); -- } -- } -- -- if (lwip_num + kernel_num > 0) { -- break; -- } -- -- if (timeout == 0) { -- break; -- } -- } while (lstack_block_wait(wakeup, timeout) == 0); -- -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- wakeup->stat.app_events += lwip_num; -- wakeup->stat.kernel_events += kernel_num; -- -- return lwip_num + kernel_num; --} -- --static void select_set_revent_fdset(struct pollfd *fds, nfds_t nfds, fd_set *eventfds, uint32_t event) --{ -- FD_ZERO(eventfds); -- -- /* Set the fd_set parameter based on the actual revents. */ -- for (int i = 0; i < nfds; i++) { -- if (fds[i].revents & event) { -- FD_SET(fds[i].fd, eventfds); -- } -- } --} -- --static void fds_poll2select(struct pollfd *fds, nfds_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) --{ -- if (fds == NULL || nfds == 0) { -- return; -- } -- -- if (readfds) { -- select_set_revent_fdset(fds, nfds, readfds, EPOLLIN); -- } -- if (writefds) { -- select_set_revent_fdset(fds, nfds, writefds, EPOLLOUT); -- } -- if (exceptfds) { -- select_set_revent_fdset(fds, nfds, exceptfds, EPOLLERR); -- } --} -- --static inline int timeval_to_ms(struct timeval *timeval, int32_t *timeout) --{ -- if (!timeval) { -- *timeout = -1; -- return 0; -- } -- if (unlikely((timeval->tv_sec < 0 || timeval->tv_usec < 0 || timeval->tv_usec >= 1000000))) { -- return -1; -- } -- *timeout = timeval->tv_sec * 1000 + timeval->tv_usec / 1000; -- return 0; --} -- --static nfds_t fds_select2poll(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct pollfd *fds) --{ -- struct pollfd *pollfds = fds; -- nfds_t nfds = 0; -- -- for (int i = 0; i < maxfd; i++) { -- if (readfds && FD_ISSET(i, readfds)) { -- pollfds[nfds].events = POLLIN; -- } -- if (writefds && FD_ISSET(i, writefds)) { -- pollfds[nfds].events |= POLLOUT; -- } -- if (exceptfds && FD_ISSET(i, exceptfds)) { -- pollfds[nfds].events |= POLLERR; -- } -- if (pollfds[nfds].events > 0) { -- pollfds[nfds].fd = i; -- nfds++; -- } -- } -- return nfds; --} -- --int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval) --{ -- if (maxfd < 0 || maxfd > FD_SETSIZE) { -- LSTACK_LOG(ERR, LSTACK, "select input param error, fd num=%d\n", maxfd); -- GAZELLE_RETURN(EINVAL); -- } -- -- /* Convert the select parameter to the poll parameter. */ -- struct pollfd fds[FD_SETSIZE] = { 0 }; -- nfds_t nfds = fds_select2poll(maxfd, readfds, writefds, exceptfds, fds); -- int timeout = 0; -- if (timeval_to_ms(timeval, &timeout)) { -- LSTACK_LOG(ERR, LSTACK, "select input param timeout error.\n"); -- GAZELLE_RETURN(EINVAL); -- } -- -- int event_num = lstack_poll(fds, nfds, timeout); -- -- /* After poll, set select fd_set by fds.revents. */ -- fds_poll2select(fds, nfds, readfds, writefds, exceptfds); -- -- return event_num; --} -- --#else /* SOCK_EVENT_V2 */ -- - #include - #include - #include -@@ -1883,4 +850,3 @@ bool sock_event_wait(struct lwip_sock *sock, bool noblocking) - - return false; - } --#endif /* SOCK_EVENT_V2 */ -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -index 60d3b23..4a962e1 100644 ---- a/src/lstack/api/lstack_rtc_api.c -+++ b/src/lstack/api/lstack_rtc_api.c -@@ -13,80 +13,15 @@ - #include - #include - --#include "lstack_epoll.h" - #include "lstack_log.h" --#include "lstack_cfg.h" --#include "lstack_protocol_stack.h" - #include "lstack_rtc_api.h" - --static int rtc_socket(int domain, int type, int protocol) --{ -- int ret; -- -- if (stack_setup_app_thread() < 0) { -- exit(1); -- } -- -- /* need call stack thread init function */ -- ret = lwip_socket(domain, type, protocol); -- return ret; --} -- --static int rtc_close(int s) --{ -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock != NULL && sock->wakeup != NULL && sock->wakeup->epollfd == s) { -- return lstack_epoll_close(s); -- } -- -- return lwip_close(s); --} -- --static int rtc_epoll_create(int flags) --{ -- if (stack_setup_app_thread() < 0) { -- exit(1); -- } -- -- return lstack_epoll_create(flags); --} -- --static int rtc_epoll_create1(int flags) --{ -- if (stack_setup_app_thread() < 0) { -- exit(1); -- } -- -- return lstack_epoll_create1(flags); --} -- --static int rtc_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) --{ -- return lstack_rtc_epoll_ctl(epfd, op, fd, event); --} -- --static int rtc_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) --{ -- return lstack_rtc_epoll_wait(epfd, events, maxevents, timeout); --} -- --static int rtc_poll(struct pollfd *fds, nfds_t nfds, int timeout) --{ -- LSTACK_LOG(ERR, LSTACK, "rtc_poll: rtc currently does not support poll\n"); -- return -1; --} -- --static int rtc_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) --{ -- LSTACK_LOG(ERR, LSTACK, "rtc_select: rtc currently does not support select\n"); -- return -1; --} - - void rtc_api_init(posix_api_t *api) - { -- api->close_fn = rtc_close; -+ api->close_fn = lwip_close; - api->shutdown_fn = lwip_shutdown; -- api->socket_fn = rtc_socket; -+ api->socket_fn = lwip_socket; - api->accept_fn = lwip_accept; - api->accept4_fn = lwip_accept4; - api->bind_fn = lwip_bind; -@@ -104,16 +39,8 @@ void rtc_api_init(posix_api_t *api) - api->writev_fn = lwip_writev; - api->recv_fn = lwip_recv; - api->send_fn = lwip_send; -- api->recvmsg_fn = (ssize_t (*)(int, const struct msghdr *, int))lwip_recvmsg; // TODO: fix unnecessary 'const' in lwipgz_posix_api.h -+ api->recvmsg_fn = lwip_recvmsg; - api->sendmsg_fn = lwip_sendmsg; - api->recvfrom_fn = lwip_recvfrom; - api->sendto_fn = lwip_sendto; -- -- api->epoll_ctl_fn = rtc_epoll_ctl; -- api->epoll_create1_fn = rtc_epoll_create1; -- api->epoll_create_fn = rtc_epoll_create; -- api->epoll_wait_fn = rtc_epoll_wait; -- -- api->poll_fn = rtc_poll; -- api->select_fn = rtc_select; - } -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -index 35439bc..7b8dec2 100644 ---- a/src/lstack/api/lstack_rtw_api.c -+++ b/src/lstack/api/lstack_rtw_api.c -@@ -19,30 +19,31 @@ - #include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" - #include "lstack_lwip.h" --#include "lstack_epoll.h" - #include "lstack_rtw_api.h" -+#include "lstack_epoll.h" -+#include "lstack_wait.h" - - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ - static int stack_broadcast_close(int fd) - { - int ret = 0; -+ struct protocol_stack *stack; - struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } - - do { -- sock = sock->listen_next; -+ if (POSIX_IS_CLOSED(sock)) { -+ break; -+ } -+ stack = get_protocol_stack_by_id(sock->stack_id); - if (stack == NULL || rpc_call_close(&stack->rpc_queue, fd)) { - ret = -1; - } - -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -+ sock = sock->listen_next; - fd = sock->conn->callback_arg.socket; -- stack = get_protocol_stack_by_fd(fd); - } while (1); - - return ret; -@@ -51,23 +52,23 @@ static int stack_broadcast_close(int fd) - static int stack_broadcast_shutdown(int fd, int how) - { - int32_t ret = 0; -+ struct protocol_stack *stack; - struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } - - do { -- sock = sock->listen_next; -+ if (POSIX_IS_CLOSED(sock)) { -+ break; -+ } -+ stack = get_protocol_stack_by_id(sock->stack_id); - if (stack == NULL || rpc_call_shutdown(&stack->rpc_queue, fd, how)) { - ret = -1; - } - -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -+ sock = sock->listen_next; - fd = sock->conn->callback_arg.socket; -- stack = get_protocol_stack_by_fd(fd); - } while (1); - - return ret; -@@ -76,26 +77,29 @@ static int stack_broadcast_shutdown(int fd, int how) - /* choice one stack bind */ - static int stack_single_bind(int fd, const struct sockaddr *name, socklen_t namelen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_bind(&stack->rpc_queue, fd, name, namelen); - } - - /* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ - static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t namelen) - { -- struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -+ struct protocol_stack *cur_stack; - struct protocol_stack *stack = NULL; - int ret, clone_fd; - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || cur_stack == NULL) { -+ if (sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); - GAZELLE_RETURN(EBADF); - } - -+ cur_stack = get_protocol_stack_by_id(sock->stack_id); - ret = rpc_call_bind(&cur_stack->rpc_queue, fd, name, namelen); - if (ret < 0) { - close(fd); -@@ -116,45 +120,30 @@ static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t n - return 0; - } - --static void inline del_accept_in_event(struct lwip_sock *sock) --{ -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- -- if (!NETCONN_IS_ACCEPTIN(sock)) { -- sock->events &= ~EPOLLIN; -- if (sock->events == 0) { -- list_del_node(&sock->event_list); -- } -- } -- -- pthread_spin_unlock(&sock->wakeup->event_list_lock); --} -- - static struct lwip_sock *get_min_accept_sock(int fd) - { -- struct lwip_sock *sock = lwip_get_socket(fd); -+ struct lwip_sock *sock; - struct lwip_sock *min_sock = NULL; - -- while (sock) { -+ for (sock = lwip_get_socket(fd); sock != NULL; sock = sock->listen_next) { - if (!netconn_is_nonblocking(sock->conn)) { -- if (sock->wakeup == NULL) { -- sock->wakeup = poll_construct_wakeup(); -- if (sock->wakeup == NULL) { -- return NULL; -- } -- sock->epoll_events = POLLIN | POLLERR; -+ /* init all sock sk_wait */ -+ if (unlikely(sock->sk_wait == NULL) || sock->sk_wait->type == WAIT_CLOSE) { -+ sock->sk_wait = poll_construct_wait(0); -+ } -+ if (!(sock->sk_wait->type & WAIT_BLOCK)) { -+ sock->sk_wait->type |= WAIT_BLOCK; - } - } -- if (!NETCONN_IS_ACCEPTIN(sock)) { -- sock = sock->listen_next; -+ -+ if (!sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0)) { - continue; - } - -- if (min_sock == NULL || min_sock->stack->conn_num > sock->stack->conn_num) { -+ if (min_sock == NULL || -+ get_protocol_stack_by_id(min_sock->stack_id)->conn_num > get_protocol_stack_by_id(sock->stack_id)->conn_num) { - min_sock = sock; - } -- -- sock = sock->listen_next; - } - - return min_sock; -@@ -171,24 +160,16 @@ static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *add - GAZELLE_RETURN(EBADF); - } - -- if (netconn_is_nonblocking(sock->conn)) { -- min_sock = get_min_accept_sock(fd); -- } else { -- while ((min_sock = get_min_accept_sock(fd)) == NULL) { -- lstack_block_wait(sock->wakeup, 0); -- } -- } -- -- if (min_sock && min_sock->conn) { -- stack = get_protocol_stack_by_fd(min_sock->conn->callback_arg.socket); -- if (stack == NULL) { -- GAZELLE_RETURN(EBADF); -+ min_sock = get_min_accept_sock(fd); -+ if (min_sock == NULL) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ min_sock = get_min_accept_sock(fd); - } -- ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); - } - -- if (min_sock && min_sock->wakeup && min_sock->wakeup->type == WAKEUP_EPOLL) { -- del_accept_in_event(min_sock); -+ if (!POSIX_IS_CLOSED(min_sock)) { -+ stack = get_protocol_stack_by_id(min_sock->stack_id); -+ ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); - } - - if (ret < 0) { -@@ -205,10 +186,12 @@ static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addr - /* choice one stack listen */ - static int stack_single_listen(int fd, int backlog) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_listen(&stack->rpc_queue, fd, backlog); - } - -@@ -221,18 +204,19 @@ static int stack_broadcast_listen(int fd, int backlog) - struct sockaddr_in6 in6; - } sockaddr_t; - -- struct protocol_stack *cur_stack = get_protocol_stack_by_fd(fd); -+ struct protocol_stack *cur_stack; - struct protocol_stack *stack = NULL; - sockaddr_t addr; - socklen_t addr_len = sizeof(addr); - int ret, clone_fd; - - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || cur_stack == NULL) { -+ if (sock == NULL) { - LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); - GAZELLE_RETURN(EBADF); - } - -+ cur_stack = get_protocol_stack_by_id(sock->stack_id); - ret = rpc_call_getsockname(&cur_stack->rpc_queue, fd, (struct sockaddr *)&addr, &addr_len); - if (ret != 0) { - return ret; -@@ -311,46 +295,56 @@ static int rtw_listen(int s, int backlog) - - static int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_connect(&stack->rpc_queue, s, name, namelen); - } - - static int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_setsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - - static int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_getsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); - } - - static int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_getpeername(&stack->rpc_queue, s, name, namelen); - } - - static int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) - { -- struct protocol_stack *stack = get_protocol_stack_by_fd(s); -- if (stack == NULL) { -+ struct protocol_stack *stack; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock == NULL) { - GAZELLE_RETURN(EBADF); - } -+ stack = get_protocol_stack_by_id(sock->stack_id); - return rpc_call_getsockname(&stack->rpc_queue, s, name, namelen); - } - -@@ -467,55 +461,16 @@ static ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, - return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); - } - --static int rtw_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) --{ -- return lstack_rtw_epoll_wait(epfd, events, maxevents, timeout); --} -- --static int rtw_poll(struct pollfd *fds, nfds_t nfds, int timeout) --{ -- return lstack_poll(fds, nfds, timeout); --} -- --static int rtw_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) --{ -- return lstack_select(nfds, readfds, writefds, exceptfds, timeout); --} -- - static int rtw_close(int s) - { -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock && sock->wakeup && sock->wakeup->epollfd == s) { -- return lstack_epoll_close(s); -- } - return stack_broadcast_close(s); - } - - static int rtw_shutdown(int fd, int how) - { -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock && sock->wakeup && sock->wakeup->epollfd == fd) { -- GAZELLE_RETURN(ENOTSOCK); -- } -- - return stack_broadcast_shutdown(fd, how); - } - --static int rtw_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) --{ -- return lstack_rtw_epoll_ctl(epfd, op, fd, event); --} -- --static int rtw_epoll_create1(int flags) --{ -- return lstack_epoll_create1(flags); --} -- --static int rtw_epoll_create(int flags) --{ -- return lstack_epoll_create(flags); --} -- - void rtw_api_init(posix_api_t *api) - { - api->close_fn = rtw_close; -@@ -538,16 +493,8 @@ void rtw_api_init(posix_api_t *api) - api->writev_fn = rtw_writev; - api->recv_fn = rtw_recv; - api->send_fn = rtw_send; -- api->recvmsg_fn = (ssize_t (*)(int, const struct msghdr *, int))rtw_recvmsg; // TODO: fix unnecessary 'const' in lwipgz_posix_api.h -+ api->recvmsg_fn = rtw_recvmsg; - api->sendmsg_fn = rtw_sendmsg; - api->recvfrom_fn = rtw_recvfrom; - api->sendto_fn = rtw_sendto; -- -- api->epoll_ctl_fn = rtw_epoll_ctl; -- api->epoll_create1_fn = rtw_epoll_create1; -- api->epoll_create_fn = rtw_epoll_create; -- api->epoll_wait_fn = rtw_epoll_wait; -- -- api->poll_fn = rtw_poll; -- api->select_fn = rtw_select; - } -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8a88c47..5869d6b 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -27,6 +27,7 @@ - #include "lstack_lwip.h" - #include "lstack_preload.h" - #include "lstack_unistd.h" -+#include "lstack_epoll.h" - #include "lstack_rtc_api.h" - #include "lstack_rtw_api.h" - #include "lstack_dummy_api.h" -@@ -35,8 +36,8 @@ - #define SOL_XDP 283 /* same as define in bits/socket.h */ - #endif - --static posix_api_t g_wrap_api_value; --static posix_api_t *g_wrap_api; -+static posix_api_t g_wrap_api_value = {0}; -+static posix_api_t *g_wrap_api = NULL; - - void wrap_api_init(void) - { -@@ -50,6 +51,8 @@ void wrap_api_init(void) - } else { - rtw_api_init(g_wrap_api); - } -+ -+ epoll_api_init(g_wrap_api); - } - - void wrap_api_exit(void) -@@ -57,50 +60,6 @@ void wrap_api_exit(void) - dummy_api_init(g_wrap_api); - } - --static inline int32_t do_epoll_create1(int32_t flags) --{ -- if (select_posix_path() == POSIX_KERNEL) { -- return posix_api->epoll_create1_fn(flags); -- } -- -- return g_wrap_api->epoll_create1_fn(flags); --} -- --static inline int32_t do_epoll_create(int32_t size) --{ -- if (select_posix_path() == POSIX_KERNEL) { -- return posix_api->epoll_create_fn(size); -- } -- -- return g_wrap_api->epoll_create_fn(size); --} -- --static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event) --{ -- if (select_posix_path() == POSIX_KERNEL) { -- return posix_api->epoll_ctl_fn(epfd, op, fd, event); -- } -- -- return g_wrap_api->epoll_ctl_fn(epfd, op, fd, event); --} -- --static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout) --{ -- if (select_posix_path() == POSIX_KERNEL) { -- return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -- } -- -- if (epfd < 0) { -- GAZELLE_RETURN(EBADF); -- } -- -- if ((events == NULL) || (timeout < -1) || (maxevents <= 0)) { -- GAZELLE_RETURN(EINVAL); -- } -- -- return g_wrap_api->epoll_wait_fn(epfd, events, maxevents, timeout); --} -- - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL) { -@@ -515,9 +474,14 @@ static bool unsupport_optname(int32_t level, int32_t optname) - static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen) - { - #define SO_NUMA_ID 0x100c -- if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP && !unsupport_optname(level, optname)) { -+ const struct protocol_stack *stack; -+ struct lwip_sock *sock; -+ -+ sock = lwip_get_socket(s); -+ if (select_sock_posix_path(sock) == POSIX_LWIP && !unsupport_optname(level, optname)) { - if (level == IPPROTO_IP && optname == SO_NUMA_ID) { -- return lwip_get_socket(s)->stack->numa_id; -+ stack = get_protocol_stack_by_id(sock->stack_id); -+ return stack->numa_id; - } - return g_wrap_api->getsockopt_fn(s, level, optname, optval, optlen); - } -@@ -551,6 +515,12 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - return posix_api->socket_fn(domain, type, protocol); - } - -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ if (stack_setup_app_thread() != 0) { -+ LSTACK_EXIT(1, "stack_setup_app_thread failed\n"); -+ } -+ } -+ - ret = g_wrap_api->socket_fn(domain, type, protocol); - if (ret >= 0) { - struct lwip_sock *sock = lwip_get_socket(ret); -@@ -677,14 +647,20 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - - static inline int32_t do_close(int fd) - { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ - /* Can not use select_sock_posix_path() ! - * When fd created by lwip_stocket() set as POSIX_KERNEL, - * lwip_close() is still required. - */ - if (select_posix_path() == POSIX_KERNEL || -- POSIX_IS_CLOSED(lwip_get_socket(fd))) { -+ POSIX_IS_CLOSED(sock)) { - return posix_api->close_fn(fd); - } -+ -+ if (select_sock_posix_path(sock) == POSIX_EPOLL) { -+ return lstack_epoll_close(fd); -+ } - return g_wrap_api->close_fn(fd); - } - -@@ -701,9 +677,56 @@ static int32_t do_shutdown(int fd, int how) - return g_wrap_api->shutdown_fn(fd, how); - } - -+ -+static inline int do_epoll_create1(int flags) -+{ -+ int epfd; -+ -+ if (select_posix_path() == POSIX_KERNEL) { -+ return posix_api->epoll_create1_fn(flags); -+ } -+ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ if (stack_setup_app_thread() != 0) { -+ LSTACK_EXIT(1, "stack_setup_app_thread failed\n"); -+ } -+ } -+ -+ epfd = g_wrap_api->epoll_create1_fn(flags); -+ if (epfd > 0) { -+ POSIX_SET_TYPE(lwip_get_socket(epfd), POSIX_EPOLL); -+ } -+ return epfd; -+} -+ -+static inline int do_epoll_create(int size) -+{ -+ /* Since Linux 2.6.8, the size argument is ignored, -+ * but must be greater than zero. */ -+ return size <= 0 ? -1 : do_epoll_create1(0); -+} -+ -+static inline int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event) -+{ -+ if (select_sock_posix_path(lwip_get_socket(epfd)) == POSIX_KERNEL) { -+ return posix_api->epoll_ctl_fn(epfd, op, fd, event); -+ } -+ -+ return g_wrap_api->epoll_ctl_fn(epfd, op, fd, event); -+} -+ -+static inline int do_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout) -+{ -+ if (select_sock_posix_path(lwip_get_socket(epfd)) == POSIX_KERNEL) { -+ return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout); -+ } -+ -+ return g_wrap_api->epoll_wait_fn(epfd, events, maxevents, timeout); -+} -+ - static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - { -- if ((select_posix_path() == POSIX_KERNEL) || fds == NULL || nfds == 0) { -+ if ((select_posix_path() == POSIX_KERNEL)) { - return posix_api->poll_fn(fds, nfds, timeout); - } - -@@ -712,18 +735,21 @@ static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout) - - static int32_t do_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) - { -- int32_t ready; - int32_t timeout; - -- if (fds == NULL || tmo_p == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- - // s * 1000 and ns / 1000000 -> ms - timeout = (tmo_p == NULL) ? -1 : (tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000); -- ready = do_poll(fds, nfds, timeout); - -- return ready; -+ return do_poll(fds, nfds, timeout); -+} -+ -+static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -+{ -+ if (select_posix_path() == POSIX_KERNEL) { -+ return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -+ } -+ -+ return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); - } - - static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct sigaction *oldact) -@@ -738,19 +764,6 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct - return lstack_sigaction(signum, act, oldact); - } - --static int32_t do_select(int32_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) --{ -- /* while input args are invalid, param timeout will steal be executed in kernel */ -- if (nfds <= 0 || !(readfds || writefds || exceptfds)) { -- return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -- } -- -- if (select_posix_path() == POSIX_KERNEL) { -- return posix_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); -- } -- -- return g_wrap_api->select_fn(nfds, readfds, writefds, exceptfds, timeout); --} - - #define POSIX_VA_PARAM(fd, cmd, type, lwip_fn, kernel_fn) \ - do { \ -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -index d0e51b2..047dfdf 100644 ---- a/src/lstack/core/lstack_lwip.c -+++ b/src/lstack/core/lstack_lwip.c -@@ -78,14 +78,12 @@ static void reset_sock_data(struct lwip_sock *sock) - } - - sock->type = 0; -- sock->stack = NULL; -- sock->wakeup = NULL; -+ sock->stack_id = 0; -+ sock->affinity_numa = 0; -+ sock->sk_wait = NULL; - sock->listen_next = NULL; -- sock->epoll_events = 0; -- sock->events = 0; - sock->call_num = 0; - sock->remain_len = 0; -- sock->already_bind_numa = 0; - - if (sock->recv_lastdata && sock->recv_lastdata != (void *)&fin_packet) { - pbuf_free(sock->recv_lastdata); -@@ -176,12 +174,14 @@ int do_lwip_init_sock(int32_t fd) - return -1; - } - -+ sock->stack_id = stack->stack_idx; -+ sock->sk_wait = NULL; -+ if (sock_event_init(&sock->sk_event) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "sock_event_init failed\n"); -+ return -1; -+ } -+ - if (get_global_cfg_params()->stack_mode_rtc) { -- sock->stack = stack; -- sock->epoll_events = 0; -- sock->events = 0; -- sock->wakeup = NULL; -- list_init_node(&sock->event_list); - return 0; - } - -@@ -207,31 +207,25 @@ int do_lwip_init_sock(int32_t fd) - } - (void)replenish_send_idlembuf(stack, sock); - -- sock->stack = stack; -- - list_init_node(&sock->recv_list); -- list_init_node(&sock->event_list); - return 0; - } - - void do_lwip_clean_sock(int fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL || sock->stack == NULL) { -+ if (POSIX_IS_CLOSED(sock)) { - return; - } - -- if (sock->wakeup && sock->wakeup->type == WAKEUP_EPOLL) { -- pthread_spin_lock(&sock->wakeup->event_list_lock); -- list_del_node(&sock->event_list); -- pthread_spin_unlock(&sock->wakeup->event_list_lock); -- } -- -- sock->stack->conn_num--; -+ sock_event_free(&sock->sk_event, sock->sk_wait); -+ sock->sk_wait = NULL; - - reset_sock_data(sock); - - list_del_node(&sock->recv_list); -+ -+ get_protocol_stack_by_id(sock->stack_id)->conn_num--; - } - - void do_lwip_free_pbuf(struct pbuf *pbuf) -@@ -310,7 +304,8 @@ struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t rema - } - - for (int i = 0; get_protocol_stack_group()->latency_start && i < actual_count; i++) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_LWIP, 0); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_LWIP, 0); - } - - return pbufs[0]; -@@ -334,7 +329,8 @@ struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t rema - } - - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP, 0); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP, 0); - } - - sock->send_pre_del = pbuf; -@@ -354,8 +350,9 @@ struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t rema - - void do_lwip_get_from_sendring_over(struct lwip_sock *sock) - { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ stack->stats.write_lwip_cnt++; - sock->send_pre_del = NULL; -- sock->stack->stats.write_lwip_cnt++; - } - - static ssize_t do_app_write(struct lwip_sock *sock, struct pbuf *pbufs[], void *buf, size_t len, uint32_t write_num) -@@ -425,8 +422,9 @@ static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t l - } - - for (int i = 0; get_protocol_stack_group()->latency_start && i < write_num; i++) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - if (pbufs[i] != NULL) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_INTO_RING, 0); - } - } - -@@ -510,7 +508,6 @@ static ssize_t do_lwip_udp_fill_sendring(struct lwip_sock *sock, const void *buf - 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"); -@@ -537,14 +534,7 @@ static ssize_t do_lwip_udp_fill_sendring(struct lwip_sock *sock, const void *buf - - 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; -- } -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - - return send_len; - } -@@ -561,7 +551,8 @@ static ssize_t __do_lwip_tcp_fill_sendring(struct lwip_sock *sock, const void *b - - /* merge data into last pbuf */ - if (sock->remain_len) { -- sock->stack->stats.sock_tx_merge++; -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ stack->stats.sock_tx_merge++; - send_len = merge_data_lastpbuf(sock, (char *)buf, len); - if (send_len >= len) { - send_len = len; -@@ -571,7 +562,6 @@ static ssize_t __do_lwip_tcp_fill_sendring(struct lwip_sock *sock, const void *b - - uint32_t write_num = (len - send_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; - - while (!netconn_is_nonblocking(sock->conn) && (write_avail < write_num)) { - if (sock->errevent > 0) { -@@ -597,14 +587,7 @@ static ssize_t __do_lwip_tcp_fill_sendring(struct lwip_sock *sock, const void *b - } - send_len += app_buff_write(sock, (char *)buf + send_len, len - send_len, write_num, addr, addrlen); - -- if (wakeup) { -- wakeup->stat.app_write_cnt += write_num; -- } -- -- if (wakeup && wakeup->type == WAKEUP_EPOLL && (sock->events & EPOLLOUT) -- && !NETCONN_IS_OUTIDLE(sock)) { -- del_sock_event(sock, EPOLLOUT); -- } -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - - END: - if (send_len == 0) { -@@ -644,9 +627,7 @@ bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock * - - replenish_again = replenish_send_idlembuf(stack, sock); - -- if (NETCONN_IS_OUTIDLE(sock)) { -- add_sock_event(sock, EPOLLOUT); -- } -+ API_EVENT(sock->conn, NETCONN_EVT_SENDPLUS, 0); - - return replenish_again; - } -@@ -726,13 +707,14 @@ ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apifl - LSTACK_LOG(ERR, LSTACK, "Code shouldn't get here!\n"); - } - -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) { - if (pbufs[i] != NULL) { -- calculate_lstack_latency(&sock->stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP, 0); -+ calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP, 0); - } - } -+ stack->stats.read_lwip_cnt += read_count; - -- sock->stack->stats.read_lwip_cnt += read_count; - return recv_len; - } - -@@ -790,7 +772,8 @@ static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int - { - // 2: call_num >= 2, don't need add new rpc send - if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) < 2) { -- while (rpc_call_tcp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ while (rpc_call_tcp_send(&stack->rpc_queue, fd, len, flags) < 0) { - usleep(1000); // 1000: wait 1ms to exec again - } - __sync_fetch_and_add(&sock->call_num, 1); -@@ -800,7 +783,8 @@ static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int - static inline void notice_stack_udp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) - { - __sync_fetch_and_add(&sock->call_num, 1); -- while (rpc_call_udp_send(&sock->stack->rpc_queue, fd, len, flags) < 0) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ while (rpc_call_udp_send(&stack->rpc_queue, fd, len, flags) < 0) { - usleep(1000); // 1000: wait 1ms to exec again - } - } -@@ -828,9 +812,9 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - } - - sock = lwip_get_socket(fd); -- if (unlikely(sock->already_bind_numa == 0 && sock->stack)) { -- thread_bind_stack(sock->stack); -- sock->already_bind_numa = 1; -+ if (unlikely(sock->affinity_numa == 0)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = 1; - } - - #if GAZELLE_SAME_NODE -@@ -838,7 +822,7 @@ ssize_t do_lwip_send_to_stack(int32_t fd, const void *buf, size_t len, int32_t f - return gazelle_same_node_ring_send(sock, buf, len, flags); - } - #endif /* GAZELLE_SAME_NODE */ -- if (sock->errevent > 0 || sock->stack == NULL) { -+ if (sock->errevent > 0) { - GAZELLE_RETURN(ENOTCONN); - } - -@@ -920,9 +904,10 @@ static struct pbuf *pbuf_free_partial(struct pbuf *pbuf, uint16_t free_len) - - static bool recv_break_for_err(struct lwip_sock *sock) - { -- bool break_wait = (sock->errevent > 0) && (!NETCONN_IS_DATAIN(sock)); - errno = err_to_errno(netconn_err(sock->conn)); -- return break_wait; -+ unsigned pending = sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0) | -+ sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0); -+ return pending; - } - - /* -@@ -931,8 +916,7 @@ static bool recv_break_for_err(struct lwip_sock *sock) - */ - static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf **pbuf) - { -- int32_t expect = 1; // only get one pbuf -- int ret = 0; -+ int32_t expect; - uint64_t time_stamp = sys_now_us(); - - if (sock->recv_lastdata != NULL) { -@@ -941,45 +925,24 @@ static int recv_ring_get_one(struct lwip_sock *sock, bool noblock, struct pbuf * - return 0; - } - -- if (noblock) { -- if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) != expect) { -+ expect = gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1); -+ if (expect == 0) { -+ if (netconn_is_nonblocking(sock->conn)) { - GAZELLE_RETURN(EAGAIN); - } -- goto END; -- } -- -- if (sock->recv_block == NULL) { -- sock->recv_block = poll_construct_wakeup(); -- if (sock->recv_block == NULL) { -- GAZELLE_RETURN(ENOMEM); -- } -- sock->recv_block->type = WAKEUP_BLOCK; -- } -- -- do { -- __atomic_store_n(&sock->recv_block->in_wait, true, __ATOMIC_RELEASE); -- if (gazelle_ring_read(sock->recv_ring, (void **)pbuf, expect) == expect) { -- break; -- } -- if (recv_break_for_err(sock)) { -- sock->recv_block = NULL; -- return -1; -- } -- ret = lstack_block_wait(sock->recv_block, sock->conn->recv_timeout); -- if (ret != 0) { -- if (errno == ETIMEDOUT) { -- errno = EAGAIN; -+ sock_event_wait(sock, true); -+ expect = gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1); -+ if (expect == 0) { -+ if (recv_break_for_err(sock)) { -+ return -1; - } -- sock->recv_block = NULL; -- return ret; -+ GAZELLE_RETURN(EAGAIN); - } -- } while (1); -- __atomic_store_n(&sock->recv_block->in_wait, false, __ATOMIC_RELEASE); -- sock->recv_block = NULL; -+ } - --END: - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, *pbuf, GAZELLE_LATENCY_READ_APP_CALL, time_stamp); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_lstack_latency(&stack->latency, *pbuf, GAZELLE_LATENCY_READ_APP_CALL, time_stamp); - } - - return 0; -@@ -1044,12 +1007,9 @@ static ssize_t recv_ring_tcp_read(struct lwip_sock *sock, void *buf, size_t len, - if (pbuf->tot_len > copy_len) { - sock->recv_lastdata = pbuf_free_partial(pbuf, copy_len); - } else { -- if (sock->wakeup) { -- sock->wakeup->stat.app_read_cnt += 1; -- } -- - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); - } - - gazelle_ring_read_over(sock->recv_ring); -@@ -1088,15 +1048,12 @@ static ssize_t recv_ring_udp_read(struct lwip_sock *sock, void *buf, size_t len, - lwip_sock_make_addr(sock->conn, &(pbuf->addr), pbuf->port, addr, addrlen); - } - -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - if (copy_len < pbuf->tot_len) { -- sock->stack->stats.sock_rx_drop++; -- } -- -- if (sock->wakeup) { -- sock->wakeup->stat.app_read_cnt++; -+ stack->stats.sock_rx_drop++; - } - if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); - } - - return copy_len; -@@ -1113,9 +1070,9 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - return -1; - } - -- if (unlikely(sock->already_bind_numa == 0 && sock->stack)) { -- thread_bind_stack(sock->stack); -- sock->already_bind_numa = 1; -+ if (unlikely(sock->affinity_numa == 0)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = 1; - } - - #if GAZELLE_SAME_NODE -@@ -1129,16 +1086,9 @@ ssize_t do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags - recvd = recv_ring_tcp_read(sock, buf, len, noblock); - } - -- /* 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); -- } -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, recvd); - - if (recvd < 0) { -- if (sock->wakeup) { -- sock->wakeup->stat.read_null++; -- } - return -1; - } - return recvd; -@@ -1148,8 +1098,9 @@ void do_lwip_add_recvlist(int32_t fd) - { - struct lwip_sock *sock = lwip_get_socket(fd); - -- if (sock && sock->stack && list_node_null(&sock->recv_list)) { -- list_add_node(&sock->recv_list, &sock->stack->recv_list); -+ if (sock && list_node_null(&sock->recv_list)) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ list_add_node(&sock->recv_list, &stack->recv_list); - } - } - -@@ -1176,7 +1127,8 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - } - - if (get_protocol_stack_group()->latency_start) { -- calculate_sock_latency(&sock->stack->latency, sock, GAZELLE_LATENCY_RECVMBOX_READY); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_RECVMBOX_READY); - } - - ssize_t len = 0; -@@ -1186,36 +1138,33 @@ void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) - len = lwip_recv(sock->conn->callback_arg.socket, NULL, 0, 0); - } - if (len < 0 && errno != EAGAIN) { -- sock->errevent = 1; -- add_sock_event(sock, EPOLLERR); -+ API_EVENT(sock->conn, NETCONN_EVT_ERROR, 0); - /* = 0: fin */ - } else if (len >= 0) { -- add_sock_event(sock, EPOLLIN); -+ API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); - } - } - } - --void do_lwip_connected_callback(struct netconn *conn) -+void do_lwip_connected_callback(int fd) - { -- if (conn == NULL) { -- return; -- } -- -- int32_t fd = conn->callback_arg.socket; - struct lwip_sock *sock = lwip_get_socket(fd); - if (POSIX_IS_CLOSED(sock)) { - return; - } - -- if (sock->wakeup != NULL && sock->wakeup->epollfd > 0) { -- posix_api->epoll_ctl_fn(sock->wakeup->epollfd, EPOLL_CTL_DEL, fd, NULL); -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ /* delete kernel event */ -+ if (sock->sk_wait != NULL) { -+ posix_api->epoll_ctl_fn(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL); -+ } -+ /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -+ posix_api->shutdown_fn(fd, SHUT_RDWR); - } - - POSIX_SET_TYPE(sock, POSIX_LWIP); - -- posix_api->shutdown_fn(fd, SHUT_RDWR); -- -- add_sock_event(sock, EPOLLOUT); -+ API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); - } - - static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const struct tcp_pcb *pcb) -@@ -1249,9 +1198,9 @@ static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const s - conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); - conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; - conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); -- conn->events = sock->events; -- conn->epoll_events = sock->epoll_events; -- conn->eventlist = !list_node_null(&sock->event_list); -+ conn->events = sock->sk_event.pending; -+ conn->epoll_events = sock->sk_event.events; -+ conn->eventlist = !list_node_null(&sock->sk_event.event_node); - } - } - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 3bb1eeb..1e7df33 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -29,7 +29,7 @@ - #include "lstack_ethdev.h" - #include "lstack_lwip.h" - #include "lstack_control_plane.h" --#include "lstack_epoll.h" -+#include "lstack_wait.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" - #include "lstack_interrupt.h" -@@ -39,9 +39,7 @@ - #include - #endif - --#define KERNEL_EVENT_10us 10 -- --static PER_THREAD struct protocol_stack *g_stack_p = NULL; -+PER_THREAD struct protocol_stack *g_stack_p = NULL; - static struct protocol_stack_group g_stack_group = {0}; - - typedef void *(*stack_thread_func)(void *arg); -@@ -81,19 +79,15 @@ struct protocol_stack_group *get_protocol_stack_group(void) - return &g_stack_group; - } - --struct protocol_stack *get_protocol_stack(void) -+struct protocol_stack *get_protocol_stack_by_id(int stack_id) - { -- return g_stack_p; --} -+ struct protocol_stack_group *stack_group; - --struct protocol_stack *get_protocol_stack_by_fd(int fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -+ if (stack_id < 0) { - return NULL; - } -- -- return sock->stack; -+ stack_group = get_protocol_stack_group(); -+ return stack_group->stacks[stack_id]; - } - - struct protocol_stack *get_bind_protocol_stack(void) -@@ -153,10 +147,11 @@ int get_min_conn_stack(struct protocol_stack_group *stack_group) - } - #endif /* GAZELLE_TCP_REUSE_IPPORT */ - --void bind_to_stack_numa(struct protocol_stack *stack) -+void bind_to_stack_numa(int stack_id) - { -- int32_t ret; -+ int ret; - pthread_t tid = pthread_self(); -+ struct protocol_stack *stack = get_protocol_stack_by_id(stack_id); - - if (get_global_cfg_params()->stack_num > 0) { - numa_run_on_node(stack->numa_id); -@@ -170,7 +165,7 @@ void bind_to_stack_numa(struct protocol_stack *stack) - } - } - --void thread_bind_stack(struct protocol_stack *stack) -+void thread_bind_stack(int stack_id) - { - static PER_THREAD uint16_t stack_sock_num[GAZELLE_MAX_STACK_NUM] = {0}; - static PER_THREAD uint16_t max_sock_stack = 0; -@@ -179,10 +174,10 @@ void thread_bind_stack(struct protocol_stack *stack) - return; - } - -- stack_sock_num[stack->stack_idx]++; -- if (stack_sock_num[stack->stack_idx] > max_sock_stack) { -- max_sock_stack = stack_sock_num[stack->stack_idx]; -- bind_to_stack_numa(stack); -+ stack_sock_num[stack_id]++; -+ if (stack_sock_num[stack_id] > max_sock_stack) { -+ max_sock_stack = stack_sock_num[stack_id]; -+ bind_to_stack_numa(stack_id); - } - } - -@@ -308,11 +303,6 @@ void low_power_idling(struct protocol_stack *stack) - } - } - --struct thread_params { -- uint16_t queue_id; -- uint16_t idx; --}; -- - static int32_t create_thread(void *arg, char *thread_name, stack_thread_func func) - { - /* thread may run slow, if arg is temp var maybe have relese */ -@@ -347,48 +337,6 @@ static int32_t create_thread(void *arg, char *thread_name, stack_thread_func fun - return 0; - } - --static void wakeup_kernel_event(struct protocol_stack *stack) --{ -- if (stack->kernel_event_num <= 0) { -- return; -- } -- -- for (int32_t i = 0; i < stack->kernel_event_num; i++) { -- struct wakeup_poll *wakeup = stack->kernel_events[i].data.ptr; -- if (wakeup->type == WAKEUP_CLOSE) { -- continue; -- } -- -- __atomic_store_n(&wakeup->have_kernel_event, true, __ATOMIC_RELEASE); -- lstack_block_wakeup(wakeup); -- } -- -- return; --} -- --static void* gazelle_kernelevent_thread(void *arg) --{ -- struct thread_params *t_params = (struct thread_params*) arg; -- uint16_t idx = t_params->idx; -- struct protocol_stack *stack = get_protocol_stack_group()->stacks[idx]; -- -- bind_to_stack_numa(stack); -- -- LSTACK_LOG(INFO, LSTACK, "kernelevent_%02hu start\n", idx); -- free(arg); -- sem_post(&g_stack_group.sem_stack_setup); -- -- for (;;) { -- stack->kernel_event_num = posix_api->epoll_wait_fn(stack->epollfd, stack->kernel_events, KERNEL_EPOLL_MAX, -1); -- if (stack->kernel_event_num > 0) { -- wakeup_kernel_event(stack); -- usleep(KERNEL_EVENT_10us); -- } -- } -- -- return NULL; --} -- - static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - { - struct thread_params *t_params = (struct thread_params*) arg; -@@ -403,16 +351,10 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - - list_init_head(&stack->recv_list); - list_init_head(&stack->same_node_recv_list); -- list_init_head(&stack->wakeup_list); - - stack_group->stacks[t_params->idx] = stack; - set_stack_idx(t_params->idx); - -- stack->epollfd = posix_api->epoll_create_fn(GAZELLE_LSTACK_MAX_CONN); -- if (stack->epollfd < 0) { -- LSTACK_LOG(ERR, LSTACK, "kernel epoll_create failed\n"); -- return -1; -- } - - if (cfg_params->stack_num > 0) { - stack->numa_id = cfg_params->numa_id; -@@ -453,7 +395,7 @@ static int32_t create_affiliate_thread(void *arg) - return -1; - } - memcpy_s(params, sizeof(*params), arg, sizeof(struct thread_params)); -- if (create_thread((void *)params, "gazellekernel", gazelle_kernelevent_thread) != 0) { -+ if (create_thread((void *)params, "gazellekernel", kernel_wait_thread) != 0) { - LSTACK_LOG(ERR, LSTACK, "gazellekernel errno=%d\n", errno); - return -1; - } -@@ -551,7 +493,9 @@ int stack_polling(unsigned wakeup_tick) - do_lwip_read_recvlist(stack, read_connect_number); - - if ((wakeup_tick & 0xf) == 0) { -- wakeup_stack_epoll(stack); -+#if SOCK_WAIT_BATCH_NOTIFY -+ stack->stats.wakeup_events += lwip_wait_foreach_notify(stack->stack_idx); -+#endif /* SOCK_WAIT_BATCH_NOTIFY */ - if (get_global_cfg_params()->send_cache_mode) { - tx_cache_send(stack->queue_id); - } -@@ -595,7 +539,7 @@ static bool stack_local_event_get(uint16_t stack_id) - if (!lockless_queue_empty(&stack->dfx_rpc_queue.queue) || - !lockless_queue_empty(&stack->rpc_queue.queue) || - !list_head_empty(&stack->recv_list) || -- !list_head_empty(&stack->wakeup_list) || -+ !lwip_wait_notify_empty(stack_id) || - tx_cache_count(stack->queue_id)) { - return true; - } -@@ -681,8 +625,6 @@ int stack_group_init(void) - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - stack_group->stack_num = 0; - -- list_init_head(&stack_group->poll_list); -- pthread_spin_init(&stack_group->poll_list_lock, PTHREAD_PROCESS_PRIVATE); - pthread_spin_init(&stack_group->socket_lock, PTHREAD_PROCESS_PRIVATE); - if (sem_init(&stack_group->sem_stack_setup, 0, 0) < 0) { - LSTACK_LOG(ERR, LSTACK, "sem_init failed errno=%d\n", errno); -@@ -783,24 +725,22 @@ OUT2: - return -1; - } - --static void stack_all_fds_close(struct protocol_stack *stack) -+ -+void stack_exit(void) - { -+ struct protocol_stack *stack = get_protocol_stack(); -+ if (stack == NULL) -+ return; -+ -+ /* close all fd */ - for (int i = 3; i < GAZELLE_MAX_CLIENTS + GAZELLE_RESERVED_CLIENTS; i++) { - struct lwip_sock *sock = lwip_get_socket(i); -- if (!POSIX_IS_CLOSED(sock) && sock->stack == stack) { -+ if (!POSIX_IS_CLOSED(sock) && sock->stack_id == stack->stack_idx) { - lwip_close(i); - } - } - } - --void stack_exit(void) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- if (stack != NULL) { -- stack_all_fds_close(stack); -- } --} -- - void stack_wait(void) - { - struct protocol_stack *stack = get_protocol_stack(); -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index b1eb60e..dc9c931 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -65,8 +65,9 @@ void time_stamp_record(int fd, struct pbuf *pbuf) - { - struct lwip_sock *sock = lwip_get_socket(fd); - -- if (get_protocol_stack_group()->latency_start && sock && sock->stack && pbuf) { -- calculate_lstack_latency(&sock->stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); -+ if (get_protocol_stack_group()->latency_start && sock && pbuf) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); - time_stamp_into_recvmbox(sock); - } - } -@@ -209,29 +210,6 @@ static void set_latency_start_flag(bool start) - } - } - --static void get_wakeup_stat(struct protocol_stack_group *stack_group, struct protocol_stack *stack, -- struct gazelle_wakeup_stat *stat) --{ -- struct list_node *node, *temp; -- -- pthread_spin_lock(&stack_group->poll_list_lock); -- -- list_for_each_node(node, temp, &stack_group->poll_list) { -- struct wakeup_poll *wakeup = list_entry(node, struct wakeup_poll, poll_list); -- -- if (wakeup->bind_stack == stack) { -- stat->kernel_events += wakeup->stat.kernel_events; -- stat->app_events += wakeup->stat.app_events; -- stat->read_null += wakeup->stat.read_null; -- stat->app_write_cnt += wakeup->stat.app_write_cnt; -- stat->app_write_rpc += wakeup->stat.app_write_rpc; -- stat->app_read_cnt += wakeup->stat.app_read_cnt; -- } -- } -- -- pthread_spin_unlock(&stack_group->poll_list_lock); --} -- - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info) - { - struct cfg_params *cfg = get_global_cfg_params(); -@@ -244,8 +222,6 @@ void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_inf - - static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_stack *stack) - { -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- - dfx->loglevel = rte_log_get_level(RTE_LOGTYPE_LSTACK); - - lstack_get_low_power_info(&dfx->low_power_info); -@@ -257,7 +233,7 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - return; - } - -- get_wakeup_stat(stack_group, stack, &dfx->data.pkts.wakeup_stat); -+ sock_wait_group_stat(stack->stack_idx, &dfx->data.pkts.wakeup_stat); - - dfx->data.pkts.call_alloc_fail = rpc_stats_get()->call_alloc_fail; - -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 26ae501..a831d3b 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -242,8 +242,8 @@ static void callback_socket(struct rpc_msg *msg) - static void callback_close(struct rpc_msg *msg) - { - int fd = msg->args[MSG_ARG_0].i; -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = lwip_get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -@@ -261,8 +261,8 @@ static void callback_shutdown(struct rpc_msg *msg) - { - int fd = msg->args[MSG_ARG_0].i; - int how = msg->args[MSG_ARG_1].i; -- struct protocol_stack *stack = get_protocol_stack_by_fd(fd); - struct lwip_sock *sock = lwip_get_socket(fd); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - - if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { - msg->recall_flag = 1; -@@ -365,14 +365,14 @@ static void callback_accept(struct rpc_msg *msg) - } - - struct lwip_sock *sock = lwip_get_socket(accept_fd); -- if (sock == NULL || sock->stack == NULL) { -+ if (sock == NULL) { - lwip_close(accept_fd); - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; - } - - msg->result = accept_fd; -- sock->stack->conn_num++; -+ stack->conn_num++; - if (rte_ring_count(sock->conn->recvmbox->ring)) { - do_lwip_add_recvlist(accept_fd); - } -@@ -751,27 +751,6 @@ int rpc_call_recvlistcnt(rpc_queue *queue) - return rpc_sync_call(queue, msg); - } - --static void callback_clean_epoll(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct wakeup_poll *wakeup = (struct wakeup_poll *)msg->args[MSG_ARG_0].p; -- -- list_del_node(&wakeup->wakeup_list[stack->stack_idx]); --} -- --int rpc_call_clean_epoll(rpc_queue *queue, void *wakeup) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_clean_epoll); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].p = wakeup; -- -- rpc_sync_call(queue, msg); -- return 0; --} -- - static void callback_arp(struct rpc_msg *msg) - { - struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index c67df93..6334f5e 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -26,7 +26,7 @@ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "same_node.h" --#include "mbox_ring.h" -+#include "lstack_lwip.h" - - #define KERNEL_EVENT_WAIT_US 10 - #define LWIP_EVENT_WAIT_US 10 -@@ -340,34 +340,26 @@ void sock_wait_kernel_free(struct sock_wait *sk_wait) - static inline bool NETCONN_NEED_ACCEPT(const struct lwip_sock *sock) - { - if (sys_mbox_valid(&sock->conn->acceptmbox)) { -- const struct mbox_ring *mr = &sock->conn->acceptmbox->mring; -- return mr->ops->count(mr) > 0; -+ return !sys_mbox_empty(sock->conn->acceptmbox); - } - return false; - } - - static inline bool NETCONN_NEED_RECV(const struct lwip_sock *sock) - { -- if (sock->lastdata.pbuf != NULL) -+ if (sock->recv_lastdata != NULL) -+ return true; -+ if (gazelle_ring_readable_count(sock->recv_ring) > 0) -+ return true; -+ if (NETCONN_NEED_SAME_NODE(sock)) - return true; -- if (sys_mbox_valid(&sock->conn->recvmbox)) { -- const struct mbox_ring *mr = &sock->conn->recvmbox->mring; -- return mr->ops->recv_count(mr) > 0; -- } - return false; - } - - static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) - { -- if (get_global_cfg_params()->stack_mode_rtc) { -- if (NETCONN_TYPE(sock->conn) == NETCONN_TCP) -- return lwip_tcp_allow_send(sock->conn->pcb.tcp); -- return false; -- } -- if (sys_mbox_valid(&sock->conn->sendmbox)) { -- const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -- return mr->ops->free_count(mr) > 0; -- } -+ if (gazelle_ring_readable_count(sock->send_ring) > 0) -+ return true; - return false; - } - -diff --git a/src/lstack/core/same_node.c b/src/lstack/core/same_node.c -index 0fe0fa8..660fefd 100644 ---- a/src/lstack/core/same_node.c -+++ b/src/lstack/core/same_node.c -@@ -34,7 +34,7 @@ void read_same_node_recv_list(struct protocol_stack *stack) - sock = list_entry(node, struct lwip_sock, recv_list); - - if (sock->same_node_rx_ring != NULL && same_node_ring_count(sock)) { -- add_sock_event(sock, EPOLLIN); -+ API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); - } - } - } -@@ -231,7 +231,8 @@ err_t find_same_node_memzone(struct tcp_pcb *pcb, struct lwip_sock *nsock) - - /* rcvlink init in alloc_socket() */ - /* remove from g_rcv_process_list in free_socket */ -- list_add_node(&nsock->recv_list, &nsock->stack->same_node_recv_list); -+ struct protocol_stack *stack = get_protocol_stack_by_id(nsock->stack_id); -+ list_add_node(&nsock->recv_list, &stack->same_node_recv_list); - return 0; - } - -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 9a5d15a..655e178 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -13,85 +13,6 @@ - #ifndef _GAZELLE_EPOLL_H_ - #define _GAZELLE_EPOLL_H_ - --#if /* SOCK_EVENT_V2 */ -- --#include --#include --#include --#include -- --#include --#include -- --#include "common/gazelle_dfx_msg.h" --#include "common/gazelle_opt.h" -- --enum wakeup_type { -- WAKEUP_EPOLL = 0, -- WAKEUP_POLL, -- WAKEUP_CLOSE, -- WAKEUP_BLOCK, --}; -- --struct protocol_stack; --struct wakeup_poll { -- /* stack thread read frequently */ -- enum wakeup_type type; -- sem_t wait; -- bool in_wait; -- struct list_node wakeup_list[PROTOCOL_STACK_MAX]; -- bool have_kernel_event; -- char pad __rte_cache_aligned; -- -- struct gazelle_wakeup_stat stat; -- struct protocol_stack *bind_stack; -- struct list_node poll_list; -- -- /* poll */ -- struct pollfd *last_fds; -- nfds_t last_nfds; -- nfds_t last_max_nfds; -- struct epoll_event *events; -- -- /* epoll */ -- int32_t epollfd; /* epoll kernel fd */ -- int32_t stack_fd_cnt[PROTOCOL_STACK_MAX]; -- struct protocol_stack *max_stack; -- struct list_node event_list; -- pthread_spinlock_t event_list_lock; --}; -- --void add_sock_event(struct lwip_sock *sock, uint32_t event); --void add_sock_event_nolock(struct lwip_sock *sock, uint32_t event); --void del_sock_event(struct lwip_sock *sock, uint32_t event); --void del_sock_event_nolock(struct lwip_sock *sock, uint32_t event); -- --void wakeup_stack_epoll(struct protocol_stack *stack); -- --int32_t lstack_epoll_create(int32_t size); --int32_t lstack_epoll_create1(int32_t flags); --int32_t lstack_rtw_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); --int32_t lstack_rtc_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event *event); --int32_t lstack_rtw_epoll_wait(int32_t epfd, struct epoll_event *events, int32_t maxevents, int32_t timeout); --int32_t lstack_rtc_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout); --int32_t lstack_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout); --int lstack_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeval); -- --int32_t lstack_block_wait(struct wakeup_poll *wakeup, int32_t timeout); -- --struct wakeup_poll* poll_construct_wakeup(void); -- --static inline void lstack_block_wakeup(struct wakeup_poll *wakeup) --{ -- if (wakeup && __atomic_load_n(&wakeup->in_wait, __ATOMIC_ACQUIRE)) { -- __atomic_store_n(&wakeup->in_wait, false, __ATOMIC_RELEASE); -- rte_mb(); -- sem_post(&wakeup->wait); -- } --} -- --#else /* SOCK_EVENT_V2 */ -- - #include - #include - -@@ -104,6 +25,4 @@ int lstack_epoll_close(int epfd); - void epoll_api_init(posix_api_t *api); - bool sock_event_wait(struct lwip_sock *sock, bool noblocking); - --#endif /* SOCK_EVENT_V2 */ -- - #endif /* _GAZELLE_EPOLL_H_ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -index f2524e4..4cc9db1 100644 ---- a/src/lstack/include/lstack_lwip.h -+++ b/src/lstack/include/lstack_lwip.h -@@ -22,11 +22,7 @@ struct lwip_sock; - struct rpc_msg; - struct protocol_stack; - -- --#define NETCONN_IS_ACCEPTIN(sock) (((sock)->conn->acceptmbox != NULL) && !sys_mbox_empty((sock)->conn->acceptmbox)) --#define NETCONN_IS_DATAIN(sock) ((gazelle_ring_readable_count((sock)->recv_ring) || (sock)->recv_lastdata) || NETCONN_NEED_SAME_NODE(sock)) - #define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_pre_del) --#define NETCONN_IS_OUTIDLE(sock) gazelle_ring_readable_count((sock)->send_ring) - #define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) - - /* lwip api */ -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index 3f6e3d3e..b77d5da 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -14,7 +14,6 @@ - #define __GAZELLE_PROTOCOL_STACK_H__ - - #include --#include - #include - - #include -@@ -43,41 +42,35 @@ struct protocol_stack { - uint16_t numa_id; - uint16_t cpu_id; - uint32_t stack_idx; -+ -+ struct netif netif; -+ struct lstack_dev_ops dev_ops; -+ - cpu_set_t idle_cpuset; /* idle cpu in numa of stack, app thread bind to it */ -- int32_t epollfd; /* kernel event thread epoll fd */ -+ - volatile enum rte_lcore_state_t state; -+ volatile bool low_power; -+ volatile uint16_t conn_num; - - struct rte_mempool *rxtx_mbuf_pool; -- struct rte_ring *rx_ring; -+ struct rte_ring *rx_ring; - struct rte_ring *tx_ring; - struct rte_ring *reg_ring; -- struct rte_ring *wakeup_ring; - struct reg_ring_msg *reg_buf; - uint32_t reg_head; - -- volatile bool low_power; -+ uint32_t rx_ring_used; -+ uint32_t tx_ring_used; -+ struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX]; - - char pad1 __rte_cache_aligned; - rpc_queue dfx_rpc_queue; - rpc_queue rpc_queue; - char pad2 __rte_cache_aligned; - -- /* kernel event thread read/write frequently */ -- struct epoll_event kernel_events[KERNEL_EPOLL_MAX]; -- int32_t kernel_event_num; -- char pad3 __rte_cache_aligned; -- -- struct netif netif; -- struct lstack_dev_ops dev_ops; -- uint32_t rx_ring_used; -- uint32_t tx_ring_used; -- -- struct rte_mbuf *pkts[NIC_QUEUE_SIZE_MAX]; - struct list_node recv_list; - struct list_node same_node_recv_list; /* used for same node processes communication */ -- struct list_node wakeup_list; - -- volatile uint16_t conn_num; - struct stats_ *lwip_stats; - struct gazelle_stack_latency latency; - struct gazelle_stack_stat stats; -@@ -93,8 +86,7 @@ struct protocol_stack_group { - struct rte_mempool *kni_pktmbuf_pool; - struct eth_params *eth_params; - struct protocol_stack *stacks[PROTOCOL_STACK_MAX]; -- struct list_node poll_list; -- pthread_spinlock_t poll_list_lock; -+ - sem_t sem_listen_thread; - struct rte_mempool *total_rxtx_pktmbuf_pool[PROTOCOL_STACK_MAX]; - sem_t sem_stack_setup; -@@ -106,16 +98,26 @@ struct protocol_stack_group { - pthread_spinlock_t socket_lock; - }; - --struct protocol_stack *get_protocol_stack(void); --struct protocol_stack *get_protocol_stack_by_fd(int fd); --struct protocol_stack *get_bind_protocol_stack(void); -+struct thread_params { -+ uint16_t queue_id; -+ uint16_t idx; -+}; -+ - struct protocol_stack_group *get_protocol_stack_group(void); - -+extern PER_THREAD struct protocol_stack *g_stack_p; -+static inline struct protocol_stack *get_protocol_stack(void) -+{ -+ return g_stack_p; -+} -+struct protocol_stack *get_protocol_stack_by_id(int stack_id); -+struct protocol_stack *get_bind_protocol_stack(void); -+ - #if GAZELLE_TCP_REUSE_IPPORT - int get_min_conn_stack(struct protocol_stack_group *stack_group); - #endif /* GAZELLE_TCP_REUSE_IPPORT */ --void bind_to_stack_numa(struct protocol_stack *stack); --void thread_bind_stack(struct protocol_stack *stack); -+void bind_to_stack_numa(int stack_id); -+void thread_bind_stack(int stack_id); - - int stack_group_init(void); - void stack_group_exit(void); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index c74981f..427a519 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -101,7 +101,6 @@ int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); - int rpc_call_replenish(rpc_queue *queue, void *sock); - int rpc_call_recvlistcnt(rpc_queue *queue); - --int rpc_call_clean_epoll(rpc_queue *queue, void *wakeup); - int rpc_call_arp(rpc_queue *queue, void *mbuf); - - int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn); --- -2.33.0 - diff --git a/0328-socket-refactor-tcp-and-udp.patch b/0328-socket-refactor-tcp-and-udp.patch deleted file mode 100644 index 58114af..0000000 --- a/0328-socket-refactor-tcp-and-udp.patch +++ /dev/null @@ -1,4524 +0,0 @@ -From 52c4cd904e90bc506ae1323465d99007e0e1a4ba Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 21 Mar 2025 17:02:04 +0800 -Subject: [PATCH] socket: refactor tcp and udp - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockctl.c | 840 +++++++++++ - src/lstack/api/lstack_sockio.c | 1488 ++++++++++++++++++++ - src/lstack/core/lstack_mempool.c | 1014 +++++++++++++ - src/lstack/include/lstack_lockless_queue.h | 81 +- - src/lstack/include/lstack_mempool.h | 325 +++++ - src/lstack/include/lstack_sockctl.h | 25 + - src/lstack/include/lstack_sockio.h | 41 + - src/lstack/include/mbox_ring.h | 583 ++++++++ - 8 files changed, 4394 insertions(+), 3 deletions(-) - create mode 100644 src/lstack/api/lstack_sockctl.c - create mode 100644 src/lstack/api/lstack_sockio.c - create mode 100644 src/lstack/core/lstack_mempool.c - create mode 100644 src/lstack/include/lstack_mempool.h - create mode 100644 src/lstack/include/lstack_sockctl.h - create mode 100644 src/lstack/include/lstack_sockio.h - create mode 100644 src/lstack/include/mbox_ring.h - -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -new file mode 100644 -index 0000000..71310b7 ---- /dev/null -+++ b/src/lstack/api/lstack_sockctl.c -@@ -0,0 +1,840 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+#include -+#include -+ -+#include "common/gazelle_base_func.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "lstack_thread_rpc.h" -+#include "lstack_protocol_stack.h" -+#include "lstack_epoll.h" -+#include "lstack_sockctl.h" -+#include "lstack_sockio.h" -+ -+ -+static void callback_getpeername(struct rpc_msg *msg) -+{ -+ msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static void callback_getsockname(struct rpc_msg *msg) -+{ -+ msg->result = lwip_getsockname(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static void callback_getsockopt(struct rpc_msg *msg) -+{ -+ msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -+ msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -+ } -+} -+ -+static void callback_setsockopt(struct rpc_msg *msg) -+{ -+ msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -+ msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].u); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), -+ msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -+ } -+} -+ -+static int rpc_call_getpeername(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getpeername); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].p = addr; -+ msg->args[MSG_ARG_2].p = addrlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rpc_call_getsockname(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getsockname); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].p = addr; -+ msg->args[MSG_ARG_2].p = addrlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rpc_call_getsockopt(int stack_id, int fd, int level, int optname, void *optval, socklen_t *optlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getsockopt); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].i = level; -+ msg->args[MSG_ARG_2].i = optname; -+ msg->args[MSG_ARG_3].p = optval; -+ msg->args[MSG_ARG_4].p = optlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rpc_call_setsockopt(int stack_id, int fd, int level, int optname, const void *optval, socklen_t optlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_setsockopt); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].i = level; -+ msg->args[MSG_ARG_2].i = optname; -+ msg->args[MSG_ARG_3].cp = optval; -+ msg->args[MSG_ARG_4].u = optlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_setsockopt(sock->stack_id, s, level, optname, optval, optlen); -+} -+ -+static int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getsockopt(sock->stack_id, s, level, optname, optval, optlen); -+} -+ -+static int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getpeername(sock->stack_id, s, name, namelen); -+} -+ -+static int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_getsockname(sock->stack_id, s, name, namelen); -+} -+ -+ -+static void callback_socket(struct rpc_msg *msg) -+{ -+ msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -+ if (msg->result < 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %ld socket failed\n", rte_gettid(), msg->result); -+ } -+} -+ -+static int rpc_call_socket(int stack_id, int domain, int type, int protocol) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_socket); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = domain; -+ msg->args[MSG_ARG_1].i = type; -+ msg->args[MSG_ARG_2].i = protocol; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_close(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ if (sockio_mbox_pending(sock)) { -+ rpc_queue *queue = &get_protocol_stack_by_id(sock->stack_id)->rpc_queue; -+ rpc_async_call(queue, msg, RPC_MSG_FREE | RPC_MSG_RECALL); /* until stack_send recall finish */ -+ return; -+ } -+ -+ msg->result = lwip_close(fd); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static void callback_shutdown(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ int how = msg->args[MSG_ARG_1].i; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ if (sockio_mbox_pending(sock)) { -+ rpc_queue *queue = &get_protocol_stack_by_id(sock->stack_id)->rpc_queue; -+ rpc_async_call(queue, msg, RPC_MSG_FREE | RPC_MSG_RECALL); -+ return; -+ } -+ -+ msg->result = lwip_shutdown(fd, how); -+ if (msg->result != 0 && errno != ENOTCONN) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), fd, msg->result); -+ } -+ -+ posix_api->shutdown_fn(fd, how); -+} -+ -+static int rpc_call_close(int stack_id, int fd) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_close); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rpc_call_shutdown(int stack_id, int fd, int how) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_shutdown); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].i = how; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_bind(struct rpc_msg *msg) -+{ -+ msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].u); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static int rpc_call_bind(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_bind); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].cp = addr; -+ msg->args[MSG_ARG_2].u = addrlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_listen(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ int backlog = msg->args[MSG_ARG_1].i; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ msg->result = -1; -+ return; -+ } -+ -+ /* new listen add to stack listen list */ -+ msg->result = lwip_listen(fd, backlog); -+ if (msg->result != 0) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -+ } -+} -+ -+static int rpc_call_listen(int stack_id, int s, int backlog) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_listen); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = s; -+ msg->args[MSG_ARG_1].i = backlog; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock) -+{ -+ dst_sock->conn->pcb.ip->so_options = src_sock->conn->pcb.ip->so_options; -+ dst_sock->conn->pcb.ip->ttl = src_sock->conn->pcb.ip->ttl; -+ dst_sock->conn->pcb.ip->tos = src_sock->conn->pcb.ip->tos; -+ dst_sock->conn->flags = src_sock->conn->flags; -+ -+ switch (NETCONN_TYPE(src_sock->conn)) { -+ case NETCONN_TCP: -+ dst_sock->conn->pcb.tcp->netif_idx = src_sock->conn->pcb.tcp->netif_idx; -+ dst_sock->conn->pcb.tcp->flags = src_sock->conn->pcb.tcp->flags; -+ dst_sock->conn->pcb.tcp->keep_idle = src_sock->conn->pcb.tcp->keep_idle; -+ dst_sock->conn->pcb.tcp->keep_intvl = src_sock->conn->pcb.tcp->keep_intvl; -+ dst_sock->conn->pcb.tcp->keep_cnt = src_sock->conn->pcb.tcp->keep_cnt; -+ break; -+ case NETCONN_UDP: -+ dst_sock->conn->pcb.udp->flags = src_sock->conn->pcb.udp->flags; -+ dst_sock->conn->pcb.udp->mcast_ifindex = src_sock->conn->pcb.udp->mcast_ifindex; -+ dst_sock->conn->pcb.udp->mcast_ttl = src_sock->conn->pcb.udp->mcast_ttl; -+ break; -+ default: -+ break; -+ } -+} -+static void callback_create_shadow_fd(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ struct sockaddr *addr = msg->args[MSG_ARG_1].p; -+ socklen_t addr_len = msg->args[MSG_ARG_2].u; -+ -+ int clone_fd = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -+ msg->result = -1; -+ return; -+ } -+ -+ int domain = addr->sa_family; -+ int type = NETCONN_TYPE(sock->conn) == NETCONN_UDP ? SOCK_DGRAM : SOCK_STREAM; -+ clone_fd = lwip_socket(domain, type, 0); -+ if (clone_fd < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = clone_fd; -+ return; -+ } -+ -+ struct lwip_sock *clone_sock = lwip_get_socket(clone_fd); -+ if (clone_sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -+ msg->result = -1; -+ return; -+ } -+ -+ do_lwip_clone_sockopt(clone_sock, sock); -+ -+ while (sock->listen_next) { -+ sock = sock->listen_next; -+ } -+ sock->listen_next = clone_sock; -+ -+ int ret = lwip_bind(clone_fd, addr, addr_len); -+ if (ret < 0) { -+ LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -+ msg->result = ret; -+ return; -+ } -+ -+ msg->result = clone_fd; -+} -+ -+static int rpc_call_shadow_fd(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_create_shadow_fd); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].cp = addr; -+ msg->args[MSG_ARG_2].u = addrlen; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_accept(struct rpc_msg *msg) -+{ -+ int fd = msg->args[MSG_ARG_0].i; -+ msg->result = -1; -+ struct protocol_stack *stack = get_protocol_stack(); -+ -+ int accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); -+ if (accept_fd < 0) { -+ stack->stats.accept_fail++; -+ LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -+ return; -+ } -+ msg->result = accept_fd; -+} -+ -+static int rpc_call_accept(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_accept); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].p = addr; -+ msg->args[MSG_ARG_2].p = addrlen; -+ msg->args[MSG_ARG_3].i = flags; -+ -+ return rpc_sync_call(queue, msg); -+} -+ -+static void callback_connect(struct rpc_msg *msg) -+{ -+ msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].u); -+ if (msg->result < 0) { -+ msg->result = -errno; -+ } -+} -+ -+static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_connect); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->args[MSG_ARG_0].i = fd; -+ msg->args[MSG_ARG_1].cp = addr; -+ msg->args[MSG_ARG_2].u = addrlen; -+ -+ int ret = rpc_sync_call(queue, msg); -+ if (ret < 0) { -+ errno = -ret; -+ ret = -1; -+ } -+ -+ if (ret < 0 && errno == EINPROGRESS) { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn))) { -+ ret = 0; -+ } -+ } -+ return ret; -+} -+ -+/* for lwip nonblock connected callback */ -+void do_lwip_connected_callback(int fd) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ return; -+ } -+ -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ /* delete kernel event */ -+ if (sock->sk_wait != NULL) { -+ posix_api->epoll_ctl_fn(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL); -+ } -+ /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -+ posix_api->shutdown_fn(fd, SHUT_RDWR); -+ } -+ -+ POSIX_SET_TYPE(sock, POSIX_LWIP); -+ -+ API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); -+} -+ -+/* when fd is listenfd, listenfd of all protocol stack thread will be closed */ -+static int stack_broadcast_close(int fd) -+{ -+ int ret = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ while (sock != NULL) { -+ if (POSIX_IS_CLOSED(sock)) { -+ ret = -1; -+ break; -+ } -+ fd = sock->conn->callback_arg.socket; -+ ret |= rpc_call_close(sock->stack_id, fd); -+ sock = sock->listen_next; -+ } -+ -+ if (ret != 0) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return ret; -+} -+ -+static int stack_broadcast_shutdown(int fd, int how) -+{ -+ int ret = 0; -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ -+ while (true) { -+ if (POSIX_IS_CLOSED(sock)) { -+ ret = -1; -+ break; -+ } -+ fd = sock->conn->callback_arg.socket; -+ ret |= rpc_call_shutdown(sock->stack_id, fd, how); -+ sock = sock->listen_next; -+ } -+ -+ if (ret != 0) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return ret; -+} -+ -+/* choice one stack bind */ -+static int stack_single_bind(int fd, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_bind(sock->stack_id, fd, name, namelen); -+} -+ -+/* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ -+static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct protocol_stack *cur_stack; -+ struct protocol_stack *stack = NULL; -+ int ret, clone_fd; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ ret = rpc_call_bind(sock->stack_id, fd, name, namelen); -+ if (ret < 0) { -+ close(fd); -+ return ret; -+ } -+ -+ cur_stack = get_protocol_stack_by_id(sock->stack_id); -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+ for (int i = 0; i < stack_group->stack_num; ++i) { -+ stack = stack_group->stacks[i]; -+ if (stack != cur_stack) { -+ clone_fd = rpc_call_shadow_fd(stack->stack_idx, fd, name, namelen); -+ if (clone_fd < 0) { -+ stack_broadcast_close(fd); -+ return clone_fd; -+ } -+ } -+ } -+ return 0; -+} -+ -+static struct lwip_sock *get_min_accept_sock(int fd) -+{ -+ struct lwip_sock *sock; -+ struct lwip_sock *min_sock = NULL; -+ -+ for (sock = lwip_get_socket(fd); sock != NULL; sock = sock->listen_next) { -+ if (!netconn_is_nonblocking(sock->conn)) { -+ /* init all sock sk_wait */ -+ if (unlikely(sock->sk_wait == NULL) || sock->sk_wait->type == WAIT_CLOSE) { -+ sock->sk_wait = poll_construct_wait(0); -+ } -+ if (!(sock->sk_wait->type & WAIT_BLOCK)) { -+ sock->sk_wait->type |= WAIT_BLOCK; -+ } -+ } -+ -+ if (!sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0)) { -+ continue; -+ } -+ -+ if (min_sock == NULL || -+ get_protocol_stack_by_id(min_sock->stack_id)->conn_num > get_protocol_stack_by_id(sock->stack_id)->conn_num) { -+ min_sock = sock; -+ } -+ } -+ -+ return min_sock; -+} -+ -+/* ergodic the protocol stack thread to find the connection, because all threads are listening */ -+static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ int ret = -1; -+ struct protocol_stack *stack; -+ struct lwip_sock *min_sock; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ min_sock = get_min_accept_sock(fd); -+ if (min_sock == NULL) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ min_sock = get_min_accept_sock(fd); -+ } -+ } -+ -+ if (!POSIX_IS_CLOSED(min_sock)) { -+ stack = get_protocol_stack_by_id(min_sock->stack_id); -+ ret = rpc_call_accept(stack->stack_idx, min_sock->conn->callback_arg.socket, addr, addrlen, flags); -+ } -+ -+ if (ret < 0) { -+ errno = EAGAIN; -+ } -+ return ret; -+} -+ -+static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ if (get_global_cfg_params()->nonblock_mode) -+ return stack_broadcast_accept4(fd, addr, addrlen, SOCK_NONBLOCK); -+ else -+ return stack_broadcast_accept4(fd, addr, addrlen, 0); -+} -+ -+/* choice one stack listen */ -+static int stack_single_listen(int fd, int backlog) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ return rpc_call_listen(sock->stack_id, fd, backlog); -+} -+ -+/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ -+static int stack_broadcast_listen(int fd, int backlog) -+{ -+ typedef union sockaddr_union { -+ struct sockaddr sa; -+ struct sockaddr_in in; -+ struct sockaddr_in6 in6; -+ } sockaddr_t; -+ -+ struct protocol_stack *cur_stack; -+ struct protocol_stack *stack = NULL; -+ sockaddr_t addr; -+ socklen_t addr_len = sizeof(addr); -+ int ret, clone_fd; -+ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ ret = rpc_call_getsockname(sock->stack_id, fd, (struct sockaddr *)&addr, &addr_len); -+ if (ret != 0) { -+ return ret; -+ } -+ -+ cur_stack = get_protocol_stack_by_id(sock->stack_id); -+ struct protocol_stack_group *stack_group = get_protocol_stack_group(); -+#if GAZELLE_TCP_REUSE_IPPORT -+ int min_conn_stk_idx = get_min_conn_stack(stack_group); -+#endif -+ -+ for (int32_t i = 0; i < stack_group->stack_num; ++i) { -+ stack = stack_group->stacks[i]; -+ if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -+ continue; -+ } -+ if (stack != cur_stack) { -+ clone_fd = rpc_call_shadow_fd(stack->stack_idx, fd, (struct sockaddr *)&addr, addr_len); -+ if (clone_fd < 0) { -+ stack_broadcast_close(fd); -+ return clone_fd; -+ } -+ } else { -+ clone_fd = fd; -+ } -+ -+#if GAZELLE_TCP_REUSE_IPPORT -+ if (min_conn_stk_idx == i) { -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 1; -+ } else { -+ lwip_get_socket(clone_fd)->conn->is_master_fd = 0; -+ } -+#endif /* GAZELLE_TCP_REUSE_IPPORT */ -+ -+ ret = rpc_call_listen(stack->stack_idx, clone_fd, backlog); -+ if (ret < 0) { -+ stack_broadcast_close(fd); -+ return ret; -+ } -+ } -+ return 0; -+} -+ -+ -+static int rtw_socket(int domain, int type, int protocol) -+{ -+ struct protocol_stack *stack = get_bind_protocol_stack(); -+ if (stack == NULL) { -+ GAZELLE_RETURN(EINVAL); -+ } -+ return rpc_call_socket(stack->stack_idx, domain, type, protocol); -+} -+ -+static int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ return stack_broadcast_accept(s, addr, addrlen); -+} -+ -+static int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ return stack_broadcast_accept4(s, addr, addrlen, flags); -+} -+ -+static int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ -+ if (NETCONN_TYPE(sock->conn) == NETCONN_UDP && -+ get_global_cfg_params()->listen_shadow) { -+ return stack_broadcast_bind(s, name, namelen); -+ } else { -+ return stack_single_bind(s, name, namelen); -+ } -+} -+ -+static int rtw_listen(int s, int backlog) -+{ -+ if (!get_global_cfg_params()->tuple_filter && -+ !get_global_cfg_params()->listen_shadow) { -+ return stack_single_listen(s, backlog); -+ } else { -+ return stack_broadcast_listen(s, backlog); -+ } -+} -+ -+static int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(s); -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ if (stack == NULL || POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ return rpc_call_connect(stack->stack_idx, s, name, namelen); -+} -+ -+static int rtw_close(int s) -+{ -+ return stack_broadcast_close(s); -+} -+ -+static int rtw_shutdown(int fd, int how) -+{ -+ return stack_broadcast_shutdown(fd, how); -+} -+ -+void sockctl_rtw_api_init(posix_api_t *api) -+{ -+ api->close_fn = rtw_close; -+ api->shutdown_fn = rtw_shutdown; -+ api->socket_fn = rtw_socket; -+ api->bind_fn = rtw_bind; -+ api->listen_fn = rtw_listen; -+ api->accept_fn = rtw_accept; -+ api->accept4_fn = rtw_accept4; -+ api->connect_fn = rtw_connect; -+ -+ api->setsockopt_fn = rtw_setsockopt; -+ api->getsockopt_fn = rtw_getsockopt; -+ api->getpeername_fn = rtw_getpeername; -+ api->getsockname_fn = rtw_getsockname; -+} -+ -+static int rtc_connect(int s, const struct sockaddr *name, socklen_t namelen) -+{ -+ int ret; -+ -+ ret = lwip_connect(s, name, namelen); -+ if (ret < 0 && errno == EINPROGRESS) { -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn))) { -+ ret = 0; -+ } -+ } -+ -+ return ret; -+} -+ -+static int rtc_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) -+{ -+ int ret; -+ struct lwip_sock *sock = lwip_get_socket(s); -+ if (POSIX_IS_CLOSED(sock)) { -+ GAZELLE_RETURN(EBADF); -+ } -+ -+ ret = lwip_accept4(s, addr, addrlen, flags); -+ if (ret < 0 && errno == EWOULDBLOCK) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ ret = lwip_accept4(s, addr, addrlen, flags); -+ } -+ } -+ return ret; -+} -+ -+static int rtc_accept(int s, struct sockaddr *addr, socklen_t *addrlen) -+{ -+ return rtc_accept4(s, addr, addrlen, 0); -+} -+ -+void sockctl_rtc_api_init(posix_api_t *api) -+{ -+ api->close_fn = lwip_close; -+ api->shutdown_fn = lwip_shutdown; -+ api->socket_fn = lwip_socket; -+ api->bind_fn = lwip_bind; -+ api->listen_fn = lwip_listen; -+ api->accept_fn = rtc_accept; -+ api->accept4_fn = rtc_accept4; -+ api->connect_fn = rtc_connect; -+ -+ api->setsockopt_fn = lwip_setsockopt; -+ api->getsockopt_fn = lwip_getsockopt; -+ api->getpeername_fn = lwip_getpeername; -+ api->getsockname_fn = lwip_getsockname; -+} -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -new file mode 100644 -index 0000000..060b3b3 ---- /dev/null -+++ b/src/lstack/api/lstack_sockio.c -@@ -0,0 +1,1488 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "lstack_thread_rpc.h" -+#include "lstack_log.h" -+#include "lstack_sockio.h" -+#include "lstack_wait.h" -+#include "mbox_ring.h" -+#include "lstack_epoll.h" -+#include "lstack_stack_stat.h" -+ -+ -+/* see lwip ip4_frag() and ip6_frag(), nfb must be a multiple of 8 */ -+#define IP_FRAG_NFB ((GAZELLE_ETH_MTU - PBUF_IP) / 8) -+#define UDP_MSS (IP_FRAG_NFB * 8 - UDP_HLEN) -+ -+#define IP4_UDP_SND_SIZE_MAX (0xFFFF - IP_HLEN - UDP_HLEN) -+#define IP6_UDP_SND_SIZE_MAX (0xFFFF - IP6_HLEN - UDP_HLEN) -+#define UDP_SND_SIZE_MAX(conn) (NETCONNTYPE_ISIPV6(netconn_type(conn)) ? IP6_UDP_SND_SIZE_MAX : IP4_UDP_SND_SIZE_MAX) -+#define UDP_SND_QUEUELEN_MAX ((IP6_UDP_SND_SIZE_MAX + UDP_MSS - 1) / UDP_MSS) -+#define UDP_SND_OUTPUT_NUM (16) -+ -+#define TCP_SND_OUTPUT_NUM OFFLOAD_TX_TSO_MTU_FRAGS -+#define TCP_SND_QUEUELEN_MAX OFFLOAD_TX_TSO_MTU_FRAGS -+#define TCP_SND_SIZE_MAX (TCP_SND_QUEUELEN_MAX * TCP_MSS) -+ -+#define TCP_SND_APPEND_LEN (TCP_MSS >> 1) -+ -+#define RECV_EXTEND_CACHE_MAX 8 -+#define RECV_EXTEND_CACHE_LEN (4 * TCP_MSS) -+ -+struct sockio_ops { -+ ssize_t (*stack_udp_write)(struct lwip_sock *sock, const void *data, size_t len, int flags, -+ const struct sockaddr *to, socklen_t tolen); -+ void (*stack_udp_send)(struct lwip_sock *sock); -+ -+ ssize_t (*stack_udp_readmsg)(struct lwip_sock *sock, struct msghdr *msg, int flags); -+ -+ ssize_t (*stack_tcp_write)(struct lwip_sock *sock, const char *data, size_t len, int flags); -+ void (*stack_tcp_send)(struct lwip_sock *sock); -+ -+ ssize_t (*stack_tcp_read)(struct lwip_sock *sock, char *data, size_t len, int flags, -+ struct sockaddr *from, socklen_t *fromlen); -+ void (*stack_tcp_recvd)(struct lwip_sock *sock, ssize_t recvd, int flags); -+}; -+static struct sockio_ops ioops = {0}; -+ -+ -+static unsigned pbuf_list_count(const struct mbox_ring *mr) -+{ -+ struct pbuf *p = mr->ops->read_tail(mr); -+ return pbuf_clen(p); -+} -+ -+static unsigned netbuf_list_count(const struct mbox_ring *mr) -+{ -+ struct netbuf *nbuf = mr->ops->read_tail(mr); -+ return pbuf_clen(nbuf->p); -+} -+ -+static void netbuf_obj_free(struct mbox_ring *mr, void *obj, bool is_tail) -+{ -+ err_t err; -+ if (unlikely(lwip_netconn_is_err_msg(obj, &err))) -+ return; -+ -+ if (is_tail && (mr->flags & MBOX_FLAG_RECV)) { -+ pbuf_free((struct pbuf *)obj); -+ } else { -+ netbuf_free((struct netbuf *)obj); -+ } -+} -+ -+static void pbuf_obj_free(struct mbox_ring *mr, void *obj, bool is_tail) -+{ -+ err_t err; -+ if (unlikely(lwip_netconn_is_err_msg(obj, &err))) -+ return; -+ pbuf_free((struct pbuf *)obj); -+} -+ -+void sockio_mbox_set_func(struct mbox_ring *mr) -+{ -+ mr->tail_count = pbuf_list_count; -+ if (mr->flags & MBOX_FLAG_TCP) { -+ /* only tcp sendmbox & recvmbox, lwip would free all acceptmbox newconn objs. */ -+ mr->obj_free_fn = pbuf_obj_free; -+ } else if (mr->flags & MBOX_FLAG_UDP) { -+ /* udp sendmbox & recvmbox */ -+ mr->obj_free_fn = netbuf_obj_free; -+ if (mr->flags & MBOX_FLAG_SEND) -+ mr->tail_count = netbuf_list_count; -+ } -+} -+ -+void sockio_peek_recv_free(struct mbox_ring *mr, unsigned n) -+{ -+ void *buf_pkts[RECV_EXTEND_CACHE_MAX]; -+ unsigned num, i; -+ -+ mr->stk_queued_num += n; -+ if (mr->stk_queued_num < (RECV_EXTEND_CACHE_MAX >> 1)) { -+ return; -+ } -+ -+ while (true) { -+ num = mr->ops->dequeue_burst(mr, buf_pkts, RECV_EXTEND_CACHE_MAX); -+ if (num == 0) -+ break; -+ if (mr->flags & MBOX_FLAG_UDP) { -+ for (i = 0; i < num; ++i) { -+ buf_pkts[i] = ((struct netbuf *)buf_pkts[i])->p; -+ } -+ } -+ mem_put_pbuf_list_bulk((struct pbuf **)buf_pkts, num); -+ mr->stk_queued_num -= num; -+ } -+} -+ -+static void sock_mbox_private_free(struct mbox_ring *mr) -+{ -+ struct rpc_msg *msg = (struct rpc_msg *)mr->private_data; -+ if (msg != NULL) { -+ rpc_msg_free(msg); -+ mr->private_data = NULL; -+ } -+} -+ -+static int sock_mbox_private_init(sys_mbox_t mb, rpc_func_t func) -+{ -+ struct rpc_msg *msg = rpc_msg_alloc(get_protocol_stack()->stack_idx, func); -+ if (msg == NULL) -+ return -1; -+ -+ memset_s(msg->args, sizeof(msg->args), 0, sizeof(msg->args)); -+ -+ mb->mring.private_data = msg; -+ mb->mring.private_data_free_fn = sock_mbox_private_free; -+ return 0; -+} -+ -+static inline struct rpc_msg *sock_mbox_private_get(sys_mbox_t mb) -+{ -+ return (struct rpc_msg *)mb->mring.private_data; -+} -+ -+ -+static inline uint16_t write_pbuf(struct pbuf *p, const char *data, uint16_t len, uint8_t optlen) -+{ -+ mem_init_pbuf(p, PBUF_TRANSPORT, len, len, PBUF_POOL); -+ if (optlen > 0) { -+ /* see pbuf_remove_header() */ -+ p->payload = (uint8_t *)p->payload + optlen; -+ } -+ -+ if (get_protocol_stack_group()->latency_start) -+ time_stamp_into_write(&p, 1); -+ -+ pbuf_take(p, data, len); -+ return len; -+} -+ -+static inline void write_pbuf_bulk(struct pbuf *pbuf_pkts[], unsigned n, uint16_t payload_size, -+ const char *data, uint16_t len, uint8_t optlen) -+{ -+ unsigned i; -+ uint16_t copied_total = 0; -+ -+ for (i = 0; i < (n & ~0x3); i += 4) { -+ rte_prefetch0(pbuf_pkts[i + 1]); -+ rte_prefetch0(data + copied_total + payload_size); -+ copied_total += write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ -+ rte_prefetch0(pbuf_pkts[i + 2]); -+ rte_prefetch0(data + copied_total + payload_size); -+ copied_total += write_pbuf(pbuf_pkts[i + 1], data + copied_total, payload_size, optlen); -+ -+ rte_prefetch0(pbuf_pkts[i + 3]); -+ rte_prefetch0(data + copied_total + payload_size); -+ copied_total += write_pbuf(pbuf_pkts[i + 2], data + copied_total, payload_size, optlen); -+ -+ if (payload_size > len - copied_total) -+ payload_size = len - copied_total; -+ copied_total += write_pbuf(pbuf_pkts[i + 3], data + copied_total, payload_size, optlen); -+ } -+ switch (n & 0x3) { -+ case 3: -+ rte_prefetch0(pbuf_pkts[i + 1]); -+ copied_total += write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ ++i; /* fallthrough */ -+ case 2: -+ rte_prefetch0(pbuf_pkts[i + 1]); -+ copied_total += write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ ++i; /* fallthrough */ -+ case 1: -+ payload_size = len - copied_total; -+ write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ /* fallthrough */ -+ } -+} -+ -+static inline void write_pbuf_list(struct pbuf *pbuf_pkts[], unsigned n, uint16_t payload_size, -+ const char *data, uint16_t len, uint8_t optlen) -+{ -+ unsigned i; -+ uint16_t copied_total = 0; -+ -+ for (i = 0; i < n - 1; ++i) { -+ rte_prefetch0(pbuf_pkts[i + 1]); -+ rte_prefetch0(data + copied_total + payload_size); -+ write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ pbuf_pkts[i]->next = pbuf_pkts[i + 1]; -+ pbuf_pkts[i]->tot_len = len - copied_total; -+ copied_total += payload_size; -+ } -+ -+ payload_size = len - copied_total; -+ write_pbuf(pbuf_pkts[i], data + copied_total, payload_size, optlen); -+ pbuf_pkts[i]->next = NULL; -+} -+ -+static uint16_t stack_udp_write_one(const struct lwip_sock *sock, struct mbox_ring *mr, -+ const char *data, uint16_t len, int flags, -+ const struct sockaddr *to, socklen_t tolen) -+{ -+ struct pbuf **extcache_list = (struct pbuf **)&sock->conn->recvmbox->mring.st_obj; -+ struct pbuf *p; -+ struct netbuf *nbuf; -+ -+ p = mem_extcache_get_pbuf(sock->stack_id, true, extcache_list); -+ if (p == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "mem_extcache_get_pbuf failed\n"); -+ set_errno(ENOMEM); -+ return 0; -+ } -+ -+ write_pbuf(p, data, len, 0); -+ -+ nbuf = netbuf_create(p); -+ lwip_sendto_netbuf(sock->conn, nbuf, to, tolen); -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ -+ mr->ops->enqueue_burst(mr, (void **)&nbuf, 1); -+ mr->app_free_count -= 1; -+ -+ return len; -+} -+ -+static uint16_t stack_udp_write_bulk(const struct lwip_sock *sock, struct mbox_ring *mr, -+ const char *data, uint16_t len, int flags, -+ const struct sockaddr *to, socklen_t tolen) -+{ -+ struct pbuf *pbuf_pkts[UDP_SND_QUEUELEN_MAX]; -+ unsigned pbuf_num; -+ struct netbuf *nbuf; -+ uint16_t payload_size; -+ uint8_t optlen; -+ uint16_t copied_total = 0; -+ -+ if (NETCONNTYPE_ISIPV6(netconn_type(sock->conn))) { -+ optlen = IP6_FRAG_HLEN; -+ payload_size = UDP_MSS - IP6_FRAG_HLEN; -+ } else { -+ optlen = 0; -+ payload_size = UDP_MSS; -+ } -+ -+ /* step1. udp append data */ -+ nbuf = (struct netbuf *)mr->ops->pop_tail(mr, NULL); -+ if (nbuf != NULL) { -+ copied_total = LWIP_MIN(len, payload_size - nbuf->tail->len); -+ pbuf_append_take(nbuf->p, nbuf->tail, data, copied_total, NULL); -+ len -= copied_total; -+ } -+ -+ /* step2. alloc a batch of pbufs */ -+ if (len > 0) { -+ struct pbuf **extcache_list = (struct pbuf **)&sock->conn->recvmbox->mring.st_obj; -+ pbuf_num = (len + payload_size - 1) / payload_size; -+ pbuf_num = mem_extcache_get_pbuf_bulk(sock->stack_id, pbuf_pkts, pbuf_num, true, extcache_list); -+ if (pbuf_num == 0) { -+ /* drop netbuf */ -+ if (nbuf != NULL) { -+ netbuf_free(nbuf); -+ } -+ LSTACK_LOG(ERR, LSTACK, "mem_extcache_get_pbuf_bulk failed, pbuf_num %u\n", pbuf_num); -+ set_errno(ENOMEM); -+ return 0; -+ } -+ -+ write_pbuf_list(pbuf_pkts, pbuf_num, payload_size, data + copied_total, len, optlen); -+ copied_total += len; -+ -+ if (nbuf == NULL) { -+ nbuf = netbuf_create(pbuf_pkts[0]); -+ lwip_sendto_netbuf(sock->conn, nbuf, to, tolen); -+ } else { -+ pbuf_cat(nbuf->p, pbuf_pkts[0]); -+ } -+ nbuf->tail = pbuf_pkts[pbuf_num - 1]; -+ } -+ -+ /* step3. enqueue the new netbuf */ -+ if ((flags & MSG_MORE) == 0) { -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ -+ mr->ops->enqueue_burst(mr, (void **)&nbuf, 1); -+ mr->app_free_count -= 1; -+ } else { -+ mr->ops->push_tail(mr, nbuf); -+ } -+ -+ return copied_total; -+} -+ -+static ssize_t stack_udp_write(struct lwip_sock *sock, const void *data, size_t len, int flags, -+ const struct sockaddr *to, socklen_t tolen) -+{ -+ struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ uint16_t copied_total; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, data=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, sock, data, len, flags)); -+ -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ set_errno(ENOTCONN); -+ return -1; -+ } -+ -+ if (unlikely(len > UDP_SND_SIZE_MAX(sock->conn))) { -+ LSTACK_LOG(ERR, LSTACK, "Message too long\n"); -+ set_errno(EMSGSIZE); -+ return -1; -+ } -+ -+ if (unlikely(mr->app_free_count < 1)) { -+ mr->app_free_count = mr->ops->free_count(mr); -+ if (unlikely(mr->app_free_count < 1)) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ set_errno(EWOULDBLOCK); -+ return -1; -+ } -+ } -+ -+ if (len <= UDP_MSS && (flags & MSG_MORE) == 0) { -+ copied_total = stack_udp_write_one(sock, mr, data, len, flags, to, tolen); -+ } else { -+ copied_total = stack_udp_write_bulk(sock, mr, data, len, flags, to, tolen); -+ } -+ -+ return copied_total > 0 ? copied_total : -1; -+} -+ -+static ssize_t stack_udp_output(struct netconn *conn, bool *output_again, struct mem_thread *mt) -+{ -+ struct mbox_ring *mr = &conn->sendmbox->mring; -+ err_t err; -+ struct netbuf *nbuf_pkts[UDP_SND_OUTPUT_NUM]; -+ unsigned nbuf_num = 0; -+ unsigned pbuf_num = 0; -+ size_t send_total = 0; -+ size_t send_len; -+ -+ *output_again = false; -+ -+ nbuf_num = mr->ops->dequeue_burst(mr, (void **)nbuf_pkts, UDP_SND_OUTPUT_NUM); -+ if (unlikely(nbuf_num == 0)) { -+ return 0; -+ } -+ if (unlikely(nbuf_num == UDP_SND_OUTPUT_NUM) && -+ mr->ops->count(mr) > 0) { -+ *output_again = true; -+ } -+ -+ for (unsigned i = 0; i < nbuf_num; ++i) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(conn=%p, fd=%d, nbuf_pkts[%d]=%p {.p=%p, .tot_len=%u})\n", -+ __FUNCTION__, conn, conn->callback_arg.socket, -+ i, nbuf_pkts[i], nbuf_pkts[i]->p, nbuf_pkts[i]->p->tot_len)); -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(get_protocol_stack()->stack_idx, &(nbuf_pkts[i]->p), 1, GAZELLE_LATENCY_WRITE_LWIP, 0); -+ -+ if (mt != NULL) { -+ pbuf_num += pbuf_clen(nbuf_pkts[i]->p); -+ } -+ -+ /* ip4_frag/ip6_frag would: -+ * 1. split pbuf list and modify tot_len. -+ * 2. free node of pbuf list, except for the pbuf head. -+ */ -+ send_len = nbuf_pkts[i]->p->tot_len; -+ /* This would add header 'UDP_HLEN' ! */ -+ err = netconn_send(conn, nbuf_pkts[i]); -+ if (err != ERR_OK) { -+ LSTACK_LOG(ERR, LSTACK, "netconn_send failed, err %d\n", err); -+ break; -+ } -+ send_total += send_len; -+ } -+ for (unsigned i = 0; i < nbuf_num; ++i) { -+ netbuf_free(nbuf_pkts[i]); -+ } -+ -+ if (mt != NULL) { -+ mem_mbuf_migrate_enqueue(mt, pbuf_num); -+ } -+ -+ return (err == ERR_OK ? send_total : -1); -+} -+ -+static void callback_udp_send(struct rpc_msg *msg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct lwip_sock *sock = msg->args[MSG_ARG_0].p; -+ struct mem_thread *mt = msg->args[MSG_ARG_1].p; -+ bool output_again; -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_sock_latency(sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ -+ msg->result = stack_udp_output(sock->conn, &output_again, mt); -+ if (output_again) { -+ rpc_async_call(&stack->rpc_queue, msg, RPC_MSG_REUSE | RPC_MSG_RECALL); -+ } -+ -+ return; -+} -+ -+static inline int rpc_call_udp_send(rpc_queue *queue, struct lwip_sock *sock) -+{ -+ struct rpc_msg *msg; -+ -+ if (get_protocol_stack_group()->latency_start) -+ time_stamp_into_rpcmsg(sock); -+ -+ msg = sock_mbox_private_get(sock->conn->sendmbox); -+ msg->args[MSG_ARG_0].p = sock; -+ msg->args[MSG_ARG_1].p = mem_thread_migrate_get(sock->stack_id); -+ -+ rpc_async_call(queue, msg, RPC_MSG_REUSE); -+ return 0; -+} -+ -+static void rtw_stack_udp_send(struct lwip_sock *sock) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ rpc_call_udp_send(&stack->rpc_queue, sock); -+} -+ -+static void rtc_stack_udp_send(struct lwip_sock *sock) -+{ -+ bool output_again; -+ do { -+ stack_udp_output(sock->conn, &output_again, NULL); -+ } while (output_again); -+} -+ -+static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, int flags) -+{ -+ struct mbox_ring *mr = &sock->conn->recvmbox->mring; -+ struct pbuf **extcache_list; -+ struct netbuf *nbuf; -+ err_t err = ERR_OK; -+ uint16_t copied_total = 0; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, msg=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, sock, msg, len, flags)); -+ -+ if (mr->ops->recv_start_burst(mr, (void **)&nbuf, 1) == 0) { -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ err = ERR_CONN; -+ } else { -+ err = ERR_WOULDBLOCK; -+ } -+ goto out; -+ } -+ if (unlikely(lwip_netconn_is_err_msg(nbuf, &err))) { -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, 0); -+ goto out; -+ } -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_READ_APP_CALL, sys_now_us()); -+ -+ /* let not free inside by MSG_PEEK */ -+ sock->lastdata.netbuf = nbuf; -+ err = lwip_recvfrom_udp_raw(sock, flags | MSG_PEEK, msg, &copied_total, 0); -+ sock->lastdata.netbuf = NULL; -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_READ_LSTACK, 0); -+ -+ if (mr->flags & MBOX_FLAG_PEEK) { -+ extcache_list = NULL; -+ } else { -+ extcache_list = (struct pbuf **)&mr->st_obj; -+ mem_extcache_put_pbuf(nbuf->p, NULL, extcache_list); -+ } -+ -+ mr->app_recvd_len += copied_total; -+ mr->app_queued_num++; -+ if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || -+ mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -+ if (extcache_list != NULL) { -+ mem_extcache_flush_pbuf(extcache_list); -+ } -+ mr->ops->recv_finish_burst(mr); -+ mr->app_queued_num = 0; -+ mr->app_recvd_len = 0; -+ } -+ -+ if (err == ERR_OK) { -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, copied_total); -+ return copied_total; -+ } -+out: -+ set_errno(err_to_errno(err)); -+ return -1; -+} -+ -+ -+static uint16_t rtw_stack_tcp_write_one(const struct lwip_sock *sock, struct mbox_ring *mr, -+ const char *data, uint16_t len, int flags) -+{ -+ struct pbuf **extcache_list = (struct pbuf **)&sock->conn->recvmbox->mring.st_obj; -+ struct pbuf *p; -+ -+ p = mem_extcache_get_pbuf(sock->stack_id, true, extcache_list); -+ if (p == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "mem_extcache_get_pbuf failed\n"); -+ set_errno(ENOMEM); -+ return 0; -+ } -+ -+ write_pbuf(p, data, len, 0); -+ if ((flags & MSG_MORE) == 0) { -+ p->tcp_psh = 1; -+ } -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ -+ mr->ops->enqueue_burst(mr, (void **)&p, 1); -+ mr->app_free_count -= 1; -+ -+ return len; -+} -+ -+static uint16_t rtw_stack_tcp_write_bulk(const struct lwip_sock *sock, struct mbox_ring *mr, -+ const char *data, uint16_t len, int flags) -+{ -+ struct pbuf **extcache_list = (struct pbuf **)&sock->conn->recvmbox->mring.st_obj; -+ unsigned pbuf_num; -+ struct pbuf *pbuf_pkts[TCP_SND_QUEUELEN_MAX]; -+ struct pbuf *tail; -+ -+ pbuf_num = (len + TCP_MSS - 1) / TCP_MSS; -+ pbuf_num = mem_extcache_get_pbuf_bulk(sock->stack_id, pbuf_pkts, pbuf_num, true, extcache_list); -+ if (unlikely(pbuf_num == 0)) { -+ LSTACK_LOG(ERR, LSTACK, "mem_extcache_get_pbuf_bulk failed, pbuf_num %u\n", pbuf_num); -+ set_errno(ENOMEM); -+ return 0; -+ } -+ -+ write_pbuf_bulk(pbuf_pkts, pbuf_num, TCP_MSS, data, len, 0); -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, pbuf_pkts, pbuf_num, GAZELLE_LATENCY_WRITE_INTO_RING, 0); -+ -+ tail = pbuf_pkts[pbuf_num - 1]; -+ if ((flags & MSG_MORE) == 0) { -+ tail->tcp_psh = 1; -+ } -+ -+ mr->app_tail_left = TCP_MSS - tail->tot_len; -+ if (mr->app_tail_left > TCP_SND_APPEND_LEN) { -+ pbuf_num--; -+ } else { -+ mr->app_tail_left = 0; -+ tail = NULL; -+ } -+ -+ /* must first enqueue before push_tail !!! */ -+ mr->app_free_count -= pbuf_num; -+ mr->ops->enqueue_burst(mr, (void **)pbuf_pkts, pbuf_num); -+ if (tail != NULL) { -+ mr->ops->push_tail(mr, tail); -+ } -+ -+ return len; -+} -+ -+static inline bool tcp_seg_need_append(uint16_t oversize_left, uint16_t payload_size, uint16_t data_len, int flags) -+{ -+ if (flags & MSG_MORE) { -+ return true; -+ } -+ /* Avoid splitting once write len into 3 segs. */ -+ if ((data_len % payload_size) <= oversize_left) -+ return true; -+ return false; -+} -+static uint16_t rtw_stack_tcp_append(struct mbox_ring *mr, const char *data, uint16_t len, int flags) -+{ -+ struct pbuf *p; -+ bool need_append; -+ uint16_t buf_copy_len; -+ -+ if (mr->app_tail_left == 0) { -+ return 0; -+ } -+ -+ buf_copy_len = 0; -+ p = (struct pbuf *)mr->ops->pop_tail(mr, NULL); -+ if (p != NULL) { -+ need_append = tcp_seg_need_append(mr->app_tail_left, TCP_MSS, len, flags); -+ if (need_append) { -+ buf_copy_len = LWIP_MIN(len, mr->app_tail_left); -+ pbuf_append_take(p, p, data, buf_copy_len, NULL); -+ } -+ mr->ops->enqueue_burst(mr, (void **)&p, 1); -+ mr->app_free_count -= 1; -+ } -+ -+ mr->app_tail_left = 0; -+ -+ return buf_copy_len; -+} -+ -+static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, size_t len, int flags) -+{ -+ struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ uint16_t buf_copy_len; -+ uint32_t total_copy_len = (uint32_t)len; -+ uint32_t copied_total = 0; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, data=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, sock, data, len, flags)); -+ -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ set_errno(ENOTCONN); -+ return -1; -+ } -+ -+ if (unlikely(mr->app_free_count < 2)) { -+ mr->app_free_count = mr->ops->free_count(mr); -+ if (unlikely(mr->app_free_count < 2)) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ set_errno(EWOULDBLOCK); -+ return -1; -+ } -+ } -+ -+ copied_total = rtw_stack_tcp_append(mr, data, LWIP_MIN(TCP_MSS, total_copy_len), flags); -+ if (copied_total == total_copy_len) { -+ return copied_total; -+ } -+ -+ if (total_copy_len <= TCP_MSS) { -+ /* write one pbuf */ -+ copied_total += rtw_stack_tcp_write_one(sock, mr, data + copied_total, total_copy_len, flags); -+ } else { -+ if (total_copy_len > mr->app_free_count * TCP_MSS) { -+ mr->app_free_count = mr->ops->free_count(mr); -+ if (unlikely(mr->app_free_count < 2)) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ set_errno(EWOULDBLOCK); -+ goto out; -+ } -+ if (total_copy_len > mr->app_free_count * TCP_MSS) { -+ total_copy_len = mr->app_free_count * TCP_MSS; -+ } -+ } -+ /* write bulk pbuf */ -+ while (total_copy_len > 0) { -+ buf_copy_len = LWIP_MIN(total_copy_len, TCP_SND_SIZE_MAX); -+ buf_copy_len = rtw_stack_tcp_write_bulk(sock, mr, data + copied_total, buf_copy_len, flags); -+ if (unlikely(buf_copy_len == 0)) { -+ goto out; -+ } -+ copied_total += buf_copy_len; -+ total_copy_len -= buf_copy_len; -+ } -+ } -+ -+out: -+ return copied_total > 0 ? copied_total : -1; -+} -+ -+static struct pbuf *rtw_tcp_output_pop_tail(struct mbox_ring *mr) -+{ -+ void *tail; -+ -+ tail = mr->ops->read_tail(mr); -+ if (tail == NULL) -+ return NULL; -+ -+ if (mr->ops->count(mr) > 0) -+ return NULL; -+ return mr->ops->pop_tail(mr, tail); -+} -+ -+static uint16_t rtw_stack_tcp_output(struct netconn *conn, bool *output_again, struct mem_thread *mt) -+{ -+ struct mbox_ring *mr = &conn->sendmbox->mring; -+ struct pbuf *pbuf_pkts[TCP_SND_OUTPUT_NUM]; -+ uint16_t pbuf_num; -+ -+ *output_again = false; -+ -+ /* must first dequeue before pop_tail !!! */ -+ pbuf_num = mr->ops->dequeue_burst(mr, (void **)pbuf_pkts, TCP_SND_OUTPUT_NUM); -+ -+ if (pbuf_num < TCP_SND_OUTPUT_NUM) { -+ if (pbuf_num == 0 || pbuf_pkts[pbuf_num - 1]->len == TCP_MSS) { -+ pbuf_pkts[pbuf_num] = rtw_tcp_output_pop_tail(mr); -+ if (pbuf_pkts[pbuf_num] != NULL) { -+ pbuf_num++; -+ } -+ } -+ -+ if (unlikely(pbuf_num == 0)) { -+ return 0; -+ } -+ } else { -+ if (mr->ops->count(mr) > 0 || mr->ops->read_tail(mr) != NULL) { -+ *output_again = true; -+ } -+ } -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(conn=%p, fd=%d, pbuf_num=%u)\n", -+ __FUNCTION__, conn, conn->callback_arg.socket, pbuf_num)); -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(get_protocol_stack()->stack_idx, pbuf_pkts, pbuf_num, GAZELLE_LATENCY_WRITE_LWIP, 0); -+ -+ if (mt != NULL) { -+ mem_mbuf_migrate_enqueue(mt, pbuf_num); -+ } -+ -+ if (pbuf_num > 1) { -+ lwip_tcp_tso_merge_seg(conn->pcb.tcp, pbuf_pkts, &pbuf_num); -+ } -+ return lwip_tcp_prepare_seg(conn->pcb.tcp, pbuf_pkts, pbuf_num); -+} -+ -+ -+static uint32_t pbuf_copy_and_free(struct pbuf **left_pbuf, struct pbuf **extcache_list, char *data, uint32_t len) -+{ -+ struct pbuf *q, *t; -+ uint16_t buf_copy_len; -+ uint32_t copied_total = 0; -+ -+ q = *left_pbuf; -+ t = NULL; -+ while (copied_total < len && q != NULL) { -+ buf_copy_len = LWIP_MIN(q->len, len - copied_total); -+ -+ if (buf_copy_len > 0) { -+ MEMCPY(data + copied_total, q->payload, buf_copy_len); -+ copied_total += buf_copy_len; -+ -+ if (buf_copy_len < q->len) { -+ pbuf_remove_header(q, buf_copy_len); -+ break; -+ } else { -+ q->tot_len = q->len = 0; -+ } -+ } -+ -+ t = q; -+ q = q->next; -+ } -+ -+ if (t != NULL && extcache_list != NULL) { -+ t->next = NULL; -+ mem_extcache_put_pbuf(*left_pbuf, t, extcache_list); -+ } -+ *left_pbuf = q; -+ -+ return copied_total; -+} -+ -+static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, int flags, -+ struct sockaddr *from, socklen_t *fromlen) -+{ -+ struct mbox_ring *mr = &sock->conn->recvmbox->mring; -+ struct pbuf **extcache_list; -+ err_t err = ERR_OK; -+ struct pbuf *p; -+ -+ uint32_t buf_copy_len; -+ uint32_t total_copy_len = len; -+ uint32_t copied_total = 0; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, data=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, sock, data, len, flags)); -+ -+ if (mr->flags & MBOX_FLAG_PEEK) { -+ extcache_list = NULL; -+ } else { -+ extcache_list = (struct pbuf **)&mr->st_obj; -+ } -+ -+ if (sock->lastdata.pbuf != NULL) { -+ // TODO: support MSG_PEEK -+ buf_copy_len = pbuf_copy_and_free(&sock->lastdata.pbuf, extcache_list, data, total_copy_len); -+ copied_total += buf_copy_len; -+ total_copy_len -= buf_copy_len; -+ mr->app_recvd_len += buf_copy_len; -+ } -+ -+ while (total_copy_len > 0) { -+ if (mr->ops->recv_start_burst(mr, (void **)&p, 1) == 0) { -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ err = ERR_CONN; -+ } else { -+ err = ERR_WOULDBLOCK; -+ } -+ break; -+ } -+ mr->app_queued_num++; -+ if (unlikely(lwip_netconn_is_err_msg(p, &err))) { -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, copied_total); -+ break; -+ } -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_READ_APP_CALL, sys_now_us()); -+ -+ sock->lastdata.pbuf = p; -+ // TODO: support MSG_PEEK -+ buf_copy_len = pbuf_copy_and_free(&sock->lastdata.pbuf, extcache_list, data + copied_total, total_copy_len); -+ copied_total += buf_copy_len; -+ total_copy_len -= buf_copy_len; -+ mr->app_recvd_len += buf_copy_len; -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_READ_LSTACK, 0); -+ -+ if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || -+ mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -+ if (sock->lastdata.pbuf == NULL) { -+ mr->ops->recv_finish_burst(mr); -+ mr->app_queued_num = 0; -+ } -+ } -+ } -+ -+ if (mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -+ if (extcache_list != NULL) { -+ mem_extcache_flush_pbuf(extcache_list); -+ } -+ mr->app_recvd_len = 0; -+ } -+ -+ lwip_tcp_recv_from(sock->conn, from, fromlen, copied_total); -+ -+ if (copied_total > 0) { -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, copied_total); -+ return copied_total; -+ } -+ -+ set_errno(err_to_errno(err)); -+ if (err == ERR_CLSD) { -+ return 0; -+ } -+ return -1; -+} -+ -+ -+#define RECVD_UNCOMMITTED(msg) ((msg)->args[MSG_ARG_2].ul) -+#define RECVD_CURR_SEQ(msg) ((msg)->args[MSG_ARG_3].ul) -+#define RECVD_LAST_SEQ(msg) ((msg)->args[MSG_ARG_4].ul) -+ -+static inline bool rpc_commit_tcp_recvd(struct rpc_msg *recvmsg, unsigned long threshold) -+{ -+ if (RECVD_UNCOMMITTED(recvmsg) >= threshold) { -+ __atomic_add_fetch(&RECVD_CURR_SEQ(recvmsg), RECVD_UNCOMMITTED(recvmsg), __ATOMIC_RELEASE); -+ RECVD_UNCOMMITTED(recvmsg) = 0; -+ return true; -+ } -+ return false; -+} -+ -+#if TCP_RECV_AND_UPDATE -+static inline unsigned long rpc_read_tcp_recvd(struct rpc_msg *recvmsg) -+{ -+ unsigned long curr_recvd_seq; -+ unsigned long recvd; -+ -+ curr_recvd_seq = __atomic_load_n(&RECVD_CURR_SEQ(recvmsg), __ATOMIC_ACQUIRE); -+ recvd = curr_recvd_seq - RECVD_LAST_SEQ(recvmsg); -+ if (recvd > 0) { -+ /* update last recvd seq */ -+ RECVD_LAST_SEQ(recvmsg) = curr_recvd_seq; -+ } -+ return recvd; -+} -+ -+static void callback_tcp_recvd(struct rpc_msg *recvmsg) -+{ -+ struct lwip_sock *sock = recvmsg->args[MSG_ARG_0].p; -+ unsigned long recvd; -+ -+ recvd = rpc_read_tcp_recvd(recvmsg); -+ lwip_tcp_recvd(sock->conn, recvd, 0); -+ -+ recvmsg->result = recvd; -+ return; -+} -+#endif /* TCP_RECV_AND_UPDATE */ -+ -+static inline int rpc_call_tcp_recvd(rpc_queue *queue, struct lwip_sock *sock, size_t recvd, int flags) -+{ -+ struct rpc_msg *recvmsg; -+ -+ recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -+ recvmsg->args[MSG_ARG_0].p = sock; -+ recvmsg->result = 0; -+ -+ RECVD_UNCOMMITTED(recvmsg) += recvd; -+ if (rpc_commit_tcp_recvd(recvmsg, TCP_WND_UPDATE_THRESHOLD << 1)) { -+ rpc_async_call(queue, recvmsg, RPC_MSG_REUSE); -+ } -+ -+ return 0; -+} -+ -+static void rtw_stack_tcp_recvd(struct lwip_sock *sock, ssize_t recvd, int flags) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ -+ if (recvd <= 0 || flags & MSG_PEEK) { -+ return; -+ } -+ rpc_call_tcp_recvd(&stack->rpc_queue, sock, recvd, flags); -+} -+ -+static void rtc_stack_tcp_recvd(struct lwip_sock *sock, ssize_t recvd, int flags) -+{ -+ if (recvd <= 0 || flags & MSG_PEEK) { -+ return; -+ } -+ lwip_tcp_recvd(sock->conn, recvd, flags); -+} -+ -+static void callback_tcp_send(struct rpc_msg *sendmsg) -+{ -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct lwip_sock *sock = sendmsg->args[MSG_ARG_0].p; -+ struct mem_thread *mt = sendmsg->args[MSG_ARG_1].p; -+ bool output_again; -+ err_t err; -+ -+ if (unlikely(sock->conn->pcb.tcp == NULL)) -+ return; -+ -+ if (get_protocol_stack_group()->latency_start) -+ calculate_sock_latency(sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -+ -+ do { -+ if (!lwip_tcp_allow_send(sock->conn->pcb.tcp)) { -+ rpc_async_call(&stack->rpc_queue, sendmsg, RPC_MSG_REUSE | RPC_MSG_RECALL); -+ break; -+ } -+ sendmsg->result += rtw_stack_tcp_output(sock->conn, &output_again, mt); -+ } while (output_again); -+ err = tcp_output(sock->conn->pcb.tcp); -+ if (unlikely(err != ERR_OK)) { -+ LSTACK_LOG(ERR, LSTACK, "tcp_output failed, sock %p, err %u\n", sock, err); -+ } -+ -+#if TCP_RECV_AND_UPDATE -+ struct rpc_msg *recvmsg; -+ if (RECVD_UNCOMMITTED(sendmsg)) { -+ RECVD_UNCOMMITTED(sendmsg) = 0; -+ recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -+ callback_tcp_recvd(recvmsg); -+ } -+#endif /* TCP_RECV_AND_UPDATE */ -+ -+ return; -+} -+ -+static inline int rpc_call_tcp_send(rpc_queue *queue, struct lwip_sock *sock) -+{ -+ struct rpc_msg *sendmsg; -+ -+ if (get_protocol_stack_group()->latency_start) -+ time_stamp_into_rpcmsg(sock); -+ -+ sendmsg = sock_mbox_private_get(sock->conn->sendmbox); -+ sendmsg->result = 0; -+ sendmsg->args[MSG_ARG_0].p = sock; -+ sendmsg->args[MSG_ARG_1].p = mem_thread_migrate_get(sock->stack_id); -+ -+#if TCP_RECV_AND_UPDATE -+ struct rpc_msg *recvmsg; -+ recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -+ RECVD_UNCOMMITTED(sendmsg) = rpc_commit_tcp_recvd(recvmsg, TCP_WND_UPDATE_THRESHOLD); -+#endif /* TCP_RECV_AND_UPDATE */ -+ -+ rpc_async_call(queue, sendmsg, RPC_MSG_REUSE); -+ return 0; -+} -+ -+static void rtw_stack_tcp_send(struct lwip_sock *sock) -+{ -+ struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -+ rpc_call_tcp_send(&stack->rpc_queue, sock); -+} -+ -+ -+static ssize_t rtc_stack_tcp_write(struct lwip_sock *sock, const char *data, size_t len, int flags) -+{ -+ struct tcp_pcb *pcb = sock->conn->pcb.tcp; -+ err_t err = ERR_OK; -+ int write_flags, write_more; -+ -+ uint16_t buf_copy_len; -+ uint32_t total_copy_len; -+ uint32_t copied_total = 0; -+ -+ write_more = TCP_WRITE_FLAG_MORE; -+ write_flags = NETCONN_COPY | -+ ((flags & MSG_MORE) ? NETCONN_MORE : 0) | -+ ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0); -+ -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ set_errno(ENOTCONN); -+ return -1; -+ } -+ -+ total_copy_len = LWIP_MIN((uint32_t)len, (uint32_t)pcb->snd_buf); -+ if (unlikely(total_copy_len == 0)) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ set_errno(EWOULDBLOCK); -+ return -1; -+ } -+ -+ while (total_copy_len > 0) { -+ if (total_copy_len <= TCP_SND_SIZE_MAX) { -+ buf_copy_len = total_copy_len; -+ write_more = 0; -+ } else { -+ buf_copy_len = TCP_SND_SIZE_MAX; -+ } -+ -+ err = tcp_write(pcb, data + copied_total, buf_copy_len, write_flags | write_more); -+ if (err != ERR_OK) { -+ LSTACK_LOG(ERR, LSTACK, "tcp_write failed, errno %d\n", err_to_errno(err)); -+ break; -+ } -+ total_copy_len -= buf_copy_len; -+ copied_total += buf_copy_len; -+ } -+ -+ if (copied_total > 0) { -+ return copied_total; -+ } -+ set_errno(err_to_errno(err)); -+ return -1; -+} -+ -+static void rtc_stack_tcp_send(struct lwip_sock *sock) -+{ -+ tcp_output(sock->conn->pcb.tcp); -+} -+ -+ -+ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, -+ struct sockaddr *from, socklen_t *fromlen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ ssize_t recvd; -+ struct iovec vec; -+ struct msghdr msg; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(%d, mem=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, fd, mem, len, flags)); -+ -+ if (unlikely(mem == NULL || len <= 0)) { -+ set_errno(EINVAL); -+ return -1; -+ } -+ -+ if (unlikely(!sock->affinity_numa)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = true; -+ } -+ -+ switch (NETCONN_TYPE(sock->conn)) { -+ case NETCONN_TCP: -+ /* TODO: support MSG_WAITALL */ -+ recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); -+ if (recvd < 0 && errno == EWOULDBLOCK) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); -+ } -+ } -+#if TCP_RECV_AND_UPDATE -+ if (recvd > 0) { -+ ioops.stack_tcp_recvd(sock, recvd, flags); -+ } -+#endif /* TCP_RECV_AND_UPDATE */ -+ break; -+ case NETCONN_UDP: -+ vec.iov_base = mem; -+ vec.iov_len = len; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ msg.msg_iov = &vec; -+ msg.msg_iovlen = 1; -+ msg.msg_name = from; -+ msg.msg_namelen = (fromlen ? *fromlen : 0); -+ recvd = ioops.stack_udp_readmsg(sock, &msg, flags); -+ if (recvd < 0 && errno == EWOULDBLOCK) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ recvd = ioops.stack_udp_readmsg(sock, &msg, flags); -+ } -+ } -+ if (recvd > 0 && fromlen != NULL) { -+ *fromlen = msg.msg_namelen; -+ } -+ break; -+ default: -+ recvd = -1; -+ break; -+ } -+ -+ return recvd; -+} -+ -+ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ ssize_t ret, recvd = 0; -+ -+ ret = lwip_recvmsg_check(NULL, msg, flags); -+ if (unlikely(ret <= 0)) { -+ return ret; -+ } -+ -+ if (unlikely(!sock->affinity_numa)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = true; -+ } -+ -+ switch (NETCONN_TYPE(sock->conn)) { -+ case NETCONN_TCP: -+ for (int i = 0; i < msg->msg_iovlen; ++i) { -+ ret = sockio_recvfrom(fd, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags, NULL, NULL); -+ if (ret <= 0) { -+ if (recvd == 0) -+ recvd = ret; -+ break; -+ } -+ recvd += ret; -+ } -+ break; -+ case NETCONN_UDP: -+ recvd = ioops.stack_udp_readmsg(sock, msg, flags); -+ if (recvd < 0 && errno == EWOULDBLOCK) { -+ if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ recvd = ioops.stack_udp_readmsg(sock, msg, flags); -+ } -+ } -+ break; -+ default: -+ recvd = -1; -+ break; -+ } -+ -+ return recvd; -+} -+ -+ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, -+ const struct sockaddr *to, socklen_t tolen) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ ssize_t ret; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(%d, mem=%p, size=%"SZT_F", flags=0x%x)\n", -+ __FUNCTION__, fd, mem, len, flags)); -+ -+ if (unlikely(mem == NULL || len <= 0)) { -+ set_errno(EINVAL); -+ return -1; -+ } -+ -+ if (unlikely(!sock->affinity_numa)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = true; -+ } -+ -+ switch (NETCONN_TYPE(sock->conn)) { -+ case NETCONN_TCP: -+ ret = ioops.stack_tcp_write(sock, mem, len, flags); -+ if (ret < 0) { -+ if (errno == EWOULDBLOCK) { -+ sock_event_wait(sock, true); -+ } -+ } else { -+ ioops.stack_tcp_send(sock); -+ } -+ break; -+ case NETCONN_UDP: -+ ret = ioops.stack_udp_write(sock, mem, len, flags, to, tolen); -+ if (ret < 0) { -+ if (errno == EWOULDBLOCK) { -+ sock_event_wait(sock, true); -+ } -+ } else { -+ ioops.stack_udp_send(sock); -+ } -+ break; -+ default: -+ ret = -1; -+ break; -+ } -+ -+ return ret; -+} -+ -+ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ ssize_t ret = -1; -+ size_t written = 0; -+ int write_more = MSG_MORE; -+ int i; -+ -+ ret = lwip_sendmsg_check(sock, msg, flags); -+ if (unlikely(ret <= 0)) { -+ return ret; -+ } -+ -+ if (unlikely(!sock->affinity_numa)) { -+ thread_bind_stack(sock->stack_id); -+ sock->affinity_numa = true; -+ } -+ -+ switch (NETCONN_TYPE(sock->conn)) { -+ case NETCONN_TCP: -+ for (i = 0; i < msg->msg_iovlen; ++i) { -+ if (i == msg->msg_iovlen - 1) { -+ write_more = 0; -+ } -+ ret = ioops.stack_tcp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more); -+ if (ret < 0) { -+ if (errno == EWOULDBLOCK) { -+ sock_event_wait(sock, true); -+ } -+ break; -+ } -+ written += ret; -+ } -+ if (written > 0) { -+ ioops.stack_tcp_send(sock); -+ } -+ break; -+ case NETCONN_UDP: -+ for (i = 0; i < msg->msg_iovlen; ++i) { -+ if (i == msg->msg_iovlen - 1) { -+ write_more = 0; -+ } -+ ret = ioops.stack_udp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more, NULL, 0); -+ if (ret < 0) { -+ if (errno == EWOULDBLOCK) { -+ sock_event_wait(sock, true); -+ } -+ break; -+ } -+ written += ret; -+ } -+ if (written > 0) { -+ ioops.stack_udp_send(sock); -+ } -+ break; -+ default: -+ written = -1; -+ break; -+ } -+ -+ return written > 0 ? written : ret; -+} -+ -+ssize_t sockio_read(int fd, void *mem, size_t len) -+{ -+ return sockio_recvfrom(fd, mem, len, 0, NULL, NULL); -+} -+ -+ssize_t sockio_write(int fd, const void *mem, size_t len) -+{ -+ return sockio_sendto(fd, mem, len, 0, NULL, 0); -+} -+ -+ssize_t sockio_recv(int fd, void *mem, size_t len, int flags) -+{ -+ return sockio_recvfrom(fd, mem, len, flags, NULL, NULL); -+} -+ -+ssize_t sockio_send(int fd, const void *mem, size_t len, int flags) -+{ -+ return sockio_sendto(fd, mem, len, flags, NULL, 0); -+} -+ -+ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt) -+{ -+ struct msghdr msg; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -+ msg.msg_iovlen = iovcnt; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ -+ return sockio_recvmsg(fd, &msg, 0); -+} -+ -+ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt) -+{ -+ struct msghdr msg; -+ -+ msg.msg_name = NULL; -+ msg.msg_namelen = 0; -+ msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -+ msg.msg_iovlen = iovcnt; -+ msg.msg_control = NULL; -+ msg.msg_controllen = 0; -+ msg.msg_flags = 0; -+ -+ return sockio_sendmsg(fd, &msg, 0); -+} -+ -+void sockio_ops_init(void) -+{ -+ struct sockio_ops *ops = &ioops; -+ -+ ops->stack_udp_write = stack_udp_write; -+ ops->stack_udp_readmsg = stack_udp_readmsg; -+ ops->stack_tcp_read = stack_tcp_read; -+ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ ops->stack_udp_send = rtc_stack_udp_send; -+ ops->stack_tcp_write = rtc_stack_tcp_write; -+ ops->stack_tcp_send = rtc_stack_tcp_send; -+ ops->stack_tcp_recvd = rtc_stack_tcp_recvd; -+ } else { -+ ops->stack_udp_send = rtw_stack_udp_send; -+ ops->stack_tcp_write = rtw_stack_tcp_write; -+ ops->stack_tcp_send = rtw_stack_tcp_send; -+ ops->stack_tcp_recvd = rtw_stack_tcp_recvd; -+ } -+} -+ -+static int sockio_mbox_init(struct lwip_sock *sock) -+{ -+ int ret; -+ sys_mbox_t sendmbox = sock->conn->sendmbox; -+ sys_mbox_t recvmbox = sock->conn->recvmbox; -+ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ return 0; -+ } -+ -+ switch (NETCONN_TYPE(sock->conn)) { -+ case NETCONN_TCP: -+ ret = sock_mbox_private_init(sendmbox, callback_tcp_send); -+#if TCP_RECV_AND_UPDATE -+ if (sys_mbox_valid(&recvmbox)) { -+ ret |= sock_mbox_private_init(recvmbox, callback_tcp_recvd); -+ } -+#endif /* TCP_RECV_AND_UPDATE */ -+ break; -+ case NETCONN_UDP: -+ ret = sock_mbox_private_init(sendmbox, callback_udp_send); -+ break; -+ default: -+ ret = 0; -+ } -+ -+ if (ret != 0) { -+ sock_mbox_private_free(&sendmbox->mring); -+ if (sys_mbox_valid(&recvmbox)) { -+ sock_mbox_private_free(&recvmbox->mring); -+ } -+ } -+ return ret; -+} -+ -+bool sockio_mbox_pending(const struct lwip_sock *sock) -+{ -+ struct rpc_msg *msg; -+ -+ if (POSIX_IS_CLOSED(sock)) -+ return false; -+ -+ if (sys_mbox_valid(&sock->conn->sendmbox)) { -+ msg = sock_mbox_private_get(sock->conn->sendmbox); -+ if (msg != NULL && !lockless_queue_node_is_poped(&msg->queue_node)) { -+ return true; -+ } -+ } -+ if (sys_mbox_valid(&sock->conn->recvmbox)) { -+ msg = sock_mbox_private_get(sock->conn->recvmbox); -+ if (msg != NULL && !lockless_queue_node_is_poped(&msg->queue_node)) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+int do_lwip_init_sock(int fd) -+{ -+ int ret; -+ struct protocol_stack *stack = get_protocol_stack(); -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock == NULL) { -+ return -1; -+ } -+ -+ sock->type = 0; -+ sock->listen_next = NULL; -+ sock->stack_id = stack->stack_idx; -+ -+ /* RTC affinity by stack_setup_app_thread() */ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ sock->affinity_numa = true; -+ } else { -+ sock->affinity_numa = false; -+ } -+ -+ sock->sk_wait = NULL; -+ ret = sock_event_init(&sock->sk_event); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "sock_event_init failed\n"); -+ return -1; -+ } -+ -+ ret = sockio_mbox_init(sock); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "sockio_mbox_init failed\n"); -+ return -1; -+ } -+ -+ get_protocol_stack_by_id(sock->stack_id)->conn_num++; -+ return 0; -+} -+ -+void do_lwip_clean_sock(int fd) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ return; -+ } -+ -+ sock_event_free(&sock->sk_event, sock->sk_wait); -+ sock->sk_wait = NULL; -+ -+ sock->listen_next = NULL; -+ -+ get_protocol_stack_by_id(sock->stack_id)->conn_num--; -+ sock->stack_id = -1; -+} -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -new file mode 100644 -index 0000000..8f01f31 ---- /dev/null -+++ b/src/lstack/core/lstack_mempool.c -@@ -0,0 +1,1014 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#include -+ -+#include -+#include -+ -+#include "lstack_mempool.h" -+#include "lstack_log.h" -+#include "lstack_cfg.h" -+#include "common/dpdk_common.h" -+#include "lstack_dpdk.h" -+#include "lstack_protocol_stack.h" -+ -+#define MEM_THREAD_MANAGER_TIMEOUT 1 -+#define MEM_THREAD_MANAGER_MAX 64 -+ -+struct mem_thread_manager { -+ struct list_node mt_work_list; -+ struct list_node mt_free_list; -+ rte_spinlock_t list_lock; -+}; -+ -+struct mem_thread_group { -+ int tid; -+ pthread_t thread; -+ struct list_node mt_node; -+ struct mem_thread mt_array[PROTOCOL_STACK_MAX]; -+}; -+ -+static struct mem_stack g_mem_stack_group[PROTOCOL_STACK_MAX] = {0}; -+static PER_THREAD struct mem_thread_group *g_mem_thread_group = NULL; -+static struct mem_thread_manager g_mem_thread_manager = {0}; -+ -+static __rte_always_inline -+struct mem_stack *mem_stack_get(int stack_id) -+{ -+ return &g_mem_stack_group[stack_id]; -+} -+ -+struct rte_mempool *mem_get_mbuf_pool(int stack_id) -+{ -+ return g_mem_stack_group[stack_id].mbuf_pool; -+} -+ -+struct rte_mempool *mem_get_rpc_pool(int stack_id) -+{ -+ return g_mem_stack_group[stack_id].rpc_pool; -+} -+ -+static void mem_thread_manager_add_work(struct mem_thread_group *mt_group) -+{ -+ rte_spinlock_lock(&g_mem_thread_manager.list_lock); -+ list_add_node(&mt_group->mt_node, &g_mem_thread_manager.mt_work_list); -+ rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+} -+ -+static inline bool mem_thread_group_exist(const struct mem_thread_group *mt_group) -+{ -+ if (pthread_tryjoin_np(mt_group->thread, NULL) == 0) -+ return false; -+ return true; -+} -+ -+static void mem_thread_group_free(struct mem_thread_group *mt_group) -+{ -+ struct mem_thread *mt; -+ int stack_id; -+ -+ for (stack_id = 0; stack_id < PROTOCOL_STACK_MAX; stack_id++) { -+ mt = &mt_group->mt_array[stack_id]; -+ mem_thread_cache_free(mt); -+ } -+ free(mt_group); -+ return; -+} -+ -+static int mem_thread_group_init(int stack_id) -+{ -+ struct mem_thread *mt; -+ -+ if (rte_lcore_id() < RTE_MAX_LCORE) { -+ LSTACK_LOG(ERR, LSTACK, "tid %d, lcore_id %u is invalid\n", rte_gettid(), rte_lcore_id()); -+ return -1; -+ } -+ -+ if (g_mem_thread_group == NULL) { -+ g_mem_thread_group = (struct mem_thread_group *)calloc(1, sizeof(struct mem_thread_group)); -+ if (g_mem_thread_group == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "alloc mem_thread_group failed, stack_id %d\n", stack_id); -+ return -1; -+ } -+ g_mem_thread_group->tid = rte_gettid(); -+ g_mem_thread_group->thread = pthread_self(); -+ list_init_node(&g_mem_thread_group->mt_node); -+ mem_thread_manager_add_work(g_mem_thread_group); -+ } -+ -+ mt = &g_mem_thread_group->mt_array[stack_id]; -+ if (mem_thread_cache_init(mt) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "mem_thread_cache_init failed, stack_id %d\n", stack_id); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static inline struct mem_thread *mem_thread_group_get(int stack_id) -+{ -+ struct mem_thread *mt; -+ -+ if (likely(g_mem_thread_group != NULL)) { -+ mt = &g_mem_thread_group->mt_array[stack_id]; -+ if (likely(mt->mbuf_cache != NULL)) -+ return mt; -+ } -+ -+ if (mem_thread_group_init(stack_id) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "mem_thread_group_init failed, stack_id %d\n", stack_id); -+ return NULL; -+ } -+ mt = &g_mem_thread_group->mt_array[stack_id]; -+ return mt; -+} -+ -+static void *mem_thread_manager_thread(void *arg) -+{ -+ struct list_node *node, *next; -+ struct mem_thread_group *mt_group; -+ unsigned count = 0; -+ -+ rte_spinlock_init(&g_mem_thread_manager.list_lock); -+ list_init_head(&g_mem_thread_manager.mt_work_list); -+ list_init_head(&g_mem_thread_manager.mt_free_list); -+ -+ while(true) { -+ sleep(MEM_THREAD_MANAGER_TIMEOUT); -+ -+ rte_spinlock_lock(&g_mem_thread_manager.list_lock); -+ -+ list_for_each_node(node, next, &g_mem_thread_manager.mt_free_list) { -+ mt_group = container_of(node, struct mem_thread_group, mt_node); -+ list_del_node(node); -+ mem_thread_group_free(mt_group); -+ } -+ -+ list_for_each_node(node, next, &g_mem_thread_manager.mt_work_list) { -+ count++; -+ if (count > MEM_THREAD_MANAGER_MAX) { -+ /* move list head after the current node, -+ * and start traversing from this node next time */ -+ list_del_node(&g_mem_thread_manager.mt_work_list); -+ list_add_node(&g_mem_thread_manager.mt_work_list, node); -+ break; -+ } -+ -+ mt_group = container_of(node, struct mem_thread_group, mt_node); -+ if (mem_thread_group_exist(mt_group)) { -+ continue; -+ } -+ list_del_node(node); -+ list_add_node(node, &g_mem_thread_manager.mt_free_list); -+ } -+ -+ rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+ } -+ -+ return NULL; -+} -+ -+int mem_thread_manager_init(void) -+{ -+ return thread_create("gzmempool", 0, mem_thread_manager_thread, NULL); -+} -+ -+static __rte_always_inline -+struct mem_thread *mem_thread_get(int stack_id) -+{ -+ /* stack thread uses mbufpool_cache instead of buf_cache */ -+ if (get_protocol_stack() != NULL) -+ return NULL; -+ -+#if MEMP_DEBUG -+ if (RTE_PER_LCORE(_lcore_id) < RTE_MAX_LCORE) { -+ LWIP_DEBUGF(MEMP_DEBUG | LWIPGZ_LOG_FATAL, ("tid %d has invalid rte_lcore_id %u !\n", -+ rte_gettid(), RTE_PER_LCORE(_lcore_id))); -+ return NULL; -+ } -+#endif /* MEMP_DEBUG */ -+ -+ return mem_thread_group_get(stack_id); -+} -+ -+struct mem_obj_ops { -+ void (*init)(struct rte_mempool *mp, void *arg, void *obj, unsigned obj_idx); -+ unsigned (*get_stack_id)(const void *obj); -+ struct rte_mempool * (*get_pool)(const void *obj); -+}; -+ -+static __rte_always_inline -+void rpc_obj_init(struct rte_mempool *mp, void *arg, void *obj, unsigned obj_idx) -+{ -+ int stack_id = *(int *)arg; -+ struct rpc_msg *msg = obj; -+ msg->stack_id = stack_id; -+} -+ -+static __rte_always_inline -+unsigned rpc_obj_get_stack_id(const void *obj) -+{ -+ return ((const struct rpc_msg *)obj)->stack_id; -+} -+ -+static __rte_always_inline -+struct rte_mempool *rpc_obj_get_pool(const void *obj) -+{ -+ int stack_id = rpc_obj_get_stack_id(obj); -+ return mem_get_rpc_pool(stack_id); -+} -+ -+static __rte_always_inline -+void mbuf_obj_init(struct rte_mempool *mp, void *arg, void *obj, unsigned obj_idx) -+{ -+ int stack_id = *(int *)arg; -+ struct rte_mbuf *mbuf = obj; -+ struct mbuf_private *priv = mbuf_to_private(mbuf); -+ priv->stack_id = stack_id; -+} -+ -+static __rte_always_inline -+unsigned mbuf_obj_get_stack_id(const void *obj) -+{ -+ return mbuf_to_private((const struct rte_mbuf *)obj)->stack_id; -+} -+ -+static __rte_always_inline -+struct rte_mempool *mbuf_obj_get_pool(const void *obj) -+{ -+ int stack_id = mbuf_obj_get_stack_id(obj); -+ return mem_get_mbuf_pool(stack_id); -+} -+ -+static const struct mem_obj_ops rpc_obj_ops = { -+ .init = rpc_obj_init, -+ .get_stack_id = rpc_obj_get_stack_id, -+ .get_pool = rpc_obj_get_pool, -+}; -+ -+static const struct mem_obj_ops mbuf_obj_ops = { -+ .init = mbuf_obj_init, -+ .get_stack_id = mbuf_obj_get_stack_id, -+ .get_pool = mbuf_obj_get_pool, -+}; -+ -+struct mempool_ops { -+ struct rte_mempool *(*create)(const char *name, unsigned n, -+ unsigned cache_size, unsigned priv_size, unsigned data_room_size, int socket_id); -+ void (*put_bulk)(struct rte_mempool *pool, void *const *obj_table, unsigned n); -+ unsigned (*get_bulk)(struct rte_mempool *pool, void **obj_table, unsigned n); -+}; -+ -+static __rte_always_inline -+struct rte_mempool *mempool_create(const char *name, unsigned n, -+ unsigned cache_size, unsigned priv_size, unsigned data_room_size, int socket_id) -+{ -+ struct rte_mempool *pool; -+ -+ LSTACK_LOG(INFO, LSTACK, "name %s, n %u, cache_size %u, priv_size %u, data_room_size %u, socket_id %d, ops_name %s\n", -+ name, n, cache_size, priv_size, data_room_size, socket_id, MEMPOOL_OPS_NAME); -+ -+ pool = rte_mempool_create(name, n, data_room_size, cache_size, priv_size, NULL, NULL, NULL, NULL, socket_id, 0); -+ if (pool != NULL) -+ rte_mempool_set_ops_byname(pool, MEMPOOL_OPS_NAME, NULL); -+ return pool; -+} -+ -+static __rte_always_inline -+void mempool_put_bulk(struct rte_mempool *pool, void *const *obj_table, unsigned n) -+{ -+ rte_mempool_put_bulk(pool, obj_table, n); -+} -+ -+static __rte_always_inline -+unsigned mempool_get_bulk(struct rte_mempool *pool, void **obj_table, unsigned n) -+{ -+ return rte_mempool_get_bulk(pool, obj_table, n) != 0 ? 0 : n; -+} -+ -+static __rte_always_inline -+struct rte_mempool *pkgmbuf_create(const char *name, unsigned n, -+ unsigned cache_size, unsigned priv_size, unsigned data_room_size, int socket_id) -+{ -+ LSTACK_LOG(INFO, LSTACK, "name %s, n %u, cache_size %u, priv_size %u, data_room_size %u, socket_id %d, ops_name %s\n", -+ name, n, cache_size, priv_size, data_room_size, socket_id, MEMPOOL_OPS_NAME); -+ -+ return rte_pktmbuf_pool_create_by_ops(name, n, cache_size, priv_size, data_room_size, socket_id, MEMPOOL_OPS_NAME); -+} -+ -+static __rte_always_inline -+void pkgmbuf_put_bulk(struct rte_mempool *pool, void *const *obj_table, unsigned n) -+{ -+ // rte_pktmbuf_free_bulk((struct rte_mbuf **)obj_table, n); -+ rte_mempool_put_bulk(pool, obj_table, n); -+} -+ -+static __rte_always_inline -+unsigned pkgmbuf_get_bulk(struct rte_mempool *pool, void **obj_table, unsigned n) -+{ -+ return rte_pktmbuf_alloc_bulk(pool, (struct rte_mbuf **)obj_table, n) != 0 ? 0 : n; -+} -+ -+static const struct mempool_ops mem_mp_ops = { -+ .create = mempool_create, -+ .put_bulk = mempool_put_bulk, -+ .get_bulk = mempool_get_bulk, -+}; -+ -+static const struct mempool_ops mbuf_mp_ops = { -+ .create = pkgmbuf_create, -+ .put_bulk = pkgmbuf_put_bulk, -+ .get_bulk = pkgmbuf_get_bulk, -+}; -+ -+ -+static struct rte_mempool *mbuf_pool_create(int stack_id) -+{ -+ struct cfg_params *cfg_params = get_global_cfg_params(); -+ char name[RTE_MEMPOOL_NAMESIZE]; -+ struct rte_mempool *pool; -+ uint32_t total_conn_mbufs, total_nic_mbufs, total_mbufs; -+ uint16_t private_size; -+ -+ total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; -+ total_nic_mbufs = cfg_params->rxqueue_size + cfg_params->txqueue_size; -+ -+ total_mbufs = (total_conn_mbufs / cfg_params->num_queue) + total_nic_mbufs + MBUFPOOL_RESERVE_NUM; -+ /* limit mbuf max num based on the dpdk capability */ -+ if (total_mbufs > MBUFPOOL_MAX_NUM) { -+ LSTACK_LOG(ERR, LSTACK, "total_mbufs %u out of the dpdk mbuf_pool range\n", total_mbufs); -+ return NULL; -+ } -+ -+ SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%hu", "mbuf_pool", stack_id); -+ private_size = RTE_ALIGN(sizeof(struct mbuf_private) + 24, RTE_CACHE_LINE_SIZE); -+ -+ pool = mbuf_mp_ops.create(name, total_mbufs, MBUFPOOL_CACHE_NUM, private_size, MBUF_DATA_SIZE, rte_socket_id()); -+ if (pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_pool_create %s failed, rte_errno %d\n", name, rte_errno); -+ return NULL; -+ } -+ -+ return pool; -+} -+ -+static struct rte_mempool *rpc_pool_create(int stack_id) -+{ -+ char name [RTE_MEMPOOL_NAMESIZE]; -+ struct rte_mempool *pool; -+ uint32_t total_bufs = get_global_cfg_params()->rpc_msg_max; -+ -+ SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%hu", "rpc_pool", stack_id); -+ -+ pool = mem_mp_ops.create(name, total_bufs, MEMPOOL_CACHE_NUM, 0, sizeof(struct rpc_msg), rte_socket_id()); -+ if (pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "rte_mempool_create %s failed, rte_errno %d\n", name, rte_errno); -+ } -+ -+ return pool; -+} -+ -+void mem_stack_pool_free(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ -+ if (ms->mbuf_pool != NULL) { -+ rte_mempool_free(ms->mbuf_pool); -+ ms->mbuf_pool = NULL; -+ } -+ if (ms->rpc_pool != NULL) { -+ rte_mempool_free(ms->rpc_pool); -+ ms->rpc_pool = NULL; -+ } -+} -+ -+int mem_stack_pool_init(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ -+ ms->mbuf_pool = mbuf_pool_create(stack_id); -+ if (ms->mbuf_pool == NULL) { -+ return -1; -+ } -+ -+ ms->rpc_pool = rpc_pool_create(stack_id); -+ if (ms->rpc_pool == NULL) { -+ mem_stack_pool_free(stack_id); -+ return -1; -+ } -+ -+ rte_mempool_obj_iter(ms->mbuf_pool, mbuf_obj_ops.init, &stack_id); -+ rte_mempool_obj_iter(ms->rpc_pool, rpc_obj_ops.init, &stack_id); -+ -+ return 0; -+} -+ -+int mem_stack_mpcache_init(int stack_id, unsigned cpu_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ -+ if (ms->mbuf_pool == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "mem_stack_get stack_id %d failed\n", stack_id); -+ return -1; -+ } -+ -+ RTE_PER_LCORE(_lcore_id) = cpu_id; -+ ms->mbuf_mpcache = rte_mempool_default_cache(ms->mbuf_pool, rte_lcore_id()); -+ ms->migrate_watermark = ms->mbuf_mpcache->size / 8; -+ -+ LSTACK_LOG(INFO, LSTACK, "tid %d, stack_id %d, lcore_id %u, migrate_watermark %u\n", -+ rte_gettid(), stack_id, rte_lcore_id(), ms->migrate_watermark); -+ -+ return 0; -+} -+ -+unsigned mem_stack_mbuf_pool_count(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ return rte_mempool_avail_count(ms->mbuf_pool); -+} -+ -+void mem_thread_cache_free(struct mem_thread *mt) -+{ -+ void *obj; -+ -+ if (mt->mbuf_migrate_ring != NULL) { -+ while (rte_ring_sc_dequeue(mt->mbuf_migrate_ring, &obj) == 0) { -+ mem_put_mbuf_bulk((struct rte_mbuf **)&obj, 1); -+ } -+ rte_ring_free(mt->mbuf_migrate_ring); -+ mt->mbuf_migrate_ring = NULL; -+ } -+ -+ if (mt->mbuf_cache != NULL) { -+ while (buf_cache_pop_bulk(mt->mbuf_cache, &obj, 1, NULL) > 0) { -+ mem_put_mbuf_bulk((struct rte_mbuf **)&obj, 1); -+ } -+ buf_cache_free(mt->mbuf_cache); -+ mt->mbuf_cache = NULL; -+ } -+ -+ if (mt->rpc_cache != NULL) { -+ while (buf_cache_pop_bulk(mt->rpc_cache, &obj, 1, NULL) > 0) { -+ mem_put_rpc(obj); -+ } -+ buf_cache_free(mt->rpc_cache); -+ mt->rpc_cache = NULL; -+ } -+} -+ -+int mem_thread_cache_init(struct mem_thread *mt) -+{ -+ if (!get_global_cfg_params()->stack_mode_rtc && !dpdk_nic_is_xdp()) { -+ char name [RTE_MEMPOOL_NAMESIZE]; -+ SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%p", "migrate_ring", mt); -+ -+ mt->mbuf_migrate_ring = rte_ring_create(name, BUF_CACHE_DEFAULT_NUM, -+ rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (mt->mbuf_migrate_ring == NULL) { -+ return -1; -+ } -+ } -+ -+ mt->mbuf_cache = buf_cache_create(BUF_CACHE_DEFAULT_NUM); -+ if (mt->mbuf_cache == NULL) { -+ mem_thread_cache_free(mt); -+ return -1; -+ } -+ -+ mt->rpc_cache = buf_cache_create(BUF_CACHE_MIN_NUM); -+ if (mt->rpc_cache == NULL) { -+ mem_thread_cache_free(mt); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+struct mem_thread *mem_thread_migrate_get(int stack_id) -+{ -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ if (mt == NULL || mt->mbuf_migrate_ring == NULL) -+ return NULL; -+ return mt; -+} -+ -+static inline void mem_preinit_pbuf(struct pbuf *p); -+void mem_mbuf_migrate_enqueue(struct mem_thread *mt, unsigned n) -+{ -+ struct mem_stack *ms; -+ struct rte_mempool_cache *mpcache; -+ int stack_id; -+ unsigned num, i; -+ void **obj_table; -+ -+ stack_id = get_protocol_stack()->stack_idx; -+ ms = mem_stack_get(stack_id); -+ mpcache = ms->mbuf_mpcache; -+ -+ mt->stk_migrate_count += n; -+ -+ if (mpcache->len <= ms->migrate_watermark) -+ return; -+ -+ num = LWIP_MIN(mpcache->len - ms->migrate_watermark, -+ mt->stk_migrate_count); -+ obj_table = &mpcache->objs[mpcache->len - num]; -+ -+ for (i = 0; i < num; i++) { -+ rte_pktmbuf_reset(obj_table[i]); -+ mem_preinit_pbuf(mbuf_to_pbuf(obj_table[i])); -+ } -+ num = rte_ring_sp_enqueue_bulk(mt->mbuf_migrate_ring, obj_table, num, NULL); -+ if (num > 0) { -+ mpcache->len -= num; -+ mt->stk_migrate_count -= num; -+ } else { -+ mt->stk_migrate_count = 0; -+ } -+} -+ -+void mem_mbuf_migrate_dequeue(struct mem_thread *mt) -+{ -+ struct buf_cache *cache; -+ unsigned num; -+ void **obj_table; -+ -+ if (mt->mbuf_migrate_ring == NULL) -+ return; -+ -+ cache = mt->mbuf_cache; -+ if (cache->head > (cache->watermark >> 1)) -+ return; -+ -+ num = cache->capacity - cache->head; -+ obj_table = &cache->objs[cache->head]; -+ -+ num = rte_ring_sc_dequeue_burst(mt->mbuf_migrate_ring, obj_table, num, NULL); -+ cache->head += num; -+} -+ -+/* see rte_mempool_cache_flush() */ -+static inline -+void pool_put_with_mpcache(struct rte_mempool *pool, struct rte_mempool_cache* mpcache, void *obj) -+{ -+ if (mpcache->len >= mpcache->flushthresh) { -+ rte_mempool_ops_enqueue_bulk(pool, &mpcache->objs[mpcache->size], -+ mpcache->len - mpcache->size); -+ mpcache->len = mpcache->size; -+ } -+ mpcache->objs[mpcache->len] = obj; -+ mpcache->len++; -+} -+ -+static inline -+void pool_put_with_bufcache(struct rte_mempool *pool, struct buf_cache* cache, void *obj) -+{ -+ if (cache->head >= cache->flushthresh) { -+ buf_cache_sub_watermark(cache); -+ rte_mempool_ops_enqueue_bulk(pool, &cache->objs[cache->watermark], -+ cache->head - cache->watermark); -+ cache->head = cache->watermark; -+ } -+ cache->objs[cache->head] = obj; -+ cache->head++; -+} -+ -+static unsigned pool_get_bulk_with_cache(const struct mempool_ops *pool_ops, -+ struct rte_mempool *pool, struct buf_cache *cache, -+ void **obj_table, unsigned n) -+{ -+ unsigned ret; -+ unsigned count = 0; -+ unsigned get_count; -+ -+ ret = buf_cache_pop_bulk(cache, obj_table, n, &count); -+ if (ret > 0) { -+ return n; -+ } -+ -+ /* get from the pool */ -+ ret = pool_ops->get_bulk(pool, obj_table, n); -+ if (unlikely(ret == 0)) { -+ LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u\n", pool->name, n); -+ return 0; -+ } -+ -+ buf_cache_add_watermark(cache); -+ if (count >= cache->watermark) { -+ return n; -+ } -+ -+ /* get from the pool, then enqueue to cache */ -+ get_count = cache->watermark - count; -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(cache=%p, watermark=%u, get_count=%u)\n", -+ __FUNCTION__, cache, cache->watermark, get_count)); -+ -+ ret = pool_ops->get_bulk(pool, &cache->objs[cache->head], get_count); -+ if (unlikely(ret == 0)) { -+ LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u\n", pool->name, get_count); -+ } else { -+ cache->head += get_count; -+ } -+ -+ return n; -+} -+ -+static void pool_put_bulk_with_cache(const struct mempool_ops *pool_ops, -+ struct rte_mempool *pool, struct buf_cache *cache, -+ void *const *obj_table, unsigned n) -+{ -+ unsigned ret; -+ unsigned count; -+ unsigned free_count = 0; -+ unsigned put_count; -+ -+ ret = buf_cache_push_bulk(cache, obj_table, n, &free_count); -+ if (ret > 0) { -+ return; -+ } -+ -+ /* put to the pool */ -+ pool_ops->put_bulk(pool, obj_table, n); -+ -+ buf_cache_sub_watermark(cache); -+ count = buf_cache_get_capacity(cache) - free_count; -+ if (count <= cache->watermark) { -+ return; -+ } -+ -+ /* dequeue from cache, then put to the pool */ -+ put_count = count - cache->watermark; -+ LWIP_DEBUGF(MEMP_DEBUG, ("pool_put_bulk_with_cache(cache=%p, watermark=%u, put_count=%u)\n", -+ cache, cache->watermark, put_count)); -+ -+ pool_ops->put_bulk(pool, &cache->objs[cache->head - put_count], put_count); -+ cache->head -= put_count; -+ -+ return; -+} -+ -+ -+void *mem_get_rpc(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ unsigned ret; -+ void *obj; -+ -+ if (mt == NULL) { -+ ret = mem_mp_ops.get_bulk(ms->rpc_pool, &obj, 1); -+ } else { -+ ret = pool_get_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, &obj, 1); -+ } -+ -+ LWIP_DEBUGF(MEMP_DEBUG, ("mem_get_rpc(stack_id=%d, obj=%p)\n", stack_id, obj)); -+ -+ return ret == 0 ? NULL : obj; -+} -+ -+void mem_put_rpc(void *obj) -+{ -+ unsigned stack_id = rpc_obj_ops.get_stack_id(obj); -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ -+ LWIP_DEBUGF(MEMP_DEBUG, ("mem_put_rpc(stack_id=%d, obj=%p)\n", stack_id, obj)); -+ -+ if (mt == NULL) { -+ mem_mp_ops.put_bulk(ms->rpc_pool, &obj, 1); -+ } else { -+ pool_put_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, &obj, 1); -+ } -+} -+ -+unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned n, bool reserve) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ unsigned ret; -+ -+ if (unlikely(n == 0)) { -+ return 0; -+ } -+ -+ if (reserve) { -+ /* don't use rte_mempool_avail_count, it traverse cpu local cache, -+ * when RTE_MAX_LCORE is too large, it's time-consuming -+ */ -+ if (rte_ring_count(ms->mbuf_pool->pool_data) < MBUFPOOL_RESERVE_NUM + n) { -+ return 0; -+ } -+ } -+ -+ if (mt == NULL) { -+ ret = mbuf_mp_ops.get_bulk(ms->mbuf_pool, (void **)mbuf_table, n); -+ } else { -+ mem_mbuf_migrate_dequeue(mt); -+ ret = pool_get_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, (void **)mbuf_table, n); -+ } -+ -+#if MEMP_DEBUG -+ for (unsigned i = 0; i < ret; ++i) { -+ LWIP_DEBUGF(MEMP_DEBUG, ("mem_get_mbuf_bulk(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); -+ } -+#endif /* MEMP_DEBUG */ -+ -+ return ret; -+} -+ -+static void mem_put_mbuf_bulk_by_pbuf(struct rte_mbuf *const *mbuf_table, unsigned n) -+{ -+ unsigned stack_id = mbuf_obj_ops.get_stack_id(mbuf_table[0]); -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ -+ if (unlikely(n == 0)) { -+ return; -+ } -+ -+#if MEMP_DEBUG -+ for (unsigned i = 0; i < n; ++i) { -+ LWIP_DEBUGF(MEMP_DEBUG, ("mem_put_mbuf_bulk(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); -+ } -+#endif /* MEMP_DEBUG */ -+ -+ if (mt == NULL) { -+ mbuf_mp_ops.put_bulk(ms->mbuf_pool, (void *const *)mbuf_table, n); -+ } else { -+ pool_put_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, (void *const *)mbuf_table, n); -+ } -+ -+} -+ -+void mem_put_mbuf_bulk(struct rte_mbuf *const *mbuf_table, unsigned n) -+{ -+ unsigned i; -+ for (i = 0; i < n; ++i) { -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ __FUNCTION__, mbuf_obj_ops.get_stack_id(mbuf_table[i]), -+ n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); -+ -+ rte_pktmbuf_free(mbuf_table[i]); -+ } -+} -+ -+ -+unsigned mem_get_pbuf_bulk(int stack_id, struct pbuf **pbuf_table, unsigned n, bool reserve) -+{ -+ struct rte_mbuf **mbuf_table = (struct rte_mbuf **)pbuf_table; -+ unsigned ret, i; -+ -+ ret = mem_get_mbuf_bulk(stack_id, mbuf_table, n, reserve); -+ if (unlikely(ret == 0)) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(stack_id); -+ stack->stats.tx_allocmbuf_fail++; -+ return 0; -+ } -+ -+ for (i = 0; i < (n & ~0x3); i += 4) { -+ pbuf_table[i] = mbuf_to_pbuf(mbuf_table[i]); -+ pbuf_table[i + 1] = mbuf_to_pbuf(mbuf_table[i + 1]); -+ pbuf_table[i + 2] = mbuf_to_pbuf(mbuf_table[i + 2]); -+ pbuf_table[i + 3] = mbuf_to_pbuf(mbuf_table[i + 3]); -+ } -+ switch (n & 0x3) { -+ case 3: -+ pbuf_table[i] = mbuf_to_pbuf(mbuf_table[i]); /* fallthrough */ -+ ++i; -+ case 2: -+ pbuf_table[i] = mbuf_to_pbuf(mbuf_table[i]); /* fallthrough */ -+ ++i; -+ case 1: -+ pbuf_table[i] = mbuf_to_pbuf(mbuf_table[i]); /* fallthrough */ -+ ++i; -+ } -+ -+ return n; -+} -+ -+void mem_preput_pbuf(struct pbuf *p) -+{ -+ struct rte_mbuf *m = pbuf_to_mbuf(p); -+ p->mbuf_refcnt = rte_mbuf_refcnt_read(m); -+ if (p->mbuf_refcnt == 1) { -+ rte_pktmbuf_reset(m); -+ } -+} -+ -+/* ignore buf->ref, and reset to 1 */ -+static __rte_always_inline -+struct rte_mbuf *pbuf_to_mbuf_prefree(struct pbuf *p) -+{ -+ if (unlikely(p == NULL)) -+ return NULL; -+ -+ if (p->next != NULL) -+ p->next = NULL; -+ -+ struct rte_mbuf *m = pbuf_to_mbuf(p); -+#if MEMP_DEBUG -+ if (rte_mbuf_refcnt_read(m) > 1) { -+ LWIP_DEBUGF(MEMP_DEBUG, ("pbuf_to_mbuf_prefree(mbuf=%p, pbuf=%p, refcnt=%u)\n", -+ m, p, rte_mbuf_refcnt_read(m))); -+ } -+#endif /* MEMP_DEBUG */ -+ if (p->mbuf_refcnt != 1) { -+ m = rte_pktmbuf_prefree_seg(m); -+ if (m != NULL) { -+ rte_pktmbuf_reset(m); -+ } -+ } -+ -+ return m; -+} -+ -+void mem_put_pbuf_bulk(struct pbuf *const *pbuf_table, unsigned n) -+{ -+ struct rte_mbuf *mbuf_table[BUF_BULK_MAX_NUM]; -+ unsigned i, copied, batch, bulk_num; -+ -+ copied = 0; -+ while (copied < n) { -+ batch = LWIP_MIN(n - copied, BUF_BULK_MAX_NUM); -+ bulk_num = 0; -+ for (i = 0; i < batch; ++i, ++copied) { -+ mbuf_table[bulk_num] = pbuf_to_mbuf_prefree(pbuf_table[copied]); -+ if (mbuf_table[bulk_num] != NULL) { -+ ++bulk_num; -+ } -+ } -+ mem_put_mbuf_bulk_by_pbuf(mbuf_table, bulk_num); -+ } -+} -+ -+void mem_put_pbuf_list_bulk(struct pbuf *const *pbuf_table, unsigned n) -+{ -+ unsigned stack_id = mbuf_obj_ops.get_stack_id(pbuf_to_mbuf(pbuf_table[0])); -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ struct mem_thread *mt = mem_thread_get(stack_id); -+ -+ struct pbuf *q, *next; -+ struct rte_mbuf *mbuf; -+ -+ for (unsigned i = 0; i < n; ++i) { -+ q = pbuf_table[i]; -+ while (q != NULL) { -+ next = q->next; -+ q->next = NULL; -+ -+ q->ref--; -+ if (q->ref > 0) -+ break; -+ mbuf = pbuf_to_mbuf_prefree(q); -+ if (mbuf == NULL) -+ break; -+ -+ q = next; -+ -+ if (mt == NULL) { -+ pool_put_with_mpcache(ms->mbuf_pool, ms->mbuf_mpcache, mbuf); -+ } else { -+ pool_put_with_bufcache(ms->mbuf_pool, mt->mbuf_cache, mbuf); -+ } -+ -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ __FUNCTION__, stack_id, n, i, mbuf, q)); -+ } -+ } -+} -+ -+struct pbuf *mem_get_pbuf(int stack_id, bool reserve) -+{ -+ int ret; -+ struct rte_mbuf *mbuf; -+ -+ if (stack_id < 0 || stack_id >= PROTOCOL_STACK_MAX) -+ stack_id = get_protocol_stack()->stack_idx; -+ -+ ret = mem_get_mbuf_bulk(stack_id, &mbuf, 1, reserve); -+ if (unlikely(ret == 0)) { -+ struct protocol_stack *stack = get_protocol_stack_by_id(stack_id); -+ stack->stats.tx_allocmbuf_fail++; -+ return NULL; -+ } -+ -+ return mbuf_to_pbuf(mbuf); -+} -+ -+void mem_put_pbuf(struct pbuf *p) -+{ -+ struct rte_mbuf *mbuf = pbuf_to_mbuf_prefree(p); -+ if (mbuf != NULL) { -+ mem_put_mbuf_bulk_by_pbuf(&mbuf, 1); -+ } -+} -+ -+unsigned mem_extcache_get_pbuf_bulk(int stack_id, struct pbuf **pbuf_table, unsigned n, bool reserve, struct pbuf **extcache_list) -+{ -+ unsigned ret; -+ struct pbuf *p; -+ -+ for (int i = 0; i < n; ++i) { -+ p = *extcache_list; -+ if (p != NULL) { -+ *extcache_list = p->next; -+ p->next = NULL; -+ pbuf_table[i] = p; -+ } else { -+ ret = mem_get_pbuf_bulk(stack_id, &pbuf_table[i], n - i, reserve); -+ if (unlikely(ret == 0)) { -+ mem_put_pbuf_bulk(pbuf_table, i); -+ return 0; -+ } -+ break; -+ } -+ } -+ -+ return n; -+} -+ -+struct pbuf *mem_extcache_get_pbuf(int stack_id, bool reserve, struct pbuf **extcache_list) -+{ -+ struct pbuf *p; -+ -+ p = *extcache_list; -+ if (p != NULL) { -+ *extcache_list = p->next; -+ p->next = NULL; -+ } else { -+ p = mem_get_pbuf(stack_id, reserve); -+ } -+ -+ return p; -+} -+ -+void mem_extcache_put_pbuf(struct pbuf *h, struct pbuf *t, struct pbuf **extcache_list) -+{ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ pbuf_free(h); -+ return; -+ } -+ -+ if (*extcache_list == NULL) { -+ *extcache_list = h; -+ } else { -+ if (t == NULL) -+ t = pbuf_list_tail(h); -+ t->next = *extcache_list; -+ *extcache_list = h; -+ } -+} -+ -+void mem_extcache_flush_pbuf(struct pbuf **extcache_list) -+{ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ return; -+ } -+ -+ struct pbuf *p = *extcache_list; -+ if (p != NULL) { -+ mem_put_pbuf_list_bulk(&p, 1); -+ *extcache_list = NULL; -+ } -+} -+ -+static inline void mem_preinit_pbuf(struct pbuf *p) -+{ -+ mem_init_pbuf(p, 0, 0, 0, PBUF_POOL_PREINIT); -+} -+ -+void mem_init_pbuf(struct pbuf *p, pbuf_layer layer, uint16_t tot_len, uint16_t len, pbuf_type type) -+{ -+ struct pbuf_custom *pc; -+ struct rte_mbuf *mbuf; -+ void *data; -+ -+ if (p->type_internal == PBUF_POOL_PREINIT) { -+ p->payload = (uint8_t *)p->payload + LWIP_MEM_ALIGN_SIZE((uint16_t)layer); -+ p->type_internal = type; -+ p->len = len; -+ p->tot_len = tot_len; -+ return; -+ } -+ -+ pc = (struct pbuf_custom *)p; -+ mbuf = pbuf_to_mbuf(p); -+ data = rte_pktmbuf_mtod(mbuf, void *); -+ -+ pbuf_alloced_custom(layer, len, type, pc, data, MBUF_PAYLOAD_SIZE); -+ p->tot_len = tot_len; -+ pc->custom_free_function = mem_put_pbuf; -+} -diff --git a/src/lstack/include/lstack_lockless_queue.h b/src/lstack/include/lstack_lockless_queue.h -index b0fc31f..bec2564 100644 ---- a/src/lstack/include/lstack_lockless_queue.h -+++ b/src/lstack/include/lstack_lockless_queue.h -@@ -15,6 +15,8 @@ - - #include - -+/* multi-producers single-consumer queue */ -+ - typedef struct lockless_queue_node { - struct lockless_queue_node *volatile next; - } lockless_queue_node; -@@ -25,6 +27,32 @@ typedef struct lockless_queue { - lockless_queue_node stub __attribute__((__aligned__(64))); - } lockless_queue; - -+ -+static inline void lockless_queue_node_set_poped(lockless_queue_node *node) -+{ -+ node->next = node; -+} -+ -+static inline bool lockless_queue_node_is_poped(lockless_queue_node *node) -+{ -+ return node->next == node; -+} -+ -+static inline bool lockless_queue_node_test_poped(lockless_queue_node *node) -+{ -+ /* -+ * if (node->next == node) { -+ * node->next = NULL; -+ * return 1; -+ * } else { -+ * return 0; -+ * } -+ */ -+ return !!__atomic_compare_exchange_n( -+ (volatile uint64_t *)&node->next, (uint64_t *)&node, (uint64_t)NULL, -+ false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); -+} -+ - static inline void lockless_queue_init(lockless_queue *queue) - { - queue->head = &queue->stub; -@@ -57,11 +85,35 @@ static inline int32_t lockless_queue_count(lockless_queue *queue) - return count; - } - -+/* -+ * tail head -+ * \_ stub _/ -+ * -+ * tail old_head head -+ * \_ stub _/ node _/ -+ * -+ * tail head -+ * \_ stub -> node _/ -+ */ - static inline void lockless_queue_mpsc_push(lockless_queue *queue, lockless_queue_node *node) - { -+ lockless_queue_node *old_head; -+ - node->next = NULL; -- lockless_queue_node *old_head = -- (lockless_queue_node *)__atomic_exchange_n((void **)&queue->head, (void*)node, __ATOMIC_ACQ_REL); -+ -+ old_head = (lockless_queue_node *)__atomic_exchange_n((void **)&queue->head, (void*)node, __ATOMIC_ACQ_REL); -+ -+ __atomic_store_n(&old_head->next, node, __ATOMIC_RELEASE); -+} -+ -+static inline void lockless_queue_mpsc_test_push(lockless_queue *queue, lockless_queue_node *node) -+{ -+ lockless_queue_node *old_head; -+ -+ if (!lockless_queue_node_test_poped(node)) -+ return; -+ -+ old_head = (lockless_queue_node *)__atomic_exchange_n((void **)&queue->head, (void*)node, __ATOMIC_ACQ_REL); - - __atomic_store_n(&old_head->next, node, __ATOMIC_RELEASE); - } -@@ -70,7 +122,13 @@ static inline lockless_queue_node* lockless_queue_mpsc_pop(lockless_queue* queue - { - lockless_queue_node *tail = queue->tail; - lockless_queue_node *next = tail->next; -+ lockless_queue_node *head; - -+ /* -+ * step1. dequeue stub. -+ * tail head -+ * \_ stub -> node -> node _/ -+ */ - if (tail == &queue->stub) { - if (next == NULL) { - return NULL; -@@ -80,21 +138,38 @@ static inline lockless_queue_node* lockless_queue_mpsc_pop(lockless_queue* queue - next = next->next; - } - -+ /* -+ * step2. dequeue tail. -+ * tail next-\ head -+ * \_ node -> node _/ -+ */ - if (next) { - queue->tail = next; -+ lockless_queue_node_set_poped(tail); - return tail; - } - -- lockless_queue_node *head = queue->head; -+ /* -+ * step3. enqueue ing. -+ * tail old_head head -+ * \_ node _/ node _/ -+ */ -+ head = queue->head; - if (tail != head) { - return NULL; - } - -+ /* -+ * step4. only one node, enqueue stub and dequeue node. -+ * tail head -+ * \_ node _/ -+ */ - lockless_queue_mpsc_push(queue, &queue->stub); - - next = tail->next; - if (next) { - queue->tail = next; -+ lockless_queue_node_set_poped(tail); - return tail; - } - -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -new file mode 100644 -index 0000000..c6adff0 ---- /dev/null -+++ b/src/lstack/include/lstack_mempool.h -@@ -0,0 +1,325 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __GAZELLE_MEM_H__ -+#define __GAZELLE_MEM_H__ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "common/dpdk_common.h" -+ -+/* fix virtio PMD error: Rx scatter is disabled and RxQ mbuf pool object is too small. */ -+#define DEV_VIRTIO_RX_MBUF_SIZE 1530 -+/* see hinic_convert_rx_buf_size() */ -+#define DEV_HINIC_RX_MBUF_SIZE 0x600 -+ -+/* IP6_HLEN - IP_HLEN: reserve 20 byte to overflow, -+ * if distinguish between IP4_MSS and IP6_MSS. */ -+#define MBUF_PAYLOAD_SIZE LWIP_MAX(PBUF_POOL_BUFSIZE, DEV_HINIC_RX_MBUF_SIZE) -+#define MBUF_DATA_SIZE (MBUF_PAYLOAD_SIZE + RTE_PKTMBUF_HEADROOM) -+/* DPDK limit ring head-tail distance in rte_ring_init. -+ * Max value is RTE_RING_SZ_MASK / HTD_MAX_DEF, RTE_RING_SZ_MASK is 0x7fffffff, HTD_MAX_DEF is 8. -+ */ -+#define MBUFPOOL_MAX_NUM 0xfffffff -+ -+#define MBUFPOOL_CACHE_NUM LWIP_MIN(NIC_QUEUE_SIZE_MAX >> 1, RTE_MEMPOOL_CACHE_MAX_SIZE) -+#define MBUFPOOL_RESERVE_NUM (NIC_QUEUE_SIZE_MAX + MBUFPOOL_CACHE_NUM) -+ -+#define MEMPOOL_OPS_NAME "ring_mt_rts" -+#define MEMPOOL_CACHE_NUM 32 -+ -+#define BUF_CACHE_MIN_NUM 32 -+#define BUF_CACHE_DEFAULT_NUM 1024 -+#define BUF_CACHE_WATERSTEP_SHIFT 4 /* 1/16 */ -+ -+#define BUF_BULK_MAX_NUM 32 -+ -+struct buf_cache { -+ unsigned size; /* Size of cache. */ -+ unsigned mask; /* Mask (size-1) of cache. */ -+ unsigned capacity; /* Usable size of cache */ -+ -+ unsigned watermark; -+ unsigned waterstep; -+ unsigned flushthresh; -+ -+ unsigned head; -+ unsigned tail; -+ -+ /* new cache line */ -+ char pad0 __rte_cache_aligned; -+ void *objs[0]; -+}; -+ -+static __rte_always_inline -+struct buf_cache *buf_cache_create(unsigned count) -+{ -+ struct buf_cache *cache; -+ unsigned size; -+ -+ size = rte_align32pow2(count); -+ if (size < BUF_CACHE_MIN_NUM) -+ return NULL; -+ -+ cache = (struct buf_cache *)calloc(1, sizeof(struct buf_cache) + sizeof(void *) * size); -+ if (cache == NULL) -+ return NULL; -+ -+ cache->size = size; -+ cache->mask = size - 1; -+ cache->capacity = size - 1; -+ if (cache->capacity > count) -+ cache->capacity = count; -+ -+ cache->head = 0; -+ cache->tail = 0; -+ -+ cache->waterstep = cache->size >> BUF_CACHE_WATERSTEP_SHIFT; -+ if (cache->waterstep < BUF_CACHE_WATERSTEP_SHIFT) -+ cache->waterstep = BUF_CACHE_WATERSTEP_SHIFT; -+ cache->watermark = cache->waterstep; -+ cache->flushthresh = cache->size - cache->waterstep; -+ -+ return cache; -+} -+ -+static __rte_always_inline -+void buf_cache_free(struct buf_cache *cache) -+{ -+ if (cache != NULL) { -+ free(cache); -+ } -+} -+ -+static __rte_always_inline -+unsigned buf_cache_count(const struct buf_cache *cache) -+{ -+ unsigned count = (cache->head - cache->tail) & cache->mask; -+ return (count > cache->capacity) ? cache->capacity : count; -+} -+ -+static __rte_always_inline -+unsigned buf_cache_free_count(const struct buf_cache *cache) -+{ -+ return cache->capacity - buf_cache_count(cache); -+} -+ -+static __rte_always_inline -+unsigned buf_cache_get_capacity(const struct buf_cache *cache) -+{ -+ return cache->capacity; -+} -+ -+static __rte_always_inline -+void buf_cache_add_watermark(struct buf_cache *cache) -+{ -+ if (cache->watermark < cache->flushthresh) { -+ cache->watermark += cache->waterstep; -+ } -+} -+ -+static __rte_always_inline -+void buf_cache_sub_watermark(struct buf_cache *cache) -+{ -+ if (cache->watermark > cache->waterstep) { -+ cache->watermark -= cache->waterstep; -+ } -+} -+ -+static __rte_always_inline -+void __buf_cache_copy_objs(void ** dst_table, void *const *src_table, unsigned n) -+{ -+ unsigned i; -+ -+ for (i = 0; i < (n & ~0x3); i += 4) { -+ dst_table[i] = src_table[i]; -+ dst_table[i + 1] = src_table[i + 1]; -+ dst_table[i + 2] = src_table[i + 2]; -+ dst_table[i + 3] = src_table[i + 3]; -+ } -+ switch (n & 0x3) { -+ case 3: -+ dst_table[i] = src_table[i]; /* fallthrough */ -+ ++i; -+ case 2: -+ dst_table[i] = src_table[i]; /* fallthrough */ -+ ++i; -+ case 1: -+ dst_table[i] = src_table[i]; /* fallthrough */ -+ } -+} -+ -+static __rte_always_inline -+unsigned buf_cache_enqueue_bulk(struct buf_cache *cache, void *const *obj_table, unsigned n, unsigned *free_space) -+{ -+ unsigned free_count = buf_cache_free_count(cache); -+ unsigned i, idx; -+ -+ if (unlikely(n > free_count)) { -+ if (free_space != NULL) { -+ *free_space = free_count; -+ } -+ return 0; -+ } -+ -+ /* refence to __rte_ring_enqueue_elems_64() */ -+ idx = cache->head & cache->mask; -+ if (likely(idx + n < cache->size)) { -+ __buf_cache_copy_objs(&cache->objs[idx], obj_table, n); -+ } else { -+ for (i = 0; idx < cache->size; i++, idx++) -+ cache->objs[idx] = obj_table[i]; -+ /* Start at the beginning */ -+ for (idx = 0; i < n; i++, idx++) -+ cache->objs[idx] = obj_table[i]; -+ } -+ -+ cache->head += n; -+ return n; -+} -+ -+static __rte_always_inline -+unsigned buf_cache_dequeue_bulk(struct buf_cache *cache, void **obj_table, unsigned n, unsigned *available) -+{ -+ unsigned count = buf_cache_count(cache); -+ unsigned i, idx; -+ -+ if (unlikely(n > count)) { -+ if (available != NULL) { -+ *available = count; -+ } -+ return 0; -+ } -+ -+ /* refence to __rte_ring_dequeue_elems_64() */ -+ idx = cache->tail & cache->mask; -+ if (likely(idx + n < cache->size)) { -+ __buf_cache_copy_objs(obj_table, &cache->objs[idx], n); -+ } else { -+ for (i = 0; idx < cache->size; i++, idx++) -+ obj_table[i] = cache->objs[idx]; -+ /* Start at the beginning */ -+ for (idx = 0; i < n; i++, idx++) -+ obj_table[i] = cache->objs[idx]; -+ } -+ -+ cache->tail += n; -+ return n; -+} -+ -+static __rte_always_inline -+unsigned buf_cache_push_bulk(struct buf_cache *cache, void *const *obj_table, unsigned n, unsigned *free_space) -+{ -+ unsigned free_count = buf_cache_free_count(cache); -+ unsigned top; -+ -+ if (unlikely(n > free_count)) { -+ if (free_space != NULL) { -+ *free_space = free_count; -+ } -+ return 0; -+ } -+ -+ top = cache->head; -+ __buf_cache_copy_objs(&cache->objs[top], obj_table, n); -+ -+ cache->head += n; -+ return n; -+} -+ -+static __rte_always_inline -+unsigned buf_cache_pop_bulk(struct buf_cache *cache, void **obj_table, unsigned n, unsigned *available) -+{ -+ unsigned count = buf_cache_count(cache); -+ unsigned top; -+ -+ if (unlikely(n > count)) { -+ if (available != NULL) { -+ *available = count; -+ } -+ return 0; -+ } -+ -+ top = cache->head; -+ __buf_cache_copy_objs(obj_table, &cache->objs[top - n], n); -+ -+ cache->head -= n; -+ return n; -+} -+ -+ -+struct mem_stack { -+ struct rte_mempool *rpc_pool; -+ -+ struct rte_mempool *mbuf_pool; -+ struct rte_mempool_cache *mbuf_mpcache; -+ unsigned migrate_watermark; -+}; -+ -+struct mem_thread { -+ struct buf_cache *rpc_cache; -+ -+ struct buf_cache *mbuf_cache; -+ struct rte_ring *mbuf_migrate_ring; -+ -+ char pad0 __rte_cache_aligned; /* new cache line */ -+ -+ unsigned stk_migrate_count; -+} __rte_cache_aligned; -+ -+void mem_stack_pool_free(int stack_id); -+int mem_stack_pool_init(int stack_id); -+int mem_stack_mpcache_init(int stack_id, unsigned cpu_id); -+ -+int mem_thread_manager_init(void); -+void mem_thread_cache_free(struct mem_thread *mt); -+int mem_thread_cache_init(struct mem_thread *mt); -+ -+unsigned mem_stack_mbuf_pool_count(int stack_id); -+struct rte_mempool *mem_get_mbuf_pool(int stack_id); -+struct rte_mempool *mem_get_rpc_pool(int stack_id); -+ -+void *mem_get_rpc(int stack_id); -+void mem_put_rpc(void *obj); -+ -+struct mem_thread *mem_thread_migrate_get(int stack_id); -+void mem_mbuf_migrate_enqueue(struct mem_thread *mt, unsigned n); -+void mem_mbuf_migrate_dequeue(struct mem_thread *mt); -+ -+unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned n, bool reserve); -+void mem_put_mbuf_bulk(struct rte_mbuf *const *mbuf_table, unsigned n); -+ -+unsigned mem_get_pbuf_bulk(int stack_id, struct pbuf **pbuf_table, unsigned n, bool reserve); -+void mem_preput_pbuf(struct pbuf *p); -+void mem_put_pbuf_bulk(struct pbuf *const *pbuf_table, unsigned n); -+void mem_put_pbuf_list_bulk(struct pbuf *const *pbuf_table, unsigned n); -+ -+struct pbuf *mem_get_pbuf(int stack_id, bool reserve); -+void mem_put_pbuf(struct pbuf *p); -+ -+unsigned mem_extcache_get_pbuf_bulk(int stack_id, struct pbuf **pbuf_table, unsigned n, bool reserve, -+ struct pbuf **extcache_list); -+struct pbuf *mem_extcache_get_pbuf(int stack_id, bool reserve, struct pbuf **extcache_list); -+void mem_extcache_put_pbuf(struct pbuf *h, struct pbuf *t, struct pbuf **extcache_list); -+void mem_extcache_flush_pbuf(struct pbuf **extcache_list); -+ -+void mem_init_pbuf(struct pbuf *p, pbuf_layer layer, uint16_t tot_len, uint16_t len, pbuf_type type); -+ -+ -+#endif /* __GAZELLE_MEM_H__ */ -\ No newline at end of file -diff --git a/src/lstack/include/lstack_sockctl.h b/src/lstack/include/lstack_sockctl.h -new file mode 100644 -index 0000000..91445ad ---- /dev/null -+++ b/src/lstack/include/lstack_sockctl.h -@@ -0,0 +1,25 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_RTC_API_H_ -+#define _LSTACK_RTC_API_H_ -+ -+#include -+ -+/* don't include lwip/sockets.h, conflict with sys/socket.h */ -+extern int lwip_fcntl(int s, int cmd, int val); -+extern int lwip_ioctl(int s, long cmd, void *argp); -+ -+void sockctl_rtw_api_init(posix_api_t *api); -+void sockctl_rtc_api_init(posix_api_t *api); -+ -+#endif /* __LSTACK_RTC_API_H_ */ -diff --git a/src/lstack/include/lstack_sockio.h b/src/lstack/include/lstack_sockio.h -new file mode 100644 -index 0000000..f4e5e99 ---- /dev/null -+++ b/src/lstack/include/lstack_sockio.h -@@ -0,0 +1,41 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef _LSTACK_SOCKIO_H_ -+#define _LSTACK_SOCKIO_H_ -+ -+#include -+#include -+ -+ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); -+ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags); -+ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); -+ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags); -+ -+ssize_t sockio_read(int fd, void *mem, size_t len); -+ssize_t sockio_write(int fd, const void *mem, size_t len); -+ -+ssize_t sockio_recv(int fd, void *mem, size_t len, int flags); -+ssize_t sockio_send(int fd, const void *mem, size_t len, int flags); -+ -+ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt); -+ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt); -+ -+ -+void sockio_ops_init(void); -+bool sockio_mbox_pending(const struct lwip_sock *sock); -+ -+/* just for lwip */ -+int do_lwip_init_sock(int fd); -+void do_lwip_clean_sock(int fd); -+ -+#endif /* _LSTACK_SOCKIO_H_ */ -diff --git a/src/lstack/include/mbox_ring.h b/src/lstack/include/mbox_ring.h -new file mode 100644 -index 0000000..c48a47b ---- /dev/null -+++ b/src/lstack/include/mbox_ring.h -@@ -0,0 +1,583 @@ -+/* -+* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. -+* gazelle is licensed under the Mulan PSL v2. -+* You can use this software according to the terms and conditions of the Mulan PSL v2. -+* You may obtain a copy of Mulan PSL v2 at: -+* http://license.coscl.org.cn/MulanPSL2 -+* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR -+* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR -+* PURPOSE. -+* See the Mulan PSL v2 for more details. -+*/ -+ -+#ifndef __MBOX_RING_H__ -+#define __MBOX_RING_H__ -+ -+#include -+#include -+ -+#include -+#include -+ -+#include "common/dpdk_common.h" -+#include "lstack_dpdk.h" -+#include "lstack_mempool.h" -+#include "lstack_cfg.h" -+ -+/* Optimize performance of creating ring. */ -+static inline -+struct rte_ring *rte_ring_create_fast(const char *name, unsigned size, unsigned flags) -+{ -+ ssize_t ring_size; -+ char ring_name[RTE_MEMZONE_NAMESIZE] = {0}; -+ struct rte_ring *ring; -+ -+ ring_size = rte_ring_get_memsize(size); -+ if (ring_size < 0) { -+ RTE_LOG(ERR, EAL, "rte_ring_get_memszie failed\n"); -+ return NULL; -+ } -+ -+ /* -+ * rte_ring_create is not used because it calls memzone_lookup_thread_unsafe function -+ * time consuming when there are many rings -+ */ -+ ring = rte_malloc_socket(NULL, ring_size, RTE_CACHE_LINE_SIZE, rte_socket_id()); -+ if (ring == NULL) { -+ RTE_LOG(ERR, EAL, "cannot create rte_ring for mbox\n"); -+ return NULL; -+ } -+ -+ if (snprintf(ring_name, sizeof(ring_name), "%s""%"PRIXPTR, name, (uintptr_t)ring) < 0) { -+ rte_free(ring); -+ RTE_LOG(ERR, EAL, "snprintf failed\n"); -+ return NULL; -+ } -+ -+ if (rte_ring_init(ring, ring_name, size, flags) != 0) { -+ rte_free(ring); -+ RTE_LOG(ERR, EAL, "cannot init rte_ring for mbox\n"); -+ return NULL; -+ } -+ -+ return ring; -+} -+ -+static inline -+void rte_ring_free_fast(struct rte_ring *ring) -+{ -+ rte_free(ring); -+} -+ -+ -+static inline -+void mbox_ring_common_free(struct mbox_ring *mr) -+{ -+ void *obj; -+ -+ if (mr->private_data_free_fn != NULL && mr->private_data != NULL) { -+ mr->private_data_free_fn(mr); -+ mr->private_data_free_fn = NULL; -+ mr->private_data = NULL; -+ } -+ -+ obj = mr->ops->pop_tail(mr, NULL); -+ if (obj != NULL) -+ mr->obj_free_fn(mr, obj, true); -+ while (true) { -+ if (mr->ops->dequeue_burst(mr, &obj, 1) == 0) -+ break; -+ mr->obj_free_fn(mr, obj, false); -+ } -+} -+ -+extern void sockio_mbox_set_func(struct mbox_ring *mr); -+static inline -+void mbox_ring_common_init(struct mbox_ring *mr) -+{ -+ mr->stk_queued_num = 0; -+ -+ mr->app_free_count = 0; -+ mr->app_queued_num = 0; -+ mr->app_tail_left = 0; -+ mr->app_recvd_len = 0; -+ -+ sockio_mbox_set_func(mr); -+} -+ -+/* single thread */ -+static inline -+int st_ring_create(struct mbox_ring *mr, const char *name, unsigned count) -+{ -+ mbox_ring_common_init(mr); -+ -+ mr->ops = &g_mbox_rtc_default_ops; -+ mr->st_obj = NULL; -+ -+ mr->ring = rte_ring_create_fast(name, count, RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (mr->ring == NULL) { -+ return -ENOMEM; -+ } -+ return 0; -+} -+ -+static inline -+void st_ring_destroy(struct mbox_ring *mr) -+{ -+ mbox_ring_common_free(mr); -+ -+ mr->ops = NULL; -+ mr->st_obj = NULL; -+ if (mr->ring != NULL) { -+ rte_ring_free_fast(mr->ring); -+ mr->ring = NULL; -+ } -+} -+ -+static inline -+unsigned st_ring_get_capacity(const struct mbox_ring *mr) -+{ -+ return mr->ring->capacity; -+} -+ -+static inline -+unsigned st_ring_count(const struct mbox_ring *mr) -+{ -+ // return rte_ring_count(mr->ring); -+ struct rte_ring *r = mr->ring; -+ uint32_t prod_tail = r->prod.tail; -+ uint32_t cons_head = r->cons.head; -+ uint32_t count = (prod_tail - cons_head) & r->mask; -+ return (count > r->capacity) ? r->capacity : count; -+} -+ -+static inline -+unsigned st_ring_free_count(const struct mbox_ring *mr) -+{ -+ return st_ring_get_capacity(mr) - st_ring_count(mr); -+} -+ -+static inline -+unsigned st_ring_enqueue_burst_start(struct mbox_ring *mr, void *const *obj_table, unsigned n) -+{ -+ struct rte_ring *r = mr->ring; -+ uint32_t prod_head, cons_tail; -+ uint32_t free_entries; -+ -+ prod_head = r->prod.head; -+ cons_tail = r->cons.tail; -+ -+ free_entries = r->capacity + cons_tail - prod_head; -+ if (unlikely(free_entries == 0)) -+ return 0; -+ if (n > free_entries) -+ n = free_entries; -+ -+ r->prod.head = prod_head + n; -+ -+ __rte_ring_enqueue_elems(r, prod_head, obj_table, sizeof(void *), n); -+ return n; -+} -+ -+static inline -+void st_ring_enqueue_burst_finish(struct mbox_ring *mr) -+{ -+ mr->ring->prod.tail = mr->ring->prod.head; -+} -+ -+static inline -+unsigned st_ring_dequeue_burst_start(struct mbox_ring *mr, void **obj_table, unsigned n) -+{ -+ struct rte_ring *r = mr->ring; -+ uint32_t cons_head, prod_tail; -+ uint32_t entries; -+ -+ cons_head = r->cons.head; -+ prod_tail = r->prod.tail; -+ -+ entries = prod_tail - cons_head; -+ if (unlikely(entries == 0)) -+ return 0; -+ if (n > entries) -+ n = entries; -+ -+ r->cons.head = cons_head + n; -+ -+ __rte_ring_dequeue_elems(r, cons_head, obj_table, sizeof(void *), n); -+ return n; -+} -+ -+static inline -+void st_ring_dequeue_burst_finish(struct mbox_ring *mr) -+{ -+ mr->ring->cons.tail = mr->ring->cons.head; -+} -+ -+static inline -+unsigned st_ring_enqueue_burst(struct mbox_ring *mr, void *const *obj_table, unsigned n) -+{ -+ n = st_ring_enqueue_burst_start(mr, obj_table, n); -+ st_ring_enqueue_burst_finish(mr); -+ return n; -+} -+ -+static inline -+unsigned st_ring_dequeue_burst(struct mbox_ring *mr, void **obj_table, unsigned n) -+{ -+ n = st_ring_dequeue_burst_start(mr, obj_table, n); -+ st_ring_dequeue_burst_finish(mr); -+ return n; -+} -+ -+static inline -+void *st_ring_read_tail(const struct mbox_ring *mr) -+{ -+ return mr->st_obj; -+} -+ -+static inline -+void st_ring_push_tail(struct mbox_ring *mr, void *obj) -+{ -+ mr->st_obj = obj; -+} -+ -+static inline -+void *st_ring_pop_tail(struct mbox_ring *mr, void *expect) -+{ -+ expect = mr->st_obj; -+ mr->st_obj = NULL; -+ return expect; -+} -+ -+static inline -+void st_ring_ops_init(struct mbox_ring_ops *ops) -+{ -+ ops->create = st_ring_create; -+ ops->destroy = st_ring_destroy; -+ -+ ops->get_capacity = st_ring_get_capacity; -+ ops->count = st_ring_count; -+ ops->free_count = st_ring_free_count; -+ -+ ops->enqueue_burst = st_ring_enqueue_burst; -+ ops->dequeue_burst = st_ring_dequeue_burst; -+ -+ ops->recv_count = st_ring_count; -+ ops->recv_start_burst = st_ring_dequeue_burst_start; -+ ops->recv_finish_burst = st_ring_dequeue_burst_finish; -+ -+ ops->read_tail = st_ring_read_tail; -+ ops->push_tail = st_ring_push_tail; -+ ops->pop_tail = st_ring_pop_tail; -+} -+ -+ -+/* multi thread */ -+static inline -+int mt_ring_create(struct mbox_ring *mr, const char *name, unsigned count) -+{ -+ mbox_ring_common_init(mr); -+ -+ if ((mr->flags & MBOX_FLAG_TCP) && (mr->flags & MBOX_FLAG_SEND)) { -+ mr->ops = &g_mbox_rtw_append_ops; -+ rte_atomic64_init(&mr->mt_obj); -+ } else { -+ mr->ops = &g_mbox_rtw_default_ops; -+ mr->st_obj = NULL; -+ } -+ if ((mr->flags & MBOX_FLAG_RECV) && !dpdk_nic_is_xdp()) { -+ mr->flags |= MBOX_FLAG_PEEK; -+ mr->ops = &g_mbox_rtw_peek_ops; -+ mr->ops->create(mr, name, count); -+ } -+ -+ mr->ring = rte_ring_create_fast(name, count, RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (mr->ring == NULL) { -+ return -ENOMEM; -+ } -+ return 0; -+} -+ -+static inline -+void mt_ring_destroy(struct mbox_ring *mr) -+{ -+ if (mr->flags & MBOX_FLAG_PEEK) { -+ mr->ops->destroy(mr); -+ } -+ mbox_ring_common_free(mr); -+ -+ mr->ops = NULL; -+ if ((mr->flags & MBOX_FLAG_TCP) && (mr->flags & MBOX_FLAG_SEND)) { -+ rte_atomic64_clear(&mr->mt_obj); -+ } else { -+ mr->st_obj = NULL; -+ } -+ -+ if (mr->ring != NULL) { -+ rte_ring_free_fast(mr->ring); -+ mr->ring = NULL; -+ } -+} -+ -+static inline -+unsigned mt_ring_get_capacity(const struct mbox_ring *mr) -+{ -+ return mr->ring->capacity; -+} -+ -+static inline -+unsigned mt_ring_count(const struct mbox_ring *mr) -+{ -+ // return rte_ring_count(mr->ring); -+ struct rte_ring *r = mr->ring; -+ uint32_t prod_tail = r->prod.tail; -+ uint32_t cons_head = r->cons.head; -+ uint32_t count = (prod_tail - cons_head) & r->mask; -+ return (count > r->capacity) ? r->capacity : count; -+} -+ -+static inline -+unsigned mt_ring_free_count(const struct mbox_ring *mr) -+{ -+ return mt_ring_get_capacity(mr) - mt_ring_count(mr); -+} -+ -+static inline -+unsigned mt_ring_enqueue_burst_start(struct mbox_ring *mr, void *const *obj_table, unsigned n) -+{ -+ struct rte_ring *r = mr->ring; -+ uint32_t prod_head, cons_tail; -+ uint32_t free_entries; -+ -+ prod_head = r->prod.head; -+ cons_tail = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE); -+ -+ free_entries = r->capacity + cons_tail - prod_head; -+ if (unlikely(free_entries == 0)) -+ return 0; -+ if (n > free_entries) -+ n = free_entries; -+ -+ r->prod.head = prod_head + n; -+ -+ __rte_ring_enqueue_elems(r, prod_head, obj_table, sizeof(void *), n); -+ return n; -+} -+ -+static inline -+void mt_ring_enqueue_burst_finish(struct mbox_ring *mr) -+{ -+ __atomic_store_n(&mr->ring->prod.tail, mr->ring->prod.head, __ATOMIC_RELEASE); -+} -+ -+static inline -+unsigned mt_ring_dequeue_burst_start(struct mbox_ring *mr, void ** obj_table, unsigned n) -+{ -+ struct rte_ring *r = mr->ring; -+ uint32_t cons_head, prod_tail; -+ uint32_t entries; -+ -+ cons_head = r->cons.head; -+ prod_tail = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE); -+ -+ entries = prod_tail - cons_head; -+ if (unlikely(entries == 0)) -+ return 0; -+ if (n > entries) -+ n = entries; -+ -+ r->cons.head = cons_head + n; -+ -+ __rte_ring_dequeue_elems(r, cons_head, obj_table, sizeof(void *), n); -+ return n; -+} -+ -+static inline -+void mt_ring_dequeue_burst_finish(struct mbox_ring *mr) -+{ -+ __atomic_store_n(&mr->ring->cons.tail, mr->ring->cons.head, __ATOMIC_RELEASE); -+} -+ -+static inline -+unsigned mt_ring_enqueue_burst(struct mbox_ring *mr, void *const *obj_table, unsigned n) -+{ -+ // return rte_ring_sp_enqueue_burst(mr->ring, obj_table, n, NULL); -+ n = mt_ring_enqueue_burst_start(mr, obj_table, n); -+ mt_ring_enqueue_burst_finish(mr); -+ return n; -+} -+ -+static inline -+unsigned mt_ring_dequeue_burst(struct mbox_ring *mr, void **obj_table, unsigned n) -+{ -+ // return rte_ring_sc_dequeue_burst(mr->ring, obj_table, n, NULL); -+ n = mt_ring_dequeue_burst_start(mr, obj_table, n); -+ mt_ring_dequeue_burst_finish(mr); -+ return n; -+} -+ -+static inline -+void *mt_ring_read_tail(const struct mbox_ring *mr) -+{ -+ return (void *)rte_atomic64_read((rte_atomic64_t *)&mr->mt_obj); -+} -+ -+static inline -+void mt_ring_push_tail(struct mbox_ring *mr, void *obj) -+{ -+ rte_atomic64_set(&mr->mt_obj, (uint64_t )obj); -+} -+ -+static inline -+void *mt_ring_pop_tail(struct mbox_ring *mr, void *expect) -+{ -+ if (expect == NULL) { -+ expect = (void *)rte_atomic64_exchange((volatile uint64_t *)&mr->mt_obj.cnt, -+ (uint64_t)NULL); -+ return expect; -+ } -+ -+ int ret = rte_atomic64_cmpset((volatile uint64_t *)&mr->mt_obj.cnt, -+ (uint64_t)expect, (uint64_t)NULL); -+ if (ret == 0) /* mt_obj != expect, cmpset failed */ -+ return NULL; -+ return expect; -+} -+ -+static inline -+void mt_ring_ops_init(struct mbox_ring_ops *ops) -+{ -+ ops->create = mt_ring_create; -+ ops->destroy = mt_ring_destroy; -+ -+ ops->get_capacity = mt_ring_get_capacity; -+ ops->count = mt_ring_count; -+ ops->free_count = mt_ring_free_count; -+ -+ ops->enqueue_burst = mt_ring_enqueue_burst; -+ ops->dequeue_burst = mt_ring_dequeue_burst; -+ -+ ops->recv_count = mt_ring_count; -+ ops->recv_start_burst = mt_ring_dequeue_burst_start; -+ ops->recv_finish_burst = mt_ring_dequeue_burst_finish; -+ -+ ops->read_tail = mt_ring_read_tail; -+ ops->push_tail = mt_ring_push_tail; -+ ops->pop_tail = mt_ring_pop_tail; -+} -+ -+/* multi thread & peek */ -+static inline -+int pk_ring_create(struct mbox_ring *mr, const char *name, unsigned count) -+{ -+ return 0; -+} -+ -+static inline -+void pk_ring_destroy(struct mbox_ring *mr) -+{ -+ void *obj; -+ while (mr->ops->recv_start_burst(mr, &obj, 1) > 0) { -+ mr->ops->recv_finish_burst(mr); -+ } -+ return; -+} -+ -+extern void sockio_peek_recv_free(struct mbox_ring *mr, unsigned n); -+static inline -+unsigned pk_ring_enqueue_burst(struct mbox_ring *mr, void *const *obj_table, unsigned n) -+{ -+ n = gazelle_ring_sp_enqueue(mr->ring, obj_table, n); -+ if (mr->flags & MBOX_FLAG_RECV) -+ sockio_peek_recv_free(mr, n); -+ return n; -+} -+ -+static inline -+unsigned pk_ring_dequeue_burst(struct mbox_ring *mr, void **obj_table, unsigned n) -+{ -+ return gazelle_ring_sc_dequeue(mr->ring, obj_table, n); -+} -+ -+static inline -+unsigned pk_ring_peek_start_burst(struct mbox_ring *mr, void **obj_table, unsigned n) -+{ -+ return gazelle_ring_read(mr->ring, obj_table, n); -+} -+static inline -+void pk_ring_peek_finish_burst(struct mbox_ring *mr) -+{ -+ gazelle_ring_read_over(mr->ring); -+} -+ -+static inline -+unsigned pk_ring_get_capacity(const struct mbox_ring *mr) -+{ -+ return mr->ring->capacity; -+} -+static inline -+unsigned pk_ring_count(const struct mbox_ring *mr) -+{ -+ return gazelle_ring_count(mr->ring); -+} -+static inline -+unsigned pk_ring_free_count(const struct mbox_ring *mr) -+{ -+ return gazelle_ring_free_count(mr->ring); -+} -+ -+static inline -+unsigned pk_ring_peek_start_count(const struct mbox_ring *mr) -+{ -+ return gazelle_ring_readable_count(mr->ring); -+} -+static inline -+unsigned pk_ring_peek_finish_count(const struct mbox_ring *mr) -+{ -+ return gazelle_ring_readover_count(mr->ring); -+} -+ -+static inline -+void pk_ring_ops_init(struct mbox_ring_ops *ops) -+{ -+ ops->create = pk_ring_create; -+ ops->destroy = pk_ring_destroy; -+ -+ ops->get_capacity = pk_ring_get_capacity; -+ ops->count = pk_ring_count; -+ ops->free_count = pk_ring_free_count; -+ -+ ops->enqueue_burst = pk_ring_enqueue_burst; -+ ops->dequeue_burst = pk_ring_dequeue_burst; -+ -+ ops->recv_count = pk_ring_peek_start_count; -+ ops->recv_start_burst = pk_ring_peek_start_burst; -+ ops->recv_finish_burst = pk_ring_peek_finish_burst; -+ -+ ops->read_tail = st_ring_read_tail; -+ ops->push_tail = st_ring_push_tail; -+ ops->pop_tail = st_ring_pop_tail; -+} -+ -+static inline -+void mbox_ring_ops_init(void) -+{ -+ st_ring_ops_init(&g_mbox_rtc_default_ops); -+ -+ mt_ring_ops_init(&g_mbox_rtw_append_ops); -+ mt_ring_ops_init(&g_mbox_rtw_default_ops); -+ /* rtw udp don't need to append data.*/ -+ g_mbox_rtw_default_ops.read_tail = st_ring_read_tail; -+ g_mbox_rtw_default_ops.pop_tail = st_ring_pop_tail; -+ g_mbox_rtw_default_ops.push_tail = st_ring_push_tail; -+ -+ pk_ring_ops_init(&g_mbox_rtw_peek_ops); -+ -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ g_mbox_default_ops = &g_mbox_rtc_default_ops; -+ } else { -+ g_mbox_default_ops = &g_mbox_rtw_default_ops; -+ } -+} -+ -+#endif /* __MBOX_RING_H__ */ --- -2.33.0 - diff --git a/0329-socket-adapt-to-tcp-and-udp.patch b/0329-socket-adapt-to-tcp-and-udp.patch deleted file mode 100644 index cc1d8e7..0000000 --- a/0329-socket-adapt-to-tcp-and-udp.patch +++ /dev/null @@ -1,5305 +0,0 @@ -From 3413b74afd91914682fc494defe17d057db8e2d2 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 21 Mar 2025 17:05:48 +0800 -Subject: [PATCH] socket: adapt to tcp and udp - -Signed-off-by: Lemmy Huang ---- - src/common/dpdk_common.h | 11 +- - src/common/gazelle_dfx_msg.h | 30 +- - src/common/gazelle_opt.h | 6 - - src/common/gazelle_reg_msg.h | 1 - - src/lstack/api/lstack_rtc_api.c | 46 - - src/lstack/api/lstack_rtw_api.c | 500 ------- - ...lstack_dummy_api.c => lstack_sock_dummy.c} | 2 +- - src/lstack/api/lstack_sockctl.c | 25 +- - src/lstack/api/lstack_wrap.c | 69 +- - src/lstack/core/lstack_cfg.c | 47 +- - src/lstack/core/lstack_control_plane.c | 38 +- - src/lstack/core/lstack_dpdk.c | 174 +-- - src/lstack/core/lstack_lwip.c | 1286 ----------------- - src/lstack/core/lstack_mempool.c | 23 +- - src/lstack/core/lstack_preload.c | 11 +- - src/lstack/core/lstack_protocol_stack.c | 63 +- - src/lstack/core/lstack_stack_stat.c | 122 +- - src/lstack/core/lstack_thread_rpc.c | 821 ++--------- - src/lstack/core/lstack_virtio.c | 3 +- - src/lstack/core/lstack_wait.c | 26 +- - src/lstack/core/same_node.c | 22 +- - src/lstack/include/lstack_cfg.h | 6 +- - src/lstack/include/lstack_dpdk.h | 20 +- - src/lstack/include/lstack_dummy_api.h | 23 - - src/lstack/include/lstack_lwip.h | 62 - - src/lstack/include/lstack_mempool.h | 2 +- - src/lstack/include/lstack_protocol_stack.h | 11 - - src/lstack/include/lstack_rtc_api.h | 25 - - .../{lstack_rtw_api.h => lstack_sock_dummy.h} | 10 +- - src/lstack/include/lstack_stack_stat.h | 16 +- - src/lstack/include/lstack_thread_rpc.h | 63 +- - src/lstack/include/mbox_ring.h | 2 +- - src/lstack/include/same_node.h | 1 - - src/lstack/netif/lstack_ethdev.c | 76 +- - src/lstack/netif/lstack_fault_inject.c | 20 +- - src/lstack/netif/lstack_flow.c | 15 +- - src/lstack/netif/lstack_vdev.c | 11 +- - src/ltran/ltran_dfx.c | 34 +- - src/ltran/ltran_forward.c | 2 +- - 39 files changed, 492 insertions(+), 3233 deletions(-) - delete mode 100644 src/lstack/api/lstack_rtc_api.c - delete mode 100644 src/lstack/api/lstack_rtw_api.c - rename src/lstack/api/{lstack_dummy_api.c => lstack_sock_dummy.c} (98%) - delete mode 100644 src/lstack/core/lstack_lwip.c - delete mode 100644 src/lstack/include/lstack_dummy_api.h - delete mode 100644 src/lstack/include/lstack_lwip.h - delete mode 100644 src/lstack/include/lstack_rtc_api.h - rename src/lstack/include/{lstack_rtw_api.h => lstack_sock_dummy.h} (77%) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index 8609216..cff193c 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -40,8 +40,7 @@ struct latency_timestamp { - struct mbuf_private { - /* struct pbuf_custom must at first */ - struct pbuf_custom pc; -- /* don't use `struct tcp_seg` directly to avoid conflicts by include lwip tcp header */ -- char ts[32]; // 32 > sizeof(struct tcp_seg) -+ int stack_id; /* the stack to which buf belongs */ - struct latency_timestamp lt; - }; - -@@ -49,13 +48,9 @@ static __rte_always_inline struct mbuf_private *mbuf_to_private(const struct rte - { - return (struct mbuf_private *)RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); - } --static __rte_always_inline struct pbuf_custom *mbuf_to_pbuf(const struct rte_mbuf *m) -+static __rte_always_inline struct pbuf *mbuf_to_pbuf(const struct rte_mbuf *m) - { -- return &mbuf_to_private(m)->pc; --} --static __rte_always_inline struct rte_mbuf *pbuf_to_mbuf(const struct pbuf *p) --{ -- return (struct rte_mbuf *)RTE_PTR_SUB(p, sizeof(struct rte_mbuf)); -+ return &mbuf_to_private(m)->pc.pbuf; - } - static __rte_always_inline struct mbuf_private *pbuf_to_private(const struct pbuf *p) - { -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 1a89e65..2c6462d 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -72,10 +72,9 @@ enum GAZELLE_STAT_MODE { - - enum GAZELLE_LATENCY_TYPE { - GAZELLE_LATENCY_INTO_MBOX, // t0 -> t1 -- GAZELLE_LATENCY_READ_LWIP, // t1 -> t2 -- GAZELLE_LATENCY_READ_APP_CALL, // t2 -> t3 -- GAZELLE_LATENCY_READ_LSTACK, // t3 -> t4 -- GAZELLE_LATENCY_READ_MAX, // t0 -> t4 -+ GAZELLE_LATENCY_READ_APP_CALL, // t1 -> t2 -+ GAZELLE_LATENCY_READ_LSTACK, // t2 -> t3 -+ GAZELLE_LATENCY_READ_MAX, // t0 -> t3 - - GAZELLE_LATENCY_WRITE_INTO_RING, // t0 -> t1 - GAZELLE_LATENCY_WRITE_LWIP, // t1 -> t2 -@@ -123,12 +122,12 @@ struct gazelle_wakeup_stat { - }; - - struct gazelle_stack_aggregate_stats { -- /* 0: RX, 1: TX, 2: APP_TX */ -- uint32_t size_1_64[3]; -- uint32_t size_65_512[3]; -- uint32_t size_513_1460[3]; -- uint32_t size_1461_8192[3]; -- uint32_t size_8193_max[3]; -+ /* 0: RX, 1: TX */ -+ uint32_t size_1_64[2]; -+ uint32_t size_65_512[2]; -+ uint32_t size_513_1460[2]; -+ uint32_t size_1461_8192[2]; -+ uint32_t size_8193_max[2]; - - uint64_t rx_bytes; - uint64_t tx_bytes; -@@ -138,7 +137,6 @@ struct gazelle_stat_pkts { - uint16_t conn_num; - uint32_t mbufpool_avail_cnt; - uint64_t call_msg_cnt; -- uint64_t recv_list_cnt; - uint64_t call_alloc_fail; - struct gazelle_stack_stat stack_stat; - struct gazelle_wakeup_stat wakeup_stat; -@@ -257,15 +255,17 @@ struct gazelle_stat_lstack_proto { - - struct gazelle_stat_lstack_conn_info { - uint32_t state; -+ uint32_t tcp_sub_state; -+ - gz_addr_t rip; - gz_addr_t lip; - uint16_t r_port; - uint16_t l_port; - uint32_t in_send; -- uint32_t recv_cnt; -- uint32_t send_ring_cnt; -- uint32_t recv_ring_cnt; -- uint32_t tcp_sub_state; -+ uint32_t recvmbox_cnt; -+ uint16_t recvmbox_tail; -+ uint32_t sendmbox_cnt; -+ uint16_t sendmbox_tail; - - uint32_t cwn; - uint32_t rcv_wnd; -diff --git a/src/common/gazelle_opt.h b/src/common/gazelle_opt.h -index 4406831..86eb874 100644 ---- a/src/common/gazelle_opt.h -+++ b/src/common/gazelle_opt.h -@@ -56,12 +56,6 @@ - #define STACK_THREAD_DEFAULT 4 - #define STACK_NIC_READ_DEFAULT 128 - --#define MTU_DEFAULT_DATA_LEN 1460 --#define VLAN_HEAD_LEN 4 --#define IPV6_EXTRA_HEAD_LEN 20 --#define MBUF_MAX_DATA_LEN (MTU_DEFAULT_DATA_LEN - VLAN_HEAD_LEN - IPV6_EXTRA_HEAD_LEN) -- --#define GAZELLE_UDP_PKGLEN_MAX (65535 - IP_HLEN - UDP_HLEN) - - /* total:33 client, index 32 is invaild client */ - #define GAZELLE_CLIENT_NUM_ALL 33 -diff --git a/src/common/gazelle_reg_msg.h b/src/common/gazelle_reg_msg.h -index ecd1e35..f573390 100644 ---- a/src/common/gazelle_reg_msg.h -+++ b/src/common/gazelle_reg_msg.h -@@ -33,7 +33,6 @@ - #define OPT_VDEV "--vdev" - #define VDEV_ARG_IFACE "iface" - --#define GAZELLE_MAX_NUMA_NODES 8 - #define SOCKET_MEM_STRLEN (GAZELLE_MAX_NUMA_NODES * 10) - - /* types for msg from lstack to ltran */ -diff --git a/src/lstack/api/lstack_rtc_api.c b/src/lstack/api/lstack_rtc_api.c -deleted file mode 100644 -index 4a962e1..0000000 ---- a/src/lstack/api/lstack_rtc_api.c -+++ /dev/null -@@ -1,46 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#include --#include -- --#include "lstack_log.h" --#include "lstack_rtc_api.h" -- -- --void rtc_api_init(posix_api_t *api) --{ -- api->close_fn = lwip_close; -- api->shutdown_fn = lwip_shutdown; -- api->socket_fn = lwip_socket; -- api->accept_fn = lwip_accept; -- api->accept4_fn = lwip_accept4; -- api->bind_fn = lwip_bind; -- api->listen_fn = lwip_listen; -- api->connect_fn = lwip_connect; -- -- api->setsockopt_fn = lwip_setsockopt; -- api->getsockopt_fn = lwip_getsockopt; -- api->getpeername_fn = lwip_getpeername; -- api->getsockname_fn = lwip_getsockname; -- -- api->read_fn = lwip_read; -- api->readv_fn = lwip_readv; -- api->write_fn = lwip_write; -- api->writev_fn = lwip_writev; -- api->recv_fn = lwip_recv; -- api->send_fn = lwip_send; -- api->recvmsg_fn = lwip_recvmsg; -- api->sendmsg_fn = lwip_sendmsg; -- api->recvfrom_fn = lwip_recvfrom; -- api->sendto_fn = lwip_sendto; --} -diff --git a/src/lstack/api/lstack_rtw_api.c b/src/lstack/api/lstack_rtw_api.c -deleted file mode 100644 -index 7b8dec2..0000000 ---- a/src/lstack/api/lstack_rtw_api.c -+++ /dev/null -@@ -1,500 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#include --#include -- --#include "common/gazelle_base_func.h" --#include "lstack_log.h" --#include "lstack_cfg.h" --#include "lstack_thread_rpc.h" --#include "lstack_protocol_stack.h" --#include "lstack_lwip.h" --#include "lstack_rtw_api.h" --#include "lstack_epoll.h" --#include "lstack_wait.h" -- --/* when fd is listenfd, listenfd of all protocol stack thread will be closed */ --static int stack_broadcast_close(int fd) --{ -- int ret = 0; -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- do { -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- if (stack == NULL || rpc_call_close(&stack->rpc_queue, fd)) { -- ret = -1; -- } -- -- sock = sock->listen_next; -- fd = sock->conn->callback_arg.socket; -- } while (1); -- -- return ret; --} -- --static int stack_broadcast_shutdown(int fd, int how) --{ -- int32_t ret = 0; -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- do { -- if (POSIX_IS_CLOSED(sock)) { -- break; -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- if (stack == NULL || rpc_call_shutdown(&stack->rpc_queue, fd, how)) { -- ret = -1; -- } -- -- sock = sock->listen_next; -- fd = sock->conn->callback_arg.socket; -- } while (1); -- -- return ret; --} -- --/* choice one stack bind */ --static int stack_single_bind(int fd, const struct sockaddr *name, socklen_t namelen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_bind(&stack->rpc_queue, fd, name, namelen); --} -- --/* bind sync to all protocol stack thread, so that any protocol stack thread can build connect */ --static int stack_broadcast_bind(int fd, const struct sockaddr *name, socklen_t namelen) --{ -- struct protocol_stack *cur_stack; -- struct protocol_stack *stack = NULL; -- int ret, clone_fd; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); -- GAZELLE_RETURN(EBADF); -- } -- -- cur_stack = get_protocol_stack_by_id(sock->stack_id); -- ret = rpc_call_bind(&cur_stack->rpc_queue, fd, name, namelen); -- if (ret < 0) { -- close(fd); -- return ret; -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- for (int i = 0; i < stack_group->stack_num; ++i) { -- stack = stack_group->stacks[i]; -- if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, name, namelen); -- if (clone_fd < 0) { -- stack_broadcast_close(fd); -- return clone_fd; -- } -- } -- } -- return 0; --} -- --static struct lwip_sock *get_min_accept_sock(int fd) --{ -- struct lwip_sock *sock; -- struct lwip_sock *min_sock = NULL; -- -- for (sock = lwip_get_socket(fd); sock != NULL; sock = sock->listen_next) { -- if (!netconn_is_nonblocking(sock->conn)) { -- /* init all sock sk_wait */ -- if (unlikely(sock->sk_wait == NULL) || sock->sk_wait->type == WAIT_CLOSE) { -- sock->sk_wait = poll_construct_wait(0); -- } -- if (!(sock->sk_wait->type & WAIT_BLOCK)) { -- sock->sk_wait->type |= WAIT_BLOCK; -- } -- } -- -- if (!sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0)) { -- continue; -- } -- -- if (min_sock == NULL || -- get_protocol_stack_by_id(min_sock->stack_id)->conn_num > get_protocol_stack_by_id(sock->stack_id)->conn_num) { -- min_sock = sock; -- } -- } -- -- return min_sock; --} -- --/* ergodic the protocol stack thread to find the connection, because all threads are listening */ --static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) --{ -- int ret = -1; -- struct lwip_sock *min_sock = NULL; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = NULL; -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- -- min_sock = get_min_accept_sock(fd); -- if (min_sock == NULL) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -- min_sock = get_min_accept_sock(fd); -- } -- } -- -- if (!POSIX_IS_CLOSED(min_sock)) { -- stack = get_protocol_stack_by_id(min_sock->stack_id); -- ret = rpc_call_accept(&stack->rpc_queue, min_sock->conn->callback_arg.socket, addr, addrlen, flags); -- } -- -- if (ret < 0) { -- errno = EAGAIN; -- } -- return ret; --} -- --static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) --{ -- return stack_broadcast_accept4(fd, addr, addrlen, 0); --} -- --/* choice one stack listen */ --static int stack_single_listen(int fd, int backlog) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_listen(&stack->rpc_queue, fd, backlog); --} -- --/* listen sync to all protocol stack thread, so that any protocol stack thread can build connect */ --static int stack_broadcast_listen(int fd, int backlog) --{ -- typedef union sockaddr_union { -- struct sockaddr sa; -- struct sockaddr_in in; -- struct sockaddr_in6 in6; -- } sockaddr_t; -- -- struct protocol_stack *cur_stack; -- struct protocol_stack *stack = NULL; -- sockaddr_t addr; -- socklen_t addr_len = sizeof(addr); -- int ret, clone_fd; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, %d get sock null or stack null\n", rte_gettid(), fd); -- GAZELLE_RETURN(EBADF); -- } -- -- cur_stack = get_protocol_stack_by_id(sock->stack_id); -- ret = rpc_call_getsockname(&cur_stack->rpc_queue, fd, (struct sockaddr *)&addr, &addr_len); -- if (ret != 0) { -- return ret; -- } -- -- struct protocol_stack_group *stack_group = get_protocol_stack_group(); --#if GAZELLE_TCP_REUSE_IPPORT -- int min_conn_stk_idx = get_min_conn_stack(stack_group); --#endif -- for (int32_t i = 0; i < stack_group->stack_num; ++i) { -- stack = stack_group->stacks[i]; -- if (stack != cur_stack) { -- clone_fd = rpc_call_shadow_fd(&stack->rpc_queue, fd, (struct sockaddr *)&addr, addr_len); -- if (clone_fd < 0) { -- stack_broadcast_close(fd); -- return clone_fd; -- } -- } else { -- clone_fd = fd; -- } --#if GAZELLE_TCP_REUSE_IPPORT -- if (min_conn_stk_idx == i) { -- lwip_get_socket(clone_fd)->conn->is_master_fd = 1; -- } else { -- lwip_get_socket(clone_fd)->conn->is_master_fd = 0; -- } --#endif -- ret = rpc_call_listen(&stack->rpc_queue, clone_fd, backlog); -- if (ret < 0) { -- stack_broadcast_close(fd); -- return ret; -- } -- } -- return 0; --} -- --static int rtw_socket(int domain, int type, int protocol) --{ -- struct protocol_stack *stack = get_bind_protocol_stack(); -- if (stack == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- return rpc_call_socket(&stack->rpc_queue, domain, type, protocol); --} -- --static int rtw_accept(int s, struct sockaddr *addr, socklen_t *addrlen) --{ -- return stack_broadcast_accept(s, addr, addrlen); --} -- --static int rtw_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) --{ -- return stack_broadcast_accept4(s, addr, addrlen, flags); --} -- --static int rtw_bind(int s, const struct sockaddr *name, socklen_t namelen) --{ -- struct lwip_sock *sock = lwip_get_socket(s); -- -- if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) { -- return stack_broadcast_bind(s, name, namelen); -- } else { -- return stack_single_bind(s, name, namelen); -- } --} -- --static int rtw_listen(int s, int backlog) --{ -- if (!get_global_cfg_params()->tuple_filter && -- !get_global_cfg_params()->listen_shadow) { -- return stack_single_listen(s, backlog); -- } else { -- return stack_broadcast_listen(s, backlog); -- } --} -- --static int rtw_connect(int s, const struct sockaddr *name, socklen_t namelen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_connect(&stack->rpc_queue, s, name, namelen); --} -- --static int rtw_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_setsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); --} -- --static int rtw_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_getsockopt(&stack->rpc_queue, s, level, optname, optval, optlen); --} -- --static int rtw_getpeername(int s, struct sockaddr *name, socklen_t *namelen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_getpeername(&stack->rpc_queue, s, name, namelen); --} -- --static int rtw_getsockname(int s, struct sockaddr *name, socklen_t *namelen) --{ -- struct protocol_stack *stack; -- struct lwip_sock *sock = lwip_get_socket(s); -- if (sock == NULL) { -- GAZELLE_RETURN(EBADF); -- } -- stack = get_protocol_stack_by_id(sock->stack_id); -- return rpc_call_getsockname(&stack->rpc_queue, s, name, namelen); --} -- --static ssize_t rtw_read(int s, void *mem, size_t len) --{ -- return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL); --} -- --static ssize_t rtw_readv(int s, const struct iovec *iov, int iovcnt) --{ -- struct msghdr msg; -- -- msg.msg_name = NULL; -- msg.msg_namelen = 0; -- msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -- msg.msg_iovlen = iovcnt; -- msg.msg_control = NULL; -- msg.msg_controllen = 0; -- msg.msg_flags = 0; -- return do_lwip_recvmsg_from_stack(s, &msg, 0); --} -- --static ssize_t rtw_write(int s, const void *mem, size_t size) --{ -- return do_lwip_send_to_stack(s, mem, size, 0, NULL, 0); --} -- --static ssize_t rtw_writev(int s, const struct iovec *iov, int iovcnt) --{ -- struct lwip_sock *sock = lwip_get_socket(s); -- struct msghdr msg; -- -- msg.msg_name = NULL; -- msg.msg_namelen = 0; -- msg.msg_iov = LWIP_CONST_CAST(struct iovec *, iov); -- msg.msg_iovlen = iovcnt; -- msg.msg_control = NULL; -- msg.msg_controllen = 0; -- msg.msg_flags = 0; -- return do_lwip_sendmsg_to_stack(sock, s, &msg, 0); --} -- --static ssize_t rtw_recv(int sockfd, void *buf, size_t len, int flags) --{ -- return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL); --} -- --static ssize_t rtw_send(int sockfd, const void *buf, size_t len, int flags) --{ -- return do_lwip_send_to_stack(sockfd, buf, len, flags, NULL, 0); --} -- --static ssize_t rtw_recvmsg(int s, struct msghdr *message, int flags) --{ -- return do_lwip_recvmsg_from_stack(s, message, flags); --} -- --static ssize_t rtw_sendmsg(int s, const struct msghdr *message, int flags) --{ -- struct lwip_sock *sock = lwip_get_socket(s); -- return do_lwip_sendmsg_to_stack(sock, s, message, flags); --} -- --static ssize_t rtw_udp_recvfrom(int sockfd, void *buf, size_t len, int flags, -- struct sockaddr *addr, socklen_t *addrlen) --{ -- struct lwip_sock *sock = lwip_get_socket(sockfd); -- int ret; -- -- while (1) { -- ret = do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); -- if (ret >= 0) { -- return ret; -- } -- if (ret < 0 && errno != EAGAIN) { -- return -1; -- } -- sock = sock->listen_next; -- if (!POSIX_IS_CLOSED(sock)) { -- sockfd = sock->conn->callback_arg.socket; -- } else { -- if (sock == NULL) { -- errno = EAGAIN; -- return -1; -- } else { -- errno = ENOTCONN; -- return -1; -- } -- } -- } --} -- --static inline ssize_t rtw_tcp_recvfrom(int sockfd, void *buf, size_t len, int flags, -- struct sockaddr *addr, socklen_t *addrlen) --{ -- return do_lwip_read_from_stack(sockfd, buf, len, flags, addr, addrlen); --} -- -- --static ssize_t rtw_recvfrom(int sockfd, void *buf, size_t len, int flags, -- struct sockaddr *addr, socklen_t *addrlen) --{ -- struct lwip_sock *sock = lwip_get_socket(sockfd); -- if (NETCONN_IS_UDP(sock)) { -- return rtw_udp_recvfrom(sockfd, buf, len, flags, addr, addrlen); -- } else { -- return rtw_tcp_recvfrom(sockfd, buf, len, flags, addr, addrlen); -- } --} -- --static ssize_t rtw_sendto(int sockfd, const void *buf, size_t len, int flags, -- const struct sockaddr *addr, socklen_t addrlen) --{ -- return do_lwip_send_to_stack(sockfd, buf, len, flags, addr, addrlen); --} -- --static int rtw_close(int s) --{ -- return stack_broadcast_close(s); --} -- --static int rtw_shutdown(int fd, int how) --{ -- return stack_broadcast_shutdown(fd, how); --} -- --void rtw_api_init(posix_api_t *api) --{ -- api->close_fn = rtw_close; -- api->shutdown_fn = rtw_shutdown; -- api->socket_fn = rtw_socket; -- api->accept_fn = rtw_accept; -- api->accept4_fn = rtw_accept4; -- api->bind_fn = rtw_bind; -- api->listen_fn = rtw_listen; -- api->connect_fn = rtw_connect; -- -- api->setsockopt_fn = rtw_setsockopt; -- api->getsockopt_fn = rtw_getsockopt; -- api->getpeername_fn = rtw_getpeername; -- api->getsockname_fn = rtw_getsockname; -- -- api->read_fn = rtw_read; -- api->readv_fn = rtw_readv; -- api->write_fn = rtw_write; -- api->writev_fn = rtw_writev; -- api->recv_fn = rtw_recv; -- api->send_fn = rtw_send; -- api->recvmsg_fn = rtw_recvmsg; -- api->sendmsg_fn = rtw_sendmsg; -- api->recvfrom_fn = rtw_recvfrom; -- api->sendto_fn = rtw_sendto; --} -diff --git a/src/lstack/api/lstack_dummy_api.c b/src/lstack/api/lstack_sock_dummy.c -similarity index 98% -rename from src/lstack/api/lstack_dummy_api.c -rename to src/lstack/api/lstack_sock_dummy.c -index 004a3aa..ce046e3 100644 ---- a/src/lstack/api/lstack_dummy_api.c -+++ b/src/lstack/api/lstack_sock_dummy.c -@@ -85,7 +85,7 @@ static ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, - return dummy_exit(); - } - --void dummy_api_init(posix_api_t *api) -+void sock_dummy_api_init(posix_api_t *api) - { - api->socket_fn = dummy_socket; - api->send_fn = dummy_send; -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index 71310b7..7da7473 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -27,9 +27,6 @@ - static void callback_getpeername(struct rpc_msg *msg) - { - msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -- } - } - - static void callback_getsockname(struct rpc_msg *msg) -@@ -191,7 +188,7 @@ static void callback_close(struct rpc_msg *msg) - - if (sockio_mbox_pending(sock)) { - rpc_queue *queue = &get_protocol_stack_by_id(sock->stack_id)->rpc_queue; -- rpc_async_call(queue, msg, RPC_MSG_FREE | RPC_MSG_RECALL); /* until stack_send recall finish */ -+ rpc_async_call(queue, msg, RPC_MSG_RECALL); /* until stack_send recall finish */ - return; - } - -@@ -209,7 +206,7 @@ static void callback_shutdown(struct rpc_msg *msg) - - if (sockio_mbox_pending(sock)) { - rpc_queue *queue = &get_protocol_stack_by_id(sock->stack_id)->rpc_queue; -- rpc_async_call(queue, msg, RPC_MSG_FREE | RPC_MSG_RECALL); -+ rpc_async_call(queue, msg, RPC_MSG_RECALL); - return; - } - -@@ -458,12 +455,15 @@ static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, s - /* for lwip nonblock connected callback */ - void do_lwip_connected_callback(int fd) - { -+ bool has_kernel; - struct lwip_sock *sock = lwip_get_socket(fd); - if (POSIX_IS_CLOSED(sock)) { - return; - } - -- if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ has_kernel = POSIX_HAS_TYPE(sock, POSIX_KERNEL); -+ POSIX_SET_TYPE(sock, POSIX_LWIP); -+ if (has_kernel) { - /* delete kernel event */ - if (sock->sk_wait != NULL) { - posix_api->epoll_ctl_fn(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL); -@@ -471,10 +471,7 @@ void do_lwip_connected_callback(int fd) - /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ - posix_api->shutdown_fn(fd, SHUT_RDWR); - } -- -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- -- API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); -+ return; - } - - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ -@@ -625,10 +622,7 @@ static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *add - - static int stack_broadcast_accept(int fd, struct sockaddr *addr, socklen_t *addrlen) - { -- if (get_global_cfg_params()->nonblock_mode) -- return stack_broadcast_accept4(fd, addr, addrlen, SOCK_NONBLOCK); -- else -- return stack_broadcast_accept4(fd, addr, addrlen, 0); -+ return stack_broadcast_accept4(fd, addr, addrlen, 0); - } - - /* choice one stack listen */ -@@ -675,9 +669,6 @@ static int stack_broadcast_listen(int fd, int backlog) - - for (int32_t i = 0; i < stack_group->stack_num; ++i) { - stack = stack_group->stacks[i]; -- if (get_global_cfg_params()->seperate_send_recv && stack->is_send_thread) { -- continue; -- } - if (stack != cur_stack) { - clone_fd = rpc_call_shadow_fd(stack->stack_idx, fd, (struct sockaddr *)&addr, addr_len); - if (clone_fd < 0) { -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 5869d6b..e22937f 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -24,13 +24,13 @@ - #include "common/gazelle_base_func.h" - #include "lstack_log.h" - #include "lstack_cfg.h" --#include "lstack_lwip.h" - #include "lstack_preload.h" - #include "lstack_unistd.h" - #include "lstack_epoll.h" --#include "lstack_rtc_api.h" --#include "lstack_rtw_api.h" --#include "lstack_dummy_api.h" -+#include "lstack_sockctl.h" -+#include "lstack_sockio.h" -+#include "lstack_sock_dummy.h" -+#include "mbox_ring.h" - - #ifndef SOL_XDP - #define SOL_XDP 283 /* same as define in bits/socket.h */ -@@ -47,17 +47,19 @@ void wrap_api_init(void) - g_wrap_api = &g_wrap_api_value; - - if (get_global_cfg_params()->stack_mode_rtc) { -- rtc_api_init(g_wrap_api); -+ sockctl_rtc_api_init(g_wrap_api); - } else { -- rtw_api_init(g_wrap_api); -+ sockctl_rtw_api_init(g_wrap_api); - } - - epoll_api_init(g_wrap_api); -+ sockio_ops_init(); -+ mbox_ring_ops_init(); - } - - void wrap_api_exit(void) - { -- dummy_api_init(g_wrap_api); -+ sock_dummy_api_init(g_wrap_api); - } - - static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen) -@@ -517,7 +519,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - - if (get_global_cfg_params()->stack_mode_rtc) { - if (stack_setup_app_thread() != 0) { -- LSTACK_EXIT(1, "stack_setup_app_thread failed\n"); -+ exit(1); - } - } - -@@ -536,30 +538,16 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - - static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t flags) - { -- if (buf == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- if (len == 0) { -- return 0; -- } -- - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return g_wrap_api->recv_fn(sockfd, buf, len, flags); -+ return sockio_recv(sockfd, buf, len, flags); - } - return posix_api->recv_fn(sockfd, buf, len, flags); - } - - static inline ssize_t do_read(int32_t s, void *mem, size_t len) - { -- if (mem == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- if (len == 0) { -- return 0; -- } -- - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->read_fn(s, mem, len); -+ return sockio_read(s, mem, len); - } - return posix_api->read_fn(s, mem, len); - } -@@ -567,7 +555,7 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->readv_fn(s, iov, iovcnt); -+ return sockio_readv(s, iov, iovcnt); - } - return posix_api->readv_fn(s, iov, iovcnt); - } -@@ -575,7 +563,7 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return g_wrap_api->send_fn(sockfd, buf, len, flags); -+ return sockio_send(sockfd, buf, len, flags); - } - return posix_api->send_fn(sockfd, buf, len, flags); - } -@@ -583,7 +571,7 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->write_fn(s, mem, size); -+ return sockio_write(s, mem, size); - } - return posix_api->write_fn(s, mem, size); - } -@@ -591,31 +579,23 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->writev_fn(s, iov, iovcnt); -+ return sockio_writev(s, iov, iovcnt); - } - return posix_api->writev_fn(s, iov, iovcnt); - } - - static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flags) - { -- if (message == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->recvmsg_fn(s, message, flags); -+ return sockio_recvmsg(s, message, flags); - } - return posix_api->recvmsg_fn(s, message, flags); - } - - static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags) - { -- if (message == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return g_wrap_api->sendmsg_fn(s, message, flags); -+ return sockio_sendmsg(s, message, flags); - } - return posix_api->sendmsg_fn(s, message, flags); - } -@@ -623,15 +603,8 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_ - static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t flags, - struct sockaddr *addr, socklen_t *addrlen) - { -- if (buf == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- if (len == 0) { -- return 0; -- } -- - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return g_wrap_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); -+ return sockio_recvfrom(sockfd, buf, len, flags, addr, addrlen); - } - return posix_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); - } -@@ -640,7 +613,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - const struct sockaddr *addr, socklen_t addrlen) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return g_wrap_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); -+ return sockio_sendto(sockfd, buf, len, flags, addr, addrlen); - } - return posix_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); - } -@@ -688,7 +661,7 @@ static inline int do_epoll_create1(int flags) - - if (get_global_cfg_params()->stack_mode_rtc) { - if (stack_setup_app_thread() != 0) { -- LSTACK_EXIT(1, "stack_setup_app_thread failed\n"); -+ exit(1); - } - } - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 04ceb89..432e4db 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -28,9 +29,7 @@ - #include - - #include --#include --#include --#include -+#include - - #include "common/gazelle_reg_msg.h" - #include "common/gazelle_base_func.h" -@@ -65,13 +64,10 @@ static int32_t parse_kni_switch(void); - static int32_t parse_listen_shadow(void); - static int32_t parse_main_thread_affinity(void); - static int32_t parse_unix_prefix(void); --static int32_t parse_read_connect_number(void); - static int32_t parse_rpc_number(void); - static int32_t parse_nic_read_number(void); - static int32_t parse_tcp_conn_count(void); - static int32_t parse_mbuf_count_per_conn(void); --static int32_t parse_send_ring_size(void); --static int32_t parse_recv_ring_size(void); - static int32_t parse_num_process(void); - static int32_t parse_process_numa(void); - static int32_t parse_process_index(void); -@@ -123,8 +119,6 @@ static struct config_vector_t g_config_tbl[] = { - { "mbuf_count_per_conn", parse_mbuf_count_per_conn }, - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, -- { "send_ring_size", parse_send_ring_size }, -- { "recv_ring_size", parse_recv_ring_size }, - { "rpc_msg_max", parse_rpc_msg_max }, - { "app_bind_numa", parse_app_bind_numa }, - { "stack_num", parse_stack_num }, -@@ -142,7 +136,6 @@ static struct config_vector_t g_config_tbl[] = { - { "app_exclude_cpus", parse_app_exclude_cpus }, - { "main_thread_affinity", parse_main_thread_affinity }, - { "unix_prefix", parse_unix_prefix }, -- { "read_connect_number", parse_read_connect_number }, - { "rpc_number", parse_rpc_number }, - { "nic_read_number", parse_nic_read_number }, - { "num_process", parse_num_process }, -@@ -1012,22 +1005,6 @@ static int32_t parse_tcp_conn_count(void) - return ret; - } - --static int32_t parse_send_ring_size(void) --{ -- int32_t ret; -- /* send ring size default value is 32 */ -- PARSE_ARG(g_config_params.send_ring_size, "send_ring_size", 32, 1, SOCK_SEND_RING_SIZE_MAX, ret); -- return ret; --} -- --static int32_t parse_recv_ring_size(void) --{ -- int32_t ret; -- /* recv ring size default value is 128 */ -- PARSE_ARG(g_config_params.recv_ring_size, "recv_ring_size", 128, 1, SOCK_RECV_RING_SIZE_MAX, ret); -- return ret; --} -- - static int32_t parse_mbuf_count_per_conn(void) - { - int32_t ret; -@@ -1036,13 +1013,6 @@ static int32_t parse_mbuf_count_per_conn(void) - return ret; - } - --static int32_t parse_read_connect_number(void) --{ -- int32_t ret; -- PARSE_ARG(g_config_params.read_connect_number, "read_connect_number", -- STACK_THREAD_DEFAULT, 1, INT32_MAX, ret); -- return ret; --} - - static int32_t parse_rpc_number(void) - { -@@ -1126,6 +1096,16 @@ static int32_t parse_conf_file(const char *path) - return 0; - } - -+static void lwip_conf_init(void) -+{ -+ const struct cfg_params *cfg = get_global_cfg_params(); -+ -+ struct sys_config sys_conf = { -+ .rtc_mode = cfg->stack_mode_rtc, -+ }; -+ sys_config_init(&sys_conf); -+} -+ - int32_t cfg_init(void) - { - int32_t ret; -@@ -1145,8 +1125,9 @@ int32_t cfg_init(void) - } - - ret = parse_conf_file(config_file); -- - free(config_file); -+ -+ lwip_conf_init(); - return ret; - } - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index bf34693..9d9e012 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -278,6 +278,8 @@ static int32_t proc_memory_init(const struct reg_response_msg *rsp_msg) - } - - ret = rte_eal_init(lc_argc, lc_argv); -+ /* rte_eal_init() would call __rte_thread_init(), and set _lcore_id. */ -+ RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY; - if (ret < 0) { - if (rte_errno == EALREADY) - LSTACK_PRE_LOG(LSTACK_INFO, "rte_eal_init aleady init ret=%d\n", ret); -@@ -389,7 +391,7 @@ static int32_t reg_conn(enum GAZELLE_TCP_LIST_STATE table_state, enum reg_ring_t - return 0; - } - --void thread_register_phase1(struct rpc_msg *msg) -+static void thread_register_phase1(struct rpc_msg *msg) - { - int32_t ret; - -@@ -415,7 +417,7 @@ void thread_register_phase1(struct rpc_msg *msg) - msg->result = ret; - } - --void thread_register_phase2(struct rpc_msg *msg) -+static void thread_register_phase2(struct rpc_msg *msg) - { - struct gazelle_stat_lstack_conn *conn = (struct gazelle_stat_lstack_conn *)msg->args[MSG_ARG_0].p; - -@@ -427,6 +429,28 @@ void thread_register_phase2(struct rpc_msg *msg) - msg->result = ret; - } - -+static int rpc_call_thread_regphase1(int stack_id, void *conn) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, thread_register_phase1); -+ if (msg == NULL) { -+ return -1; -+ } -+ msg->args[MSG_ARG_0].p = conn; -+ return rpc_sync_call(queue, msg); -+} -+ -+static int rpc_call_thread_regphase2(int stack_id, void *conn) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, thread_register_phase2); -+ if (msg == NULL) { -+ return -1; -+ } -+ msg->args[MSG_ARG_0].p = conn; -+ return rpc_sync_call(queue, msg); -+} -+ - int32_t client_reg_thrd_ring(void) - { - int32_t ret; -@@ -625,10 +649,9 @@ static int32_t thread_register(void) - /* register all connected conn before listen conn, avoid creating new conn */ - struct protocol_stack_group *stack_group = get_protocol_stack_group(); - for (int32_t i = 0; i < stack_group->stack_num; i++) { -- conn->conn_num = rpc_call_conntable(&stack_group->stacks[i]->rpc_queue, -- conn->conn_list, GAZELLE_LSTACK_MAX_CONN); -+ conn->conn_num = rpc_call_conntable(i, conn->conn_list, GAZELLE_LSTACK_MAX_CONN); - -- ret = rpc_call_thread_regphase1(&stack_group->stacks[i]->rpc_queue, conn); -+ ret = rpc_call_thread_regphase1(i, conn); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "thread_register_phase1 failed ret=%d!\n", ret); - free(conn); -@@ -637,10 +660,9 @@ static int32_t thread_register(void) - } - - for (int32_t i = 0; i < stack_group->stack_num; i++) { -- conn->conn_num = rpc_call_conntable(&stack_group->stacks[i]->rpc_queue, -- conn->conn_list, GAZELLE_LSTACK_MAX_CONN); -+ conn->conn_num = rpc_call_conntable(i, conn->conn_list, GAZELLE_LSTACK_MAX_CONN); - -- ret = rpc_call_thread_regphase2(&stack_group->stacks[i]->rpc_queue, conn); -+ ret = rpc_call_thread_regphase2(i, conn); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "thread_register_phase2 failed ret=%d!\n", ret); - free(conn); -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index fcb78ca..8f896c9 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -38,17 +38,15 @@ - - #include - #include --#include - - #include "lstack_log.h" - #include "common/dpdk_common.h" - #include "common/gazelle_base_func.h" --#include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" --#include "lstack_lwip.h" - #include "lstack_cfg.h" - #include "lstack_virtio.h" - #include "lstack_dpdk.h" -+#include "mbox_ring.h" - - struct eth_params { - uint16_t port_id; -@@ -109,6 +107,8 @@ int32_t dpdk_eal_init(void) - struct cfg_params *global_params = get_global_cfg_params(); - - ret = rte_eal_init(global_params->dpdk_argc, global_params->dpdk_argv); -+ /* rte_eal_init() would call __rte_thread_init(), and set _lcore_id. */ -+ RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY; - if (ret < 0) { - if (rte_errno == EALREADY) { - LSTACK_PRE_LOG(LSTACK_INFO, "rte_eal_init aleady init\n"); -@@ -135,58 +135,6 @@ int32_t dpdk_eal_init(void) - return ret; - } - --struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -- uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id) --{ -- int32_t ret; -- char pool_name[PATH_MAX]; -- struct rte_mempool *pool; -- -- ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d \n", ret); -- return NULL; -- } -- /* limit mbuf max num based on the dpdk capability */ -- if (nb_mbuf > MBUF_MAX_NUM) { -- LSTACK_LOG(ERR, LSTACK, "out of the dpdk mbuf quantity range\n"); -- return NULL; -- } -- -- /* time stamp before pbuf_custom as priv_data */ -- uint16_t private_size = sizeof(struct mbuf_private); -- if (xdp_eth_enabled()) { -- /* reserved for xdp metadata, see struct xsk_tx_metadata in /usr/include/linux/if_xdp.h */ -- private_size += 24; -- } -- private_size = RTE_ALIGN(private_size, RTE_CACHE_LINE_SIZE); -- pool = rte_pktmbuf_pool_create(pool_name, nb_mbuf, mbuf_cache_size, private_size, MBUF_SZ, numa_id); -- if (pool == NULL) { -- LSTACK_LOG(ERR, LSTACK, "cannot create %s pool rte_err=%d\n", pool_name, rte_errno); -- } -- -- return pool; --} -- --static struct rte_mempool* get_pktmbuf_mempool(const char *name, uint16_t queue_id) --{ -- int32_t ret; -- char pool_name[PATH_MAX]; -- struct rte_mempool *pool; -- -- ret = snprintf_s(pool_name, sizeof(pool_name), PATH_MAX - 1, "%s_%hu", name, queue_id); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); -- return NULL; -- } -- pool = rte_mempool_lookup(pool_name); -- if (pool == NULL) { -- LSTACK_LOG(ERR, LSTACK, "look up %s pool rte_err=%d\n", pool_name, rte_errno); -- } -- -- return pool; --} -- - static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_id) - { - int ret; -@@ -207,115 +155,56 @@ static struct reg_ring_msg *create_reg_mempool(const char *name, uint16_t queue_ - return reg_buf; - } - --int32_t pktmbuf_pool_init(struct protocol_stack *stack) --{ -- stack->rxtx_mbuf_pool = get_pktmbuf_mempool("rxtx_mbuf", stack->queue_id); -- if (stack->rxtx_mbuf_pool == NULL) { -- LSTACK_LOG(ERR, LSTACK, "rxtx_mbuf_pool is NULL\n"); -- return -1; -- } -- -- if (use_ltran()) { -- stack->reg_buf = create_reg_mempool("reg_ring_msg", stack->queue_id); -- if (stack->reg_buf == NULL) { -- LSTACK_LOG(ERR, LSTACK, "rxtx_mbuf_pool is NULL\n"); -- return -1; -- } -- } -- -- return 0; --} -- --struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t size, -- uint32_t flags, int32_t idx) -+int32_t create_shared_ring(struct protocol_stack *stack) - { -- char pool_name [RTE_MEMPOOL_NAMESIZE]; -- struct rte_mempool *mempool; -- int32_t ret = snprintf_s(pool_name, sizeof(pool_name), RTE_MEMPOOL_NAMESIZE - 1, -- "%s_%d", name, idx); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "snprintf_s fail ret=%d\n", ret); -- return NULL; -+ if (!use_ltran()) { -+ return 0; - } - -- mempool = rte_mempool_create(pool_name, count, size, -- 0, 0, NULL, NULL, NULL, NULL, rte_socket_id(), flags); -- if (mempool == NULL) { -- LSTACK_LOG(ERR, LSTACK, "%s create failed. errno: %d.\n", name, rte_errno); -+ stack->rx_ring = rte_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (stack->rx_ring == NULL) { -+ return -1; - } - -- return mempool; --} -- --int32_t create_shared_ring(struct protocol_stack *stack) --{ -- rpc_queue_init(&stack->rpc_queue, stack->queue_id); -- rpc_queue_init(&stack->dfx_rpc_queue, stack->queue_id); -- -- if (use_ltran()) { -- stack->rx_ring = gazelle_ring_create_fast("RING_RX", VDEV_RX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -- if (stack->rx_ring == NULL) { -- return -1; -- } -- -- stack->tx_ring = gazelle_ring_create_fast("RING_TX", VDEV_TX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -- if (stack->tx_ring == NULL) { -- return -1; -- } -- -- stack->reg_ring = gazelle_ring_create_fast("SHARED_REG_RING", VDEV_REG_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -- if (stack->reg_ring == NULL) { -- return -1; -- } -+ stack->tx_ring = rte_ring_create_fast("RING_TX", VDEV_TX_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (stack->tx_ring == NULL) { -+ return -1; - } - -- return 0; --} -- --int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve) --{ -- if (reserve) { -- /* -- * don't use rte_mempool_avail_count, it traverse cpu local cache, -- * when RTE_MAX_LCORE is too large, it's time-consuming -- */ -- if (rte_ring_count(pool->pool_data) < MBUFPOOL_RESERVE_NUM + num) { -- return -ENOMEM; -- } -+ stack->reg_ring = rte_ring_create_fast("SHARED_REG_RING", VDEV_REG_QUEUE_SZ, RING_F_SP_ENQ | RING_F_SC_DEQ); -+ if (stack->reg_ring == NULL) { -+ return -1; - } - -- int32_t ret = rte_pktmbuf_alloc_bulk(pool, mbufs, num); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_alloc_bulk fail allocNum=%d, ret=%d, info:%s \n", -- num, ret, rte_strerror(-ret)); -- return ret; -+ stack->reg_buf = create_reg_mempool("reg_ring_msg", stack->queue_id); -+ if (stack->reg_buf == NULL) { -+ LSTACK_LOG(ERR, LSTACK, "reg_buf is NULL\n"); -+ return -1; - } - - return 0; - } - --int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num) -+int32_t fill_mbuf_to_ring(int stack_id, struct rte_ring *ring, uint32_t mbuf_num) - { - int32_t ret; - uint32_t batch; - uint32_t remain = mbuf_num; -- struct rte_mbuf *free_buf[FREE_RX_QUEUE_SZ]; -+ struct rte_mbuf *free_buf[VDEV_RX_QUEUE_SZ]; - - while (remain > 0) { -- batch = LWIP_MIN(remain, RING_SIZE(FREE_RX_QUEUE_SZ)); -+ batch = LWIP_MIN(remain, RING_SIZE(VDEV_RX_QUEUE_SZ)); - -- ret = dpdk_alloc_pktmbuf(mempool, free_buf, batch, true); -+ ret = mem_get_mbuf_bulk(stack_id, free_buf, batch, true); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "cannot alloc mbuf for ring, count: %u ret=%d\n", batch, ret); - return -1; - } - - ret = gazelle_ring_sp_enqueue(ring, (void **)free_buf, batch); -- if (ret == 0) { -+ if (ret < batch) { -+ mem_put_mbuf_bulk(&free_buf[ret], batch - ret); - LSTACK_LOG(ERR, LSTACK, "cannot enqueue to ring, count: %u\n", batch); -- for (int i = 0; i < batch; i++) { -- rte_pktmbuf_free(free_buf[i]); -- } - return -1; - } - -@@ -592,7 +481,7 @@ static int32_t dpdk_ethdev_setup(const struct eth_params *eth_params, uint16_t i - int32_t ret; - uint16_t numa_id = 0; - struct cfg_params *cfg = get_global_cfg_params(); -- struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[idx]; -+ struct rte_mempool *rxtx_mbuf_pool = mem_get_mbuf_pool(idx); - - if (!cfg->use_ltran && cfg->num_process == 1) { - numa_id = (cfg->stack_num > 0) ? cfg->numa_id : numa_node_of_cpu(cfg->cpus[idx]); -@@ -651,7 +540,7 @@ int32_t dpdk_ethdev_start(void) - int32_t dpdk_init_lstack_kni(void) - { - struct protocol_stack_group *stack_group = get_protocol_stack_group(); -- stack_group->kni_pktmbuf_pool = create_pktmbuf_mempool("kni_mbuf", KNI_NB_MBUF, 0, 0, rte_socket_id()); -+ stack_group->kni_pktmbuf_pool = rte_pktmbuf_pool_create("kni_mbuf", KNI_NB_MBUF, 0, 0, MBUF_DATA_SIZE, rte_socket_id()); - if (stack_group->kni_pktmbuf_pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "kni_mbuf is NULL\n"); - return -1; -@@ -1030,7 +919,7 @@ uint32_t dpdk_total_socket_memory(void) - struct cfg_params *cfg = get_global_cfg_params(); - - /* calculate the memory(bytes) of rxtx_mempool */ -- elt_size = sizeof(struct rte_mbuf) + MBUF_SZ + RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); -+ elt_size = sizeof(struct rte_mbuf) + MBUF_DATA_SIZE + RTE_ALIGN(sizeof(struct mbuf_private), RTE_CACHE_LINE_SIZE); - per_pktmbuf_mempool_size = rte_mempool_calc_obj_size(elt_size, 0, NULL); - - /* calculate the memory(bytes) of rpc_mempool, reserved num is (app threads + lstack threads + listen thread) */ -@@ -1038,13 +927,12 @@ uint32_t dpdk_total_socket_memory(void) - per_rpc_mempool_size = rte_mempool_calc_obj_size(elt_size, 0, NULL); - - /* calculate the memory(bytes) of rings, reserved num is GAZELLE_LSTACK_MAX_CONN. */ -- per_conn_ring_size = rte_ring_get_memsize(cfg->send_ring_size) + -- rte_ring_get_memsize(cfg->recv_ring_size) + -- rte_ring_get_memsize(DEFAULT_ACCEPTMBOX_SIZE); -+ per_conn_ring_size = rte_ring_get_memsize(DEFAULT_SENDMBOX_SIZE) + -+ rte_ring_get_memsize(DEFAULT_ACCEPTMBOX_SIZE); - - total_socket_memory = fixed_mem + bytes_to_mb( - (per_pktmbuf_mempool_size * dpdk_pktmbuf_mempool_num()) * cfg->num_queue + -- per_rpc_mempool_size * cfg->rpc_msg_max * (RPC_MEMPOOL_THREAD_NUM + cfg->num_queue + 1) + -+ per_rpc_mempool_size * cfg->rpc_msg_max + - per_conn_ring_size * GAZELLE_LSTACK_MAX_CONN); - - return total_socket_memory; -diff --git a/src/lstack/core/lstack_lwip.c b/src/lstack/core/lstack_lwip.c -deleted file mode 100644 -index 047dfdf..0000000 ---- a/src/lstack/core/lstack_lwip.c -+++ /dev/null -@@ -1,1286 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#include --#include --#include -- --#include --#include -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "common/gazelle_base_func.h" --#include "lstack_log.h" --#include "lstack_cfg.h" --#include "lstack_protocol_stack.h" --#include "lstack_stack_stat.h" --#include "lstack_epoll.h" --#include "lstack_dpdk.h" --#include "lstack_lwip.h" -- --static const uint8_t fin_packet = 0; -- --static void free_ring_pbuf(struct rte_ring *ring) --{ -- void *pbufs[SOCK_RECV_RING_SIZE]; -- -- do { -- gazelle_ring_read(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE)); -- gazelle_ring_read_over(ring); -- } while (gazelle_ring_readable_count(ring)); -- -- do { -- uint32_t num = gazelle_ring_sc_dequeue(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE)); -- -- for (uint32_t i = 0; i < num; i++) { -- pbuf_free(pbufs[i]); -- } -- } while (gazelle_ring_readover_count(ring)); --} -- --static void reset_sock_data(struct lwip_sock *sock) --{ -- /* check null pointer in ring_free func */ -- if (sock->recv_ring) { -- free_ring_pbuf(sock->recv_ring); -- gazelle_ring_free_fast(sock->recv_ring); -- sock->recv_ring = NULL; -- } -- -- if (sock->send_ring) { -- free_ring_pbuf(sock->send_ring); -- gazelle_ring_free_fast(sock->send_ring); -- sock->send_ring = NULL; -- } -- -- if (sock->send_pre_del) { -- pbuf_free(sock->send_pre_del); -- sock->send_pre_del = NULL; -- } -- -- sock->type = 0; -- sock->stack_id = 0; -- sock->affinity_numa = 0; -- sock->sk_wait = NULL; -- sock->listen_next = NULL; -- sock->call_num = 0; -- sock->remain_len = 0; -- -- if (sock->recv_lastdata && sock->recv_lastdata != (void *)&fin_packet) { -- pbuf_free(sock->recv_lastdata); -- } -- sock->recv_lastdata = NULL; --} -- --static struct pbuf *init_mbuf_to_pbuf(struct rte_mbuf *mbuf, pbuf_layer layer, uint16_t length, pbuf_type type) --{ -- struct pbuf_custom *pbuf_custom = mbuf_to_pbuf(mbuf); -- -- void *data = rte_pktmbuf_mtod(mbuf, void *); -- struct pbuf *pbuf = pbuf_alloced_custom(layer, length, type, pbuf_custom, data, MAX_PACKET_SZ); -- if (pbuf) { -- pbuf->allow_append = 1; -- pbuf->addr = *IP_ANY_TYPE; -- pbuf->port = 0; -- pthread_spin_init(&pbuf->pbuf_lock, PTHREAD_PROCESS_SHARED); -- } -- -- return pbuf; --} -- --static uint32_t update_replenish_mbuf_cnt(struct protocol_stack *stack, struct lwip_sock *sock) --{ -- const uint32_t min_alloc_mbuf_num = 4; -- struct rte_ring *ring = sock->send_ring; -- -- uint32_t replenish_cnt = gazelle_ring_free_count(ring); -- if (replenish_cnt <= min_alloc_mbuf_num) { -- return replenish_cnt; -- } -- -- uint32_t resu = replenish_cnt; -- uint32_t tcp_conn_count = get_global_cfg_params()->tcp_conn_count; -- uint16_t send_ring_size = get_global_cfg_params()->send_ring_size; -- uint16_t proportion = stack->conn_num / tcp_conn_count; -- uint32_t replenish_mbuf_cnt_cal = (send_ring_size >> proportion); -- -- if (replenish_mbuf_cnt_cal <= min_alloc_mbuf_num) { -- resu = min_alloc_mbuf_num; -- } else if (replenish_mbuf_cnt_cal < replenish_cnt) { -- resu = replenish_mbuf_cnt_cal; -- } else { -- resu = replenish_cnt + 1; -- } -- -- return resu - 1; --} -- --/* true: need replenish again */ --static bool replenish_send_idlembuf(struct protocol_stack *stack, struct lwip_sock *sock) --{ -- void *pbuf[SOCK_SEND_RING_SIZE_MAX]; -- struct rte_ring *ring = sock->send_ring; -- -- uint32_t replenish_cnt = update_replenish_mbuf_cnt(stack, sock); -- if (replenish_cnt == 0) { -- return false; -- } -- if (dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)pbuf, replenish_cnt, true) != 0) { -- stack->stats.tx_allocmbuf_fail++; -- return true; -- } -- -- uint32_t i = 0; -- for (; i < replenish_cnt - 1; i++) { -- rte_prefetch0(mbuf_to_pbuf((void *)pbuf[i + 1])); -- pbuf[i] = init_mbuf_to_pbuf(pbuf[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- } -- pbuf[i] = init_mbuf_to_pbuf((struct rte_mbuf *)pbuf[i], PBUF_TRANSPORT, MBUF_MAX_DATA_LEN, PBUF_RAM); -- -- uint32_t num = gazelle_ring_sp_enqueue(ring, pbuf, replenish_cnt); -- for (uint32_t i = num; i < replenish_cnt; i++) { -- pbuf_free(pbuf[i]); -- } -- -- sem_post(&sock->snd_ring_sem); -- -- return false; --} -- --int do_lwip_init_sock(int32_t fd) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- return -1; -- } -- -- sock->stack_id = stack->stack_idx; -- sock->sk_wait = NULL; -- if (sock_event_init(&sock->sk_event) != 0) { -- LSTACK_LOG(ERR, LSTACK, "sock_event_init failed\n"); -- return -1; -- } -- -- if (get_global_cfg_params()->stack_mode_rtc) { -- return 0; -- } -- -- if (sock->recv_ring != NULL || sock->send_ring != NULL) { -- LSTACK_LOG(ERR, LSTACK, "socket(%d) not close but open again?\n", fd); -- } -- -- reset_sock_data(sock); -- -- sock->recv_ring = gazelle_ring_create_fast("sock_recv", SOCK_RECV_RING_SIZE, RING_F_SP_ENQ | RING_F_SC_DEQ); -- if (sock->recv_ring == NULL) { -- LSTACK_LOG(ERR, LSTACK, "sock_recv create failed. errno: %d.\n", rte_errno); -- return -1; -- } -- -- sock->send_ring = gazelle_ring_create_fast("sock_send", -- get_global_cfg_params()->send_ring_size, -- RING_F_SP_ENQ | RING_F_SC_DEQ); -- if (sock->send_ring == NULL) { -- gazelle_ring_free_fast(sock->recv_ring); -- LSTACK_LOG(ERR, LSTACK, "sock_send create failed. errno: %d.\n", rte_errno); -- return -1; -- } -- (void)replenish_send_idlembuf(stack, sock); -- -- list_init_node(&sock->recv_list); -- return 0; --} -- --void do_lwip_clean_sock(int fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- return; -- } -- -- sock_event_free(&sock->sk_event, sock->sk_wait); -- sock->sk_wait = NULL; -- -- reset_sock_data(sock); -- -- list_del_node(&sock->recv_list); -- -- get_protocol_stack_by_id(sock->stack_id)->conn_num--; --} -- --void do_lwip_free_pbuf(struct pbuf *pbuf) --{ -- if (pbuf == NULL) { -- return; -- } -- -- struct rte_mbuf *mbuf = pbuf_to_mbuf(pbuf); -- -- rte_pktmbuf_free_seg(mbuf); --} -- --struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type) --{ -- int ret; -- struct rte_mbuf *mbuf; -- struct protocol_stack *stack = get_protocol_stack(); -- -- /* ensure arp packet can be sent */ -- if (layer == PBUF_LINK && length == SIZEOF_ETHARP_HDR) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1, false); -- } else { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf, 1, true); -- } -- if (ret != 0) { -- stack->stats.tx_allocmbuf_fail++; -- return NULL; -- } -- -- return init_mbuf_to_pbuf(mbuf, layer, length, type); --} -- --static inline bool pbuf_allow_append(struct pbuf *pbuf, uint16_t remain_size) --{ -- int ret; -- -- /* Using pthread_spin_trylock to avoid deadlock between app thread and lstack threads */ -- ret = pthread_spin_trylock(&pbuf->pbuf_lock); -- if (ret != 0) { -- return false; -- } -- -- if (pbuf->tot_len > remain_size) { -- pthread_spin_unlock(&pbuf->pbuf_lock); -- return false; -- } -- if (pbuf->allow_append == 1) { -- __sync_fetch_and_sub(&pbuf->allow_append, 1); -- } -- -- pthread_spin_unlock(&pbuf->pbuf_lock); -- return true; --} -- --struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size) --{ -- int count; -- /* when remain_size is 0, fill_sendring write one pbuf to sendring */ -- if (remain_size == 0) { -- count = 1; -- } else { -- count = (remain_size + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN; -- } -- -- struct pbuf *pbufs[count]; -- -- int actual_count = gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbufs, count); -- /* it's impossible to enter this branch theoretically */ -- if (unlikely((actual_count != count) || -- ((actual_count != 0) && pbufs[0]->tot_len != remain_size))) { -- LSTACK_LOG(ERR, LSTACK, "udp get pbuf from sendring error, expected: %d, actual: %d\n", -- count, actual_count); -- LSTACK_LOG(ERR, LSTACK, "udp get pbuf size error, expected: %d, actual: %d\n", -- remain_size, actual_count == 0 ? 0 : pbufs[0]->tot_len); -- } -- -- for (int i = 0; get_protocol_stack_group()->latency_start && i < actual_count; i++) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_LWIP, 0); -- } -- -- return pbufs[0]; --} -- --struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size) --{ -- struct pbuf *pbuf = NULL; -- -- if (unlikely(sock->send_pre_del)) { -- if (pbuf_allow_append(sock->send_pre_del, remain_size)) { -- return sock->send_pre_del; -- } else { -- return NULL; -- } -- } -- -- gazelle_ring_sc_dequeue(sock->send_ring, (void **)&pbuf, 1); -- if (pbuf == NULL) { -- return NULL; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LWIP, 0); -- } -- -- sock->send_pre_del = pbuf; -- -- if (!gazelle_ring_readover_count(sock->send_ring)) { -- if (!pbuf_allow_append(pbuf, remain_size)) { -- return NULL; -- } -- } else { -- if (pbuf->tot_len > remain_size) { -- return NULL; -- } -- } -- -- return pbuf; --} -- --void do_lwip_get_from_sendring_over(struct lwip_sock *sock) --{ -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- stack->stats.write_lwip_cnt++; -- sock->send_pre_del = NULL; --} -- --static ssize_t do_app_write(struct lwip_sock *sock, struct pbuf *pbufs[], void *buf, size_t len, uint32_t write_num) --{ -- ssize_t send_len = 0; -- uint32_t i = 0; -- -- for (i = 0; i < write_num - 1; i++) { -- rte_prefetch0(pbufs[i + 1]); -- rte_prefetch0(pbufs[i + 1]->payload); -- rte_prefetch0((char *)buf + send_len + MBUF_MAX_DATA_LEN); -- rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, MBUF_MAX_DATA_LEN); -- pbufs[i]->tot_len = pbufs[i]->len = MBUF_MAX_DATA_LEN; -- send_len += MBUF_MAX_DATA_LEN; -- -- /* if udp pkg len > mtu, use pbuf chain to send it */ -- if (NETCONN_IS_UDP(sock) && i > 0) { -- pbuf_cat(pbufs[0], pbufs[i]); -- } -- } -- -- /* reduce the branch in loop */ -- size_t copy_len = len - send_len; -- rte_memcpy((char *)pbufs[i]->payload, (char *)buf + send_len, copy_len); -- pbufs[i]->tot_len = pbufs[i]->len = copy_len; -- send_len += copy_len; -- -- if (NETCONN_IS_UDP(sock) && i > 0) { -- pbuf_cat(pbufs[0], pbufs[i]); -- } -- -- return send_len; --} -- --static inline ssize_t app_buff_write(struct lwip_sock *sock, void *buf, size_t len, uint32_t write_num, -- const struct sockaddr *addr, socklen_t addrlen) --{ -- struct pbuf *pbufs[SOCK_SEND_RING_SIZE_MAX]; -- -- (void)gazelle_ring_read(sock->send_ring, (void **)pbufs, write_num); -- -- if (get_protocol_stack_group()->latency_start) { -- uint64_t time_stamp = sys_now_us(); -- time_stamp_into_pbuf(write_num, pbufs, time_stamp); -- } -- -- ssize_t send_len = do_app_write(sock, pbufs, buf, len, write_num); -- -- if (addr) { -- if (addr->sa_family == AF_INET) { -- struct sockaddr_in *saddr = (struct sockaddr_in *)addr; -- for (int i = 0; i < write_num; i++) { -- pbufs[i]->addr.u_addr.ip4.addr = saddr->sin_addr.s_addr; -- pbufs[i]->port = lwip_ntohs((saddr)->sin_port); -- IP_SET_TYPE(&pbufs[i]->addr, IPADDR_TYPE_V4); -- } -- } else if (addr->sa_family == AF_INET6) { -- struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; -- for (int i = 0; i < write_num; i++) { -- memcpy_s(pbufs[i]->addr.u_addr.ip6.addr, IPV6_ADDR_LEN, saddr->sin6_addr.s6_addr, IPV6_ADDR_LEN); -- pbufs[i]->port = lwip_ntohs((saddr)->sin6_port); -- IP_SET_TYPE(&pbufs[i]->addr, IPADDR_TYPE_V6); -- } -- } else { -- return 0; -- } -- } -- -- for (int i = 0; get_protocol_stack_group()->latency_start && i < write_num; i++) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- if (pbufs[i] != NULL) { -- calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_WRITE_INTO_RING, 0); -- } -- } -- -- gazelle_ring_read_over(sock->send_ring); -- -- sock->remain_len = MBUF_MAX_DATA_LEN - pbufs[write_num - 1]->len; -- return send_len; --} -- --static inline struct pbuf *gazelle_ring_readlast(struct rte_ring *r) --{ -- struct pbuf *last_pbuf = NULL; -- volatile uint32_t tail = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE); -- uint32_t last = r->prod.tail - 1; -- if (last + 1 == tail || last + 1 - tail > r->capacity) { -- return NULL; -- } -- -- __rte_ring_dequeue_elems(r, last, (void **)&last_pbuf, sizeof(void *), 1); -- -- if (pthread_spin_trylock(&last_pbuf->pbuf_lock) != 0) { -- return NULL; -- } -- if (last_pbuf->allow_append != 1) { -- pthread_spin_unlock(&last_pbuf->pbuf_lock); -- return NULL; -- } -- -- return last_pbuf; --} -- --static inline void gazelle_ring_lastover(struct pbuf *last_pbuf) --{ -- pthread_spin_unlock(&last_pbuf->pbuf_lock); --} -- --static inline size_t merge_data_lastpbuf(struct lwip_sock *sock, void *buf, size_t len) --{ -- struct pbuf *last_pbuf = gazelle_ring_readlast(sock->send_ring); -- if (last_pbuf == NULL) { -- sock->remain_len = 0; -- return 0; -- } -- -- size_t send_len = MBUF_MAX_DATA_LEN - last_pbuf->len; -- if (send_len >= len) { -- sock->remain_len = send_len - len; -- send_len = len; -- } else { -- sock->remain_len = 0; -- } -- -- uint16_t offset = last_pbuf->len; -- last_pbuf->tot_len = last_pbuf->len = offset + send_len; -- rte_memcpy((char *)last_pbuf->payload + offset, buf, send_len); -- -- gazelle_ring_lastover(last_pbuf); -- -- return send_len; --} -- --int sem_timedwait_nsecs(sem_t *sem) --{ -- struct timespec ts; -- clock_gettime(CLOCK_REALTIME, &ts); -- long long wait_nsec = ts.tv_nsec + SEND_TIME_WAIT_NS; -- ts.tv_nsec = wait_nsec % SECOND_NSECOND; -- long add = wait_nsec / SECOND_NSECOND; -- ts.tv_sec += add; -- return sem_timedwait(sem, &ts); --} -- --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 (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); -- -- 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) { -- LSTACK_LOG(WARNING, LSTACK, "sock send_ring is already exhausted.\n"); -- sem_timedwait_nsecs(&sock->snd_ring_sem); -- GAZELLE_RETURN(ENOMEM); -- } -- -- send_len = app_buff_write(sock, (char *)buf, len, write_num, addr, addrlen); -- -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- -- 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 (sock->remain_len) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- stack->stats.sock_tx_merge++; -- send_len = merge_data_lastpbuf(sock, (char *)buf, len); -- if (send_len >= len) { -- send_len = len; -- goto END; -- } -- } -- -- uint32_t write_num = (len - send_len + MBUF_MAX_DATA_LEN - 1) / MBUF_MAX_DATA_LEN; -- uint32_t write_avail = gazelle_ring_readable_count(sock->send_ring); -- -- while (!netconn_is_nonblocking(sock->conn) && (write_avail < write_num)) { -- if (sock->errevent > 0) { -- GAZELLE_RETURN(ENOTCONN); -- } -- /* wait until (send_ring_size / 4) */ -- if (write_avail > (rte_ring_get_capacity(sock->send_ring) >> 2)) { -- break; -- } -- write_avail = gazelle_ring_readable_count(sock->send_ring); -- } -- -- /* send_ring is full, data attach last pbuf */ -- if (write_avail == 0) { -- sem_timedwait_nsecs(&sock->snd_ring_sem); -- goto END; -- } -- -- /* send_ring have idle */ -- if (write_num > write_avail) { -- write_num = write_avail; -- len = write_num * MBUF_MAX_DATA_LEN; -- } -- send_len += app_buff_write(sock, (char *)buf + send_len, len - send_len, write_num, addr, addrlen); -- -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- --END: -- if (send_len == 0) { -- errno = EAGAIN; -- return -1; -- } -- -- return send_len; --} -- --static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags); --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) --{ -- ssize_t ret, send_len = 0; -- -- while (true) { -- ret = __do_lwip_tcp_fill_sendring(sock, (char *)buf + send_len, len - send_len, addr, addrlen); -- // send = 0 : tcp peer close connection ? -- if (unlikely(ret <= 0)) { -- break; -- } -- send_len += ret; -- if (send_len == len || netconn_is_nonblocking(sock->conn)) { -- break; -- } -- -- notice_stack_tcp_send(sock, sock->conn->callback_arg.socket, ret, 0); -- } -- -- return send_len == 0 ? ret : send_len; --} -- --bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock) --{ -- bool replenish_again = false; -- -- replenish_again = replenish_send_idlembuf(stack, sock); -- -- API_EVENT(sock->conn, NETCONN_EVT_SENDPLUS, 0); -- -- return replenish_again; --} -- --static inline void free_recv_ring_readover(struct rte_ring *ring) --{ -- void *pbufs[SOCK_RECV_RING_SIZE]; -- uint32_t num = gazelle_ring_sc_dequeue(ring, pbufs, RING_SIZE(SOCK_RECV_RING_SIZE)); -- for (uint32_t i = 0; i < num; i++) { -- pbuf_free(pbufs[i]); -- } --} -- --static inline struct pbuf *pbuf_last(struct pbuf *pbuf) --{ -- while (pbuf->next) { -- pbuf = pbuf->next; -- } -- return pbuf; --} -- --ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, u8_t apiflags) --{ -- if (sock->conn->recvmbox == NULL) { -- sock->conn->pending_err = ERR_CONN; -- GAZELLE_RETURN(ENOTCONN); -- } -- -- free_recv_ring_readover(sock->recv_ring); -- -- uint32_t free_count = gazelle_ring_free_count(sock->recv_ring); -- if (free_count == 0) { -- sock->conn->pending_err = ERR_WOULDBLOCK; -- GAZELLE_RETURN(EAGAIN); -- } -- -- uint32_t data_count = rte_ring_count(sock->conn->recvmbox->ring); -- uint32_t read_num = LWIP_MIN(free_count, data_count); -- struct pbuf *pbufs[SOCK_RECV_RING_SIZE]; -- uint32_t read_count = 0; -- ssize_t recv_len = 0; -- -- for (uint32_t i = 0; i < read_num; i++) { -- -- err_t err = ERR_OK; -- if (NETCONN_IS_UDP(sock)) { -- err = netconn_recv_udp_raw_pbuf_flags(sock->conn, &pbufs[i], apiflags); -- } else { -- err = netconn_recv_tcp_pbuf_flags(sock->conn, &pbufs[i], apiflags); -- } -- if (err != ERR_OK) { -- /* fin has been read from recvmbox, put it to recv_ring */ -- if (!NETCONN_IS_UDP(sock) && -- (netconn_is_flag_set(sock->conn, NETCONN_FIN_RX_PENDING) || err == ERR_CLSD)) { -- /* fin has been read, lwip don't need to process fin packet */ -- netconn_clear_flags(sock->conn, NETCONN_FIN_RX_PENDING); -- pbufs[i] = NULL; -- read_count++; -- break; -- } -- -- /* store err to pending_err again, clear it after app read */ -- sock->conn->pending_err = err; -- GAZELLE_RETURN(err_to_errno(err)); -- } -- -- recv_len += pbufs[i]->tot_len; -- lstack_calculate_aggregate(0, pbufs[i]->tot_len); -- read_count++; -- -- /* once we have some data to return, only add more if we don't need to wait */ -- apiflags |= NETCONN_DONTBLOCK | NETCONN_NOFIN; -- } -- -- uint32_t enqueue_num = gazelle_ring_sp_enqueue(sock->recv_ring, (void **)pbufs, read_count); -- if (enqueue_num != read_count) { -- LSTACK_LOG(ERR, LSTACK, "Code shouldn't get here!\n"); -- } -- -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- for (uint32_t i = 0; get_protocol_stack_group()->latency_start && i < read_count; i++) { -- if (pbufs[i] != NULL) { -- calculate_lstack_latency(&stack->latency, pbufs[i], GAZELLE_LATENCY_READ_LWIP, 0); -- } -- } -- stack->stats.read_lwip_cnt += read_count; -- -- return recv_len; --} -- --static int32_t check_msg_vaild(const struct msghdr *message) --{ -- ssize_t buflen = 0; -- -- if (message == NULL || message->msg_iovlen <= 0 || message->msg_iovlen > IOV_MAX) { -- GAZELLE_RETURN(EINVAL); -- } -- -- for (int32_t i = 0; i < message->msg_iovlen; i++) { -- if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len < 0) || -- ((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) || -- ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) < 0)) { -- GAZELLE_RETURN(EINVAL); -- } -- buflen = (ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len); -- } -- -- return 0; --} -- --ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int32_t flags) --{ -- ssize_t buflen = 0; -- -- if (check_msg_vaild(message)) { -- GAZELLE_RETURN(EINVAL); -- } -- -- for (int32_t i = 0; i < message->msg_iovlen; i++) { -- if (message->msg_iov[i].iov_len == 0) { -- continue; -- } -- -- ssize_t recvd_local = do_lwip_read_from_stack(s, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, -- flags, NULL, NULL); -- if (recvd_local > 0) { -- buflen += recvd_local; -- } -- if (recvd_local < 0 || (recvd_local < (int)message->msg_iov[i].iov_len) || (flags & MSG_PEEK)) { -- if (buflen <= 0) { -- buflen = recvd_local; -- } -- break; -- } -- flags |= MSG_DONTWAIT; -- } -- -- return buflen; --} -- --static inline void notice_stack_tcp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) --{ -- // 2: call_num >= 2, don't need add new rpc send -- if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) < 2) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- while (rpc_call_tcp_send(&stack->rpc_queue, fd, len, flags) < 0) { -- usleep(1000); // 1000: wait 1ms to exec again -- } -- __sync_fetch_and_add(&sock->call_num, 1); -- } --} -- --static inline void notice_stack_udp_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) --{ -- __sync_fetch_and_add(&sock->call_num, 1); -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- while (rpc_call_udp_send(&stack->rpc_queue, fd, len, flags) < 0) { -- usleep(1000); // 1000: wait 1ms to exec again -- } --} -- --static inline void notice_stack_send(struct lwip_sock *sock, int32_t fd, int32_t len, int32_t flags) --{ -- if (NETCONN_IS_UDP(sock)) { -- notice_stack_udp_send(sock, fd, len, flags); -- } else { -- notice_stack_tcp_send(sock, fd, len, flags); -- } --} -- --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) --{ -- struct lwip_sock *sock; -- ssize_t send = 0; -- -- if (buf == NULL) { -- GAZELLE_RETURN(EINVAL); -- } -- if (addr && addr->sa_family != AF_INET && addr->sa_family != AF_INET6) { -- GAZELLE_RETURN(EINVAL); -- } -- -- sock = lwip_get_socket(fd); -- if (unlikely(sock->affinity_numa == 0)) { -- thread_bind_stack(sock->stack_id); -- sock->affinity_numa = 1; -- } -- --#if GAZELLE_SAME_NODE -- if (sock->same_node_tx_ring != NULL) { -- return gazelle_same_node_ring_send(sock, buf, len, flags); -- } --#endif /* GAZELLE_SAME_NODE */ -- if (sock->errevent > 0) { -- 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); -- return send; --} -- --ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, const struct msghdr *message, int32_t flags) --{ -- int32_t ret; -- int32_t i; -- ssize_t buflen = 0; -- -- if (check_msg_vaild(message)) { -- GAZELLE_RETURN(EINVAL); -- } -- -- for (i = 0; i < message->msg_iovlen; i++) { -- if (message->msg_iov[i].iov_len == 0) { -- continue; -- } -- -- 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; -- } -- -- buflen += ret; -- -- if (ret < message->msg_iov[i].iov_len) { -- break; -- } -- } -- -- if (buflen > 0) { -- notice_stack_send(sock, s, buflen, flags); -- } -- return buflen; --} -- --static struct pbuf *pbuf_free_partial(struct pbuf *pbuf, uint16_t free_len) --{ -- uint32_t tot_len = pbuf->tot_len - free_len; -- -- while (free_len && pbuf) { -- if (free_len >= pbuf->len) { -- free_len = free_len - pbuf->len; -- pbuf = pbuf->next; -- } else { -- pbuf_remove_header(pbuf, free_len); -- break; -- } -- } -- -- if (pbuf) { -- pbuf->tot_len = tot_len; -- } -- return pbuf; --} -- --static bool recv_break_for_err(struct lwip_sock *sock) --{ -- errno = err_to_errno(netconn_err(sock->conn)); -- unsigned pending = sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0) | -- sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0); -- return pending; --} -- --/* -- * 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) --{ -- int32_t expect; -- uint64_t time_stamp = sys_now_us(); -- -- if (sock->recv_lastdata != NULL) { -- *pbuf = sock->recv_lastdata; -- sock->recv_lastdata = NULL; -- return 0; -- } -- -- expect = gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1); -- if (expect == 0) { -- if (netconn_is_nonblocking(sock->conn)) { -- GAZELLE_RETURN(EAGAIN); -- } -- sock_event_wait(sock, true); -- expect = gazelle_ring_read(sock->recv_ring, (void **)pbuf, 1); -- if (expect == 0) { -- if (recv_break_for_err(sock)) { -- return -1; -- } -- GAZELLE_RETURN(EAGAIN); -- } -- } -- -- if (get_protocol_stack_group()->latency_start) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_lstack_latency(&stack->latency, *pbuf, GAZELLE_LATENCY_READ_APP_CALL, time_stamp); -- } -- -- 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; -- } -- -- 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 | recvd, &pbuf) != 0) { -- /* When the buffer is empty, it will be returned directly -- if in non-blocking mode or if data has already been received */ -- break; -- } -- -- 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; /* it's impossible to get here */ -- } -- pbuf_copy_partial(pbuf, (char *)buf + recvd, copy_len, 0); -- -- recvd += copy_len; -- recv_left -= copy_len; -- -- if (pbuf->tot_len > copy_len) { -- sock->recv_lastdata = pbuf_free_partial(pbuf, copy_len); -- } else { -- if (get_protocol_stack_group()->latency_start) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); -- } -- -- gazelle_ring_read_over(sock->recv_ring); -- } -- } -- -- 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); -- } -- -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- if (copy_len < pbuf->tot_len) { -- stack->stats.sock_rx_drop++; -- } -- if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_READ_LSTACK, 0); -- } -- -- 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 = lwip_get_socket(fd); -- bool noblock = (flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn); -- -- if (recv_break_for_err(sock)) { -- return -1; -- } -- -- if (unlikely(sock->affinity_numa == 0)) { -- thread_bind_stack(sock->stack_id); -- sock->affinity_numa = 1; -- } -- --#if GAZELLE_SAME_NODE -- if (sock->same_node_rx_ring != NULL) { -- recvd = gazelle_same_node_ring_recv(sock, buf, len, flags); -- } else --#endif /* GAZELLE_SAME_NODE */ -- if (NETCONN_IS_UDP(sock)) { -- recvd = recv_ring_udp_read(sock, buf, len, noblock, addr, addrlen); -- } else { -- recvd = recv_ring_tcp_read(sock, buf, len, noblock); -- } -- -- API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, recvd); -- -- if (recvd < 0) { -- return -1; -- } -- return recvd; --} -- --void do_lwip_add_recvlist(int32_t fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- if (sock && list_node_null(&sock->recv_list)) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- list_add_node(&sock->recv_list, &stack->recv_list); -- } --} -- --void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num) --{ -- struct list_node *list = &(stack->recv_list); -- struct list_node *node, *temp; -- struct lwip_sock *sock; -- uint32_t read_num = 0; -- -- list_for_each_node(node, temp, list) { -- sock = list_entry(node, struct lwip_sock, recv_list); -- -- if (++read_num > max_num) { -- /* list head move to next send */ -- list_del_node(&stack->recv_list); -- list_add_node(&stack->recv_list, &sock->recv_list); -- break; -- } -- -- if (sock->conn == NULL || sock->conn->recvmbox == NULL || rte_ring_count(sock->conn->recvmbox->ring) == 0) { -- list_del_node(&sock->recv_list); -- continue; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_RECVMBOX_READY); -- } -- -- ssize_t len = 0; -- if (NETCONN_IS_UDP(sock)) { -- len = lwip_recv(sock->conn->callback_arg.socket, NULL, SSIZE_MAX, 0); -- } else { -- len = lwip_recv(sock->conn->callback_arg.socket, NULL, 0, 0); -- } -- if (len < 0 && errno != EAGAIN) { -- API_EVENT(sock->conn, NETCONN_EVT_ERROR, 0); -- /* = 0: fin */ -- } else if (len >= 0) { -- API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); -- } -- } --} -- --void do_lwip_connected_callback(int fd) --{ -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- return; -- } -- -- if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -- /* delete kernel event */ -- if (sock->sk_wait != NULL) { -- posix_api->epoll_ctl_fn(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL); -- } -- /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -- posix_api->shutdown_fn(fd, SHUT_RDWR); -- } -- -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- -- API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); --} -- --static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const struct tcp_pcb *pcb) --{ -- struct netconn *netconn = (struct netconn *)pcb->callback_arg; -- -- conn->lip = *((gz_addr_t *)&pcb->local_ip); -- conn->rip = *((gz_addr_t *)&pcb->remote_ip); -- conn->l_port = pcb->local_port; -- conn->r_port = pcb->remote_port; -- conn->in_send = pcb->snd_queuelen; -- conn->tcp_sub_state = pcb->state; -- conn->cwn = pcb->cwnd; -- conn->rcv_wnd = pcb->rcv_wnd; -- conn->snd_wnd = pcb->snd_wnd; -- conn->snd_buf = pcb->snd_buf; -- conn->lastack = pcb->lastack; -- conn->snd_nxt = pcb->snd_nxt; -- conn->rcv_nxt = pcb->rcv_nxt; -- conn->keepalive = (ip_get_option(pcb, SOF_KEEPALIVE) != 0); -- conn->keep_idle = pcb->keep_idle; -- conn->keep_intvl = pcb->keep_intvl; -- conn->keep_cnt = pcb->keep_cnt; -- conn->pingpong = tcp_in_pingpong(pcb); -- -- if (netconn != NULL) { -- conn->fd = netconn->callback_arg.socket; -- conn->recv_cnt = (netconn->recvmbox == NULL) ? 0 : rte_ring_count(netconn->recvmbox->ring); -- struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -- if (!POSIX_IS_CLOSED(sock)) { -- conn->recv_ring_cnt = (sock->recv_ring == NULL) ? 0 : gazelle_ring_readable_count(sock->recv_ring); -- conn->recv_ring_cnt += (sock->recv_lastdata) ? 1 : 0; -- conn->send_ring_cnt = (sock->send_ring == NULL) ? 0 : gazelle_ring_readover_count(sock->send_ring); -- conn->events = sock->sk_event.pending; -- conn->epoll_events = sock->sk_event.events; -- conn->eventlist = !list_node_null(&sock->sk_event.event_node); -- } -- } --} -- --void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock) --{ -- dst_sock->conn->pcb.ip->so_options = src_sock->conn->pcb.ip->so_options; -- dst_sock->conn->pcb.ip->ttl = src_sock->conn->pcb.ip->ttl; -- dst_sock->conn->pcb.ip->tos = src_sock->conn->pcb.ip->tos; -- dst_sock->conn->flags = src_sock->conn->flags; -- if (NETCONN_IS_UDP(src_sock)) { -- dst_sock->conn->pcb.udp->flags = src_sock->conn->pcb.udp->flags; -- dst_sock->conn->pcb.udp->mcast_ifindex = src_sock->conn->pcb.udp->mcast_ifindex; -- dst_sock->conn->pcb.udp->mcast_ttl = src_sock->conn->pcb.udp->mcast_ttl; -- } else { -- dst_sock->conn->pcb.tcp->netif_idx = src_sock->conn->pcb.tcp->netif_idx; -- dst_sock->conn->pcb.tcp->flags = src_sock->conn->pcb.tcp->flags; -- dst_sock->conn->pcb.tcp->keep_idle = src_sock->conn->pcb.tcp->keep_idle; -- dst_sock->conn->pcb.tcp->keep_intvl = src_sock->conn->pcb.tcp->keep_intvl; -- dst_sock->conn->pcb.tcp->keep_cnt = src_sock->conn->pcb.tcp->keep_cnt; -- } --} -- --uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, -- uint32_t max_num) --{ -- struct tcp_pcb *pcb = NULL; -- uint32_t conn_num = 0; -- -- if (conn == NULL) { -- return -1; -- } -- -- for (pcb = tcp_active_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -- conn[conn_num].state = GAZELLE_ACTIVE_LIST; -- copy_pcb_to_conn(conn + conn_num, pcb); -- conn_num++; -- } -- -- for (pcb = tcp_tw_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -- conn[conn_num].state = GAZELLE_TIME_WAIT_LIST; -- copy_pcb_to_conn(conn + conn_num, pcb); -- conn_num++; -- } -- -- for (struct tcp_pcb_listen *pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL && conn_num < max_num; -- pcbl = pcbl->next) { -- conn[conn_num].state = GAZELLE_LISTEN_LIST; -- conn[conn_num].lip = *((gz_addr_t *)&pcbl->local_ip); -- conn[conn_num].l_port = pcbl->local_port; -- conn[conn_num].tcp_sub_state = pcbl->state; -- struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -- conn[conn_num].fd = netconn != NULL ? netconn->callback_arg.socket : -1; -- if (netconn != NULL && netconn->acceptmbox != NULL) { -- conn[conn_num].recv_cnt = rte_ring_count(netconn->acceptmbox->ring); -- } -- conn_num++; -- } -- -- return conn_num; --} -- --uint32_t do_lwip_get_connnum(void) --{ -- struct tcp_pcb *pcb = NULL; -- struct tcp_pcb_listen *pcbl = NULL; -- uint32_t conn_num = 0; -- -- for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { -- conn_num++; -- } -- -- for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { -- conn_num++; -- } -- -- for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { -- conn_num++; -- } -- -- return conn_num; --} -- -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 8f01f31..983f2f0 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -332,13 +332,14 @@ static const struct mempool_ops mbuf_mp_ops = { - }; - - --static struct rte_mempool *mbuf_pool_create(int stack_id) -+static struct rte_mempool *mbuf_pool_create(int stack_id, uint16_t numa_id) - { - struct cfg_params *cfg_params = get_global_cfg_params(); - char name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; - uint32_t total_conn_mbufs, total_nic_mbufs, total_mbufs; - uint16_t private_size; -+ uint16_t xdp_metadata = 0; - - total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; - total_nic_mbufs = cfg_params->rxqueue_size + cfg_params->txqueue_size; -@@ -351,9 +352,13 @@ static struct rte_mempool *mbuf_pool_create(int stack_id) - } - - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%hu", "mbuf_pool", stack_id); -- private_size = RTE_ALIGN(sizeof(struct mbuf_private) + 24, RTE_CACHE_LINE_SIZE); -+ /* reserved for xdp metadata, see struct xsk_tx_metadata in /usr/include/linux/if_xdp.h */ -+ if (xdp_eth_enabled()) { -+ xdp_metadata = 24; -+ } -+ private_size = RTE_ALIGN(sizeof(struct mbuf_private) + xdp_metadata, RTE_CACHE_LINE_SIZE); - -- pool = mbuf_mp_ops.create(name, total_mbufs, MBUFPOOL_CACHE_NUM, private_size, MBUF_DATA_SIZE, rte_socket_id()); -+ pool = mbuf_mp_ops.create(name, total_mbufs, MBUFPOOL_CACHE_NUM, private_size, MBUF_DATA_SIZE, numa_id); - if (pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_pool_create %s failed, rte_errno %d\n", name, rte_errno); - return NULL; -@@ -362,7 +367,7 @@ static struct rte_mempool *mbuf_pool_create(int stack_id) - return pool; - } - --static struct rte_mempool *rpc_pool_create(int stack_id) -+static struct rte_mempool *rpc_pool_create(int stack_id, uint16_t numa_id) - { - char name [RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; -@@ -370,7 +375,7 @@ static struct rte_mempool *rpc_pool_create(int stack_id) - - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%hu", "rpc_pool", stack_id); - -- pool = mem_mp_ops.create(name, total_bufs, MEMPOOL_CACHE_NUM, 0, sizeof(struct rpc_msg), rte_socket_id()); -+ pool = mem_mp_ops.create(name, total_bufs, MEMPOOL_CACHE_NUM, 0, sizeof(struct rpc_msg), numa_id); - if (pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "rte_mempool_create %s failed, rte_errno %d\n", name, rte_errno); - } -@@ -392,16 +397,16 @@ void mem_stack_pool_free(int stack_id) - } - } - --int mem_stack_pool_init(int stack_id) -+int mem_stack_pool_init(int stack_id, unsigned numa_id) - { - struct mem_stack *ms = mem_stack_get(stack_id); - -- ms->mbuf_pool = mbuf_pool_create(stack_id); -+ ms->mbuf_pool = mbuf_pool_create(stack_id, numa_id); - if (ms->mbuf_pool == NULL) { - return -1; - } - -- ms->rpc_pool = rpc_pool_create(stack_id); -+ ms->rpc_pool = rpc_pool_create(stack_id, numa_id); - if (ms->rpc_pool == NULL) { - mem_stack_pool_free(stack_id); - return -1; -@@ -469,7 +474,7 @@ void mem_thread_cache_free(struct mem_thread *mt) - - int mem_thread_cache_init(struct mem_thread *mt) - { -- if (!get_global_cfg_params()->stack_mode_rtc && !dpdk_nic_is_xdp()) { -+ if (!get_global_cfg_params()->stack_mode_rtc && !xdp_eth_enabled()) { - char name [RTE_MEMPOOL_NAMESIZE]; - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%p", "migrate_ring", mt); - -diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c -index bdb61e9..2de25f9 100644 ---- a/src/lstack/core/lstack_preload.c -+++ b/src/lstack/core/lstack_preload.c -@@ -94,15 +94,10 @@ enum posix_type select_sock_posix_path(struct lwip_sock *sock) - } - - /* CLOSED means not sockfd, such as file fd or unix fd */ -- if (POSIX_IS_CLOSED(sock) || POSIX_IS_TYPE(sock, POSIX_KERNEL)) { -+ if (POSIX_IS_CLOSED(sock)) { - return POSIX_KERNEL; - } -- -- if (likely(POSIX_IS_TYPE(sock, POSIX_LWIP))) { -- return POSIX_LWIP; -- } -- -- return POSIX_ALL; -+ return sock->type; - } - - enum posix_type select_posix_path(void) -@@ -193,6 +188,6 @@ int preload_info_init(void) - } - - g_preload_info.preload_switch = 1; -- -+ LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n"); - return preload_check_bind_proc(); - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index 1e7df33..c07d8e7 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -27,13 +27,13 @@ - #include "lstack_cfg.h" - #include "lstack_dpdk.h" - #include "lstack_ethdev.h" --#include "lstack_lwip.h" - #include "lstack_control_plane.h" - #include "lstack_wait.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" - #include "lstack_interrupt.h" - #include "lstack_protocol_stack.h" -+#include "lstack_mempool.h" - - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - #include -@@ -349,8 +349,8 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - stack->stack_idx = t_params->idx; - stack->lwip_stats = &lwip_stats; - -- list_init_head(&stack->recv_list); -- list_init_head(&stack->same_node_recv_list); -+ rpc_queue_init(&stack->rpc_queue, stack->queue_id); -+ rpc_queue_init(&stack->dfx_rpc_queue, stack->queue_id); - - stack_group->stacks[t_params->idx] = stack; - set_stack_idx(t_params->idx); -@@ -367,11 +367,6 @@ static int32_t init_stack_value(struct protocol_stack *stack, void *arg) - } - } - -- if (pktmbuf_pool_init(stack) != 0) { -- LSTACK_LOG(ERR, LSTACK, "pktmbuf_pool_init failed\n"); -- return -1; -- } -- - if (create_shared_ring(stack) != 0) { - LSTACK_LOG(ERR, LSTACK, "create_shared_ring failed\n"); - return -1; -@@ -426,11 +421,14 @@ static struct protocol_stack *stack_thread_init(void *arg) - if (stack_affinity_cpu(stack->cpu_id) != 0) { - goto END; - } -- RTE_PER_LCORE(_lcore_id) = stack->cpu_id; - } else { - stack_affinity_numa(stack->numa_id); - } - -+ if (mem_stack_mpcache_init(stack->stack_idx, stack->cpu_id) < 0) { -+ goto END; -+ } -+ - lwip_init(); - /* Using errno to return lwip_init() result. */ - if (errno != 0) { -@@ -468,7 +466,6 @@ int stack_polling(unsigned wakeup_tick) - bool use_sockmap = cfg->use_sockmap; - bool stack_mode_rtc = cfg->stack_mode_rtc; - uint32_t rpc_number = cfg->rpc_number; -- uint32_t read_connect_number = cfg->read_connect_number; - struct protocol_stack *stack = get_protocol_stack(); - uint32_t timeout; - -@@ -490,8 +487,6 @@ int stack_polling(unsigned wakeup_tick) - return force_quit; - } - -- do_lwip_read_recvlist(stack, read_connect_number); -- - if ((wakeup_tick & 0xf) == 0) { - #if SOCK_WAIT_BATCH_NOTIFY - stack->stats.wakeup_events += lwip_wait_foreach_notify(stack->stack_idx); -@@ -505,10 +500,6 @@ int stack_polling(unsigned wakeup_tick) - /* run to completion mode currently does not support sockmap */ - if (use_sockmap) { - netif_poll(&stack->netif); -- /* reduce traversal times */ -- if ((wakeup_tick & 0xff) == 0) { -- read_same_node_recv_list(stack); -- } - } - #endif /* GAZELLE_SAME_NODE */ - -@@ -538,7 +529,6 @@ static bool stack_local_event_get(uint16_t stack_id) - struct protocol_stack *stack = g_stack_group.stacks[stack_id]; - if (!lockless_queue_empty(&stack->dfx_rpc_queue.queue) || - !lockless_queue_empty(&stack->rpc_queue.queue) || -- !list_head_empty(&stack->recv_list) || - !lwip_wait_notify_empty(stack_id) || - tx_cache_count(stack->queue_id)) { - return true; -@@ -582,9 +572,8 @@ static void* gazelle_stack_thread(void *arg) - - static int stack_group_init_mempool(void) - { -+ int ret; - struct cfg_params *cfg_params = get_global_cfg_params(); -- uint32_t total_mbufs = dpdk_pktmbuf_mempool_num(); -- struct rte_mempool *rxtx_mbuf = NULL; - uint32_t cpu_id = 0; - unsigned numa_id = 0; - int queue_id = 0; -@@ -607,13 +596,12 @@ static int stack_group_init_mempool(void) - return -1; - } - -- rxtx_mbuf = create_pktmbuf_mempool("rxtx_mbuf", total_mbufs, RXTX_CACHE_SZ, queue_id, numa_id); -- if (rxtx_mbuf == NULL) { -- LSTACK_LOG(ERR, LSTACK, "numid=%d, rxtx_mbuf idx=%d, create_pktmbuf_mempool fail\n", numa_id, queue_id); -+ ret = mem_stack_pool_init(queue_id, numa_id); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "mem_stack_pool_init failed, cpuid=%u, numid=%d, queue_id=%d\n", -+ cpu_id, numa_id, queue_id); - return -1; - } -- -- get_protocol_stack_group()->total_rxtx_pktmbuf_pool[queue_id] = rxtx_mbuf; - } - } - -@@ -633,6 +621,11 @@ int stack_group_init(void) - - stack_group->stack_setup_fail = 0; - -+ if (mem_thread_manager_init() != 0) { -+ LSTACK_LOG(ERR, LSTACK, "mem_thread_manager_init failed\n"); -+ return -1; -+ } -+ - if (get_global_cfg_params()->is_primary) { - if (stack_group_init_mempool() != 0) { - LSTACK_LOG(ERR, LSTACK, "stack group init mempool failed\n"); -@@ -640,7 +633,7 @@ int stack_group_init(void) - } - } - -- return 0; -+ return sock_wait_group_init(); - } - - int stack_setup_app_thread(void) -@@ -749,6 +742,24 @@ void stack_wait(void) - } - } - -+static void stack_exit_by_rpc(struct rpc_msg *msg) -+{ -+ stack_exit(); -+} -+ -+static int rpc_call_stack_exit(int stack_id) -+{ -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, stack_exit_by_rpc); -+ if (msg == NULL) { -+ return -1; -+ } -+ -+ msg->flags |= RPC_MSG_EXIT; -+ rpc_async_call(queue, msg, RPC_MSG_FREE | RPC_MSG_EXIT); -+ return 0; -+} -+ - void stack_group_exit(void) - { - int i; -@@ -762,7 +773,7 @@ void stack_group_exit(void) - } - - if (stack != stack_group->stacks[i]) { -- rpc_call_stack_exit(&stack_group->stacks[i]->rpc_queue); -+ rpc_call_stack_exit(i); - } - } - -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index dc9c931..3b3bd75 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -26,29 +26,15 @@ - #include "common/gazelle_dfx_msg.h" - #include "lstack_thread_rpc.h" - #include "lstack_protocol_stack.h" --#include "lstack_epoll.h" - #include "lstack_dpdk.h" - #include "lstack_stack_stat.h" - #include "lstack_virtio.h" --#include "lstack_dump.h" -+#include "lstack_wait.h" -+#include "lstack_mempool.h" - --void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new) -+void time_stamp_into_write(struct pbuf *pbufs[], uint32_t num) - { -- if (!get_protocol_stack_group()->latency_start) { -- return; -- } -- struct latency_timestamp *lt_old; -- struct latency_timestamp *lt_new; -- -- lt_old = &pbuf_to_private(pbuf_old)->lt; -- lt_new = &pbuf_to_private(pbuf_new)->lt; -- -- lt_new->stamp = lt_old->stamp; -- lt_new->check = lt_old->check; -- lt_new->type = lt_old->type; -- for (int i = 0; i < GAZELLE_LATENCY_MAX; i++) { -- lt_new->stamp_seg[i] = lt_old->stamp_seg[i]; -- } -+ time_stamp_into_pbuf(num, pbufs, sys_now_us()); - } - - void time_stamp_into_rpcmsg(struct lwip_sock *sock) -@@ -56,28 +42,29 @@ void time_stamp_into_rpcmsg(struct lwip_sock *sock) - sock->stamp.rpc_time_stamp = sys_now_us(); - } - --void time_stamp_into_recvmbox(struct lwip_sock *sock) -+static void time_stamp_into_recvmbox(struct lwip_sock *sock) - { - sock->stamp.mbox_time_stamp = sys_now_us(); - } - - void time_stamp_record(int fd, struct pbuf *pbuf) - { -- struct lwip_sock *sock = lwip_get_socket(fd); -- -- if (get_protocol_stack_group()->latency_start && sock && pbuf) { -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_INTO_MBOX, 0); -- time_stamp_into_recvmbox(sock); -+ if (get_protocol_stack_group()->latency_start && pbuf) { -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (sock != NULL) { -+ calculate_sock_latency(sock, GAZELLE_LATENCY_RECVMBOX_READY); -+ calculate_lstack_latency(sock->stack_id, &pbuf, 1, GAZELLE_LATENCY_INTO_MBOX, 0); -+ time_stamp_into_recvmbox(sock); -+ } - } - } - --void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct lwip_sock *sock, -- enum GAZELLE_LATENCY_TYPE type) -+void calculate_sock_latency(struct lwip_sock *sock, enum GAZELLE_LATENCY_TYPE type) - { - uint64_t latency; - uint64_t stamp; - struct stack_latency *latency_stat; -+ struct protocol_stack *stack; - - if (type == GAZELLE_LATENCY_WRITE_RPC_MSG) { - stamp = sock->stamp.rpc_time_stamp; -@@ -87,12 +74,13 @@ void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct - return; - } - -- if (stamp < stack_latency->start_time) { -+ stack = get_protocol_stack(); -+ if (stamp < stack->latency.start_time) { - return; - } - - latency = sys_now_us() - stamp; -- latency_stat = &stack_latency->latency[type]; -+ latency_stat = &stack->latency.latency[type]; - - latency_stat->latency_total += latency; - latency_stat->latency_max = (latency_stat->latency_max > latency) ? latency_stat->latency_max : latency; -@@ -112,47 +100,54 @@ void calculate_latency_stat(struct gazelle_stack_latency *stack_latency, uint64_ - latency_stat->latency_pkts++; - } - --void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, -+void calculate_lstack_latency(int stack_id, struct pbuf *const *pbufs, uint32_t num, - enum GAZELLE_LATENCY_TYPE type, uint64_t time_record) - { - uint64_t latency; - uint16_t lt_type; - struct latency_timestamp *lt; -+ struct gazelle_stack_latency *stack_latency; -+ struct protocol_stack *stack; - -- if (pbuf == NULL || type >= GAZELLE_LATENCY_MAX) { -+ stack = get_protocol_stack_by_id(stack_id); -+ if (stack == NULL) - return; -- } -+ stack_latency = &stack->latency; -+ lt_type = (type / GAZELLE_LATENCY_READ_MAX) ? GAZELLE_LATENCY_WR : GAZELLE_LATENCY_RD; - -- lt = &pbuf_to_private(pbuf)->lt; -- if (lt == NULL) { -- return; -- } -+ for (uint32_t i = 0; i < num; ++i) { -+ if (pbufs[i] == NULL) { -+ continue; -+ } -+ lt = &pbuf_to_private(pbufs[i])->lt; - -- lt_type = (type / GAZELLE_LATENCY_READ_MAX) ? GAZELLE_LATENCY_WR : GAZELLE_LATENCY_RD; -- if (lt->stamp != ~(lt->check) || lt->stamp < stack_latency->start_time || lt_type != lt->type) { -- return; -- } -+ if (lt->stamp != ~(lt->check) || -+ lt->stamp < stack_latency->start_time || -+ lt_type != lt->type) { -+ continue; -+ } - -- if (time_record == 0) { -- lt->stamp_seg[type] = sys_now_us() - lt->stamp; -- } else { -- lt->stamp_seg[type] = time_record > (lt->stamp_seg[type - 1] + lt->stamp) ? -- (time_record - lt->stamp) : lt->stamp_seg[type - 1]; -- } -+ if (time_record == 0) { -+ lt->stamp_seg[type] = sys_now_us() - lt->stamp; -+ } else { -+ lt->stamp_seg[type] = time_record > (lt->stamp_seg[type - 1] + lt->stamp) ? -+ (time_record - lt->stamp) : lt->stamp_seg[type - 1]; -+ } - -- latency = lt->stamp_seg[type]; -- if (((lt_type == GAZELLE_LATENCY_RD && type > GAZELLE_LATENCY_READ_LWIP) || -- (lt_type == GAZELLE_LATENCY_WR && type > GAZELLE_LATENCY_WRITE_INTO_RING)) && -- latency >= lt->stamp_seg[type - 1]) { -- latency -= lt->stamp_seg[type - 1]; -- } -+ latency = lt->stamp_seg[type]; -+ if (((lt_type == GAZELLE_LATENCY_RD && type > GAZELLE_LATENCY_INTO_MBOX) || -+ (lt_type == GAZELLE_LATENCY_WR && type > GAZELLE_LATENCY_WRITE_INTO_RING)) && -+ latency >= lt->stamp_seg[type - 1]) { -+ latency -= lt->stamp_seg[type - 1]; -+ } - -- /* calculate the time of the entire read/write process */ -- if (type == GAZELLE_LATENCY_READ_MAX - 1 || type == GAZELLE_LATENCY_WRITE_MAX - 1) { -- calculate_latency_stat(stack_latency, lt->stamp_seg[type], type + 1); -- } -+ /* calculate the time of the entire read/write process */ -+ if (type == GAZELLE_LATENCY_READ_MAX - 1 || type == GAZELLE_LATENCY_WRITE_MAX - 1) { -+ calculate_latency_stat(stack_latency, lt->stamp_seg[type], type + 1); -+ } - -- calculate_latency_stat(stack_latency, latency, type); -+ calculate_latency_stat(stack_latency, latency, type); -+ } - } - - void lstack_calculate_aggregate(int type, uint32_t len) -@@ -240,13 +235,7 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - int32_t rpc_call_result = rpc_msgcnt(&stack->rpc_queue); - dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; - -- if (stack_get_state(stack) == RUNNING) { -- rpc_call_result = rpc_call_mbufpoolsize(&stack->dfx_rpc_queue); -- dfx->data.pkts.mbufpool_avail_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -- -- rpc_call_result = rpc_call_recvlistcnt(&stack->dfx_rpc_queue); -- dfx->data.pkts.recv_list_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -- } -+ dfx->data.pkts.mbufpool_avail_cnt = mem_stack_mbuf_pool_count(stack->stack_idx); - - dfx->data.pkts.conn_num = stack->conn_num; - } -@@ -323,13 +312,12 @@ static void get_stack_dfx_data(struct gazelle_stack_dfx_data *dfx, struct protoc - break; - case GAZELLE_STAT_LSTACK_SHOW_CONN: - if (stack_get_state(stack) == RUNNING) { -- rpc_call_result = rpc_call_conntable(&stack->dfx_rpc_queue, dfx->data.conn.conn_list, -+ rpc_call_result = rpc_call_conntable(stack->stack_idx, dfx->data.conn.conn_list, - GAZELLE_LSTACK_MAX_CONN); - dfx->data.conn.conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; -- rpc_call_result = rpc_call_connnum(&stack->dfx_rpc_queue); -+ rpc_call_result = rpc_call_connnum(stack->stack_idx); - dfx->data.conn.total_conn_num = (rpc_call_result < 0) ? 0 : rpc_call_result; - } -- - break; - case GAZELLE_STAT_LSTACK_SHOW_LATENCY: - ret = memcpy_s(&dfx->data.latency, sizeof(dfx->data.latency), &stack->latency, sizeof(stack->latency)); -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index a831d3b..7b3e432 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -9,33 +9,17 @@ - * PURPOSE. - * See the Mulan PSL v2 for more details. - */ --#include --#include --#include - --#include "lwip/lwipgz_posix_api.h" -+#include -+#include - - #include "lstack_log.h" - #include "lstack_cfg.h" --#include "lstack_dpdk.h" - #include "lstack_stack_stat.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" --#include "lstack_epoll.h" --#include "lstack_lwip.h" -- --struct rpc_pool_array { --#define RPC_POOL_MAX_COUNT 1024 -- struct rpc_msg_pool *array[RPC_POOL_MAX_COUNT]; -- pthread_mutex_t lock; -- int cur_count; --}; -+#include "lstack_mempool.h" - --static struct rpc_pool_array g_rpc_pool_array = { -- .lock = PTHREAD_MUTEX_INITIALIZER, --}; -- --static PER_THREAD struct rpc_msg_pool *g_rpc_pool = NULL; - static struct rpc_stats g_rpc_stats; - - struct rpc_stats *rpc_stats_get(void) -@@ -44,114 +28,60 @@ struct rpc_stats *rpc_stats_get(void) - } - - __rte_always_inline --static struct rpc_msg *get_rpc_msg(struct rpc_msg_pool *rpc_pool) --{ -- int ret; -- struct rpc_msg *msg = NULL; -- ret = rte_mempool_get(rpc_pool->mempool, (void **)&msg); -- if (ret < 0) { -- errno = ENOMEM; -- return NULL; -- } -- return msg; --} -- --__rte_always_inline --static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func, struct rpc_msg_pool *pool) -+static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func) - { - msg->func = func; -- msg->rpcpool = pool; -- msg->recall_flag = 0; -+ msg->flags = 0; - pthread_spin_init(&msg->lock, PTHREAD_PROCESS_PRIVATE); --} -- --static struct rpc_msg_pool *rpc_msg_pool_init(void) --{ -- struct rpc_msg_pool *rpc_pool; -- pthread_mutex_lock(&g_rpc_pool_array.lock); -- if (g_rpc_pool_array.cur_count >= RPC_POOL_MAX_COUNT) { -- pthread_mutex_unlock(&g_rpc_pool_array.lock); -- return g_rpc_pool_array.array[rte_gettid() % RPC_POOL_MAX_COUNT]; -- } - -- rpc_pool = calloc(1, sizeof(struct rpc_msg_pool)); -- if (rpc_pool == NULL) { -- LSTACK_LOG(INFO, LSTACK, "g_rpc_pool calloc failed\n"); -- goto END; -- } -- rpc_pool->mempool = -- create_mempool("rpc_pool", get_global_cfg_params()->rpc_msg_max, sizeof(struct rpc_msg), 0, rte_gettid()); -- if (rpc_pool->mempool == NULL) { -- LSTACK_LOG(INFO, LSTACK, "rpc_pool create failed, errno is %d\n", errno); -- free(rpc_pool); -- goto END; -- } -- -- g_rpc_pool_array.array[g_rpc_pool_array.cur_count++] = rpc_pool; -- pthread_mutex_unlock(&g_rpc_pool_array.lock); -- return rpc_pool; --END: -- pthread_mutex_unlock(&g_rpc_pool_array.lock); -- g_rpc_stats.call_alloc_fail++; -- return NULL; -+ lockless_queue_node_set_poped(&msg->queue_node); - } - -- --static struct rpc_msg *rpc_msg_alloc(rpc_func_t func) -+struct rpc_msg *rpc_msg_alloc(int stack_id, rpc_func_t func) - { - struct rpc_msg *msg; - -- if (unlikely(g_rpc_pool == NULL)) { -- g_rpc_pool = rpc_msg_pool_init(); -- if (g_rpc_pool == NULL) { -- exit(-1); -- } -- } -- -- msg = get_rpc_msg(g_rpc_pool); -+ msg = mem_get_rpc(stack_id); - if (unlikely(msg == NULL)) { - g_rpc_stats.call_alloc_fail++; - return NULL; - } - -- rpc_msg_init(msg, func, g_rpc_pool); -+ rpc_msg_init(msg, func); - return msg; - } - --__rte_always_inline --static void rpc_msg_free(struct rpc_msg *msg) -+void rpc_msg_free(struct rpc_msg *msg) - { - pthread_spin_destroy(&msg->lock); -- if (msg->rpcpool != NULL && msg->rpcpool->mempool != NULL) { -- rte_mempool_put(msg->rpcpool->mempool, (void *)msg); -- } else { -- free(msg); -- } -+ mem_put_rpc(msg); - } - --__rte_always_inline --static void rpc_call(rpc_queue *queue, struct rpc_msg *msg) -+void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg, int flags) - { -- lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -- intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); --} -+ if (flags & RPC_MSG_RECALL) -+ msg->flags |= flags; /* if RECALL, keep the previous flags. */ -+ else -+ msg->flags = flags & (~RPC_MSG_SYNC); - --__rte_always_inline --static void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg) --{ -- msg->sync_flag = 0; -- rpc_call(queue, msg); -+ if (msg->flags & RPC_MSG_REUSE) -+ lockless_queue_mpsc_test_push(&queue->queue, &msg->queue_node); -+ else -+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -+ -+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); - } - --__rte_always_inline --static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) -+int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - { - int ret; - - pthread_spin_trylock(&msg->lock); - -- msg->sync_flag = 1; -- rpc_call(queue, msg); -+ msg->flags = RPC_MSG_SYNC; -+ lockless_queue_mpsc_push(&queue->queue, &msg->queue_node); -+ -+ intr_wakeup(queue->queue_id, INTR_REMOTE_EVENT); - - // waiting stack unlock - pthread_spin_lock(&msg->lock); -@@ -161,36 +91,15 @@ static int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg) - return ret; - } - --int rpc_msgcnt(rpc_queue *queue) -+void rpc_queue_init(rpc_queue *queue, uint16_t queue_id) - { -- return lockless_queue_count(&queue->queue); -+ lockless_queue_init(&queue->queue); -+ queue->queue_id = queue_id; - } - --static struct rpc_msg *rpc_msg_alloc_except(rpc_func_t func) --{ -- struct rpc_msg *msg = calloc(1, sizeof(struct rpc_msg)); -- if (msg == NULL) { -- return NULL; -- } -- -- rpc_msg_init(msg, func, NULL); -- return msg; --} -- --static void stack_exit_by_rpc(struct rpc_msg *msg) --{ -- stack_exit(); --} -- --int rpc_call_stack_exit(rpc_queue *queue) -+int rpc_msgcnt(rpc_queue *queue) - { -- struct rpc_msg *msg = rpc_msg_alloc_except(stack_exit_by_rpc); -- if (msg == NULL) { -- return -1; -- } -- -- rpc_async_call(queue, msg); -- return 0; -+ return lockless_queue_count(&queue->queue); - } - - int rpc_poll_msg(rpc_queue *queue, int max_num) -@@ -203,7 +112,6 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - if (node == NULL) { - break; - } -- - msg = container_of(node, struct rpc_msg, queue_node); - - if (likely(msg->func)) { -@@ -212,17 +120,19 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - g_rpc_stats.call_null++; - } - -- if (unlikely(msg->func == stack_exit_by_rpc)) { -- force_quit = 1; -- } -- if (msg->recall_flag) { -- msg->recall_flag = 0; -+ if (msg->flags & RPC_MSG_RECALL) { -+ msg->flags &= ~RPC_MSG_RECALL; - continue; - } - -- if (msg->sync_flag) { -+ if (unlikely(msg->flags & RPC_MSG_EXIT)) { -+ force_quit = 1; -+ } -+ -+ if (msg->flags & RPC_MSG_SYNC) { - pthread_spin_unlock(&msg->lock); -- } else { -+ } -+ if (msg->flags & RPC_MSG_FREE) { - rpc_msg_free(msg); - } - } -@@ -231,560 +141,145 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - } - - --static void callback_socket(struct rpc_msg *msg) --{ -- msg->result = lwip_socket(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i); -- if (msg->result < 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, %ld socket failed\n", rte_gettid(), msg->result); -- } --} -- --static void callback_close(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- -- if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); /* until stack_send recall finish */ -- return; -- } -- -- msg->result = lwip_close(fd); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --static void callback_shutdown(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- int how = msg->args[MSG_ARG_1].i; -- struct lwip_sock *sock = lwip_get_socket(fd); -- struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); -- -- if (sock && __atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) > 0) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- return; -- } -- -- msg->result = lwip_shutdown(fd, how); -- if (msg->result != 0 && errno != ENOTCONN) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), fd, msg->result); -- } -- -- posix_api->shutdown_fn(fd, how); --} -- --static void callback_bind(struct rpc_msg *msg) --{ -- msg->result = lwip_bind(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].cp, msg->args[MSG_ARG_2].u); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --static void callback_listen(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- int backlog = msg->args[MSG_ARG_1].i; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- msg->result = -1; -- return; -- } -- -- /* new listen add to stack listen list */ -- msg->result = lwip_listen(fd, backlog); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d failed %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --static void callback_create_shadow_fd(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- struct sockaddr *addr = msg->args[MSG_ARG_1].p; -- socklen_t addr_len = msg->args[MSG_ARG_2].u; -- -- int clone_fd = 0; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d\n", fd); -- msg->result = -1; -- return; -- } -- -- int domain = addr->sa_family; -- int type = NETCONN_IS_UDP(sock) ? SOCK_DGRAM : SOCK_STREAM; -- clone_fd = lwip_socket(domain, type, 0); -- if (clone_fd < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone socket failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = clone_fd; -- return; -- } -- -- struct lwip_sock *clone_sock = lwip_get_socket(clone_fd); -- if (clone_sock == NULL) { -- LSTACK_LOG(ERR, LSTACK, "get sock null fd=%d clone_fd=%d\n", fd, clone_fd); -- msg->result = -1; -- return; -- } -- -- do_lwip_clone_sockopt(clone_sock, sock); -- -- while (sock->listen_next) { -- sock = sock->listen_next; -- } -- sock->listen_next = clone_sock; -- -- int ret = lwip_bind(clone_fd, addr, addr_len); -- if (ret < 0) { -- LSTACK_LOG(ERR, LSTACK, "clone bind failed clone_fd=%d errno=%d\n", clone_fd, errno); -- msg->result = ret; -- return; -- } -- -- msg->result = clone_fd; --} -- --static void callback_accept(struct rpc_msg *msg) -+static void callback_arp(struct rpc_msg *msg) - { -- int fd = msg->args[MSG_ARG_0].i; -- msg->result = -1; -+ struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; - struct protocol_stack *stack = get_protocol_stack(); - -- int accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); -- if (accept_fd < 0) { -- stack->stats.accept_fail++; -- LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -- return; -- } -- -- struct lwip_sock *sock = lwip_get_socket(accept_fd); -- if (sock == NULL) { -- lwip_close(accept_fd); -- LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); -- return; -- } -- -- msg->result = accept_fd; -- stack->conn_num++; -- if (rte_ring_count(sock->conn->recvmbox->ring)) { -- do_lwip_add_recvlist(accept_fd); -- } --} -- --static void callback_connect(struct rpc_msg *msg) --{ -- msg->result = lwip_connect(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].u); -- if (msg->result < 0) { -- msg->result = -errno; -- } --} -- --int rpc_call_socket(rpc_queue *queue, int domain, int type, int protocol) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_socket); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = domain; -- msg->args[MSG_ARG_1].i = type; -- msg->args[MSG_ARG_2].i = protocol; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_close(rpc_queue *queue, int fd) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_close); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_shutdown(rpc_queue *queue, int fd, int how) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_shutdown); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].i = how; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_bind(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_bind); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].u = addrlen; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_listen(rpc_queue *queue, int s, int backlog) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_listen); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = s; -- msg->args[MSG_ARG_1].i = backlog; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_shadow_fd(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_create_shadow_fd); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].u = addrlen; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_accept); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].p = addr; -- msg->args[MSG_ARG_2].p = addrlen; -- msg->args[MSG_ARG_3].i = flags; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_connect); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].cp = addr; -- msg->args[MSG_ARG_2].u = addrlen; -- -- int ret = rpc_sync_call(queue, msg); -- if (ret < 0) { -- errno = -ret; -- return -1; -- } -- return ret; --} -- --static void callback_getpeername(struct rpc_msg *msg) --{ -- msg->result = lwip_getpeername(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); --} -- --static void callback_getsockname(struct rpc_msg *msg) --{ -- msg->result = lwip_getsockname(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d fail %ld\n", rte_gettid(), msg->args[MSG_ARG_0].i, msg->result); -- } --} -- --static void callback_getsockopt(struct rpc_msg *msg) --{ -- msg->result = lwip_getsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -- msg->args[MSG_ARG_3].p, msg->args[MSG_ARG_4].p); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), -- msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -- } --} -- --static void callback_setsockopt(struct rpc_msg *msg) --{ -- msg->result = lwip_setsockopt(msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, -- msg->args[MSG_ARG_3].cp, msg->args[MSG_ARG_4].u); -- if (msg->result != 0) { -- LSTACK_LOG(ERR, LSTACK, "tid %d, fd %d, level %d, optname %d, fail %ld\n", rte_gettid(), -- msg->args[MSG_ARG_0].i, msg->args[MSG_ARG_1].i, msg->args[MSG_ARG_2].i, msg->result); -- } --} -- --int rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_getpeername); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].p = addr; -- msg->args[MSG_ARG_2].p = addrlen; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_getsockname); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].p = addr; -- msg->args[MSG_ARG_2].p = addrlen; -- -- return rpc_sync_call(queue, msg); --} -- --int rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_getsockopt); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].i = level; -- msg->args[MSG_ARG_2].i = optname; -- msg->args[MSG_ARG_3].p = optval; -- msg->args[MSG_ARG_4].p = optlen; -- -- return rpc_sync_call(queue, msg); -+ eth_dev_recv(mbuf, stack); - } - --int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen) -+int rpc_call_arp(int stack_id, void *mbuf) - { -- struct rpc_msg *msg = rpc_msg_alloc(callback_setsockopt); -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_arp); - if (msg == NULL) { - return -1; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].i = level; -- msg->args[MSG_ARG_2].i = optname; -- msg->args[MSG_ARG_3].cp = optval; -- msg->args[MSG_ARG_4].u = optlen; -+ msg->args[MSG_ARG_0].p = mbuf; - -- return rpc_sync_call(queue, msg); -+ rpc_async_call(queue, msg, RPC_MSG_FREE); -+ return 0; - } - --static void callback_tcp_send(struct rpc_msg *msg) --{ -- int fd = msg->args[MSG_ARG_0].i; -- size_t len = UINT16_MAX; /* ignore msg->args[MSG_ARG_1].size; */ -- struct protocol_stack *stack = get_protocol_stack(); -- int ret; -- msg->result = -1; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (unlikely(POSIX_IS_CLOSED(sock))) { -- return; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -+static void copy_pcb_to_conn(struct gazelle_stat_lstack_conn_info *conn, const struct tcp_pcb *pcb) -+{ -+ struct netconn *netconn = (struct netconn *)pcb->callback_arg; -+ const struct mbox_ring *mr; -+ -+ conn->lip = *((gz_addr_t *)&pcb->local_ip); -+ conn->rip = *((gz_addr_t *)&pcb->remote_ip); -+ conn->l_port = pcb->local_port; -+ conn->r_port = pcb->remote_port; -+ conn->in_send = pcb->snd_queuelen; -+ conn->tcp_sub_state = pcb->state; -+ conn->cwn = pcb->cwnd; -+ conn->rcv_wnd = pcb->rcv_wnd; -+ conn->snd_wnd = pcb->snd_wnd; -+ conn->snd_buf = pcb->snd_buf; -+ conn->lastack = pcb->lastack; -+ conn->snd_nxt = pcb->snd_nxt; -+ conn->rcv_nxt = pcb->rcv_nxt; -+ conn->keepalive = (ip_get_option(pcb, SOF_KEEPALIVE) != 0); -+ conn->keep_idle = pcb->keep_idle; -+ conn->keep_intvl = pcb->keep_intvl; -+ conn->keep_cnt = pcb->keep_cnt; -+ conn->pingpong = tcp_in_pingpong(pcb); -+ -+ if (netconn != NULL) { -+ if (sys_mbox_valid(&netconn->recvmbox)) { -+ mr = &netconn->recvmbox->mring; -+ conn->recvmbox_cnt = mr->ops->recv_count(mr); -+ conn->recvmbox_tail = mr->tail_count(mr); -+ } -+ if (sys_mbox_valid(&netconn->sendmbox)) { -+ mr = &netconn->sendmbox->mring; -+ conn->sendmbox_cnt = mr->ops->count(mr); -+ conn->sendmbox_tail = mr->tail_count(mr); -+ } - -- ret = lwip_send(fd, sock, len, 0); -- if (unlikely(ret < 0) && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; -- } -- msg->result = 0; -- -- ret = do_lwip_replenish_sendring(stack, sock); -- if (ret > 0 || NETCONN_IS_DATAOUT(sock)) { -- if (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- return; -+ conn->fd = netconn->callback_arg.socket; -+ struct lwip_sock *sock = lwip_get_socket(netconn->callback_arg.socket); -+ if (!POSIX_IS_CLOSED(sock)) { -+ struct sock_event *sk_event = &sock->sk_event; -+ conn->events = sk_event->pending; -+ conn->epoll_events = sk_event->events; -+ conn->eventlist = !list_node_null(&sk_event->event_node); - } - } -- -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; - } - --static void callback_udp_send(struct rpc_msg *msg) -+static uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, -+ uint32_t max_num) - { -- int fd = msg->args[MSG_ARG_0].i; -- size_t len = msg->args[MSG_ARG_1].size; -- struct protocol_stack *stack = get_protocol_stack(); -- int ret; -- msg->result = -1; -- -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (unlikely(POSIX_IS_CLOSED(sock))) { -- return; -- } -- -- if (get_protocol_stack_group()->latency_start) { -- calculate_sock_latency(&stack->latency, sock, GAZELLE_LATENCY_WRITE_RPC_MSG); -- } -- -- ret = lwip_send(fd, sock, len, 0); -- if (unlikely(ret < 0) && (errno == ENOTCONN || errno == ECONNRESET || errno == ECONNABORTED)) { -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; -- } -- msg->result = 0; -- -- ret = do_lwip_replenish_sendring(stack, sock); -- if (ret > 0 && (__atomic_load_n(&sock->call_num, __ATOMIC_ACQUIRE) == 1)) { -- rpc_call_replenish(&stack->rpc_queue, sock); -- return; -- } -+ struct tcp_pcb *pcb = NULL; -+ uint32_t conn_num = 0; -+ const struct mbox_ring *mr; - -- __sync_fetch_and_sub(&sock->call_num, 1); -- return; --} -- --int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_udp_send); -- if (msg == NULL) { -+ if (conn == NULL) { - return -1; - } - -- if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(lwip_get_socket(fd)); -+ for (pcb = tcp_active_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -+ conn[conn_num].state = GAZELLE_ACTIVE_LIST; -+ copy_pcb_to_conn(conn + conn_num, pcb); -+ conn_num++; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].size = len; -- msg->args[MSG_ARG_2].i = flags; -- -- rpc_async_call(queue, msg); -- return 0; --} -- --int rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_tcp_send); -- if (msg == NULL) { -- return -1; -+ for (pcb = tcp_tw_pcbs; pcb != NULL && conn_num < max_num; pcb = pcb->next) { -+ conn[conn_num].state = GAZELLE_TIME_WAIT_LIST; -+ copy_pcb_to_conn(conn + conn_num, pcb); -+ conn_num++; - } - -- if (get_protocol_stack_group()->latency_start) { -- time_stamp_into_rpcmsg(lwip_get_socket(fd)); -+ for (struct tcp_pcb_listen *pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL && conn_num < max_num; -+ pcbl = pcbl->next) { -+ conn[conn_num].state = GAZELLE_LISTEN_LIST; -+ conn[conn_num].lip = *((gz_addr_t *)&pcbl->local_ip); -+ conn[conn_num].l_port = pcbl->local_port; -+ conn[conn_num].tcp_sub_state = pcbl->state; -+ struct netconn *netconn = (struct netconn *)pcbl->callback_arg; -+ conn[conn_num].fd = netconn != NULL ? netconn->callback_arg.socket : -1; -+ if (netconn != NULL) { -+ if (sys_mbox_valid(&netconn->acceptmbox)) { -+ mr = &netconn->acceptmbox->mring; -+ conn[conn_num].recvmbox_cnt = mr->ops->count(mr); -+ } -+ } -+ conn_num++; - } - -- msg->args[MSG_ARG_0].i = fd; -- msg->args[MSG_ARG_1].size = len; -- msg->args[MSG_ARG_2].i = flags; -- -- rpc_async_call(queue, msg); -- return 0; -+ return conn_num; - } - --static void callback_replenish_sendring(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- struct lwip_sock *sock = (struct lwip_sock *)msg->args[MSG_ARG_0].p; -- -- msg->result = do_lwip_replenish_sendring(stack, sock); -- if (msg->result == true) { -- msg->recall_flag = 1; -- rpc_call(&stack->rpc_queue, msg); -- } --} -- --int rpc_call_replenish(rpc_queue *queue, void *sock) -+static void callback_get_conntable(struct rpc_msg *msg) - { -- struct rpc_msg *msg = rpc_msg_alloc(callback_replenish_sendring); -- if (msg == NULL) { -- return -1; -- } -- -- msg->args[MSG_ARG_0].p = sock; -+ struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -+ unsigned max_num = msg->args[MSG_ARG_1].u; - -- rpc_async_call(queue, msg); -- return 0; -+ msg->result = do_lwip_get_conntable(conn, max_num); - } - --static void callback_recvlist_count(struct rpc_msg *msg) -+static uint32_t do_lwip_get_connnum(void) - { -- struct protocol_stack *stack = get_protocol_stack(); -- struct list_node *list = &stack->recv_list; -- int count = 0; -- struct list_node *node; -- struct list_node *temp; -+ struct tcp_pcb *pcb = NULL; -+ struct tcp_pcb_listen *pcbl = NULL; -+ uint32_t conn_num = 0; - -- list_for_each_node(node, temp, list) { -- count++; -+ for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { -+ conn_num++; - } -- msg->result = count; --} - --int rpc_call_recvlistcnt(rpc_queue *queue) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_recvlist_count); -- if (msg == NULL) { -- return -1; -+ for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) { -+ conn_num++; - } - -- return rpc_sync_call(queue, msg); --} -- --static void callback_arp(struct rpc_msg *msg) --{ -- struct rte_mbuf *mbuf = (struct rte_mbuf *)msg->args[MSG_ARG_0].p; -- struct protocol_stack *stack = get_protocol_stack(); -- -- eth_dev_recv(mbuf, stack); --} -- --int rpc_call_arp(rpc_queue *queue, void *mbuf) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_arp); -- if (msg == NULL) { -- return -1; -+ for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { -+ conn_num++; - } - -- msg->args[MSG_ARG_0].p = mbuf; -- -- rpc_async_call(queue, msg); -- return 0; --} -- --static void callback_mempool_size(struct rpc_msg *msg) --{ -- struct protocol_stack *stack = get_protocol_stack(); -- -- msg->result = rte_mempool_avail_count(stack->rxtx_mbuf_pool); --} -- --static void callback_get_conntable(struct rpc_msg *msg) --{ -- struct gazelle_stat_lstack_conn_info *conn = (struct gazelle_stat_lstack_conn_info *)msg->args[MSG_ARG_0].p; -- unsigned max_num = msg->args[MSG_ARG_1].u; -- -- msg->result = do_lwip_get_conntable(conn, max_num); -+ return conn_num; - } - - static void callback_get_connnum(struct rpc_msg *msg) -@@ -792,9 +287,10 @@ static void callback_get_connnum(struct rpc_msg *msg) - msg->result = do_lwip_get_connnum(); - } - --int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn) -+int rpc_call_conntable(int stack_id, void *conn_table, unsigned max_conn) - { -- struct rpc_msg *msg = rpc_msg_alloc(callback_get_conntable); -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->dfx_rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_get_conntable); - if (msg == NULL) { - return -1; - } -@@ -805,44 +301,13 @@ int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn) - return rpc_sync_call(queue, msg); - } - --int rpc_call_connnum(rpc_queue *queue) -+int rpc_call_connnum(int stack_id) - { -- struct rpc_msg *msg = rpc_msg_alloc(callback_get_connnum); -+ rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->dfx_rpc_queue; -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_get_connnum); - if (msg == NULL) { - return -1; - } - - return rpc_sync_call(queue, msg); - } -- --int rpc_call_mbufpoolsize(rpc_queue *queue) --{ -- struct rpc_msg *msg = rpc_msg_alloc(callback_mempool_size); -- if (msg == NULL) { -- return -1; -- } -- -- return rpc_sync_call(queue, msg); --} -- --extern void thread_register_phase1(struct rpc_msg *msg); --int rpc_call_thread_regphase1(rpc_queue *queue, void *conn) --{ -- struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase1); -- if (msg == NULL) { -- return -1; -- } -- msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(queue, msg); --} -- --extern void thread_register_phase2(struct rpc_msg *msg); --int rpc_call_thread_regphase2(rpc_queue *queue, void *conn) --{ -- struct rpc_msg *msg = rpc_msg_alloc(thread_register_phase2); -- if (msg == NULL) { -- return -1; -- } -- msg->args[MSG_ARG_0].p = conn; -- return rpc_sync_call(queue, msg); --} -diff --git a/src/lstack/core/lstack_virtio.c b/src/lstack/core/lstack_virtio.c -index f6855d1..2c2d74e 100644 ---- a/src/lstack/core/lstack_virtio.c -+++ b/src/lstack/core/lstack_virtio.c -@@ -24,6 +24,7 @@ - #include "lstack_port_map.h" - #include "lstack_interrupt.h" - #include "lstack_virtio.h" -+#include "mbox_ring.h" - - #define VIRTIO_USER_NAME "virtio_user" - #define VIRTIO_DPDK_PARA_LEN 256 -@@ -293,7 +294,7 @@ static int virtio_port_init(uint16_t port) - } - - for (uint16_t q = 0; q < rx_queue_num; q++) { -- struct rte_mempool *rxtx_mbuf_pool = get_protocol_stack_group()->total_rxtx_pktmbuf_pool[q % mbuf_total_num]; -+ struct rte_mempool *rxtx_mbuf_pool = mem_get_mbuf_pool(q % mbuf_total_num); - retval = rte_eth_rx_queue_setup(port, q, VIRTIO_TX_RX_RING_SIZE, rte_eth_dev_socket_id(port), - NULL, rxtx_mbuf_pool); - if (retval < 0) { -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 6334f5e..c67df93 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -26,7 +26,7 @@ - #include "lstack_log.h" - #include "lstack_cfg.h" - #include "same_node.h" --#include "lstack_lwip.h" -+#include "mbox_ring.h" - - #define KERNEL_EVENT_WAIT_US 10 - #define LWIP_EVENT_WAIT_US 10 -@@ -340,26 +340,34 @@ void sock_wait_kernel_free(struct sock_wait *sk_wait) - static inline bool NETCONN_NEED_ACCEPT(const struct lwip_sock *sock) - { - if (sys_mbox_valid(&sock->conn->acceptmbox)) { -- return !sys_mbox_empty(sock->conn->acceptmbox); -+ const struct mbox_ring *mr = &sock->conn->acceptmbox->mring; -+ return mr->ops->count(mr) > 0; - } - return false; - } - - static inline bool NETCONN_NEED_RECV(const struct lwip_sock *sock) - { -- if (sock->recv_lastdata != NULL) -- return true; -- if (gazelle_ring_readable_count(sock->recv_ring) > 0) -- return true; -- if (NETCONN_NEED_SAME_NODE(sock)) -+ if (sock->lastdata.pbuf != NULL) - return true; -+ if (sys_mbox_valid(&sock->conn->recvmbox)) { -+ const struct mbox_ring *mr = &sock->conn->recvmbox->mring; -+ return mr->ops->recv_count(mr) > 0; -+ } - return false; - } - - static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) - { -- if (gazelle_ring_readable_count(sock->send_ring) > 0) -- return true; -+ if (get_global_cfg_params()->stack_mode_rtc) { -+ if (NETCONN_TYPE(sock->conn) == NETCONN_TCP) -+ return lwip_tcp_allow_send(sock->conn->pcb.tcp); -+ return false; -+ } -+ if (sys_mbox_valid(&sock->conn->sendmbox)) { -+ const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ return mr->ops->free_count(mr) > 0; -+ } - return false; - } - -diff --git a/src/lstack/core/same_node.c b/src/lstack/core/same_node.c -index 660fefd..eb3610e 100644 ---- a/src/lstack/core/same_node.c -+++ b/src/lstack/core/same_node.c -@@ -20,25 +20,10 @@ - #include "lstack_protocol_stack.h" - #include "lstack_stack_stat.h" - #include "same_node.h" --#include "lstack_epoll.h" --#include "lstack_lwip.h" -+#include "lstack_wait.h" - --#if GAZELLE_SAME_NODE --void read_same_node_recv_list(struct protocol_stack *stack) --{ -- struct list_node *list = &(stack->same_node_recv_list); -- struct list_node *node, *temp; -- struct lwip_sock *sock; -- -- list_for_each_node(node, temp, list) { -- sock = list_entry(node, struct lwip_sock, recv_list); -- -- if (sock->same_node_rx_ring != NULL && same_node_ring_count(sock)) { -- API_EVENT(sock->conn, NETCONN_EVT_RCVPLUS, 0); -- } -- } --} - -+#if GAZELLE_SAME_NODE - /* process on same node use ring to recv data */ - ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags) - { -@@ -231,8 +216,7 @@ err_t find_same_node_memzone(struct tcp_pcb *pcb, struct lwip_sock *nsock) - - /* rcvlink init in alloc_socket() */ - /* remove from g_rcv_process_list in free_socket */ -- struct protocol_stack *stack = get_protocol_stack_by_id(nsock->stack_id); -- list_add_node(&nsock->recv_list, &stack->same_node_recv_list); -+ API_EVENT(nsock->conn, NETCONN_EVT_RCVPLUS, 0); - return 0; - } - -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index d59407b..3e671b5 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -128,15 +128,12 @@ struct cfg_params { - bool listen_shadow; // true:listen in all stack thread. false:listen in one stack thread. - bool stack_interrupt; - -- uint32_t read_connect_number; - uint32_t nic_read_number; - uint32_t rpc_number; - uint32_t rpc_msg_max; - }; - - struct { // socket -- uint16_t send_ring_size; -- uint16_t recv_ring_size; - uint32_t tcp_conn_count; - uint32_t mbuf_count_per_conn; - }; -@@ -167,7 +164,8 @@ static inline uint8_t use_ltran(void) - - static inline bool xdp_eth_enabled(void) - { -- if (strlen(get_global_cfg_params()->xdp_eth_name)) { -+ /* strlen > 0 */ -+ if (get_global_cfg_params()->xdp_eth_name[0] != '\0') { - return true; - } - return false; -diff --git a/src/lstack/include/lstack_dpdk.h b/src/lstack/include/lstack_dpdk.h -index 6251be7..f70477e 100644 ---- a/src/lstack/include/lstack_dpdk.h -+++ b/src/lstack/include/lstack_dpdk.h -@@ -13,6 +13,7 @@ - #ifndef _GAZELLE_DPDK_H_ - #define _GAZELLE_DPDK_H_ - -+#include - #include - #include - #include -@@ -20,21 +21,10 @@ - #include "common/gazelle_opt.h" - #include "common/gazelle_dfx_msg.h" - --#define RXTX_CACHE_SZ (VDEV_RX_QUEUE_SZ) -- - #define KNI_NB_MBUF (DEFAULT_RING_SIZE << 4) - --#define MAX_PACKET_SZ 1538 -- - #define RING_SIZE(x) ((x) - 1) - --#define MBUF_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) -- --/* DPDK limit ring head-tail distance in rte_ring_init. -- * Max value is RTE_RING_SZ_MASK / HTD_MAX_DEF, RTE_RING_SZ_MASK is 0x7fffffff, HTD_MAX_DEF is 8. -- */ --#define MBUF_MAX_NUM 0xfffffff -- - struct protocol_stack; - - int32_t dpdk_eal_init(void); -@@ -47,13 +37,7 @@ int init_dpdk_ethdev(void); - int thread_affinity_default(void); - - int32_t create_shared_ring(struct protocol_stack *stack); --int32_t fill_mbuf_to_ring(struct rte_mempool *mempool, struct rte_ring *ring, uint32_t mbuf_num); --int32_t pktmbuf_pool_init(struct protocol_stack *stack); --struct rte_mempool *create_mempool(const char *name, uint32_t count, uint32_t size, -- uint32_t flags, int32_t idx); --struct rte_mempool *create_pktmbuf_mempool(const char *name, uint32_t nb_mbuf, -- uint32_t mbuf_cache_size, uint16_t queue_id, unsigned numa_id); --int32_t dpdk_alloc_pktmbuf(struct rte_mempool *pool, struct rte_mbuf **mbufs, uint32_t num, bool reserve); -+int32_t fill_mbuf_to_ring(int stack_id, struct rte_ring *ring, uint32_t mbuf_num); - - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - void dpdk_skip_nic_init(void); -diff --git a/src/lstack/include/lstack_dummy_api.h b/src/lstack/include/lstack_dummy_api.h -deleted file mode 100644 -index 48bce31..0000000 ---- a/src/lstack/include/lstack_dummy_api.h -+++ /dev/null -@@ -1,23 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#ifndef _LSTACK_DUMMY_API_H_ --#define _LSTACK_DUMMY_API_H_ -- --int dummy_socket(int domain, int type, int protocol); --ssize_t dummy_write(int s, const void *mem, size_t size); --ssize_t dummy_writev(int s, const struct iovec *iov, int iovcnt); --ssize_t dummy_sendmsg(int s, const struct msghdr *message, int flags); --ssize_t dummy_send(int sockfd, const void *buf, size_t len, int flags); --ssize_t dummy_sendto(int sockfd, const void *buf, size_t len, int flags, -- const struct sockaddr *addr, socklen_t addrlen); --#endif /* __LSTACK_DUMMY_API_H_ */ -diff --git a/src/lstack/include/lstack_lwip.h b/src/lstack/include/lstack_lwip.h -deleted file mode 100644 -index 4cc9db1..0000000 ---- a/src/lstack/include/lstack_lwip.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#ifndef __GAZELLE_LWIP_H__ --#define __GAZELLE_LWIP_H__ --#include -- --#include "common/gazelle_dfx_msg.h" --#include "common/dpdk_common.h" --#include "same_node.h" -- --struct lwip_sock; --struct rpc_msg; --struct protocol_stack; -- --#define NETCONN_IS_DATAOUT(sock) (gazelle_ring_readover_count((sock)->send_ring) || (sock)->send_pre_del) --#define NETCONN_IS_UDP(sock) (NETCONNTYPE_GROUP(netconn_type((sock)->conn)) == NETCONN_UDP) -- --/* lwip api */ --struct pbuf *do_lwip_tcp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); --struct pbuf *do_lwip_udp_get_from_sendring(struct lwip_sock *sock, uint16_t remain_size); --void do_lwip_get_from_sendring_over(struct lwip_sock *sock); --ssize_t do_lwip_read_from_lwip(struct lwip_sock *sock, int32_t flags, uint8_t apiflags); -- --/* lwip api */ --void do_lwip_free_pbuf(struct pbuf *pbuf); --struct pbuf *do_lwip_alloc_pbuf(pbuf_layer layer, uint16_t length, pbuf_type type); -- --/* lwip api */ --void do_lwip_add_recvlist(int32_t fd); --/* stack api */ --void do_lwip_read_recvlist(struct protocol_stack *stack, uint32_t max_num); -- -- --/* app api */ --ssize_t do_lwip_sendmsg_to_stack(struct lwip_sock *sock, int32_t s, -- const struct msghdr *message, int32_t flags); --ssize_t do_lwip_recvmsg_from_stack(int32_t s, const struct msghdr *message, int32_t flags); -- --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 do_lwip_read_from_stack(int32_t fd, void *buf, size_t len, int32_t flags, -- struct sockaddr *addr, socklen_t *addrlen); -- --/* stack api */ --bool do_lwip_replenish_sendring(struct protocol_stack *stack, struct lwip_sock *sock); -- --void do_lwip_clone_sockopt(struct lwip_sock *dst_sock, struct lwip_sock *src_sock); -- --uint32_t do_lwip_get_conntable(struct gazelle_stat_lstack_conn_info *conn, uint32_t max_num); --uint32_t do_lwip_get_connnum(void); -- --#endif -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index c6adff0..a602610 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -284,7 +284,7 @@ struct mem_thread { - } __rte_cache_aligned; - - void mem_stack_pool_free(int stack_id); --int mem_stack_pool_init(int stack_id); -+int mem_stack_pool_init(int stack_id, unsigned numa_id); - int mem_stack_mpcache_init(int stack_id, unsigned cpu_id); - - int mem_thread_manager_init(void); -diff --git a/src/lstack/include/lstack_protocol_stack.h b/src/lstack/include/lstack_protocol_stack.h -index b77d5da..8653fb0 100644 ---- a/src/lstack/include/lstack_protocol_stack.h -+++ b/src/lstack/include/lstack_protocol_stack.h -@@ -29,12 +29,6 @@ - #include "lstack_ethdev.h" - #include "lstack_tx_cache.h" - --#define SOCK_RECV_RING_SIZE (get_global_cfg_params()->recv_ring_size) --#define SOCK_RECV_RING_SIZE_MAX (2048) --#define SOCK_SEND_RING_SIZE_MAX (2048) -- --#define MBUFPOOL_RESERVE_NUM (2 * get_global_cfg_params()->rxqueue_size + 1024) -- - struct protocol_stack { - uint32_t tid; - uint16_t queue_id; -@@ -52,7 +46,6 @@ struct protocol_stack { - volatile bool low_power; - volatile uint16_t conn_num; - -- struct rte_mempool *rxtx_mbuf_pool; - struct rte_ring *rx_ring; - struct rte_ring *tx_ring; - struct rte_ring *reg_ring; -@@ -68,9 +61,6 @@ struct protocol_stack { - rpc_queue rpc_queue; - char pad2 __rte_cache_aligned; - -- struct list_node recv_list; -- struct list_node same_node_recv_list; /* used for same node processes communication */ -- - struct stats_ *lwip_stats; - struct gazelle_stack_latency latency; - struct gazelle_stack_stat stats; -@@ -88,7 +78,6 @@ struct protocol_stack_group { - struct protocol_stack *stacks[PROTOCOL_STACK_MAX]; - - sem_t sem_listen_thread; -- struct rte_mempool *total_rxtx_pktmbuf_pool[PROTOCOL_STACK_MAX]; - sem_t sem_stack_setup; - bool stack_setup_fail; - -diff --git a/src/lstack/include/lstack_rtc_api.h b/src/lstack/include/lstack_rtc_api.h -deleted file mode 100644 -index b4b7e1c..0000000 ---- a/src/lstack/include/lstack_rtc_api.h -+++ /dev/null -@@ -1,25 +0,0 @@ --/* --* Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. --* gazelle is licensed under the Mulan PSL v2. --* You can use this software according to the terms and conditions of the Mulan PSL v2. --* You may obtain a copy of Mulan PSL v2 at: --* http://license.coscl.org.cn/MulanPSL2 --* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR --* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR --* PURPOSE. --* See the Mulan PSL v2 for more details. --*/ -- --#ifndef _LSTACK_RTC_API_H_ --#define _LSTACK_RTC_API_H_ -- --#include -- --/* don't include lwip/sockets.h, conflict with sys/socket.h */ --extern int lwip_fcntl(int s, int cmd, int val); --extern int lwip_ioctl(int s, long cmd, void *argp); -- --void dummy_api_init(posix_api_t *api); --void rtc_api_init(posix_api_t *api); -- --#endif /* __LSTACK_RTC_API_H_ */ -diff --git a/src/lstack/include/lstack_rtw_api.h b/src/lstack/include/lstack_sock_dummy.h -similarity index 77% -rename from src/lstack/include/lstack_rtw_api.h -rename to src/lstack/include/lstack_sock_dummy.h -index 437901a..99491d1 100644 ---- a/src/lstack/include/lstack_rtw_api.h -+++ b/src/lstack/include/lstack_sock_dummy.h -@@ -10,11 +10,9 @@ - * See the Mulan PSL v2 for more details. - */ - --#ifndef _LSTACK_RTW_API_H_ --#define _LSTACK_RTW_API_H_ -+#ifndef _LSTACK_SOCK_DUMMY_H_ -+#define _LSTACK_SOCK_DUMMY_H_ - --#include -+void sock_dummy_api_init(posix_api_t *api); - --void rtw_api_init(posix_api_t *api); -- --#endif /* _LSTACK_RTW_API_H_ */ -+#endif /* _LSTACK_SOCK_DUMMY_H_ */ -diff --git a/src/lstack/include/lstack_stack_stat.h b/src/lstack/include/lstack_stack_stat.h -index ef33365..e6e6abd 100644 ---- a/src/lstack/include/lstack_stack_stat.h -+++ b/src/lstack/include/lstack_stack_stat.h -@@ -13,30 +13,26 @@ - #ifndef GAZELLE_STACK_STAT_H - #define GAZELLE_STACK_STAT_H - -+#include -+#include -+ - struct gazelle_stack_latency; --struct pbuf; - struct rpc_msg; - struct gazelle_stat_low_power_info; --struct wakeup_poll; --struct protocol_stack; - enum GAZELLE_LATENCY_TYPE; - enum GAZELLE_STAT_MODE; - struct gazelle_stat_msg_request; --struct lwip_sock; - --void calculate_lstack_latency(struct gazelle_stack_latency *stack_latency, const struct pbuf *pbuf, -+void calculate_lstack_latency(int stack_id, struct pbuf *const *pbuf, uint32_t num, - enum GAZELLE_LATENCY_TYPE type, uint64_t time_record); --void calculate_sock_latency(struct gazelle_stack_latency *stack_latency, struct lwip_sock *sock, -- enum GAZELLE_LATENCY_TYPE type); -+void calculate_sock_latency(struct lwip_sock *sock, enum GAZELLE_LATENCY_TYPE type); - void stack_stat_init(void); - int handle_stack_cmd(int fd, struct gazelle_stat_msg_request *msg); - int handle_dpdk_cmd(int fd, enum GAZELLE_STAT_MODE stat_mode); - void lstack_get_low_power_info(struct gazelle_stat_low_power_info *low_power_info); --void unregister_wakeup(struct protocol_stack *stack, struct wakeup_poll *wakeup); - void lstack_calculate_aggregate(int type, uint32_t len); --void time_stamp_transfer_pbuf(struct pbuf *pbuf_old, struct pbuf *pbuf_new); -+void time_stamp_into_write(struct pbuf *pbufs[], uint32_t num); - void time_stamp_into_rpcmsg(struct lwip_sock *sock); --void time_stamp_into_recvmbox(struct lwip_sock *sock); - void time_stamp_record(int fd, struct pbuf *pbuf); - - #endif /* GAZELLE_STACK_STAT_H */ -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 427a519..32dde53 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -26,8 +26,6 @@ - #define MSG_ARG_4 (4) - #define RPM_MSG_ARG_SIZE (5) - --#define RPC_MEMPOOL_THREAD_NUM 64 -- - typedef struct rpc_queue rpc_queue; - struct rpc_queue { - struct lockless_queue queue; -@@ -38,6 +36,7 @@ struct rpc_stats { - uint16_t call_null; - uint64_t call_alloc_fail; - }; -+struct rpc_stats *rpc_stats_get(void); - - union rpc_msg_arg { - int i; -@@ -52,62 +51,34 @@ union rpc_msg_arg { - struct rpc_msg; - typedef void (*rpc_func_t)(struct rpc_msg *msg); - struct rpc_msg { -- int8_t sync_flag : 1; -- int8_t recall_flag : 1; -+#define RPC_MSG_SYNC 0x01 -+#define RPC_MSG_FREE 0x02 -+#define RPC_MSG_EXIT 0x04 -+#define RPC_MSG_RECALL 0x08 -+#define RPC_MSG_REUSE 0x10 -+ int flags; -+ int stack_id; /* the stack to which buf belongs */ - - long result; /* func return val */ - rpc_func_t func; /* msg handle func hook */ - union rpc_msg_arg args[RPM_MSG_ARG_SIZE]; /* resolve by type */ - -- struct rpc_msg_pool { -- struct rte_mempool *mempool; -- } *rpcpool; -- - pthread_spinlock_t lock; /* msg handler unlock notice sender msg process done */ - lockless_queue_node queue_node; - }; - --static inline void rpc_queue_init(rpc_queue *queue, uint16_t queue_id) --{ -- lockless_queue_init(&queue->queue); -- queue->queue_id = queue_id; --} --struct rpc_stats *rpc_stats_get(void); -+struct rpc_msg *rpc_msg_alloc(int stack_id, rpc_func_t func); -+void rpc_msg_free(struct rpc_msg *msg); -+ -+void rpc_queue_init(rpc_queue *queue, uint16_t queue_id); - int rpc_msgcnt(rpc_queue *queue); - int rpc_poll_msg(rpc_queue *queue, int max_num); - --int rpc_call_stack_exit(rpc_queue *queue); -- --/* #include will conflict with lwip/sockets.h */ --struct sockaddr; -- --int rpc_call_close(rpc_queue *queue, int fd); --int rpc_call_shutdown(rpc_queue *queue, int fd, int how); --int rpc_call_socket(rpc_queue *queue, int domain, int type, int protocol); --int rpc_call_bind(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); --int rpc_call_listen(rpc_queue *queue, int s, int backlog); --int rpc_call_shadow_fd(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); --int rpc_call_accept(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags); --int rpc_call_connect(rpc_queue *queue, int fd, const struct sockaddr *addr, socklen_t addrlen); -- --int rpc_call_getpeername(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); --int rpc_call_getsockname(rpc_queue *queue, int fd, struct sockaddr *addr, socklen_t *addrlen); --int rpc_call_getsockopt(rpc_queue *queue, int fd, int level, int optname, void *optval, socklen_t *optlen); --int rpc_call_setsockopt(rpc_queue *queue, int fd, int level, int optname, const void *optval, socklen_t optlen); -- --int rpc_call_tcp_send(rpc_queue *queue, int fd, size_t len, int flags); --int rpc_call_udp_send(rpc_queue *queue, int fd, size_t len, int flags); -- --int rpc_call_replenish(rpc_queue *queue, void *sock); --int rpc_call_recvlistcnt(rpc_queue *queue); -- --int rpc_call_arp(rpc_queue *queue, void *mbuf); -- --int rpc_call_conntable(rpc_queue *queue, void *conn_table, unsigned max_conn); --int rpc_call_connnum(rpc_queue *queue); --int rpc_call_mbufpoolsize(rpc_queue *queue); -+int rpc_sync_call(rpc_queue *queue, struct rpc_msg *msg); -+void rpc_async_call(rpc_queue *queue, struct rpc_msg *msg, int flags); - --int rpc_call_thread_regphase1(rpc_queue *queue, void *conn); --int rpc_call_thread_regphase2(rpc_queue *queue, void *conn); -+int rpc_call_conntable(int stack_id, void *conn_table, unsigned max_conn); -+int rpc_call_connnum(int stack_id); -+int rpc_call_arp(int stack_id, void *mbuf); - - #endif -diff --git a/src/lstack/include/mbox_ring.h b/src/lstack/include/mbox_ring.h -index c48a47b..7ffdcf4 100644 ---- a/src/lstack/include/mbox_ring.h -+++ b/src/lstack/include/mbox_ring.h -@@ -285,7 +285,7 @@ int mt_ring_create(struct mbox_ring *mr, const char *name, unsigned count) - mr->ops = &g_mbox_rtw_default_ops; - mr->st_obj = NULL; - } -- if ((mr->flags & MBOX_FLAG_RECV) && !dpdk_nic_is_xdp()) { -+ if ((mr->flags & MBOX_FLAG_RECV) && !xdp_eth_enabled()) { - mr->flags |= MBOX_FLAG_PEEK; - mr->ops = &g_mbox_rtw_peek_ops; - mr->ops->create(mr, name, count); -diff --git a/src/lstack/include/same_node.h b/src/lstack/include/same_node.h -index 90a5b76..a7ae64d 100644 ---- a/src/lstack/include/same_node.h -+++ b/src/lstack/include/same_node.h -@@ -19,7 +19,6 @@ - - unsigned same_node_ring_count(const struct lwip_sock *sock); - --void read_same_node_recv_list(struct protocol_stack *stack); - ssize_t gazelle_same_node_ring_recv(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags); - ssize_t gazelle_same_node_ring_send(struct lwip_sock *sock, const void *buf, size_t len, int32_t flags); - -diff --git a/src/lstack/netif/lstack_ethdev.c b/src/lstack/netif/lstack_ethdev.c -index a370714..f2ec977 100644 ---- a/src/lstack/netif/lstack_ethdev.c -+++ b/src/lstack/netif/lstack_ethdev.c -@@ -31,16 +31,13 @@ - #include "lstack_stack_stat.h" - #include "lstack_log.h" - #include "lstack_dpdk.h" --#include "lstack_lwip.h" - #include "lstack_protocol_stack.h" - #include "lstack_thread_rpc.h" - #include "lstack_flow.h" - #include "lstack_tx_cache.h" - #include "lstack_virtio.h" - #include "lstack_ethdev.h" -- --/* FRAME_MTU + 14byte header */ --#define MBUF_MAX_LEN 1514 -+#include "lstack_mempool.h" - - /* any protocol stack thread receives arp packet and sync it to other threads, - * so that it can have the arp table */ -@@ -62,23 +59,23 @@ static void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cu - continue; - } - -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -+ ret = mem_get_mbuf_bulk(stack->stack_idx, &mbuf_copy, 1, true); -+ if (ret == 0) { - stack->stats.rx_allocmbuf_fail++; - return; - } - copy_mbuf(mbuf_copy, mbuf); - -- ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ ret = rpc_call_arp(stack->stack_idx, mbuf_copy); - if (ret != 0) { -- rte_pktmbuf_free(mbuf_copy); -+ mem_put_mbuf_bulk(&mbuf_copy, 1); - return; - } - } - #if RTE_VERSION < RTE_VERSION_NUM(23, 11, 0, 0) - if (get_global_cfg_params()->kni_switch) { -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -+ ret = mem_get_mbuf_bulk(cur_stack->stack_idx, &mbuf_copy, 1, true); -+ if (ret == 0) { - cur_stack->stats.rx_allocmbuf_fail++; - return; - } -@@ -87,8 +84,8 @@ static void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cu - } - #endif - if (get_global_cfg_params()->flow_bifurcation) { -- ret = dpdk_alloc_pktmbuf(cur_stack->rxtx_mbuf_pool, &mbuf_copy, 1, true); -- if (ret != 0) { -+ ret = mem_get_mbuf_bulk(cur_stack->stack_idx, &mbuf_copy, 1, true); -+ if (ret == 0) { - cur_stack->stats.rx_allocmbuf_fail++; - return; - } -@@ -100,12 +97,10 @@ static void stack_broadcast_arp(struct rte_mbuf *mbuf, struct protocol_stack *cu - - void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - { -- int32_t ret; -- void *payload = NULL; -+ int ret; - struct pbuf *next = NULL; - struct pbuf *prev = NULL; - struct pbuf *head = NULL; -- struct pbuf_custom *pc = NULL; - struct rte_mbuf *m = mbuf; - uint16_t len, pkt_len; - struct rte_mbuf *next_m = NULL; -@@ -114,14 +109,9 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - - while (m != NULL) { - len = (uint16_t)rte_pktmbuf_data_len(m); -- payload = rte_pktmbuf_mtod(m, void *); -- pc = mbuf_to_pbuf(m); -- next = pbuf_alloced_custom(PBUF_RAW, (uint16_t)len, PBUF_RAM, pc, payload, (uint16_t)len); -- if (next == NULL) { -- stack->stats.rx_allocmbuf_fail++; -- break; -- } -- next->tot_len = pkt_len; -+ next = mbuf_to_pbuf(m); -+ mem_init_pbuf(next, PBUF_RAW, pkt_len, len, PBUF_POOL); -+ - pkt_len -= len; - - if (head == NULL) { -@@ -135,6 +125,8 @@ void eth_dev_recv(struct rte_mbuf *mbuf, struct protocol_stack *stack) - next_m = m->next; - m->next = NULL; - m = next_m; -+ -+ mem_preput_pbuf(next); - } - - if (head != NULL) { -@@ -291,15 +283,16 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - struct protocol_stack *stack = get_protocol_stack(); - struct rte_mbuf *pre_mbuf = NULL; - struct rte_mbuf *first_mbuf = NULL; -+ struct rte_mbuf *mbuf; - void *buf_addr; - - while (likely(pbuf != NULL)) { -- struct rte_mbuf *mbuf = pbuf_to_mbuf(pbuf); -- -+ mbuf = pbuf_to_mbuf(pbuf); -+ // rte_mbuf_refcnt_set(mbuf, pbuf->ref + 1); -+ rte_mbuf_refcnt_update(mbuf, 1); - mbuf->data_len = pbuf->len; - mbuf->pkt_len = pbuf->tot_len; - mbuf->next = NULL; -- buf_addr = rte_pktmbuf_mtod(mbuf, void *); - - /* - * |rte_mbuf | mbuf_private | data_off | data | -@@ -307,6 +300,7 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - * buf_addr payload - * m->buf_addr pointer pbuf->payload - */ -+ buf_addr = rte_pktmbuf_mtod(mbuf, void *); - mbuf->data_off += (uint8_t *)pbuf->payload - (uint8_t *)buf_addr; - - if (first_mbuf == NULL) { -@@ -316,26 +310,19 @@ static err_t eth_dev_output(struct netif *netif, struct pbuf *pbuf) - first_mbuf->nb_segs++; - pre_mbuf->next = mbuf; - } -- -- if (likely(first_mbuf->pkt_len > MBUF_MAX_LEN)) { -- mbuf->ol_flags |= RTE_MBUF_F_TX_TCP_SEG; -- mbuf->tso_segsz = MBUF_MAX_DATA_LEN; -- } -- - pre_mbuf = mbuf; -- rte_mbuf_refcnt_update(mbuf, 1); - -- if (get_protocol_stack_group()->latency_start) { -- calculate_lstack_latency(&stack->latency, pbuf, GAZELLE_LATENCY_WRITE_LSTACK, 0); -- } -+ if (get_protocol_stack_group()->latency_start) -+ calculate_lstack_latency(stack->stack_idx, &pbuf, 1, GAZELLE_LATENCY_WRITE_LSTACK, 0); -+ - pbuf = pbuf->next; - } - - uint32_t sent_pkts = stack->dev_ops.tx_xmit(stack, &first_mbuf, 1); - stack->stats.tx += sent_pkts; - if (sent_pkts < 1) { -+ mem_put_mbuf_bulk(&first_mbuf, 1); - stack->stats.tx_drop++; -- rte_pktmbuf_free(first_mbuf); - return ERR_MEM; - } - -@@ -349,7 +336,7 @@ static err_t eth_dev_init(struct netif *netif) - netif->name[0] = 'e'; - netif->name[1] = 't'; - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; -- netif->mtu = FRAME_MTU; -+ netif->mtu = GAZELLE_IP_MTU; - netif->output = etharp_output; - netif->linkoutput = eth_dev_output; - netif->output_ip6 = ethip6_output; -@@ -368,18 +355,11 @@ static err_t eth_dev_init(struct netif *netif) - RTE_ETH_RX_OFFLOAD_UDP_CKSUM | - RTE_ETH_RX_OFFLOAD_IPV4_CKSUM); - netif_set_txol_flags(netif, RTE_ETH_TX_OFFLOAD_TCP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_TSO); -- /* 16: see kernel MAX_SKB_FRAGS define in skbuff.h */ -- netif_set_max_pbuf_frags(netif, 16); -+ netif_set_max_pbuf_frags(netif, OFFLOAD_TX_TSO_4K_FRAGS); - } else { - netif_set_rxol_flags(netif, get_protocol_stack_group()->rx_offload); - netif_set_txol_flags(netif, get_protocol_stack_group()->tx_offload); -- /* 40: dpdk pmd support 40 max segs */ -- netif_set_max_pbuf_frags(netif, 40); -- } -- netif_set_min_tso_seglen(netif, 256); -- -- if (get_global_cfg_params()->stack_mode_rtc) { -- netif_set_rtc_mode(netif); -+ netif_set_max_pbuf_frags(netif, OFFLOAD_TX_TSO_MTU_FRAGS); - } - - return ERR_OK; -@@ -400,7 +380,7 @@ int32_t ethdev_init(struct protocol_stack *stack) - - if (use_ltran()) { - stack->rx_ring_used = 0; -- int32_t ret = fill_mbuf_to_ring(stack->rxtx_mbuf_pool, stack->rx_ring, RING_SIZE(VDEV_RX_QUEUE_SZ)); -+ int32_t ret = fill_mbuf_to_ring(stack->stack_idx, stack->rx_ring, RING_SIZE(VDEV_RX_QUEUE_SZ)); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "fill mbuf to rx_ring failed ret=%d\n", ret); - return ret; -diff --git a/src/lstack/netif/lstack_fault_inject.c b/src/lstack/netif/lstack_fault_inject.c -index 9fae745..59eb8bd 100644 ---- a/src/lstack/netif/lstack_fault_inject.c -+++ b/src/lstack/netif/lstack_fault_inject.c -@@ -161,10 +161,8 @@ static int32_t inject_packet_loss_random(struct protocol_stack *stack, struct rt - if (rand_num > boundary) { - return nr_pkts; - } -- -- for (int32_t i = 0; i < nr_pkts; ++i) { -- rte_pktmbuf_free(pkts[i]); -- } -+ -+ mem_put_mbuf_bulk(pkts, nr_pkts); - return nr_pkts; - } - -@@ -184,7 +182,7 @@ static int32_t inject_packet_duplicate_random(struct protocol_stack *stack, stru - return nr_pkts; - } - -- struct rte_mempool *mp = stack->rxtx_mbuf_pool; -+ struct rte_mempool *mp = mem_get_mbuf_pool(stack->stack_idx); - struct rte_mbuf *mbuf_clone = NULL; - int32_t ret = 0; - -@@ -192,14 +190,14 @@ static int32_t inject_packet_duplicate_random(struct protocol_stack *stack, stru - int32_t count = count_max; - while (count--) { - mbuf_clone = rte_pktmbuf_clone(pkts[i], mp); -- rte_pktmbuf_free(pkts[i]); -+ mem_put_mbuf_bulk(&pkts[i], 1); - if (mbuf_clone == NULL) { - LSTACK_LOG(ERR, LSTACK, "fault inject mbuf_clone fail.\n"); - return 0; - } - ret = vdev_tx_xmit(stack, &mbuf_clone, 1); - if (ret < 1) { -- rte_pktmbuf_free(mbuf_clone); -+ mem_put_mbuf_bulk(&mbuf_clone, 1); - return ret; - } - } -@@ -215,7 +213,7 @@ static int32_t send_reorder_array(struct protocol_stack *stack) - for (int32_t i = 0; i < g_reorder[idx].cur_cnt; ++i) { - ret = vdev_tx_xmit(stack, g_reorder[idx].array + i, 1); - if (ret < 1) { -- rte_pktmbuf_free(*(g_reorder[idx].array + i)); -+ mem_put_mbuf_bulk(g_reorder[idx].array + i, 1); - } - } - g_reorder[idx].cur_cnt = 0; -@@ -239,7 +237,7 @@ static int32_t inject_packet_reorder_random(struct protocol_stack *stack, struct - return nr_pkts; - } - -- struct rte_mempool *mp = stack->rxtx_mbuf_pool; -+ struct rte_mempool *mp = mem_get_mbuf_pool(stack->stack_idx); - struct rte_mbuf *mbuf_clone = NULL; - int32_t idx = stack->stack_idx; - for (int32_t i = 0; i < nr_pkts; ++i) { -@@ -251,8 +249,8 @@ static int32_t inject_packet_reorder_random(struct protocol_stack *stack, struct - } - *(g_reorder[idx].array + g_reorder[idx].cur_cnt++) = mbuf_clone; - /* func rte_pktmbuf_clone will add refcnt of mbuf, so following operation will free mbuf double */ -- rte_pktmbuf_free(pkts[i]); -- rte_pktmbuf_free(pkts[i]); -+ mem_put_mbuf_bulk(&pkts[i], 1); -+ mem_put_mbuf_bulk(&pkts[i], 1); - } else { - send_reorder_array(stack); - } -diff --git a/src/lstack/netif/lstack_flow.c b/src/lstack/netif/lstack_flow.c -index ec09e45..7f2d9bd 100644 ---- a/src/lstack/netif/lstack_flow.c -+++ b/src/lstack/netif/lstack_flow.c -@@ -29,6 +29,7 @@ - #include "lstack_cfg.h" - #include "lstack_protocol_stack.h" - #include "lstack_flow.h" -+#include "lstack_mempool.h" - - #define MAX_PATTERN_NUM 4 - #define MAX_ACTION_NUM 2 -@@ -435,7 +436,7 @@ static void transfer_tcp_to_thread(struct rte_mbuf *mbuf, uint16_t stk_idx) - struct protocol_stack *stack = get_protocol_stack_group()->stacks[stk_idx]; - int ret = -1; - while (ret != 0) { -- ret = rpc_call_arp(&stack->rpc_queue, mbuf); -+ ret = rpc_call_arp(stack->stack_idx, mbuf); - printf("transfer_tcp_to_thread, ret : %d \n", ret); - } - } -@@ -449,17 +450,15 @@ static void parse_arp_and_transefer(char* buf) - int32_t ret; - for (int32_t i = 0; i < stack_group->stack_num; i++) { - stack = stack_group->stacks[i]; -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -- while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ while (mem_get_mbuf_bulk(stack->stack_idx, &mbuf_copy, 1, false) == 0) { - stack->stats.rx_allocmbuf_fail++; - } - copy_mbuf(mbuf_copy, mbuf); - -- ret = rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ ret = rpc_call_arp(stack->stack_idx, mbuf_copy); - - while (ret != 0) { -- rpc_call_arp(&stack->rpc_queue, mbuf_copy); -+ rpc_call_arp(stack->stack_idx, mbuf_copy); - } - } - } -@@ -478,9 +477,7 @@ static void parse_tcp_and_transefer(char* buf) - struct rte_mbuf *mbuf_copy = NULL; - struct protocol_stack *stack = stack_group->stacks[stk_index]; - -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -- while (ret != 0) { -- ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, &mbuf_copy, 1, false); -+ while (mem_get_mbuf_bulk(stack->stack_idx, &mbuf_copy, 1, false) == 0) { - stack->stats.rx_allocmbuf_fail++; - } - -diff --git a/src/lstack/netif/lstack_vdev.c b/src/lstack/netif/lstack_vdev.c -index 14d8cc6..425f8dd 100644 ---- a/src/lstack/netif/lstack_vdev.c -+++ b/src/lstack/netif/lstack_vdev.c -@@ -32,12 +32,11 @@ - #include "common/dpdk_common.h" - #include "lstack_protocol_stack.h" - #include "common/gazelle_reg_msg.h" --#include "lstack_lwip.h" - #include "lstack_flow.h" - #include "lstack_vdev.h" - #include "lstack_port_map.h" - #include "lstack_virtio.h" -- -+#include "lstack_mempool.h" - #include "lstack_interrupt.h" - - /* INUSE_TX_PKTS_WATERMARK < VDEV_RX_QUEUE_SZ; -@@ -64,8 +63,8 @@ static uint32_t ltran_rx_poll(struct protocol_stack *stack, struct rte_mbuf **pk - stack->rx_ring_used += rcvd_pkts; - if (unlikely(stack->rx_ring_used >= USED_RX_PKTS_WATERMARK)) { - uint32_t free_cnt = LWIP_MIN(stack->rx_ring_used, RING_SIZE(VDEV_RX_QUEUE_SZ)); -- int32_t ret = dpdk_alloc_pktmbuf(stack->rxtx_mbuf_pool, (struct rte_mbuf **)free_buf, free_cnt, true); -- if (likely(ret == 0)) { -+ int ret = mem_get_mbuf_bulk(stack->stack_idx, (struct rte_mbuf **)free_buf, free_cnt, true); -+ if (likely(ret > 0)) { - nr_pkts = gazelle_ring_sp_enqueue(stack->rx_ring, (void **)free_buf, free_cnt); - stack->rx_ring_used -= nr_pkts; - } else { -@@ -167,9 +166,7 @@ static uint32_t ltran_tx_xmit(struct protocol_stack *stack, struct rte_mbuf **pk - do { - if (unlikely(stack->tx_ring_used >= INUSE_TX_PKTS_WATERMARK)) { - uint32_t free_pkts = gazelle_ring_sc_dequeue(stack->tx_ring, (void **)free_buf, stack->tx_ring_used); -- for (uint32_t i = 0; i < free_pkts; i++) { -- rte_pktmbuf_free(free_buf[i]); -- } -+ mem_put_mbuf_bulk(free_buf, free_pkts); - stack->tx_ring_used -= free_pkts; - } - -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index f6d1148..1722460 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -740,7 +740,6 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("app_write: %-18"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_write_cnt); - printf("write_lwip: %-17"PRIu64" ", lstack_stat->data.pkts.stack_stat.write_lwip_cnt); - printf("app_write_rpc: %-14"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.app_write_rpc); -- printf("recv_list: %-18"PRIu64" ", lstack_stat->data.pkts.recv_list_cnt); - printf("conn_num: %-19hu ", lstack_stat->data.pkts.conn_num); - - printf("kernel_events: %-14"PRIu64"\n", lstack_stat->data.pkts.wakeup_stat.kernel_events); -@@ -902,11 +901,10 @@ static void gazelle_print_lstack_stat_latency(void *buf, const struct gazelle_st - printf("Recv:\n"); - - printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_INTO_MBOX].latency_stat_result); -- printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_READ_LWIP].latency_stat_result); -- printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_READ_APP_CALL].latency_stat_result); -- printf("range: t3--->t4\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -- printf("range: t0--->t4\n%s", res[GAZELLE_LATENCY_READ_MAX].latency_stat_result); -- printf("t0: read from nic t1: into recvmbox t2: into recvring t3: app read start t4: app read end\n"); -+ printf("range: t1--->t2\n%s", res[GAZELLE_LATENCY_READ_APP_CALL].latency_stat_result); -+ printf("range: t2--->t3\n%s", res[GAZELLE_LATENCY_READ_LSTACK].latency_stat_result); -+ printf("range: t0--->t3\n%s", res[GAZELLE_LATENCY_READ_MAX].latency_stat_result); -+ printf("t0: read from nic t1: into recvmbox t2: app read start t3: app read end\n"); - - printf("Send:\n"); - printf("range: t0--->t1\n%s", res[GAZELLE_LATENCY_WRITE_INTO_RING].latency_stat_result); -@@ -1271,7 +1269,7 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - printf("Active Internet connections (servers and established)\n"); - do { - printf("\n------ stack tid: %6u ------time=%s\n", stat->tid, sys_local_time_str); -- printf("No. Proto lwip_recv recv_ring in_send send_ring cwn rcv_wnd snd_wnd snd_buf snd_nxt" -+ printf("No. Proto recvmbox recvtail sendmbox sendtail in_send cwn rcv_wnd snd_wnd snd_buf snd_nxt" - " lastack rcv_nxt events epoll_ev evlist fd Local Address" - " Foreign Address State" - " keep-alive keep-alive(idle,intvl,cnt) pingpong\n"); -@@ -1292,10 +1290,12 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); - sprintf_s(str_raddr, sizeof(str_raddr), "%s:%hu", str_rip, conn_info->r_port); -- printf("%-6utcp %-10u%-10u%-8u%-10u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -- "%-52s %-52s %s %-5d %s %d\n", -- i, conn_info->recv_cnt, conn_info->recv_ring_cnt, conn_info->in_send, -- conn_info->send_ring_cnt, conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, -+ printf("%-6utcp %-9u%-9u%-9u%-9u%-8u%-9d%-9d%-10d%-10d%-15u%-15u%-15u%-10x%-10x%-7d%-7d" -+ "%-52s %-52s %s %-5d %s %d\n", i, -+ conn_info->recvmbox_cnt, conn_info->recvmbox_tail, -+ conn_info->sendmbox_cnt, conn_info->sendmbox_tail, -+ conn_info->in_send, -+ conn_info->cwn, conn_info->rcv_wnd, conn_info->snd_wnd, - conn_info->snd_buf, conn_info->snd_nxt, conn_info->lastack, conn_info->rcv_nxt, conn_info->events, - conn_info->epoll_events, conn_info->eventlist, conn_info->fd, - str_laddr, str_raddr, tcp_state_to_str(conn_info->tcp_sub_state), -@@ -1304,14 +1304,14 @@ static void gazelle_print_lstack_stat_conn(void *buf, const struct gazelle_stat_ - inet_ntop(domain, lip, str_ip, sizeof(str_ip)); - sprintf_s(str_laddr, sizeof(str_laddr), "%s:%hu", str_ip, conn_info->l_port); - sprintf_s(str_raddr, sizeof(str_raddr), "%s:*", domain == AF_INET ? "0.0.0.0" : "::0"); -- printf("%-6utcp %-147u%-7d%-52s %-52s LISTEN\n", i, conn_info->recv_cnt, -+ printf("%-6utcp %-147u%-7d%-52s %-52s LISTEN\n", i, conn_info->recvmbox_cnt, - conn_info->fd, str_laddr, str_raddr); - } else { - printf("Got unknow tcp conn::%s:%5hu, state:%u\n", - inet_ntop(domain, lip, str_ip, sizeof(str_ip)), conn_info->l_port, conn_info->state); - } -- unread_pkts += conn_info->recv_ring_cnt + conn_info->recv_cnt; -- unsend_pkts += conn_info->send_ring_cnt + conn_info->in_send; -+ unread_pkts += conn_info->recvmbox_cnt; -+ unsend_pkts += conn_info->sendmbox_cnt + conn_info->in_send; - } - if (conn->conn_num > 0) { - printf("Total unread pkts:%u unsend pkts:%u\n", unread_pkts, unsend_pkts); -@@ -1479,12 +1479,6 @@ static void gazelle_print_lstack_aggregate(void *buf, const struct gazelle_stat_ - printf("tx_size_1461_8192 byte: %u\n", stats->size_1461_8192[1]); - printf("tx_size_8193_max byte: %u\n", stats->size_8193_max[1]); - -- printf("app_tx_szie_1_64: %u\n", stats->size_1_64[2]); -- printf("app_tx_size_65_512: %u\n", stats->size_65_512[2]); -- printf("app_tx_size_513_1460 byte: %u\n", stats->size_513_1460[2]); -- printf("app_tx_size_1461_8192 byte: %u\n", stats->size_1461_8192[2]); -- printf("app_tx_size_8193_max byte: %u\n", stats->size_8193_max[2]); -- - if ((dfx->eof != 0) || (ret != GAZELLE_OK)) { - break; - } -diff --git a/src/ltran/ltran_forward.c b/src/ltran/ltran_forward.c -index aef5e46..b62421a 100644 ---- a/src/ltran/ltran_forward.c -+++ b/src/ltran/ltran_forward.c -@@ -292,7 +292,7 @@ static uint32_t get_vlan_offset(const struct rte_mbuf *m) - uint32_t offset = 0; - struct rte_ether_hdr *ethh = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); - u16_t type = ethh->ether_type; -- if (type == PP_HTONS(RTE_ETHER_TYPE_VLAN)) { -+ if (type == htons(RTE_ETHER_TYPE_VLAN)) { - offset += sizeof(struct rte_vlan_hdr); - } - return offset; --- -2.33.0 - diff --git a/0330-cfg-add-mem_cache_max-and-change-default-rpc_msg_max.patch b/0330-cfg-add-mem_cache_max-and-change-default-rpc_msg_max.patch deleted file mode 100644 index e399bcd..0000000 --- a/0330-cfg-add-mem_cache_max-and-change-default-rpc_msg_max.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 9469121fdc2e20ebda9b062bb7876ae8dee921d7 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 24 Mar 2025 17:16:40 +0800 -Subject: [PATCH] cfg: add mem_cache_max and change default rpc_msg_max - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_cfg.c | 14 +++++++++++++- - src/lstack/core/lstack_mempool.c | 8 ++++---- - src/lstack/include/lstack_cfg.h | 7 ++++--- - src/lstack/include/lstack_mempool.h | 2 +- - src/lstack/lstack.conf | 9 --------- - 5 files changed, 22 insertions(+), 18 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 432e4db..78f9198 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -36,6 +36,7 @@ - #include "lstack_log.h" - #include "lstack_dpdk.h" - #include "lstack_cfg.h" -+#include "lstack_mempool.h" - - #define DEFAULT_CONF_FILE "/etc/gazelle/lstack.conf" - #define LSTACK_CONF_ENV "LSTACK_CONF_PATH" -@@ -82,6 +83,7 @@ static int32_t parse_nic_txqueue_size(void); - static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); - static int32_t parse_rpc_msg_max(void); -+static int32_t parse_mem_cache_num(void); - static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); -@@ -120,6 +122,7 @@ static struct config_vector_t g_config_tbl[] = { - { "nic_rxqueue_size", parse_nic_rxqueue_size}, - { "nic_txqueue_size", parse_nic_txqueue_size}, - { "rpc_msg_max", parse_rpc_msg_max }, -+ { "mem_cache_num", parse_mem_cache_num }, - { "app_bind_numa", parse_app_bind_numa }, - { "stack_num", parse_stack_num }, - { "num_cpus", parse_stack_cpu_number }, -@@ -1424,7 +1427,16 @@ static int32_t parse_nic_vlan_mode(void) - static int32_t parse_rpc_msg_max(void) - { - int32_t ret; -- PARSE_ARG(g_config_params.rpc_msg_max, "rpc_msg_max", 4096, 1, 8192, ret); -+ PARSE_ARG(g_config_params.rpc_msg_max, "rpc_msg_max", -+ 4096, GAZELLE_RESERVED_CLIENTS, MEMP_NUM_SYS_MBOX + GAZELLE_RESERVED_CLIENTS, ret); -+ return ret; -+} -+ -+static int32_t parse_mem_cache_num(void) -+{ -+ int32_t ret; -+ PARSE_ARG(g_config_params.mem_cache_num, "mem_cache_num", -+ MEMPOOL_CACHE_NUM, BUF_CACHE_MIN_NUM, BUF_CACHE_MAX_NUM, ret); - return ret; - } - -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 983f2f0..72c7d67 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -332,7 +332,7 @@ static const struct mempool_ops mbuf_mp_ops = { - }; - - --static struct rte_mempool *mbuf_pool_create(int stack_id, uint16_t numa_id) -+static struct rte_mempool *mbuf_pool_create(int stack_id, unsigned numa_id) - { - struct cfg_params *cfg_params = get_global_cfg_params(); - char name[RTE_MEMPOOL_NAMESIZE]; -@@ -367,7 +367,7 @@ static struct rte_mempool *mbuf_pool_create(int stack_id, uint16_t numa_id) - return pool; - } - --static struct rte_mempool *rpc_pool_create(int stack_id, uint16_t numa_id) -+static struct rte_mempool *rpc_pool_create(int stack_id, unsigned numa_id) - { - char name [RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; -@@ -478,14 +478,14 @@ int mem_thread_cache_init(struct mem_thread *mt) - char name [RTE_MEMPOOL_NAMESIZE]; - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%p", "migrate_ring", mt); - -- mt->mbuf_migrate_ring = rte_ring_create(name, BUF_CACHE_DEFAULT_NUM, -+ mt->mbuf_migrate_ring = rte_ring_create(name, BUF_CACHE_MAX_NUM, - rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); - if (mt->mbuf_migrate_ring == NULL) { - return -1; - } - } - -- mt->mbuf_cache = buf_cache_create(BUF_CACHE_DEFAULT_NUM); -+ mt->mbuf_cache = buf_cache_create(get_global_cfg_params()->mem_cache_num); - if (mt->mbuf_cache == NULL) { - mem_thread_cache_free(mt); - return -1; -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index 3e671b5..b4cdd07 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -130,12 +130,13 @@ struct cfg_params { - - uint32_t nic_read_number; - uint32_t rpc_number; -- uint32_t rpc_msg_max; - }; - - struct { // socket -- uint32_t tcp_conn_count; -- uint32_t mbuf_count_per_conn; -+ uint16_t tcp_conn_count; -+ uint16_t mbuf_count_per_conn; -+ uint16_t rpc_msg_max; -+ uint16_t mem_cache_num; - }; - - struct { // deprecated -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index a602610..848509c 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -45,7 +45,7 @@ - #define MEMPOOL_CACHE_NUM 32 - - #define BUF_CACHE_MIN_NUM 32 --#define BUF_CACHE_DEFAULT_NUM 1024 -+#define BUF_CACHE_MAX_NUM 1024 - #define BUF_CACHE_WATERSTEP_SHIFT 4 /* 1/16 */ - - #define BUF_BULK_MAX_NUM 32 -diff --git a/src/lstack/lstack.conf b/src/lstack/lstack.conf -index 490bdfc..4084ce3 100644 ---- a/src/lstack/lstack.conf -+++ b/src/lstack/lstack.conf -@@ -23,16 +23,7 @@ low_power_mode=0 - tcp_conn_count = 1500 - mbuf_count_per_conn = 170 - --# send ring size, default is 32, max is 2048 --# if udp pktlen exceeds 45952(32 * 1436)B, send_ring_size must be at least 64. --send_ring_size = 32 -- --#recv ring size, default is 128, max is 2048 --recv_ring_size = 128 -- - #protocol stack thread per loop params --#read data form protocol stack into recv_ring --read_connect_number = 4 - #process rpc msg number - rpc_number = 4 - #read nic pkts number --- -2.33.0 - diff --git a/0331-cfg-add-mem_async_mode.patch b/0331-cfg-add-mem_async_mode.patch deleted file mode 100644 index 13a8fc9..0000000 --- a/0331-cfg-add-mem_async_mode.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 9da8d8a3e4a37049793db6fac45bb98b60a612a6 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 25 Mar 2025 15:31:55 +0800 -Subject: [PATCH] cfg: add mem_async_mode - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_cfg.c | 11 +++++++++++ - src/lstack/core/lstack_mempool.c | 2 +- - src/lstack/include/lstack_cfg.h | 1 + - src/lstack/include/mbox_ring.h | 10 ++++++---- - 4 files changed, 19 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c -index 78f9198..ddb419d 100644 ---- a/src/lstack/core/lstack_cfg.c -+++ b/src/lstack/core/lstack_cfg.c -@@ -84,6 +84,7 @@ static int32_t parse_stack_thread_mode(void); - static int32_t parse_nic_vlan_mode(void); - static int32_t parse_rpc_msg_max(void); - static int32_t parse_mem_cache_num(void); -+static int32_t parse_mem_async_mode(void); - static int32_t parse_send_cache_mode(void); - static int32_t parse_flow_bifurcation(void); - static int32_t parse_stack_interrupt(void); -@@ -151,6 +152,7 @@ static struct config_vector_t g_config_tbl[] = { - { "use_sockmap", parse_use_sockmap }, - { "udp_enable", parse_udp_enable }, - { "stack_thread_mode", parse_stack_thread_mode }, -+ { "mem_async_mode", parse_mem_async_mode }, - { "nic_vlan_mode", parse_nic_vlan_mode }, - { "send_cache_mode", parse_send_cache_mode }, - { "flow_bifurcation", parse_flow_bifurcation}, -@@ -1440,6 +1442,15 @@ static int32_t parse_mem_cache_num(void) - return ret; - } - -+static int32_t parse_mem_async_mode(void) -+{ -+ // TODO -+ g_config_params.mem_async_mode = 1; -+ if (g_config_params.stack_mode_rtc || xdp_eth_enabled()) -+ g_config_params.mem_async_mode = 0; -+ return 0; -+} -+ - static int32_t parse_send_cache_mode(void) - { - int32_t ret; -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 72c7d67..eeae797 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -474,7 +474,7 @@ void mem_thread_cache_free(struct mem_thread *mt) - - int mem_thread_cache_init(struct mem_thread *mt) - { -- if (!get_global_cfg_params()->stack_mode_rtc && !xdp_eth_enabled()) { -+ if (get_global_cfg_params()->mem_async_mode) { - char name [RTE_MEMPOOL_NAMESIZE]; - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%p", "migrate_ring", mt); - -diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h -index b4cdd07..e1639a1 100644 ---- a/src/lstack/include/lstack_cfg.h -+++ b/src/lstack/include/lstack_cfg.h -@@ -137,6 +137,7 @@ struct cfg_params { - uint16_t mbuf_count_per_conn; - uint16_t rpc_msg_max; - uint16_t mem_cache_num; -+ bool mem_async_mode; - }; - - struct { // deprecated -diff --git a/src/lstack/include/mbox_ring.h b/src/lstack/include/mbox_ring.h -index 7ffdcf4..f6acdef 100644 ---- a/src/lstack/include/mbox_ring.h -+++ b/src/lstack/include/mbox_ring.h -@@ -285,10 +285,12 @@ int mt_ring_create(struct mbox_ring *mr, const char *name, unsigned count) - mr->ops = &g_mbox_rtw_default_ops; - mr->st_obj = NULL; - } -- if ((mr->flags & MBOX_FLAG_RECV) && !xdp_eth_enabled()) { -- mr->flags |= MBOX_FLAG_PEEK; -- mr->ops = &g_mbox_rtw_peek_ops; -- mr->ops->create(mr, name, count); -+ if (mr->flags & MBOX_FLAG_RECV) { -+ if (get_global_cfg_params()->mem_async_mode) { -+ mr->flags |= MBOX_FLAG_PEEK; -+ mr->ops = &g_mbox_rtw_peek_ops; -+ mr->ops->create(mr, name, count); -+ } - } - - mr->ring = rte_ring_create_fast(name, count, RING_F_SP_ENQ | RING_F_SC_DEQ); --- -2.33.0 - diff --git a/0332-mempool-add-mem_thread_cache_flush.patch b/0332-mempool-add-mem_thread_cache_flush.patch deleted file mode 100644 index f51c8a7..0000000 --- a/0332-mempool-add-mem_thread_cache_flush.patch +++ /dev/null @@ -1,617 +0,0 @@ -From 8ff71cad286a1a1952f427ce48a815322569189a Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Thu, 27 Mar 2025 15:20:02 +0800 -Subject: [PATCH] mempool: add mem_thread_cache_flush fix - PBUF_POOL_PREINIT - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_unistd.c | 20 +-- - src/lstack/core/lstack_mempool.c | 259 ++++++++++++++++++++++++---- - src/lstack/include/lstack_mempool.h | 19 +- - src/lstack/include/lstack_unistd.h | 3 + - 4 files changed, 250 insertions(+), 51 deletions(-) - -diff --git a/src/lstack/api/lstack_unistd.c b/src/lstack/api/lstack_unistd.c -index e3b9b1f..431e0a2 100644 ---- a/src/lstack/api/lstack_unistd.c -+++ b/src/lstack/api/lstack_unistd.c -@@ -58,7 +58,7 @@ bool sig_need_dump(int sig) - return true; - } - --static void pthread_block_sig(int sig) -+void pthread_block_sig(int sig) - { - sigset_t mask; - -@@ -67,6 +67,15 @@ static void pthread_block_sig(int sig) - pthread_sigmask(SIG_BLOCK, &mask, NULL); - } - -+void pthread_unblock_sig(int sig) -+{ -+ sigset_t mask; -+ -+ sigemptyset(&mask); -+ sigaddset(&mask, sig); -+ pthread_sigmask(SIG_UNBLOCK, &mask, NULL); -+} -+ - static void lstack_sigaction_default_handler(int sig, siginfo_t *info, void *context) - { - static bool skip_process_exit = false; -@@ -118,15 +127,6 @@ static void lstack_sig_default_handler(int sig) - lstack_sigaction_default_handler(sig, NULL, NULL); - } - --static void pthread_unblock_sig(int sig) --{ -- sigset_t mask; -- -- sigemptyset(&mask); -- sigaddset(&mask, sig); -- pthread_sigmask(SIG_UNBLOCK, &mask, NULL); --} -- - int lstack_signal_init(void) - { - unsigned int i; -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index eeae797..7e2a706 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -21,14 +21,18 @@ - #include "common/dpdk_common.h" - #include "lstack_dpdk.h" - #include "lstack_protocol_stack.h" -+#include "lstack_unistd.h" - --#define MEM_THREAD_MANAGER_TIMEOUT 1 --#define MEM_THREAD_MANAGER_MAX 64 -+#define MEM_THREAD_FLUSH_SIG (SIGRTMIN + 11) -+#define MEM_THREAD_MANAGER_FLUSH_MS 100 -+#define MEM_THREAD_MANAGER_FREE_S 2 -+#define MEM_THREAD_MANAGER_FREE_MAX 64 - - struct mem_thread_manager { - struct list_node mt_work_list; - struct list_node mt_free_list; - rte_spinlock_t list_lock; -+ uint32_t flush_time; - }; - - struct mem_thread_group { -@@ -36,6 +40,9 @@ struct mem_thread_group { - pthread_t thread; - struct list_node mt_node; - struct mem_thread mt_array[PROTOCOL_STACK_MAX]; -+ -+ bool used_flag; -+ uint32_t used_time; - }; - - static struct mem_stack g_mem_stack_group[PROTOCOL_STACK_MAX] = {0}; -@@ -58,11 +65,73 @@ struct rte_mempool *mem_get_rpc_pool(int stack_id) - return g_mem_stack_group[stack_id].rpc_pool; - } - --static void mem_thread_manager_add_work(struct mem_thread_group *mt_group) -+static inline bool mem_thread_group_in_used(const struct mem_thread_group *mt_grooup, uint32_t timeout) - { -- rte_spinlock_lock(&g_mem_thread_manager.list_lock); -- list_add_node(&mt_group->mt_node, &g_mem_thread_manager.mt_work_list); -- rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+ return mt_grooup->used_flag || -+ (sys_now() - mt_grooup->used_time < timeout); -+} -+ -+static inline void mem_thread_group_used(void) -+{ -+ g_mem_thread_group->used_flag = true; -+ g_mem_thread_group->used_time = sys_now(); -+} -+ -+static inline void mem_thread_group_done(void) -+{ -+ g_mem_thread_group->used_flag = false; -+} -+ -+static void mem_thread_cache_flush(struct mem_thread *mt); -+static unsigned mem_thread_cache_count(const struct mem_thread *mt); -+static void mem_thread_group_action_flush(int signum) -+{ -+ struct mem_thread *mt; -+ int stack_id; -+ -+ if (g_mem_thread_group == NULL) -+ return; -+ if (mem_thread_group_in_used(g_mem_thread_group, MEM_THREAD_MANAGER_FLUSH_MS)) -+ return; -+ -+ for (stack_id = 0; stack_id < PROTOCOL_STACK_MAX; stack_id++) { -+ mt = &g_mem_thread_group->mt_array[stack_id]; -+ mem_thread_cache_flush(mt); -+ } -+} -+ -+static int mem_thread_group_register_flush(void) -+{ -+ sighandler_t handler; -+ handler = signal(MEM_THREAD_FLUSH_SIG, mem_thread_group_action_flush); -+ if (handler == SIG_ERR) { -+ LSTACK_LOG(ERR, LSTACK, "signal failed\n"); -+ return -1; -+ } -+ pthread_unblock_sig(MEM_THREAD_FLUSH_SIG); -+ return 0; -+} -+ -+static inline void mem_thread_group_notify_flush(const struct mem_thread_group *mt_group, uint32_t timeout) -+{ -+ const struct mem_thread *mt; -+ int stack_id; -+ unsigned count = 0; -+ -+ if (mem_thread_group_in_used(mt_group, timeout)) -+ return; -+ -+ for (stack_id = 0; stack_id < PROTOCOL_STACK_MAX; stack_id++) { -+ mt = &mt_group->mt_array[stack_id]; -+ count += mem_thread_cache_count(mt); -+ } -+ if (count == 0) { -+ return; -+ } -+ -+ if (pthread_kill(mt_group->thread, MEM_THREAD_FLUSH_SIG) != 0) { -+ LSTACK_LOG(ERR, LSTACK, "pthread_kill tid %d failed\n", mt_group->tid); -+ } - } - - static inline bool mem_thread_group_exist(const struct mem_thread_group *mt_group) -@@ -72,6 +141,13 @@ static inline bool mem_thread_group_exist(const struct mem_thread_group *mt_grou - return true; - } - -+static void mem_thread_manager_add_work(struct mem_thread_group *mt_group) -+{ -+ rte_spinlock_lock(&g_mem_thread_manager.list_lock); -+ list_add_node(&mt_group->mt_node, &g_mem_thread_manager.mt_work_list); -+ rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+} -+ - static void mem_thread_group_free(struct mem_thread_group *mt_group) - { - struct mem_thread *mt; -@@ -100,6 +176,8 @@ static int mem_thread_group_init(int stack_id) - LSTACK_LOG(ERR, LSTACK, "alloc mem_thread_group failed, stack_id %d\n", stack_id); - return -1; - } -+ mem_thread_group_register_flush(); -+ - g_mem_thread_group->tid = rte_gettid(); - g_mem_thread_group->thread = pthread_self(); - list_init_node(&g_mem_thread_group->mt_node); -@@ -107,7 +185,7 @@ static int mem_thread_group_init(int stack_id) - } - - mt = &g_mem_thread_group->mt_array[stack_id]; -- if (mem_thread_cache_init(mt) != 0) { -+ if (mem_thread_cache_init(mt, stack_id) != 0) { - LSTACK_LOG(ERR, LSTACK, "mem_thread_cache_init failed, stack_id %d\n", stack_id); - return -1; - } -@@ -133,6 +211,31 @@ static inline struct mem_thread *mem_thread_group_get(int stack_id) - return mt; - } - -+static void mem_thread_manager_flush_all(void) -+{ -+ struct list_node *node, *next; -+ struct mem_thread_group *mt_group; -+ uint32_t now = sys_now(); -+ -+ rte_spinlock_lock(&g_mem_thread_manager.list_lock); -+ -+ if (now - g_mem_thread_manager.flush_time < MEM_THREAD_MANAGER_FLUSH_MS) { -+ rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+ return; -+ } -+ g_mem_thread_manager.flush_time = now; -+ -+ list_for_each_node(node, next, &g_mem_thread_manager.mt_work_list) { -+ mt_group = container_of(node, struct mem_thread_group, mt_node); -+ /* skip myself */ -+ if (mt_group == g_mem_thread_group) -+ continue; -+ mem_thread_group_notify_flush(mt_group, MEM_THREAD_MANAGER_FLUSH_MS); -+ } -+ -+ rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -+} -+ - static void *mem_thread_manager_thread(void *arg) - { - struct list_node *node, *next; -@@ -142,9 +245,10 @@ static void *mem_thread_manager_thread(void *arg) - rte_spinlock_init(&g_mem_thread_manager.list_lock); - list_init_head(&g_mem_thread_manager.mt_work_list); - list_init_head(&g_mem_thread_manager.mt_free_list); -+ g_mem_thread_manager.flush_time = sys_now(); - - while(true) { -- sleep(MEM_THREAD_MANAGER_TIMEOUT); -+ sleep(MEM_THREAD_MANAGER_FREE_S); - - rte_spinlock_lock(&g_mem_thread_manager.list_lock); - -@@ -156,7 +260,7 @@ static void *mem_thread_manager_thread(void *arg) - - list_for_each_node(node, next, &g_mem_thread_manager.mt_work_list) { - count++; -- if (count > MEM_THREAD_MANAGER_MAX) { -+ if (count > MEM_THREAD_MANAGER_FREE_MAX) { - /* move list head after the current node, - * and start traversing from this node next time */ - list_del_node(&g_mem_thread_manager.mt_work_list); -@@ -166,6 +270,7 @@ static void *mem_thread_manager_thread(void *arg) - - mt_group = container_of(node, struct mem_thread_group, mt_node); - if (mem_thread_group_exist(mt_group)) { -+ mem_thread_group_notify_flush(mt_group, MEM_THREAD_MANAGER_FREE_S * MS_PER_S); - continue; - } - list_del_node(node); -@@ -183,8 +288,7 @@ int mem_thread_manager_init(void) - return thread_create("gzmempool", 0, mem_thread_manager_thread, NULL); - } - --static __rte_always_inline --struct mem_thread *mem_thread_get(int stack_id) -+static inline struct mem_thread *mem_thread_get(int stack_id) - { - /* stack thread uses mbufpool_cache instead of buf_cache */ - if (get_protocol_stack() != NULL) -@@ -443,42 +547,97 @@ unsigned mem_stack_mbuf_pool_count(int stack_id) - return rte_mempool_avail_count(ms->mbuf_pool); - } - --void mem_thread_cache_free(struct mem_thread *mt) -+static void mem_thread_cache_flush(struct mem_thread *mt) - { -- void *obj; -+ struct mem_stack *ms = mem_stack_get(mt->stack_id); -+ void *obj_table[BUF_BULK_MAX_NUM]; -+ unsigned num; - - if (mt->mbuf_migrate_ring != NULL) { -- while (rte_ring_sc_dequeue(mt->mbuf_migrate_ring, &obj) == 0) { -- mem_put_mbuf_bulk((struct rte_mbuf **)&obj, 1); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(mem_thread=%p, stack_id=%d, mbuf_migrate_ring count=%u)\n", -+ __FUNCTION__, mt, mt->stack_id, rte_ring_count(mt->mbuf_migrate_ring))); -+ -+ while (true) { -+ num = rte_ring_sc_dequeue_burst(mt->mbuf_migrate_ring, obj_table, BUF_BULK_MAX_NUM, NULL); -+ if (num == 0) -+ break; -+ mbuf_mp_ops.put_bulk(ms->mbuf_pool, obj_table, num); - } -- rte_ring_free(mt->mbuf_migrate_ring); -- mt->mbuf_migrate_ring = NULL; - } - - if (mt->mbuf_cache != NULL) { -- while (buf_cache_pop_bulk(mt->mbuf_cache, &obj, 1, NULL) > 0) { -- mem_put_mbuf_bulk((struct rte_mbuf **)&obj, 1); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(mem_thread=%p, stack_id=%d, mbuf_cache count=%u)\n", -+ __FUNCTION__, mt, mt->stack_id, buf_cache_count(mt->mbuf_cache))); -+ -+ while (true) { -+ num = LWIP_MIN(buf_cache_count(mt->mbuf_cache), BUF_BULK_MAX_NUM); -+ num = buf_cache_pop_bulk(mt->mbuf_cache, obj_table, num, NULL); -+ if (num == 0) -+ break; -+ mbuf_mp_ops.put_bulk(ms->mbuf_pool, obj_table, num); - } -- buf_cache_free(mt->mbuf_cache); -- mt->mbuf_cache = NULL; -+ buf_cache_reset_watermark(mt->mbuf_cache); - } - - if (mt->rpc_cache != NULL) { -- while (buf_cache_pop_bulk(mt->rpc_cache, &obj, 1, NULL) > 0) { -- mem_put_rpc(obj); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(mem_thread=%p, stack_id=%d, rpc_cache count=%u)\n", -+ __FUNCTION__, mt, mt->stack_id, buf_cache_count(mt->rpc_cache))); -+ -+ while (true) { -+ num = LWIP_MIN(buf_cache_count(mt->rpc_cache), BUF_BULK_MAX_NUM); -+ num = buf_cache_pop_bulk(mt->rpc_cache, obj_table, num, NULL); -+ if (num == 0) -+ break; -+ mem_mp_ops.put_bulk(ms->rpc_pool, obj_table, num); - } -+ buf_cache_reset_watermark(mt->rpc_cache); -+ } -+} -+ -+static unsigned mem_thread_cache_count(const struct mem_thread *mt) -+{ -+ unsigned count = 0; -+ -+ if (mt->mbuf_migrate_ring != NULL) { -+ count += rte_ring_count(mt->mbuf_migrate_ring); -+ } -+ if (mt->mbuf_cache != NULL) { -+ count += buf_cache_count(mt->mbuf_cache); -+ } -+ if (mt->rpc_cache != NULL) { -+ count += buf_cache_count(mt->rpc_cache); -+ } -+ return count; -+} -+ -+void mem_thread_cache_free(struct mem_thread *mt) -+{ -+ mem_thread_cache_flush(mt); -+ -+ if (mt->mbuf_migrate_ring != NULL) { -+ rte_ring_free(mt->mbuf_migrate_ring); -+ mt->mbuf_migrate_ring = NULL; -+ } -+ if (mt->mbuf_cache != NULL) { -+ buf_cache_free(mt->mbuf_cache); -+ mt->mbuf_cache = NULL; -+ } -+ if (mt->rpc_cache != NULL) { - buf_cache_free(mt->rpc_cache); - mt->rpc_cache = NULL; - } - } - --int mem_thread_cache_init(struct mem_thread *mt) -+int mem_thread_cache_init(struct mem_thread *mt, int stack_id) - { -+ mt->stack_id = stack_id; -+ - if (get_global_cfg_params()->mem_async_mode) { - char name [RTE_MEMPOOL_NAMESIZE]; - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%p", "migrate_ring", mt); - -- mt->mbuf_migrate_ring = rte_ring_create(name, BUF_CACHE_MAX_NUM, -+ mt->mbuf_migrate_ring = rte_ring_create(name, -+ LWIP_MAX(get_global_cfg_params()->mem_cache_num, MIGRATE_RING_MIN_NUM), - rte_socket_id(), RING_F_SP_ENQ | RING_F_SC_DEQ); - if (mt->mbuf_migrate_ring == NULL) { - return -1; -@@ -522,9 +681,17 @@ void mem_mbuf_migrate_enqueue(struct mem_thread *mt, unsigned n) - mpcache = ms->mbuf_mpcache; - - mt->stk_migrate_count += n; -+ if (mt->stk_migrate_count < BUF_CACHE_WATERSTEP_MIN) -+ return; -+ if (mpcache->len < ms->migrate_watermark) -+ return; - -- if (mpcache->len <= ms->migrate_watermark) -+ /* no sufficient mbuf */ -+ if (rte_ring_count(ms->mbuf_pool->pool_data) < MBUFPOOL_RESERVE_NUM) { -+ mem_thread_manager_flush_all(); -+ mt->stk_migrate_count = 0; - return; -+ } - - num = LWIP_MIN(mpcache->len - ms->migrate_watermark, - mt->stk_migrate_count); -@@ -654,8 +821,8 @@ static void pool_put_bulk_with_cache(const struct mempool_ops *pool_ops, - - /* dequeue from cache, then put to the pool */ - put_count = count - cache->watermark; -- LWIP_DEBUGF(MEMP_DEBUG, ("pool_put_bulk_with_cache(cache=%p, watermark=%u, put_count=%u)\n", -- cache, cache->watermark, put_count)); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(cache=%p, watermark=%u, put_count=%u)\n", -+ __FUNCTION__, cache, cache->watermark, put_count)); - - pool_ops->put_bulk(pool, &cache->objs[cache->head - put_count], put_count); - cache->head -= put_count; -@@ -674,10 +841,12 @@ void *mem_get_rpc(int stack_id) - if (mt == NULL) { - ret = mem_mp_ops.get_bulk(ms->rpc_pool, &obj, 1); - } else { -+ mem_thread_group_used(); - ret = pool_get_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, &obj, 1); -+ mem_thread_group_done(); - } - -- LWIP_DEBUGF(MEMP_DEBUG, ("mem_get_rpc(stack_id=%d, obj=%p)\n", stack_id, obj)); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, obj=%p)\n", __FUNCTION__, stack_id, obj)); - - return ret == 0 ? NULL : obj; - } -@@ -688,12 +857,14 @@ void mem_put_rpc(void *obj) - struct mem_stack *ms = mem_stack_get(stack_id); - struct mem_thread *mt = mem_thread_get(stack_id); - -- LWIP_DEBUGF(MEMP_DEBUG, ("mem_put_rpc(stack_id=%d, obj=%p)\n", stack_id, obj)); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, obj=%p)\n", __FUNCTION__, stack_id, obj)); - - if (mt == NULL) { - mem_mp_ops.put_bulk(ms->rpc_pool, &obj, 1); - } else { -+ mem_thread_group_used(); - pool_put_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, &obj, 1); -+ mem_thread_group_done(); - } - } - -@@ -712,6 +883,7 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - * when RTE_MAX_LCORE is too large, it's time-consuming - */ - if (rte_ring_count(ms->mbuf_pool->pool_data) < MBUFPOOL_RESERVE_NUM + n) { -+ mem_thread_manager_flush_all(); - return 0; - } - } -@@ -719,14 +891,16 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - if (mt == NULL) { - ret = mbuf_mp_ops.get_bulk(ms->mbuf_pool, (void **)mbuf_table, n); - } else { -+ mem_thread_group_used(); - mem_mbuf_migrate_dequeue(mt); - ret = pool_get_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, (void **)mbuf_table, n); -+ mem_thread_group_done(); - } - - #if MEMP_DEBUG - for (unsigned i = 0; i < ret; ++i) { -- LWIP_DEBUGF(MEMP_DEBUG, ("mem_get_mbuf_bulk(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -- stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ __FUNCTION__, stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); - } - #endif /* MEMP_DEBUG */ - -@@ -745,15 +919,17 @@ static void mem_put_mbuf_bulk_by_pbuf(struct rte_mbuf *const *mbuf_table, unsign - - #if MEMP_DEBUG - for (unsigned i = 0; i < n; ++i) { -- LWIP_DEBUGF(MEMP_DEBUG, ("mem_put_mbuf_bulk(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -- stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, n=%u, mbuf_table[%u]=%p, pbuf=%p)\n", -+ __FUNCTION__, stack_id, n, i, mbuf_table[i], mbuf_to_pbuf(mbuf_table[i]))); - } - #endif /* MEMP_DEBUG */ - - if (mt == NULL) { - mbuf_mp_ops.put_bulk(ms->mbuf_pool, (void *const *)mbuf_table, n); - } else { -+ mem_thread_group_used(); - pool_put_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, (void *const *)mbuf_table, n); -+ mem_thread_group_done(); - } - - } -@@ -826,8 +1002,8 @@ struct rte_mbuf *pbuf_to_mbuf_prefree(struct pbuf *p) - struct rte_mbuf *m = pbuf_to_mbuf(p); - #if MEMP_DEBUG - if (rte_mbuf_refcnt_read(m) > 1) { -- LWIP_DEBUGF(MEMP_DEBUG, ("pbuf_to_mbuf_prefree(mbuf=%p, pbuf=%p, refcnt=%u)\n", -- m, p, rte_mbuf_refcnt_read(m))); -+ LWIP_DEBUGF(MEMP_DEBUG, ("%s(mbuf=%p, pbuf=%p, refcnt=%u)\n", -+ __FUNCTION__, m, p, rte_mbuf_refcnt_read(m))); - } - #endif /* MEMP_DEBUG */ - if (p->mbuf_refcnt != 1) { -@@ -868,6 +1044,9 @@ void mem_put_pbuf_list_bulk(struct pbuf *const *pbuf_table, unsigned n) - struct pbuf *q, *next; - struct rte_mbuf *mbuf; - -+ if (mt != NULL) -+ mem_thread_group_used(); -+ - for (unsigned i = 0; i < n; ++i) { - q = pbuf_table[i]; - while (q != NULL) { -@@ -893,6 +1072,10 @@ void mem_put_pbuf_list_bulk(struct pbuf *const *pbuf_table, unsigned n) - __FUNCTION__, stack_id, n, i, mbuf, q)); - } - } -+ -+ if (mt != NULL) -+ mem_thread_group_done(); -+ return; - } - - struct pbuf *mem_get_pbuf(int stack_id, bool reserve) -@@ -1001,7 +1184,9 @@ void mem_init_pbuf(struct pbuf *p, pbuf_layer layer, uint16_t tot_len, uint16_t - struct rte_mbuf *mbuf; - void *data; - -- if (p->type_internal == PBUF_POOL_PREINIT) { -+ /* PBUF_POOL_PREINIT maybe give back to mbuf_pool, and alloc to NIC rx. -+ * so ignore PBUF_POOL_PREINIT at this time. */ -+ if (layer == PBUF_TRANSPORT && p->type_internal == PBUF_POOL_PREINIT) { - p->payload = (uint8_t *)p->payload + LWIP_MEM_ALIGN_SIZE((uint16_t)layer); - p->type_internal = type; - p->len = len; -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index 848509c..e636fda 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -44,12 +44,15 @@ - #define MEMPOOL_OPS_NAME "ring_mt_rts" - #define MEMPOOL_CACHE_NUM 32 - --#define BUF_CACHE_MIN_NUM 32 -+#define BUF_CACHE_MIN_NUM 16 - #define BUF_CACHE_MAX_NUM 1024 - #define BUF_CACHE_WATERSTEP_SHIFT 4 /* 1/16 */ -+#define BUF_CACHE_WATERSTEP_MIN 4 - - #define BUF_BULK_MAX_NUM 32 - -+#define MIGRATE_RING_MIN_NUM (BUF_CACHE_MIN_NUM << 1) -+ - struct buf_cache { - unsigned size; /* Size of cache. */ - unsigned mask; /* Mask (size-1) of cache. */ -@@ -91,8 +94,8 @@ struct buf_cache *buf_cache_create(unsigned count) - cache->tail = 0; - - cache->waterstep = cache->size >> BUF_CACHE_WATERSTEP_SHIFT; -- if (cache->waterstep < BUF_CACHE_WATERSTEP_SHIFT) -- cache->waterstep = BUF_CACHE_WATERSTEP_SHIFT; -+ if (cache->waterstep < BUF_CACHE_WATERSTEP_MIN) -+ cache->waterstep = BUF_CACHE_WATERSTEP_MIN; - cache->watermark = cache->waterstep; - cache->flushthresh = cache->size - cache->waterstep; - -@@ -142,6 +145,12 @@ void buf_cache_sub_watermark(struct buf_cache *cache) - } - } - -+static __rte_always_inline -+void buf_cache_reset_watermark(struct buf_cache *cache) -+{ -+ cache->watermark = cache->waterstep; -+} -+ - static __rte_always_inline - void __buf_cache_copy_objs(void ** dst_table, void *const *src_table, unsigned n) - { -@@ -273,6 +282,8 @@ struct mem_stack { - }; - - struct mem_thread { -+ int stack_id; -+ - struct buf_cache *rpc_cache; - - struct buf_cache *mbuf_cache; -@@ -289,7 +300,7 @@ int mem_stack_mpcache_init(int stack_id, unsigned cpu_id); - - int mem_thread_manager_init(void); - void mem_thread_cache_free(struct mem_thread *mt); --int mem_thread_cache_init(struct mem_thread *mt); -+int mem_thread_cache_init(struct mem_thread *mt, int stack_id); - - unsigned mem_stack_mbuf_pool_count(int stack_id); - struct rte_mempool *mem_get_mbuf_pool(int stack_id); -diff --git a/src/lstack/include/lstack_unistd.h b/src/lstack/include/lstack_unistd.h -index 3bcee5a..397cd19 100644 ---- a/src/lstack/include/lstack_unistd.h -+++ b/src/lstack/include/lstack_unistd.h -@@ -16,6 +16,9 @@ - #include - #include - -+void pthread_block_sig(int sig); -+void pthread_unblock_sig(int sig); -+ - int lstack_signal_init(void); - int lstack_sigaction(int sig_num, const struct sigaction *action, struct sigaction *old_action); - pid_t lstack_fork(void); --- -2.33.0 - diff --git a/0333-dfx-support-sk_wait-stat.patch b/0333-dfx-support-sk_wait-stat.patch deleted file mode 100644 index ebd305d..0000000 --- a/0333-dfx-support-sk_wait-stat.patch +++ /dev/null @@ -1,526 +0,0 @@ -From 4884431653c978adfc03053e1803dd93b58ca3a0 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 1 Apr 2025 20:50:08 +0800 -Subject: [PATCH] dfx: support sk_wait stat - -Signed-off-by: Lemmy Huang ---- - src/common/gazelle_dfx_msg.h | 27 ++++++++-------- - src/lstack/api/lstack_sockctl.c | 7 ++-- - src/lstack/api/lstack_sockio.c | 45 +++++++++++++++++--------- - src/lstack/core/lstack_mempool.c | 18 +++++++---- - src/lstack/core/lstack_stack_stat.c | 12 +++---- - src/lstack/core/lstack_thread_rpc.c | 16 ++++----- - src/lstack/core/lstack_wait.c | 15 ++++++--- - src/lstack/include/lstack_mempool.h | 3 +- - src/lstack/include/lstack_thread_rpc.h | 9 ++---- - src/lstack/include/lstack_wait.h | 4 ++- - src/ltran/ltran_dfx.c | 31 ++++++++---------- - 11 files changed, 105 insertions(+), 82 deletions(-) - -diff --git a/src/common/gazelle_dfx_msg.h b/src/common/gazelle_dfx_msg.h -index 2c6462d..2f1066d 100644 ---- a/src/common/gazelle_dfx_msg.h -+++ b/src/common/gazelle_dfx_msg.h -@@ -94,31 +94,33 @@ enum GAZELLE_TCP_LIST_STATE { - }; - - struct gazelle_stack_stat { -+ uint32_t conn_num; -+ uint32_t mbuf_pool_cnt; - uint64_t wakeup_events; -- uint64_t write_lwip_cnt; -- uint64_t send_pkts_fail; -- uint64_t read_lwip_drop; -- uint64_t read_lwip_cnt; - uint64_t rx_allocmbuf_fail; - uint64_t tx_allocmbuf_fail; -- uint64_t call_null; - uint64_t rx_drop; - uint64_t rx; - uint64_t tx_drop; - uint64_t tx; - uint64_t tx_prepare_fail; -- uint64_t accept_fail; -- uint64_t sock_rx_drop; -- uint64_t sock_tx_merge; - }; - - struct gazelle_wakeup_stat { -+ uint64_t kernel_events; - uint64_t app_events; -- uint64_t app_write_rpc; -+ uint64_t accept_fail; - uint64_t app_write_cnt; - uint64_t app_read_cnt; - uint64_t read_null; -- uint64_t kernel_events; -+ uint64_t sock_rx_drop; -+ uint64_t sock_tx_merge; -+}; -+ -+struct gazelle_rpc_stat { -+ uint32_t rpc_pool_cnt; -+ uint64_t call_alloc_fail; -+ uint64_t call_msg_cnt; - }; - - struct gazelle_stack_aggregate_stats { -@@ -134,12 +136,9 @@ struct gazelle_stack_aggregate_stats { - }; - - struct gazelle_stat_pkts { -- uint16_t conn_num; -- uint32_t mbufpool_avail_cnt; -- uint64_t call_msg_cnt; -- uint64_t call_alloc_fail; - struct gazelle_stack_stat stack_stat; - struct gazelle_wakeup_stat wakeup_stat; -+ struct gazelle_rpc_stat rpc_stat; - struct gazelle_stack_aggregate_stats aggregate_stats; - }; - -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index 7da7473..7ff7163 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -388,13 +388,16 @@ static int rpc_call_shadow_fd(int stack_id, int fd, const struct sockaddr *addr, - - static void callback_accept(struct rpc_msg *msg) - { -+ struct lwip_sock *sock; - int fd = msg->args[MSG_ARG_0].i; - msg->result = -1; -- struct protocol_stack *stack = get_protocol_stack(); - - int accept_fd = lwip_accept4(fd, msg->args[MSG_ARG_1].p, msg->args[MSG_ARG_2].p, msg->args[MSG_ARG_3].i); - if (accept_fd < 0) { -- stack->stats.accept_fail++; -+ sock = lwip_get_socket(fd); -+ if (!POSIX_IS_CLOSED(sock)) { -+ SOCK_WAIT_STAT(sock->sk_wait, accept_fail, 1); -+ } - LSTACK_LOG(ERR, LSTACK, "fd %d ret %d\n", fd, accept_fd); - return; - } -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 060b3b3..89a6acb 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -49,7 +49,7 @@ struct sockio_ops { - const struct sockaddr *to, socklen_t tolen); - void (*stack_udp_send)(struct lwip_sock *sock); - -- ssize_t (*stack_udp_readmsg)(struct lwip_sock *sock, struct msghdr *msg, int flags); -+ ssize_t (*stack_udp_readmsg)(struct lwip_sock *sock, struct msghdr *msg, size_t len, int flags); - - ssize_t (*stack_tcp_write)(struct lwip_sock *sock, const char *data, size_t len, int flags); - void (*stack_tcp_send)(struct lwip_sock *sock); -@@ -260,6 +260,8 @@ static uint16_t stack_udp_write_one(const struct lwip_sock *sock, struct mbox_ri - mr->ops->enqueue_burst(mr, (void **)&nbuf, 1); - mr->app_free_count -= 1; - -+ SOCK_WAIT_STAT(sock->sk_wait, app_write_cnt, 1); -+ - return len; - } - -@@ -268,7 +270,7 @@ static uint16_t stack_udp_write_bulk(const struct lwip_sock *sock, struct mbox_r - const struct sockaddr *to, socklen_t tolen) - { - struct pbuf *pbuf_pkts[UDP_SND_QUEUELEN_MAX]; -- unsigned pbuf_num; -+ unsigned pbuf_num = 0; - struct netbuf *nbuf; - uint16_t payload_size; - uint8_t optlen; -@@ -328,6 +330,8 @@ static uint16_t stack_udp_write_bulk(const struct lwip_sock *sock, struct mbox_r - mr->ops->push_tail(mr, nbuf); - } - -+ SOCK_WAIT_STAT(sock->sk_wait, app_write_cnt, pbuf_num); -+ - return copied_total; - } - -@@ -473,7 +477,7 @@ static void rtc_stack_udp_send(struct lwip_sock *sock) - } while (output_again); - } - --static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, int flags) -+static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, size_t len, int flags) - { - struct mbox_ring *mr = &sock->conn->recvmbox->mring; - struct pbuf **extcache_list; -@@ -505,6 +509,8 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, int - err = lwip_recvfrom_udp_raw(sock, flags | MSG_PEEK, msg, &copied_total, 0); - sock->lastdata.netbuf = NULL; - -+ SOCK_WAIT_STAT(sock->sk_wait, app_read_cnt, 1); -+ SOCK_WAIT_STAT(sock->sk_wait, sock_rx_drop, copied_total < len ? 1 : 0); - if (get_protocol_stack_group()->latency_start) - calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_READ_LSTACK, 0); - -@@ -532,6 +538,8 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, int - return copied_total; - } - out: -+ SOCK_WAIT_STAT(sock->sk_wait, read_null, 1); -+ - set_errno(err_to_errno(err)); - return -1; - } -@@ -561,6 +569,8 @@ static uint16_t rtw_stack_tcp_write_one(const struct lwip_sock *sock, struct mbo - mr->ops->enqueue_burst(mr, (void **)&p, 1); - mr->app_free_count -= 1; - -+ SOCK_WAIT_STAT(sock->sk_wait, app_write_cnt, 1); -+ - return len; - } - -@@ -582,6 +592,7 @@ static uint16_t rtw_stack_tcp_write_bulk(const struct lwip_sock *sock, struct mb - - write_pbuf_bulk(pbuf_pkts, pbuf_num, TCP_MSS, data, len, 0); - -+ SOCK_WAIT_STAT(sock->sk_wait, app_write_cnt, pbuf_num); - if (get_protocol_stack_group()->latency_start) - calculate_lstack_latency(sock->stack_id, pbuf_pkts, pbuf_num, GAZELLE_LATENCY_WRITE_INTO_RING, 0); - -@@ -670,6 +681,7 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - } - - copied_total = rtw_stack_tcp_append(mr, data, LWIP_MIN(TCP_MSS, total_copy_len), flags); -+ SOCK_WAIT_STAT(sock->sk_wait, sock_tx_merge, copied_total > 0 ? 1 : 0); - if (copied_total == total_copy_len) { - return copied_total; - } -@@ -843,6 +855,7 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - break; - } - -+ SOCK_WAIT_STAT(sock->sk_wait, app_read_cnt, 1); - if (get_protocol_stack_group()->latency_start) - calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_READ_APP_CALL, sys_now_us()); - -@@ -879,6 +892,8 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - return copied_total; - } - -+ SOCK_WAIT_STAT(sock->sk_wait, read_null, 1); -+ - set_errno(err_to_errno(err)); - if (err == ERR_CLSD) { - return 0; -@@ -1133,10 +1148,10 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - msg.msg_iovlen = 1; - msg.msg_name = from; - msg.msg_namelen = (fromlen ? *fromlen : 0); -- recvd = ioops.stack_udp_readmsg(sock, &msg, flags); -+ recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { - if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -- recvd = ioops.stack_udp_readmsg(sock, &msg, flags); -+ recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - } - } - if (recvd > 0 && fromlen != NULL) { -@@ -1154,11 +1169,11 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - { - struct lwip_sock *sock = lwip_get_socket(fd); -- ssize_t ret, recvd = 0; -+ ssize_t len, recvd = 0; - -- ret = lwip_recvmsg_check(NULL, msg, flags); -- if (unlikely(ret <= 0)) { -- return ret; -+ len = lwip_recvmsg_check(NULL, msg, flags); -+ if (unlikely(len <= 0)) { -+ return len; - } - - if (unlikely(!sock->affinity_numa)) { -@@ -1169,20 +1184,20 @@ ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - switch (NETCONN_TYPE(sock->conn)) { - case NETCONN_TCP: - for (int i = 0; i < msg->msg_iovlen; ++i) { -- ret = sockio_recvfrom(fd, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags, NULL, NULL); -- if (ret <= 0) { -+ len = sockio_recvfrom(fd, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags, NULL, NULL); -+ if (len <= 0) { - if (recvd == 0) -- recvd = ret; -+ recvd = len; - break; - } -- recvd += ret; -+ recvd += len; - } - break; - case NETCONN_UDP: -- recvd = ioops.stack_udp_readmsg(sock, msg, flags); -+ recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { - if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -- recvd = ioops.stack_udp_readmsg(sock, msg, flags); -+ recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - } - } - break; -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 7e2a706..bb47830 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -65,6 +65,18 @@ struct rte_mempool *mem_get_rpc_pool(int stack_id) - return g_mem_stack_group[stack_id].rpc_pool; - } - -+unsigned mem_stack_mbuf_pool_count(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ return rte_mempool_avail_count(ms->mbuf_pool); -+} -+ -+unsigned mem_stack_rpc_pool_count(int stack_id) -+{ -+ struct mem_stack *ms = mem_stack_get(stack_id); -+ return rte_mempool_avail_count(ms->rpc_pool); -+} -+ - static inline bool mem_thread_group_in_used(const struct mem_thread_group *mt_grooup, uint32_t timeout) - { - return mt_grooup->used_flag || -@@ -541,12 +553,6 @@ int mem_stack_mpcache_init(int stack_id, unsigned cpu_id) - return 0; - } - --unsigned mem_stack_mbuf_pool_count(int stack_id) --{ -- struct mem_stack *ms = mem_stack_get(stack_id); -- return rte_mempool_avail_count(ms->mbuf_pool); --} -- - static void mem_thread_cache_flush(struct mem_thread *mt) - { - struct mem_stack *ms = mem_stack_get(mt->stack_id); -diff --git a/src/lstack/core/lstack_stack_stat.c b/src/lstack/core/lstack_stack_stat.c -index 3b3bd75..c84b7b1 100644 ---- a/src/lstack/core/lstack_stack_stat.c -+++ b/src/lstack/core/lstack_stack_stat.c -@@ -221,6 +221,8 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - - lstack_get_low_power_info(&dfx->low_power_info); - -+ stack->stats.conn_num = stack->conn_num; -+ stack->stats.mbuf_pool_cnt = mem_stack_mbuf_pool_count(stack->stack_idx); - int32_t ret = memcpy_s(&dfx->data.pkts.stack_stat, sizeof(struct gazelle_stack_stat), - &stack->stats, sizeof(struct gazelle_stack_stat)); - if (ret != EOK) { -@@ -229,15 +231,9 @@ static void get_stack_stats(struct gazelle_stack_dfx_data *dfx, struct protocol_ - } - - sock_wait_group_stat(stack->stack_idx, &dfx->data.pkts.wakeup_stat); -+ rpc_get_stat(&stack->rpc_queue, &dfx->data.pkts.rpc_stat); - -- dfx->data.pkts.call_alloc_fail = rpc_stats_get()->call_alloc_fail; -- -- int32_t rpc_call_result = rpc_msgcnt(&stack->rpc_queue); -- dfx->data.pkts.call_msg_cnt = (rpc_call_result < 0) ? 0 : rpc_call_result; -- -- dfx->data.pkts.mbufpool_avail_cnt = mem_stack_mbuf_pool_count(stack->stack_idx); -- -- dfx->data.pkts.conn_num = stack->conn_num; -+ return; - } - - static void get_stack_dfx_data_proto(struct gazelle_stack_dfx_data *dfx, struct protocol_stack *stack, -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 7b3e432..84e5814 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -10,6 +10,8 @@ - * See the Mulan PSL v2 for more details. - */ - -+#include -+ - #include - #include - -@@ -20,11 +22,13 @@ - #include "lstack_thread_rpc.h" - #include "lstack_mempool.h" - --static struct rpc_stats g_rpc_stats; -+static struct gazelle_rpc_stat g_rpc_stats = {0}; - --struct rpc_stats *rpc_stats_get(void) -+void rpc_get_stat(rpc_queue *queue, struct gazelle_rpc_stat *stat) - { -- return &g_rpc_stats; -+ g_rpc_stats.rpc_pool_cnt = mem_stack_rpc_pool_count(queue->queue_id); -+ g_rpc_stats.call_msg_cnt = rpc_msgcnt(queue); -+ memcpy_s(stat, sizeof(struct gazelle_rpc_stat), &g_rpc_stats, sizeof(struct gazelle_rpc_stat)); - } - - __rte_always_inline -@@ -114,11 +118,7 @@ int rpc_poll_msg(rpc_queue *queue, int max_num) - } - msg = container_of(node, struct rpc_msg, queue_node); - -- if (likely(msg->func)) { -- msg->func(msg); -- } else { -- g_rpc_stats.call_null++; -- } -+ msg->func(msg); - - if (msg->flags & RPC_MSG_RECALL) { - msg->flags &= ~RPC_MSG_RECALL; -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index c67df93..381290c 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -129,10 +129,17 @@ void sock_wait_group_stat(int stack_id, struct gazelle_wakeup_stat *stat) - list_for_each_node(node, next, &g_wait_group.group_list) { - sk_wait = list_entry(node, struct sock_wait, group_node); - -- if (sk_wait->affinity.bind_stack_id == stack_id) { -- memcpy_s(stat, sizeof(struct gazelle_wakeup_stat), -- &sk_wait->stat, sizeof(struct gazelle_wakeup_stat)); -- } -+ if (sk_wait->affinity.bind_stack_id != stack_id) -+ continue; -+ -+ stat->kernel_events += sk_wait->stat.kernel_events ; -+ stat->app_events += sk_wait->stat.app_events ; -+ stat->accept_fail += sk_wait->stat.accept_fail ; -+ stat->app_write_cnt += sk_wait->stat.app_write_cnt ; -+ stat->app_read_cnt += sk_wait->stat.app_read_cnt ; -+ stat->read_null += sk_wait->stat.read_null ; -+ stat->sock_rx_drop += sk_wait->stat.sock_rx_drop ; -+ stat->sock_tx_merge += sk_wait->stat.sock_tx_merge ; - } - - rte_spinlock_unlock(&g_wait_group.group_list_lock); -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index e636fda..bd170bb 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -302,9 +302,10 @@ int mem_thread_manager_init(void); - void mem_thread_cache_free(struct mem_thread *mt); - int mem_thread_cache_init(struct mem_thread *mt, int stack_id); - --unsigned mem_stack_mbuf_pool_count(int stack_id); - struct rte_mempool *mem_get_mbuf_pool(int stack_id); - struct rte_mempool *mem_get_rpc_pool(int stack_id); -+unsigned mem_stack_mbuf_pool_count(int stack_id); -+unsigned mem_stack_rpc_pool_count(int stack_id); - - void *mem_get_rpc(int stack_id); - void mem_put_rpc(void *obj); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 32dde53..013ff29 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -16,6 +16,7 @@ - #include - #include - -+#include "common/gazelle_dfx_msg.h" - #include "lstack_lockless_queue.h" - #include "lstack_interrupt.h" - -@@ -32,12 +33,6 @@ struct rpc_queue { - uint16_t queue_id; - }; - --struct rpc_stats { -- uint16_t call_null; -- uint64_t call_alloc_fail; --}; --struct rpc_stats *rpc_stats_get(void); -- - union rpc_msg_arg { - int i; - unsigned int u; -@@ -67,6 +62,8 @@ struct rpc_msg { - lockless_queue_node queue_node; - }; - -+void rpc_get_stat(rpc_queue *queue, struct gazelle_rpc_stat *stat); -+ - struct rpc_msg *rpc_msg_alloc(int stack_id, rpc_func_t func); - void rpc_msg_free(struct rpc_msg *msg); - -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -index ed154b4..306c6a4 100644 ---- a/src/lstack/include/lstack_wait.h -+++ b/src/lstack/include/lstack_wait.h -@@ -73,7 +73,6 @@ struct sock_wait { - - /* dfx stat */ - struct list_node group_node; -- struct gazelle_wakeup_stat stat; - - /* epoll kernel fd */ - int epfd; -@@ -83,6 +82,9 @@ struct sock_wait { - unsigned kernel_nfds; - struct wait_affinity affinity; - -+#define SOCK_WAIT_STAT(sk_wait, name, count) if ((sk_wait) != NULL && (sk_wait)->type != WAIT_CLOSE) { (sk_wait)->stat.name += count; } -+ struct gazelle_wakeup_stat stat; -+ - char pad0 __rte_cache_aligned; /* new cache line */ - - #if SOCK_WAIT_BATCH_NOTIFY -diff --git a/src/ltran/ltran_dfx.c b/src/ltran/ltran_dfx.c -index 1722460..01ff2c3 100644 ---- a/src/ltran/ltran_dfx.c -+++ b/src/ltran/ltran_dfx.c -@@ -734,26 +734,23 @@ static void show_lstack_stats(struct gazelle_stack_dfx_data *lstack_stat) - printf("tx_pkts: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.tx); - printf("tx_drop: %-20"PRIu64" ", lstack_stat->data.pkts.stack_stat.tx_drop); - printf("tx_allocmbuf_fail: %-10"PRIu64"\n", lstack_stat->data.pkts.stack_stat.tx_allocmbuf_fail); -+ -+ printf("mbuf_pool_freecnt: %-10"PRIu32" ", lstack_stat->data.pkts.stack_stat.mbuf_pool_cnt); -+ printf("conn_num: %-19hu ", lstack_stat->data.pkts.stack_stat.conn_num); -+ printf("wakeup_events: %-14"PRIu64" \n", lstack_stat->data.pkts.stack_stat.wakeup_events); -+ -+ printf("rpc_pool_cnt: %-15"PRIu32" ", lstack_stat->data.pkts.rpc_stat.rpc_pool_cnt); -+ printf("call_alloc_fail: %-12"PRIu64" ", lstack_stat->data.pkts.rpc_stat.call_alloc_fail); -+ printf("call_msg: %-19"PRIu64" \n", lstack_stat->data.pkts.rpc_stat.call_msg_cnt); -+ -+ printf("kernel_events: %-14"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.kernel_events); -+ printf("app_events: %-17"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.app_events); - printf("app_read: %-19"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_read_cnt); -- printf("read_lwip: %-18"PRIu64" ", lstack_stat->data.pkts.stack_stat.read_lwip_cnt); -- printf("read_lwip_drop: %-13"PRIu64" \n", lstack_stat->data.pkts.stack_stat.read_lwip_drop); - printf("app_write: %-18"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_write_cnt); -- printf("write_lwip: %-17"PRIu64" ", lstack_stat->data.pkts.stack_stat.write_lwip_cnt); -- printf("app_write_rpc: %-14"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.app_write_rpc); -- printf("conn_num: %-19hu ", lstack_stat->data.pkts.conn_num); -- -- printf("kernel_events: %-14"PRIu64"\n", lstack_stat->data.pkts.wakeup_stat.kernel_events); -- printf("wakeup_events: %-14"PRIu64" ", lstack_stat->data.pkts.stack_stat.wakeup_events); -- printf("app_events: %-17"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.app_events); - printf("read_null: %-18"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.read_null); -- printf("call_msg: %-19"PRIu64" ", lstack_stat->data.pkts.call_msg_cnt); -- printf("call_alloc_fail: %-12"PRIu64" ", lstack_stat->data.pkts.call_alloc_fail); -- printf("call_null: %-18"PRIu64" \n", lstack_stat->data.pkts.stack_stat.call_null); -- printf("send_pkts_fail: %-13"PRIu64" ", lstack_stat->data.pkts.stack_stat.send_pkts_fail); -- printf("mbuf_pool_freecnt: %-10"PRIu32" \n", lstack_stat->data.pkts.mbufpool_avail_cnt); -- printf("accpet_fail: %-16"PRIu64" ", lstack_stat->data.pkts.stack_stat.accept_fail); -- printf("sock_rx_drop: %-15"PRIu64" ", lstack_stat->data.pkts.stack_stat.sock_rx_drop); -- printf("sock_tx_merge: %-16"PRIu64" \n", lstack_stat->data.pkts.stack_stat.sock_tx_merge); -+ printf("sock_rx_drop: %-15"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.sock_rx_drop); -+ printf("sock_tx_merge: %-14"PRIu64" ", lstack_stat->data.pkts.wakeup_stat.sock_tx_merge); -+ printf("accpet_fail: %-16"PRIu64" \n", lstack_stat->data.pkts.wakeup_stat.accept_fail); - } - - static void gazelle_print_lstack_stat_detail(struct gazelle_stack_dfx_data *lstack_stat, --- -2.33.0 - diff --git a/0334-mempool-fix-copy_mbuf_private.patch b/0334-mempool-fix-copy_mbuf_private.patch deleted file mode 100644 index 869e6d8..0000000 --- a/0334-mempool-fix-copy_mbuf_private.patch +++ /dev/null @@ -1,75 +0,0 @@ -From b189e23541622329d3df7cf95ecf20b2394e3539 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 6 Apr 2025 16:02:40 +0800 -Subject: [PATCH] mempool: fix copy_mbuf_private - -Signed-off-by: Lemmy Huang ---- - src/common/dpdk_common.h | 18 +++++++++++------- - src/lstack/core/lstack_dpdk.c | 2 +- - 2 files changed, 12 insertions(+), 8 deletions(-) - -diff --git a/src/common/dpdk_common.h b/src/common/dpdk_common.h -index cff193c..fca4aa3 100644 ---- a/src/common/dpdk_common.h -+++ b/src/common/dpdk_common.h -@@ -38,9 +38,11 @@ struct latency_timestamp { - uint16_t type; // latency type - }; - struct mbuf_private { -- /* struct pbuf_custom must at first */ -+ /* struct pbuf_custom must at first. do not copy in copy_mbuf_private() !!! */ - struct pbuf_custom pc; -- int stack_id; /* the stack to which buf belongs */ -+ /* the stack to which buf belongs. do not copy in copy_mbuf_private() !!! */ -+ int stack_id; -+ - struct latency_timestamp lt; - }; - -@@ -57,11 +59,16 @@ static __rte_always_inline struct mbuf_private *pbuf_to_private(const struct pbu - return mbuf_to_private(pbuf_to_mbuf(p)); - } - -+static __rte_always_inline void copy_mbuf_private(struct mbuf_private *dst, const struct mbuf_private *src) -+{ -+ rte_memcpy(&dst->lt, &src->lt, sizeof(struct latency_timestamp)); -+} -+ - /* NOTE!!! magic code, even the order. - * I wrote it carefully, and check the assembly. for example, there is 24 ins in A72, - * and if there is no cache miss, it only take less than 20 cycle(store pipe is the bottleneck). - */ --static __rte_always_inline void copy_mbuf(struct rte_mbuf *dst, struct rte_mbuf *src) -+static __rte_always_inline void copy_mbuf(struct rte_mbuf *dst, const struct rte_mbuf *src) - { - /* In the direction of tx, data is copied from lstack to ltran. It is necessary to judge whether - the length of data transmitted from lstack has been tampered with to prevent overflow -@@ -79,10 +86,7 @@ static __rte_always_inline void copy_mbuf(struct rte_mbuf *dst, struct rte_mbuf - uint8_t *src_data = rte_pktmbuf_mtod(src, void*); - rte_memcpy(dst_data, src_data, data_len); - -- // copy private date. -- dst_data = (uint8_t *)mbuf_to_private(dst); -- src_data = (uint8_t *)mbuf_to_private(src); -- rte_memcpy(dst_data, src_data, sizeof(struct mbuf_private)); -+ copy_mbuf_private(mbuf_to_private(dst), mbuf_to_private(src)); - } - - static __rte_always_inline void time_stamp_into_mbuf(uint32_t rx_count, struct rte_mbuf *buf[], uint64_t time_stamp) -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index 8f896c9..baba571 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -196,7 +196,7 @@ int32_t fill_mbuf_to_ring(int stack_id, struct rte_ring *ring, uint32_t mbuf_num - batch = LWIP_MIN(remain, RING_SIZE(VDEV_RX_QUEUE_SZ)); - - ret = mem_get_mbuf_bulk(stack_id, free_buf, batch, true); -- if (ret != 0) { -+ if (ret == 0) { - LSTACK_LOG(ERR, LSTACK, "cannot alloc mbuf for ring, count: %u ret=%d\n", batch, ret); - return -1; - } --- -2.33.0 - diff --git a/0335-socket-fix-connect-blocking.patch b/0335-socket-fix-connect-blocking.patch deleted file mode 100644 index eb9d21e..0000000 --- a/0335-socket-fix-connect-blocking.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 3d17332feaa4104d614fb0ba72d29e56b4e87cf2 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 16 Apr 2025 09:56:46 +0800 -Subject: [PATCH] socket: fix connect blocking - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 17 +++++++++++------ - src/lstack/api/lstack_sockctl.c | 8 ++++---- - src/lstack/api/lstack_sockio.c | 14 +++++++------- - src/lstack/core/lstack_wait.c | 2 +- - src/lstack/include/lstack_epoll.h | 2 +- - 5 files changed, 24 insertions(+), 19 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 3940f43..ed6d2f0 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -814,12 +814,12 @@ void epoll_api_init(posix_api_t *api) - api->select_fn = lstack_select; - } - --bool sock_event_wait(struct lwip_sock *sock, bool noblocking) -+bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking) - { - bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; - uint32_t start; - int timeout; -- unsigned pending; -+ unsigned pending = 0; - - if (!rtc_mode && noblocking) - return false; -@@ -829,6 +829,7 @@ bool sock_event_wait(struct lwip_sock *sock, bool noblocking) - } - if (!(sock->sk_wait->type & WAIT_BLOCK)) { - sock->sk_wait->type |= WAIT_BLOCK; -+ rte_wmb(); - } - - if (rtc_mode) { -@@ -840,13 +841,17 @@ bool sock_event_wait(struct lwip_sock *sock, bool noblocking) - timeout = sock->conn->recv_timeout == 0 ? -1 : sock->conn->recv_timeout; - start = sys_now(); - do { -- pending = sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_RCVPLUS, 0) | -+ pending = sock_event_hold_pending(sock, WAIT_BLOCK, evt, 0) | - sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0); -- if (pending) { -- return true; -+ if (pending != 0) { -+ break; - } - timeout = sock->sk_wait->timedwait_fn(sock->sk_wait, timeout, start); - } while (timeout != 0); - -- return false; -+ if (evt == NETCONN_EVT_SENDPLUS) { -+ /* remove WAIT_BLOCK type */ -+ sock->sk_wait->type &= ~WAIT_BLOCK; -+ } -+ return pending != 0; - } -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index 7ff7163..d1ef36a 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -448,7 +448,7 @@ static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, s - - if (ret < 0 && errno == EINPROGRESS) { - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn))) { -+ if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, netconn_is_nonblocking(sock->conn))) { - ret = 0; - } - } -@@ -607,7 +607,7 @@ static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *add - - min_sock = get_min_accept_sock(fd); - if (min_sock == NULL) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { - min_sock = get_min_accept_sock(fd); - } - } -@@ -786,7 +786,7 @@ static int rtc_connect(int s, const struct sockaddr *name, socklen_t namelen) - ret = lwip_connect(s, name, namelen); - if (ret < 0 && errno == EINPROGRESS) { - struct lwip_sock *sock = lwip_get_socket(s); -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn))) { -+ if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, netconn_is_nonblocking(sock->conn))) { - ret = 0; - } - } -@@ -804,7 +804,7 @@ static int rtc_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int fla - - ret = lwip_accept4(s, addr, addrlen, flags); - if (ret < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { - ret = lwip_accept4(s, addr, addrlen, flags); - } - } -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 89a6acb..438f1ce 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -1128,7 +1128,7 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - /* TODO: support MSG_WAITALL */ - recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { - recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); - } - } -@@ -1150,7 +1150,7 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - msg.msg_namelen = (fromlen ? *fromlen : 0); - recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { - recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - } - } -@@ -1196,7 +1196,7 @@ ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - case NETCONN_UDP: - recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { - recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - } - } -@@ -1233,7 +1233,7 @@ ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, - ret = ioops.stack_tcp_write(sock, mem, len, flags); - if (ret < 0) { - if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, true); -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); - } - } else { - ioops.stack_tcp_send(sock); -@@ -1243,7 +1243,7 @@ ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, - ret = ioops.stack_udp_write(sock, mem, len, flags, to, tolen); - if (ret < 0) { - if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, true); -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); - } - } else { - ioops.stack_udp_send(sock); -@@ -1284,7 +1284,7 @@ ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - ret = ioops.stack_tcp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more); - if (ret < 0) { - if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, true); -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); - } - break; - } -@@ -1302,7 +1302,7 @@ ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - ret = ioops.stack_udp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more, NULL, 0); - if (ret < 0) { - if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, true); -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); - } - break; - } -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 381290c..866e293 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -421,7 +421,7 @@ unsigned sock_event_hold_pending(const struct lwip_sock *sock, - } - break; - case NETCONN_EVT_SENDPLUS: -- if (sock->sk_event.events & EPOLLOUT) { -+ if (sock->sk_event.events & EPOLLOUT || type & WAIT_BLOCK) { - if (len > 0 || - NETCONN_ALLOW_SEND(sock)) { - event = EPOLLOUT; -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 655e178..99a7162 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -23,6 +23,6 @@ void poll_destruct_wait(void); - - int lstack_epoll_close(int epfd); - void epoll_api_init(posix_api_t *api); --bool sock_event_wait(struct lwip_sock *sock, bool noblocking); -+bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking); - - #endif /* _GAZELLE_EPOLL_H_ */ --- -2.33.0 - diff --git a/0336-socket-fix-stack_tcp_read-do-not-recv_finish_burst.patch b/0336-socket-fix-stack_tcp_read-do-not-recv_finish_burst.patch deleted file mode 100644 index 9e7972c..0000000 --- a/0336-socket-fix-stack_tcp_read-do-not-recv_finish_burst.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 062a2006981cd9918a3b698241fe1cd64b99fbdb Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Thu, 17 Apr 2025 14:52:26 +0800 -Subject: [PATCH] socket: fix stack_tcp_read do not recv_finish_burst - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 438f1ce..0ebd9e2 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -838,6 +838,14 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - copied_total += buf_copy_len; - total_copy_len -= buf_copy_len; - mr->app_recvd_len += buf_copy_len; -+ -+ if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || -+ mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -+ if (sock->lastdata.pbuf == NULL) { -+ mr->ops->recv_finish_burst(mr); -+ mr->app_queued_num = 0; -+ } -+ } - } - - while (total_copy_len > 0) { --- -2.33.0 - diff --git a/0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch b/0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch deleted file mode 100644 index d9127dc..0000000 --- a/0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch +++ /dev/null @@ -1,167 +0,0 @@ -From b928e5c8027272c75f46395aa2bef25962d844f3 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 18 Apr 2025 14:41:20 +0800 -Subject: [PATCH] tcp: add GAZELLE_TCP_ASYNC_RECVD fix mbuf OOM caused by - untimely sockio_peek_recv_free - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 68 ++++++++++++++-------------------- - 1 file changed, 27 insertions(+), 41 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 0ebd9e2..46c8992 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -910,47 +910,34 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - } - - --#define RECVD_UNCOMMITTED(msg) ((msg)->args[MSG_ARG_2].ul) --#define RECVD_CURR_SEQ(msg) ((msg)->args[MSG_ARG_3].ul) --#define RECVD_LAST_SEQ(msg) ((msg)->args[MSG_ARG_4].ul) -- --static inline bool rpc_commit_tcp_recvd(struct rpc_msg *recvmsg, unsigned long threshold) -+#if GAZELLE_TCP_ASYNC_RECVD -+#define RECVD_UNSUBMITED(msg) ((msg)->args[MSG_ARG_2].ul) -+static inline bool rpc_submit_tcp_recvd(struct rpc_msg *recvmsg, size_t threshold, size_t recvd) - { -- if (RECVD_UNCOMMITTED(recvmsg) >= threshold) { -- __atomic_add_fetch(&RECVD_CURR_SEQ(recvmsg), RECVD_UNCOMMITTED(recvmsg), __ATOMIC_RELEASE); -- RECVD_UNCOMMITTED(recvmsg) = 0; -+ RECVD_UNSUBMITED(recvmsg) += recvd; -+ if (RECVD_UNSUBMITED(recvmsg) >= threshold) { -+ RECVD_UNSUBMITED(recvmsg) = 0; - return true; - } - return false; - } - --#if TCP_RECV_AND_UPDATE --static inline unsigned long rpc_read_tcp_recvd(struct rpc_msg *recvmsg) --{ -- unsigned long curr_recvd_seq; -- unsigned long recvd; -- -- curr_recvd_seq = __atomic_load_n(&RECVD_CURR_SEQ(recvmsg), __ATOMIC_ACQUIRE); -- recvd = curr_recvd_seq - RECVD_LAST_SEQ(recvmsg); -- if (recvd > 0) { -- /* update last recvd seq */ -- RECVD_LAST_SEQ(recvmsg) = curr_recvd_seq; -- } -- return recvd; --} -- - static void callback_tcp_recvd(struct rpc_msg *recvmsg) - { - struct lwip_sock *sock = recvmsg->args[MSG_ARG_0].p; -- unsigned long recvd; -+ struct mbox_ring *mr; -+ u32_t recvd; - -- recvd = rpc_read_tcp_recvd(recvmsg); -- lwip_tcp_recvd(sock->conn, recvd, 0); -+ mr = &sock->conn->recvmbox->mring; -+ if (mr->flags & MBOX_FLAG_PEEK) { -+ sockio_peek_recv_free(mr, 0); -+ } - -+ recvd = lwip_netconn_get_recvd(sock->conn, 0, 0); -+ lwip_netconn_update_recvd(sock->conn, recvd); - recvmsg->result = recvd; - return; - } --#endif /* TCP_RECV_AND_UPDATE */ - - static inline int rpc_call_tcp_recvd(rpc_queue *queue, struct lwip_sock *sock, size_t recvd, int flags) - { -@@ -960,22 +947,23 @@ static inline int rpc_call_tcp_recvd(rpc_queue *queue, struct lwip_sock *sock, s - recvmsg->args[MSG_ARG_0].p = sock; - recvmsg->result = 0; - -- RECVD_UNCOMMITTED(recvmsg) += recvd; -- if (rpc_commit_tcp_recvd(recvmsg, TCP_WND_UPDATE_THRESHOLD << 1)) { -+ if (rpc_submit_tcp_recvd(recvmsg, TCP_WND >> 1, recvd)) { - rpc_async_call(queue, recvmsg, RPC_MSG_REUSE); - } -- - return 0; - } -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ - - static void rtw_stack_tcp_recvd(struct lwip_sock *sock, ssize_t recvd, int flags) - { -+#if GAZELLE_TCP_ASYNC_RECVD - struct protocol_stack *stack = get_protocol_stack_by_id(sock->stack_id); - - if (recvd <= 0 || flags & MSG_PEEK) { - return; - } - rpc_call_tcp_recvd(&stack->rpc_queue, sock, recvd, flags); -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ - } - - static void rtc_stack_tcp_recvd(struct lwip_sock *sock, ssize_t recvd, int flags) -@@ -1012,14 +1000,14 @@ static void callback_tcp_send(struct rpc_msg *sendmsg) - LSTACK_LOG(ERR, LSTACK, "tcp_output failed, sock %p, err %u\n", sock, err); - } - --#if TCP_RECV_AND_UPDATE -+#if GAZELLE_TCP_ASYNC_RECVD - struct rpc_msg *recvmsg; -- if (RECVD_UNCOMMITTED(sendmsg)) { -- RECVD_UNCOMMITTED(sendmsg) = 0; -+ if (RECVD_UNSUBMITED(sendmsg)) { -+ RECVD_UNSUBMITED(sendmsg) = 0; - recvmsg = sock_mbox_private_get(sock->conn->recvmbox); - callback_tcp_recvd(recvmsg); - } --#endif /* TCP_RECV_AND_UPDATE */ -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ - - return; - } -@@ -1036,11 +1024,11 @@ static inline int rpc_call_tcp_send(rpc_queue *queue, struct lwip_sock *sock) - sendmsg->args[MSG_ARG_0].p = sock; - sendmsg->args[MSG_ARG_1].p = mem_thread_migrate_get(sock->stack_id); - --#if TCP_RECV_AND_UPDATE -+#if GAZELLE_TCP_ASYNC_RECVD - struct rpc_msg *recvmsg; - recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -- RECVD_UNCOMMITTED(sendmsg) = rpc_commit_tcp_recvd(recvmsg, TCP_WND_UPDATE_THRESHOLD); --#endif /* TCP_RECV_AND_UPDATE */ -+ RECVD_UNSUBMITED(sendmsg) = rpc_submit_tcp_recvd(recvmsg, TCP_WND >> 2, 0); -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ - - rpc_async_call(queue, sendmsg, RPC_MSG_REUSE); - return 0; -@@ -1140,11 +1128,9 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); - } - } --#if TCP_RECV_AND_UPDATE - if (recvd > 0) { - ioops.stack_tcp_recvd(sock, recvd, flags); - } --#endif /* TCP_RECV_AND_UPDATE */ - break; - case NETCONN_UDP: - vec.iov_base = mem; -@@ -1412,11 +1398,11 @@ static int sockio_mbox_init(struct lwip_sock *sock) - switch (NETCONN_TYPE(sock->conn)) { - case NETCONN_TCP: - ret = sock_mbox_private_init(sendmbox, callback_tcp_send); --#if TCP_RECV_AND_UPDATE -+#if GAZELLE_TCP_ASYNC_RECVD - if (sys_mbox_valid(&recvmbox)) { - ret |= sock_mbox_private_init(recvmbox, callback_tcp_recvd); - } --#endif /* TCP_RECV_AND_UPDATE */ -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ - break; - case NETCONN_UDP: - ret = sock_mbox_private_init(sendmbox, callback_udp_send); --- -2.33.0 - diff --git a/0338-socket-fix-tcp-closed.patch b/0338-socket-fix-tcp-closed.patch deleted file mode 100644 index 41f9dcd..0000000 --- a/0338-socket-fix-tcp-closed.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 933f0e59f77fe450ab255c07c9f4b994de4be11f Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sat, 19 Apr 2025 21:20:52 +0800 -Subject: [PATCH] socket: fix tcp closed - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 48 ++++++++++++++-------------------- - 1 file changed, 19 insertions(+), 29 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 46c8992..0bd31ab 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -817,7 +817,7 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - struct mbox_ring *mr = &sock->conn->recvmbox->mring; - struct pbuf **extcache_list; - err_t err = ERR_OK; -- struct pbuf *p; -+ struct pbuf *p = NULL; - - uint32_t buf_copy_len; - uint32_t total_copy_len = len; -@@ -832,50 +832,40 @@ static ssize_t stack_tcp_read(struct lwip_sock *sock, char *data, size_t len, in - extcache_list = (struct pbuf **)&mr->st_obj; - } - -- if (sock->lastdata.pbuf != NULL) { -- // TODO: support MSG_PEEK -- buf_copy_len = pbuf_copy_and_free(&sock->lastdata.pbuf, extcache_list, data, total_copy_len); -- copied_total += buf_copy_len; -- total_copy_len -= buf_copy_len; -- mr->app_recvd_len += buf_copy_len; -- -- if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || -- mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -- if (sock->lastdata.pbuf == NULL) { -- mr->ops->recv_finish_burst(mr); -- mr->app_queued_num = 0; -- } -- } -- } -- - while (total_copy_len > 0) { -- if (mr->ops->recv_start_burst(mr, (void **)&p, 1) == 0) { -- if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -- err = ERR_CONN; -- } else { -- err = ERR_WOULDBLOCK; -+ if (sock->lastdata.pbuf == NULL) { -+ if (mr->ops->recv_start_burst(mr, (void **)&sock->lastdata.pbuf, 1) == 0) { -+ if (unlikely(sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0))) { -+ err = ERR_CONN; -+ } else { -+ err = ERR_WOULDBLOCK; -+ } -+ break; - } -- break; -+ mr->app_queued_num++; -+ SOCK_WAIT_STAT(sock->sk_wait, app_read_cnt, 1); - } -- mr->app_queued_num++; -- if (unlikely(lwip_netconn_is_err_msg(p, &err))) { -+ -+ if (unlikely(lwip_netconn_is_err_msg(sock->lastdata.pbuf, &err))) { - API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, copied_total); - break; - } - -- SOCK_WAIT_STAT(sock->sk_wait, app_read_cnt, 1); -- if (get_protocol_stack_group()->latency_start) -+ if (get_protocol_stack_group()->latency_start) { -+ p = sock->lastdata.pbuf; - calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_READ_APP_CALL, sys_now_us()); -+ } - -- sock->lastdata.pbuf = p; - // TODO: support MSG_PEEK - buf_copy_len = pbuf_copy_and_free(&sock->lastdata.pbuf, extcache_list, data + copied_total, total_copy_len); - copied_total += buf_copy_len; - total_copy_len -= buf_copy_len; - mr->app_recvd_len += buf_copy_len; - -- if (get_protocol_stack_group()->latency_start) -+ if (get_protocol_stack_group()->latency_start) { - calculate_lstack_latency(sock->stack_id, &p, 1, GAZELLE_LATENCY_READ_LSTACK, 0); -+ p = NULL; -+ } - - if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || - mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { --- -2.33.0 - diff --git a/0339-socket-fix-sk_wait-cannot-be-interrupted-by-signals.patch b/0339-socket-fix-sk_wait-cannot-be-interrupted-by-signals.patch deleted file mode 100644 index 27c3a6e..0000000 --- a/0339-socket-fix-sk_wait-cannot-be-interrupted-by-signals.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 56f8d17ddf0a8668d87d2060f97f6c177bc5ce3d Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 20 Apr 2025 12:54:06 +0800 -Subject: [PATCH] socket: fix sk_wait cannot be interrupted by signals - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 19 +++++++++++++------ - src/lstack/core/lstack_wait.c | 8 ++++---- - src/lstack/include/lstack_wait.h | 2 +- - 3 files changed, 18 insertions(+), 11 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index ed6d2f0..19cc9d6 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -40,13 +40,16 @@ static int rtc_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint3 - - if (timeout > 0 && timeout <= (int)(sys_now() - start)) { - timeout = 0; -+ } else if (timeout < 0) { -+ errno = 0; - } - return timeout; - } - - static int rtw_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint32_t start) - { -- return sys_mutex_timedlock_internal(&sk_wait->mutex, timeout); -+ /* when sem interrupted by signals, errno = EINTR */ -+ return sys_sem_wait_internal(&sk_wait->sem, timeout); - } - - static void rtc_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -@@ -83,7 +86,7 @@ static void rtw_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event - } - rte_spinlock_unlock(&sk_wait->epcb.lock); - -- sys_mutex_unlock_internal(&sk_wait->mutex); -+ sys_sem_signal_internal(&sk_wait->sem); - } - - static void rtw_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -@@ -112,7 +115,7 @@ static void rtw_poll_notify_event(struct sock_wait *sk_wait, struct sock_event * - return; - } - #endif /* SOCK_WAIT_BATCH_NOTIFY */ -- sys_mutex_unlock_internal(&sk_wait->mutex); -+ sys_sem_signal_internal(&sk_wait->sem); - } - static void rtw_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) - { -@@ -433,7 +436,7 @@ int lstack_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int t - } - - timeout = sk_wait->timedwait_fn(sk_wait, timeout, start); -- } while (timeout != 0); -+ } while (timeout > 0 || (timeout < 0 && errno == 0)); - - sk_wait->stat.app_events += lwip_num; - sk_wait->stat.kernel_events += kernel_num; -@@ -706,7 +709,7 @@ int lstack_poll(struct pollfd *fds, nfds_t nfds, int timeout) - } - - timeout = sk_wait->timedwait_fn(sk_wait, timeout, start); -- } while (timeout != 0); -+ } while (timeout > 0 || (timeout < 0 && errno == 0)); - - sk_wait->stat.app_events += lwip_num; - sk_wait->stat.kernel_events += kernel_num; -@@ -847,7 +850,11 @@ bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocki - break; - } - timeout = sock->sk_wait->timedwait_fn(sock->sk_wait, timeout, start); -- } while (timeout != 0); -+ } while (timeout > 0 || (timeout < 0 && errno == 0)); -+ -+ if (errno == ETIMEDOUT) { -+ errno = EAGAIN; -+ } - - if (evt == NETCONN_EVT_SENDPLUS) { - /* remove WAIT_BLOCK type */ -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 866e293..816f340 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -208,7 +208,7 @@ void* kernel_wait_thread(void *arg) - if (sk_wait->type == WAIT_CLOSE) - continue; - rte_atomic16_set(&sk_wait->kernel_pending, true); -- sys_mutex_unlock_internal(&sk_wait->mutex); -+ sys_sem_signal_internal(&sk_wait->sem); - } - usleep(KERNEL_EVENT_WAIT_US); - } -@@ -285,7 +285,7 @@ int sock_wait_common_init(struct sock_wait *sk_wait) - { - sk_wait->lwip_nfds = 0; - sk_wait->kernel_nfds = 0; -- sys_mutex_new_internal(&sk_wait->mutex); -+ sys_sem_new_internal(&sk_wait->sem, 0); - - #if SOCK_WAIT_BATCH_NOTIFY - for (int i = 0; i < PROTOCOL_STACK_MAX; ++i) { -@@ -318,7 +318,7 @@ void sock_wait_common_free(struct sock_wait *sk_wait) - #endif /* SOCK_WAIT_BATCH_NOTIFY */ - - sock_wait_group_del(sk_wait); -- sys_mutex_free_internal(&sk_wait->mutex); -+ sys_sem_free_internal(&sk_wait->sem); - } - - int sock_wait_kernel_init(struct sock_wait *sk_wait, int epfd, int stack_num) -@@ -543,7 +543,7 @@ unsigned lwip_wait_foreach_notify(int stack_id) - - sock_wait_foreach_event(sk_wait, stack_id); - -- sys_mutex_unlock_internal(&sk_wait->mutex); -+ sys_sem_signal_internal(&sk_wait->sem); - count++; - } - return count; -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -index 306c6a4..a1d35dd 100644 ---- a/src/lstack/include/lstack_wait.h -+++ b/src/lstack/include/lstack_wait.h -@@ -98,7 +98,7 @@ struct sock_wait { - /* kernel event flag */ - rte_atomic16_t kernel_pending; - /* run-to-wakeup blocking lock */ -- struct sys_mutex mutex; -+ struct sys_sem sem; /* Do not use mutex, as it cannot be interrupted by signals */ - - union { - struct epoll_cb epcb; --- -2.33.0 - diff --git a/0340-mempool-modify-mbuf-num-and-rpc_msg-num.patch b/0340-mempool-modify-mbuf-num-and-rpc_msg-num.patch deleted file mode 100644 index f560ef0..0000000 --- a/0340-mempool-modify-mbuf-num-and-rpc_msg-num.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 243f24d1a2123537bc4b280064f32d38af450826 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 20 Apr 2025 20:06:24 +0800 -Subject: [PATCH] mempool: modify mbuf num and rpc_msg num - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_dpdk.c | 5 +++-- - src/lstack/core/lstack_mempool.c | 24 +++++++++++++----------- - src/lstack/include/lstack_mempool.h | 2 +- - 3 files changed, 17 insertions(+), 14 deletions(-) - -diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c -index baba571..ddcd5ae 100644 ---- a/src/lstack/core/lstack_dpdk.c -+++ b/src/lstack/core/lstack_dpdk.c -@@ -901,8 +901,9 @@ uint32_t dpdk_pktmbuf_mempool_num(void) - { - struct cfg_params *cfg = get_global_cfg_params(); - -- return (MBUFPOOL_RESERVE_NUM + cfg->rxqueue_size + cfg->txqueue_size + -- (cfg->tcp_conn_count * cfg->mbuf_count_per_conn) / cfg->num_queue); -+ return (MBUFPOOL_RESERVE_NUM + MBUFPOOL_CACHE_NUM + -+ cfg->rxqueue_size + cfg->txqueue_size + -+ (cfg->tcp_conn_count * cfg->mbuf_count_per_conn) / cfg->num_queue); - } - - uint32_t dpdk_total_socket_memory(void) -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index bb47830..b03c3ef 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -450,20 +450,15 @@ static const struct mempool_ops mbuf_mp_ops = { - - static struct rte_mempool *mbuf_pool_create(int stack_id, unsigned numa_id) - { -- struct cfg_params *cfg_params = get_global_cfg_params(); - char name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; -- uint32_t total_conn_mbufs, total_nic_mbufs, total_mbufs; -+ uint32_t total_bufs; - uint16_t private_size; - uint16_t xdp_metadata = 0; - -- total_conn_mbufs = cfg_params->mbuf_count_per_conn * cfg_params->tcp_conn_count; -- total_nic_mbufs = cfg_params->rxqueue_size + cfg_params->txqueue_size; -- -- total_mbufs = (total_conn_mbufs / cfg_params->num_queue) + total_nic_mbufs + MBUFPOOL_RESERVE_NUM; -- /* limit mbuf max num based on the dpdk capability */ -- if (total_mbufs > MBUFPOOL_MAX_NUM) { -- LSTACK_LOG(ERR, LSTACK, "total_mbufs %u out of the dpdk mbuf_pool range\n", total_mbufs); -+ total_bufs = dpdk_pktmbuf_mempool_num(); -+ if (total_bufs > MEMPOOL_MAX_NUM) { -+ LSTACK_LOG(ERR, LSTACK, "total_bufs %u out of the dpdk mempool range\n", total_bufs); - return NULL; - } - -@@ -474,7 +469,7 @@ static struct rte_mempool *mbuf_pool_create(int stack_id, unsigned numa_id) - } - private_size = RTE_ALIGN(sizeof(struct mbuf_private) + xdp_metadata, RTE_CACHE_LINE_SIZE); - -- pool = mbuf_mp_ops.create(name, total_mbufs, MBUFPOOL_CACHE_NUM, private_size, MBUF_DATA_SIZE, numa_id); -+ pool = mbuf_mp_ops.create(name, total_bufs, MBUFPOOL_CACHE_NUM, private_size, MBUF_DATA_SIZE, numa_id); - if (pool == NULL) { - LSTACK_LOG(ERR, LSTACK, "rte_pktmbuf_pool_create %s failed, rte_errno %d\n", name, rte_errno); - return NULL; -@@ -487,7 +482,14 @@ static struct rte_mempool *rpc_pool_create(int stack_id, unsigned numa_id) - { - char name [RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; -- uint32_t total_bufs = get_global_cfg_params()->rpc_msg_max; -+ uint32_t total_bufs; -+ -+ total_bufs = MEMPOOL_CACHE_NUM + BUF_CACHE_MIN_NUM + -+ (get_global_cfg_params()->rpc_msg_max / get_global_cfg_params()->num_queue); -+ if (total_bufs > MEMPOOL_MAX_NUM) { -+ LSTACK_LOG(ERR, LSTACK, "total_bufs %u out of the dpdk mempool range\n", total_bufs); -+ return NULL; -+ } - - SYS_FORMAT_NAME(name, RTE_MEMPOOL_NAMESIZE, "%s_%hu", "rpc_pool", stack_id); - -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index bd170bb..131029e 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -36,7 +36,7 @@ - /* DPDK limit ring head-tail distance in rte_ring_init. - * Max value is RTE_RING_SZ_MASK / HTD_MAX_DEF, RTE_RING_SZ_MASK is 0x7fffffff, HTD_MAX_DEF is 8. - */ --#define MBUFPOOL_MAX_NUM 0xfffffff -+#define MEMPOOL_MAX_NUM 0xfffffff - - #define MBUFPOOL_CACHE_NUM LWIP_MIN(NIC_QUEUE_SIZE_MAX >> 1, RTE_MEMPOOL_CACHE_MAX_SIZE) - #define MBUFPOOL_RESERVE_NUM (NIC_QUEUE_SIZE_MAX + MBUFPOOL_CACHE_NUM) --- -2.33.0 - diff --git a/0341-mempool-fix-mbox_ring-free-not-call-recv_finish_burs.patch b/0341-mempool-fix-mbox_ring-free-not-call-recv_finish_burs.patch deleted file mode 100644 index 8695395..0000000 --- a/0341-mempool-fix-mbox_ring-free-not-call-recv_finish_burs.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 532f3450a0b4212e03636c05593c05a50e95914d Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 21 Apr 2025 14:42:02 +0800 -Subject: [PATCH] mempool: fix mbox_ring free not call recv_finish_burst - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 16 ++++++++++++++-- - src/lstack/include/lstack_lockless_queue.h | 8 ++++---- - src/lstack/include/lstack_sockio.h | 2 +- - src/lstack/include/mbox_ring.h | 8 +++++--- - 4 files changed, 24 insertions(+), 10 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 0bd31ab..66e84d2 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -1410,9 +1410,11 @@ static int sockio_mbox_init(struct lwip_sock *sock) - return ret; - } - --bool sockio_mbox_pending(const struct lwip_sock *sock) -+bool sockio_mbox_pending(struct lwip_sock *sock) - { -- struct rpc_msg *msg; -+ const struct rpc_msg *msg; -+ const struct mbox_ring *mr; -+ err_t err; - - if (POSIX_IS_CLOSED(sock)) - return false; -@@ -1428,6 +1430,16 @@ bool sockio_mbox_pending(const struct lwip_sock *sock) - if (msg != NULL && !lockless_queue_node_is_poped(&msg->queue_node)) { - return true; - } -+ -+ /* PEEK lastdata is only used to mark the last read location and not for releasing. -+ * all peek bufs should free after pk_ring_dequeue_burst. */ -+ mr = &sock->conn->recvmbox->mring; -+ if (mr->flags & MBOX_FLAG_PEEK && mr->flags & MBOX_FLAG_TCP) { -+ if (sock->lastdata.pbuf != NULL && -+ !lwip_netconn_is_err_msg(sock->lastdata.pbuf, &err)) { -+ sock->lastdata.pbuf = NULL; -+ } -+ } - } - - return false; -diff --git a/src/lstack/include/lstack_lockless_queue.h b/src/lstack/include/lstack_lockless_queue.h -index bec2564..4f9b37b 100644 ---- a/src/lstack/include/lstack_lockless_queue.h -+++ b/src/lstack/include/lstack_lockless_queue.h -@@ -33,7 +33,7 @@ static inline void lockless_queue_node_set_poped(lockless_queue_node *node) - node->next = node; - } - --static inline bool lockless_queue_node_is_poped(lockless_queue_node *node) -+static inline bool lockless_queue_node_is_poped(const lockless_queue_node *node) - { - return node->next == node; - } -@@ -60,18 +60,18 @@ static inline void lockless_queue_init(lockless_queue *queue) - queue->stub.next = NULL; - } - --static inline bool lockless_queue_empty(lockless_queue *queue) -+static inline bool lockless_queue_empty(const lockless_queue *queue) - { - return (queue->head == queue->tail) && (queue->tail == &queue->stub); - } - --static inline int32_t lockless_queue_count(lockless_queue *queue) -+static inline int32_t lockless_queue_count(const lockless_queue *queue) - { - if (lockless_queue_empty(queue)) { - return 0; - } - -- lockless_queue_node *tail = queue->tail; -+ const lockless_queue_node *tail = queue->tail; - if (tail == &queue->stub) { - tail = queue->stub.next; - } -diff --git a/src/lstack/include/lstack_sockio.h b/src/lstack/include/lstack_sockio.h -index f4e5e99..265d620 100644 ---- a/src/lstack/include/lstack_sockio.h -+++ b/src/lstack/include/lstack_sockio.h -@@ -32,7 +32,7 @@ ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt); - - - void sockio_ops_init(void); --bool sockio_mbox_pending(const struct lwip_sock *sock); -+bool sockio_mbox_pending(struct lwip_sock *sock); - - /* just for lwip */ - int do_lwip_init_sock(int fd); -diff --git a/src/lstack/include/mbox_ring.h b/src/lstack/include/mbox_ring.h -index f6acdef..2e3ac6a 100644 ---- a/src/lstack/include/mbox_ring.h -+++ b/src/lstack/include/mbox_ring.h -@@ -84,6 +84,9 @@ void mbox_ring_common_free(struct mbox_ring *mr) - obj = mr->ops->pop_tail(mr, NULL); - if (obj != NULL) - mr->obj_free_fn(mr, obj, true); -+ -+ if (mr->flags & MBOX_FLAG_RECV) -+ mr->ops->recv_finish_burst(mr); - while (true) { - if (mr->ops->dequeue_burst(mr, &obj, 1) == 0) - break; -@@ -479,9 +482,8 @@ static inline - void pk_ring_destroy(struct mbox_ring *mr) - { - void *obj; -- while (mr->ops->recv_start_burst(mr, &obj, 1) > 0) { -- mr->ops->recv_finish_burst(mr); -- } -+ while (mr->ops->recv_start_burst(mr, &obj, 1) > 0) { } -+ mr->ops->recv_finish_burst(mr); - return; - } - --- -2.33.0 - diff --git a/0342-mempool-mem_get_rpc-add-reserve-limit.patch b/0342-mempool-mem_get_rpc-add-reserve-limit.patch deleted file mode 100644 index 49c96f4..0000000 --- a/0342-mempool-mem_get_rpc-add-reserve-limit.patch +++ /dev/null @@ -1,363 +0,0 @@ -From 5ce675c15ae4312d115686ce6f6ac7fb322b6f10 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 22 Apr 2025 15:03:00 +0800 -Subject: [PATCH] mempool: mem_get_rpc add reserve limit - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockctl.c | 24 ++++++++-------- - src/lstack/api/lstack_sockio.c | 2 +- - src/lstack/core/lstack_control_plane.c | 4 +-- - src/lstack/core/lstack_mempool.c | 37 +++++++++++++++++-------- - src/lstack/core/lstack_protocol_stack.c | 2 +- - src/lstack/core/lstack_thread_rpc.c | 10 +++---- - src/lstack/include/lstack_mempool.h | 3 +- - src/lstack/include/lstack_thread_rpc.h | 2 +- - 8 files changed, 49 insertions(+), 35 deletions(-) - -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index d1ef36a..f53b4cd 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -60,7 +60,7 @@ static void callback_setsockopt(struct rpc_msg *msg) - static int rpc_call_getpeername(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getpeername); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_getpeername); - if (msg == NULL) { - return -1; - } -@@ -75,7 +75,7 @@ static int rpc_call_getpeername(int stack_id, int fd, struct sockaddr *addr, soc - static int rpc_call_getsockname(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getsockname); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_getsockname); - if (msg == NULL) { - return -1; - } -@@ -90,7 +90,7 @@ static int rpc_call_getsockname(int stack_id, int fd, struct sockaddr *addr, soc - static int rpc_call_getsockopt(int stack_id, int fd, int level, int optname, void *optval, socklen_t *optlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_getsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_getsockopt); - if (msg == NULL) { - return -1; - } -@@ -107,7 +107,7 @@ static int rpc_call_getsockopt(int stack_id, int fd, int level, int optname, voi - static int rpc_call_setsockopt(int stack_id, int fd, int level, int optname, const void *optval, socklen_t optlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_setsockopt); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_setsockopt); - if (msg == NULL) { - return -1; - } -@@ -169,7 +169,7 @@ static void callback_socket(struct rpc_msg *msg) - static int rpc_call_socket(int stack_id, int domain, int type, int protocol) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_socket); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, true, callback_socket); - if (msg == NULL) { - return -1; - } -@@ -221,7 +221,7 @@ static void callback_shutdown(struct rpc_msg *msg) - static int rpc_call_close(int stack_id, int fd) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_close); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_close); - if (msg == NULL) { - return -1; - } -@@ -234,7 +234,7 @@ static int rpc_call_close(int stack_id, int fd) - static int rpc_call_shutdown(int stack_id, int fd, int how) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_shutdown); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_shutdown); - if (msg == NULL) { - return -1; - } -@@ -256,7 +256,7 @@ static void callback_bind(struct rpc_msg *msg) - static int rpc_call_bind(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_bind); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_bind); - if (msg == NULL) { - return -1; - } -@@ -289,7 +289,7 @@ static void callback_listen(struct rpc_msg *msg) - static int rpc_call_listen(int stack_id, int s, int backlog) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_listen); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_listen); - if (msg == NULL) { - return -1; - } -@@ -374,7 +374,7 @@ static void callback_create_shadow_fd(struct rpc_msg *msg) - static int rpc_call_shadow_fd(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_create_shadow_fd); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_create_shadow_fd); - if (msg == NULL) { - return -1; - } -@@ -407,7 +407,7 @@ static void callback_accept(struct rpc_msg *msg) - static int rpc_call_accept(int stack_id, int fd, struct sockaddr *addr, socklen_t *addrlen, int flags) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_accept); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_accept); - if (msg == NULL) { - return -1; - } -@@ -431,7 +431,7 @@ static void callback_connect(struct rpc_msg *msg) - static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, socklen_t addrlen) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_connect); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_connect); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 66e84d2..9eafc22 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -143,7 +143,7 @@ static void sock_mbox_private_free(struct mbox_ring *mr) - - static int sock_mbox_private_init(sys_mbox_t mb, rpc_func_t func) - { -- struct rpc_msg *msg = rpc_msg_alloc(get_protocol_stack()->stack_idx, func); -+ struct rpc_msg *msg = rpc_msg_alloc(get_protocol_stack()->stack_idx, true, func); - if (msg == NULL) - return -1; - -diff --git a/src/lstack/core/lstack_control_plane.c b/src/lstack/core/lstack_control_plane.c -index 9d9e012..6ad0192 100644 ---- a/src/lstack/core/lstack_control_plane.c -+++ b/src/lstack/core/lstack_control_plane.c -@@ -432,7 +432,7 @@ static void thread_register_phase2(struct rpc_msg *msg) - static int rpc_call_thread_regphase1(int stack_id, void *conn) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, thread_register_phase1); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, thread_register_phase1); - if (msg == NULL) { - return -1; - } -@@ -443,7 +443,7 @@ static int rpc_call_thread_regphase1(int stack_id, void *conn) - static int rpc_call_thread_regphase2(int stack_id, void *conn) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, thread_register_phase2); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, thread_register_phase2); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index b03c3ef..00b299a 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -67,16 +67,24 @@ struct rte_mempool *mem_get_rpc_pool(int stack_id) - - unsigned mem_stack_mbuf_pool_count(int stack_id) - { -- struct mem_stack *ms = mem_stack_get(stack_id); -+ const struct mem_stack *ms = mem_stack_get(stack_id); - return rte_mempool_avail_count(ms->mbuf_pool); - } - - unsigned mem_stack_rpc_pool_count(int stack_id) - { -- struct mem_stack *ms = mem_stack_get(stack_id); -+ const struct mem_stack *ms = mem_stack_get(stack_id); - return rte_mempool_avail_count(ms->rpc_pool); - } - -+static inline unsigned mem_stack_pool_ring_count(const struct rte_mempool *pool) -+{ -+ /* don't use rte_mempool_avail_count, it traverse cpu local cache, -+ * when RTE_MAX_LCORE is too large, it's time-consuming -+ */ -+ return rte_ring_count(pool->pool_data); -+} -+ - static inline bool mem_thread_group_in_used(const struct mem_thread_group *mt_grooup, uint32_t timeout) - { - return mt_grooup->used_flag || -@@ -484,8 +492,7 @@ static struct rte_mempool *rpc_pool_create(int stack_id, unsigned numa_id) - struct rte_mempool *pool; - uint32_t total_bufs; - -- total_bufs = MEMPOOL_CACHE_NUM + BUF_CACHE_MIN_NUM + -- (get_global_cfg_params()->rpc_msg_max / get_global_cfg_params()->num_queue); -+ total_bufs = RPCPOOL_RESERVE_NUM + MEMP_NUM_SYS_MBOX; - if (total_bufs > MEMPOOL_MAX_NUM) { - LSTACK_LOG(ERR, LSTACK, "total_bufs %u out of the dpdk mempool range\n", total_bufs); - return NULL; -@@ -695,7 +702,7 @@ void mem_mbuf_migrate_enqueue(struct mem_thread *mt, unsigned n) - return; - - /* no sufficient mbuf */ -- if (rte_ring_count(ms->mbuf_pool->pool_data) < MBUFPOOL_RESERVE_NUM) { -+ if (mem_stack_pool_ring_count(ms->mbuf_pool) < MBUFPOOL_RESERVE_NUM) { - mem_thread_manager_flush_all(); - mt->stk_migrate_count = 0; - return; -@@ -780,7 +787,8 @@ static unsigned pool_get_bulk_with_cache(const struct mempool_ops *pool_ops, - /* get from the pool */ - ret = pool_ops->get_bulk(pool, obj_table, n); - if (unlikely(ret == 0)) { -- LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u\n", pool->name, n); -+ LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u, count %u\n", -+ pool->name, n, mem_stack_pool_ring_count(pool)); - return 0; - } - -@@ -796,7 +804,8 @@ static unsigned pool_get_bulk_with_cache(const struct mempool_ops *pool_ops, - - ret = pool_ops->get_bulk(pool, &cache->objs[cache->head], get_count); - if (unlikely(ret == 0)) { -- LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u\n", pool->name, get_count); -+ LSTACK_LOG(ERR, LSTACK, "pool %s get_bulk failed, n %u, count %u\n", -+ pool->name, get_count, mem_stack_pool_ring_count(pool)); - } else { - cache->head += get_count; - } -@@ -839,13 +848,20 @@ static void pool_put_bulk_with_cache(const struct mempool_ops *pool_ops, - } - - --void *mem_get_rpc(int stack_id) -+void *mem_get_rpc(int stack_id, bool reserve) - { - struct mem_stack *ms = mem_stack_get(stack_id); - struct mem_thread *mt = mem_thread_get(stack_id); - unsigned ret; - void *obj; - -+ if (reserve) { -+ if (mem_stack_pool_ring_count(ms->rpc_pool) < RPCPOOL_RESERVE_NUM) { -+ mem_thread_manager_flush_all(); -+ return NULL; -+ } -+ } -+ - if (mt == NULL) { - ret = mem_mp_ops.get_bulk(ms->rpc_pool, &obj, 1); - } else { -@@ -887,10 +903,7 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - } - - if (reserve) { -- /* don't use rte_mempool_avail_count, it traverse cpu local cache, -- * when RTE_MAX_LCORE is too large, it's time-consuming -- */ -- if (rte_ring_count(ms->mbuf_pool->pool_data) < MBUFPOOL_RESERVE_NUM + n) { -+ if (mem_stack_pool_ring_count(ms->mbuf_pool) < MBUFPOOL_RESERVE_NUM + n) { - mem_thread_manager_flush_all(); - return 0; - } -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index c07d8e7..d375ecc 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -750,7 +750,7 @@ static void stack_exit_by_rpc(struct rpc_msg *msg) - static int rpc_call_stack_exit(int stack_id) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, stack_exit_by_rpc); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, stack_exit_by_rpc); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/core/lstack_thread_rpc.c b/src/lstack/core/lstack_thread_rpc.c -index 84e5814..6bf83d0 100644 ---- a/src/lstack/core/lstack_thread_rpc.c -+++ b/src/lstack/core/lstack_thread_rpc.c -@@ -41,11 +41,11 @@ static void rpc_msg_init(struct rpc_msg *msg, rpc_func_t func) - lockless_queue_node_set_poped(&msg->queue_node); - } - --struct rpc_msg *rpc_msg_alloc(int stack_id, rpc_func_t func) -+struct rpc_msg *rpc_msg_alloc(int stack_id, bool reserve, rpc_func_t func) - { - struct rpc_msg *msg; - -- msg = mem_get_rpc(stack_id); -+ msg = mem_get_rpc(stack_id, reserve); - if (unlikely(msg == NULL)) { - g_rpc_stats.call_alloc_fail++; - return NULL; -@@ -152,7 +152,7 @@ static void callback_arp(struct rpc_msg *msg) - int rpc_call_arp(int stack_id, void *mbuf) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_arp); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_arp); - if (msg == NULL) { - return -1; - } -@@ -290,7 +290,7 @@ static void callback_get_connnum(struct rpc_msg *msg) - int rpc_call_conntable(int stack_id, void *conn_table, unsigned max_conn) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->dfx_rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_get_conntable); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_get_conntable); - if (msg == NULL) { - return -1; - } -@@ -304,7 +304,7 @@ int rpc_call_conntable(int stack_id, void *conn_table, unsigned max_conn) - int rpc_call_connnum(int stack_id) - { - rpc_queue *queue = &get_protocol_stack_by_id(stack_id)->dfx_rpc_queue; -- struct rpc_msg *msg = rpc_msg_alloc(stack_id, callback_get_connnum); -+ struct rpc_msg *msg = rpc_msg_alloc(stack_id, false, callback_get_connnum); - if (msg == NULL) { - return -1; - } -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index 131029e..6a31503 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -40,6 +40,7 @@ - - #define MBUFPOOL_CACHE_NUM LWIP_MIN(NIC_QUEUE_SIZE_MAX >> 1, RTE_MEMPOOL_CACHE_MAX_SIZE) - #define MBUFPOOL_RESERVE_NUM (NIC_QUEUE_SIZE_MAX + MBUFPOOL_CACHE_NUM) -+#define RPCPOOL_RESERVE_NUM 512 - - #define MEMPOOL_OPS_NAME "ring_mt_rts" - #define MEMPOOL_CACHE_NUM 32 -@@ -307,7 +308,7 @@ struct rte_mempool *mem_get_rpc_pool(int stack_id); - unsigned mem_stack_mbuf_pool_count(int stack_id); - unsigned mem_stack_rpc_pool_count(int stack_id); - --void *mem_get_rpc(int stack_id); -+void *mem_get_rpc(int stack_id, bool reserve); - void mem_put_rpc(void *obj); - - struct mem_thread *mem_thread_migrate_get(int stack_id); -diff --git a/src/lstack/include/lstack_thread_rpc.h b/src/lstack/include/lstack_thread_rpc.h -index 013ff29..2d577ae 100644 ---- a/src/lstack/include/lstack_thread_rpc.h -+++ b/src/lstack/include/lstack_thread_rpc.h -@@ -64,7 +64,7 @@ struct rpc_msg { - - void rpc_get_stat(rpc_queue *queue, struct gazelle_rpc_stat *stat); - --struct rpc_msg *rpc_msg_alloc(int stack_id, rpc_func_t func); -+struct rpc_msg *rpc_msg_alloc(int stack_id, bool reserve, rpc_func_t func); - void rpc_msg_free(struct rpc_msg *msg); - - void rpc_queue_init(rpc_queue *queue, uint16_t queue_id); --- -2.33.0 - diff --git a/0343-mempool-fix-pthread_tryjoin_np-coredump-when-mysqld-.patch b/0343-mempool-fix-pthread_tryjoin_np-coredump-when-mysqld-.patch deleted file mode 100644 index 073073b..0000000 --- a/0343-mempool-fix-pthread_tryjoin_np-coredump-when-mysqld-.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 00b47db8233ba31eabf0b8c4b3b015607afdcf78 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 23 Apr 2025 09:26:45 +0800 -Subject: [PATCH] mempool: fix pthread_tryjoin_np coredump when mysqld shutdown - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_mempool.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 00b299a..4dd7574 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -23,6 +23,8 @@ - #include "lstack_protocol_stack.h" - #include "lstack_unistd.h" - -+#define MEM_THREAD_TASK_PATH "/proc/%d/task/%d/stat" -+#define MEM_THREAD_MAX_PATH 32 /* cat /proc/sys/kernel/pid_max */ - #define MEM_THREAD_FLUSH_SIG (SIGRTMIN + 11) - #define MEM_THREAD_MANAGER_FLUSH_MS 100 - #define MEM_THREAD_MANAGER_FREE_S 2 -@@ -36,6 +38,7 @@ struct mem_thread_manager { - }; - - struct mem_thread_group { -+ char task_path[MEM_THREAD_MAX_PATH]; - int tid; - pthread_t thread; - struct list_node mt_node; -@@ -156,8 +159,13 @@ static inline void mem_thread_group_notify_flush(const struct mem_thread_group * - - static inline bool mem_thread_group_exist(const struct mem_thread_group *mt_group) - { -- if (pthread_tryjoin_np(mt_group->thread, NULL) == 0) -- return false; -+ if (access(mt_group->task_path, R_OK) != 0) { -+ if (errno == ENOENT) { -+ return false; -+ } -+ LSTACK_LOG(ERR, LSTACK, "mem_thread_group_exist access %s failed, errno %d\n", -+ mt_group->task_path, errno); -+ } - return true; - } - -@@ -200,6 +208,8 @@ static int mem_thread_group_init(int stack_id) - - g_mem_thread_group->tid = rte_gettid(); - g_mem_thread_group->thread = pthread_self(); -+ SYS_FORMAT_NAME(g_mem_thread_group->task_path, sizeof(g_mem_thread_group->task_path), -+ MEM_THREAD_TASK_PATH, getpid(), g_mem_thread_group->tid); - list_init_node(&g_mem_thread_group->mt_node); - mem_thread_manager_add_work(g_mem_thread_group); - } --- -2.33.0 - diff --git a/0344-mempool-stop-using-cache-when-too-many-threads.patch b/0344-mempool-stop-using-cache-when-too-many-threads.patch deleted file mode 100644 index ae5f15d..0000000 --- a/0344-mempool-stop-using-cache-when-too-many-threads.patch +++ /dev/null @@ -1,158 +0,0 @@ -From ce877b0e0171bc878a4b0a19f328634381bfa375 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 23 Apr 2025 14:20:08 +0800 -Subject: [PATCH] mempool: stop using cache when too many threads - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_mempool.c | 53 ++++++++++++++++++++++---------- - 1 file changed, 36 insertions(+), 17 deletions(-) - -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 4dd7574..70ac8c6 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -35,6 +35,7 @@ struct mem_thread_manager { - struct list_node mt_free_list; - rte_spinlock_t list_lock; - uint32_t flush_time; -+ unsigned thread_num; - }; - - struct mem_thread_group { -@@ -173,6 +174,7 @@ static void mem_thread_manager_add_work(struct mem_thread_group *mt_group) - { - rte_spinlock_lock(&g_mem_thread_manager.list_lock); - list_add_node(&mt_group->mt_node, &g_mem_thread_manager.mt_work_list); -+ g_mem_thread_manager.thread_num++; - rte_spinlock_unlock(&g_mem_thread_manager.list_lock); - } - -@@ -305,6 +307,7 @@ static void *mem_thread_manager_thread(void *arg) - } - list_del_node(node); - list_add_node(node, &g_mem_thread_manager.mt_free_list); -+ g_mem_thread_manager.thread_num--; - } - - rte_spinlock_unlock(&g_mem_thread_manager.list_lock); -@@ -502,7 +505,7 @@ static struct rte_mempool *rpc_pool_create(int stack_id, unsigned numa_id) - struct rte_mempool *pool; - uint32_t total_bufs; - -- total_bufs = RPCPOOL_RESERVE_NUM + MEMP_NUM_SYS_MBOX; -+ total_bufs = LWIP_MAX(RPCPOOL_RESERVE_NUM, MBUFPOOL_RESERVE_NUM) + MEMP_NUM_SYS_MBOX; - if (total_bufs > MEMPOOL_MAX_NUM) { - LSTACK_LOG(ERR, LSTACK, "total_bufs %u out of the dpdk mempool range\n", total_bufs); - return NULL; -@@ -783,7 +786,7 @@ void pool_put_with_bufcache(struct rte_mempool *pool, struct buf_cache* cache, v - - static unsigned pool_get_bulk_with_cache(const struct mempool_ops *pool_ops, - struct rte_mempool *pool, struct buf_cache *cache, -- void **obj_table, unsigned n) -+ void **obj_table, unsigned n, unsigned pool_count) - { - unsigned ret; - unsigned count = 0; -@@ -802,6 +805,13 @@ static unsigned pool_get_bulk_with_cache(const struct mempool_ops *pool_ops, - return 0; - } - -+ /* Stop using cache when too many threads. */ -+ ret = MBUFPOOL_RESERVE_NUM + BUF_CACHE_MIN_NUM * g_mem_thread_manager.thread_num; -+ if (unlikely(ret > pool_count)) { -+ buf_cache_reset_watermark(cache); -+ return n; -+ } -+ - buf_cache_add_watermark(cache); - if (count >= cache->watermark) { - return n; -@@ -862,27 +872,32 @@ void *mem_get_rpc(int stack_id, bool reserve) - { - struct mem_stack *ms = mem_stack_get(stack_id); - struct mem_thread *mt = mem_thread_get(stack_id); -- unsigned ret; -+ unsigned ret = 0; -+ unsigned pool_count; - void *obj; - -- if (reserve) { -- if (mem_stack_pool_ring_count(ms->rpc_pool) < RPCPOOL_RESERVE_NUM) { -- mem_thread_manager_flush_all(); -- return NULL; -- } -+ pool_count = mem_stack_pool_ring_count(ms->rpc_pool); -+ if (reserve && pool_count < RPCPOOL_RESERVE_NUM) { -+ goto out; - } - - if (mt == NULL) { - ret = mem_mp_ops.get_bulk(ms->rpc_pool, &obj, 1); - } else { - mem_thread_group_used(); -- ret = pool_get_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, &obj, 1); -+ ret = pool_get_bulk_with_cache(&mem_mp_ops, ms->rpc_pool, mt->rpc_cache, -+ &obj, 1, pool_count); - mem_thread_group_done(); - } - - LWIP_DEBUGF(MEMP_DEBUG, ("%s(stack_id=%d, obj=%p)\n", __FUNCTION__, stack_id, obj)); - -- return ret == 0 ? NULL : obj; -+out: -+ if (unlikely(ret == 0)) { -+ mem_thread_manager_flush_all(); -+ return NULL; -+ } -+ return obj; - } - - void mem_put_rpc(void *obj) -@@ -906,17 +921,16 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - { - struct mem_stack *ms = mem_stack_get(stack_id); - struct mem_thread *mt = mem_thread_get(stack_id); -- unsigned ret; -+ unsigned ret = 0; -+ unsigned pool_count; - - if (unlikely(n == 0)) { - return 0; - } - -- if (reserve) { -- if (mem_stack_pool_ring_count(ms->mbuf_pool) < MBUFPOOL_RESERVE_NUM + n) { -- mem_thread_manager_flush_all(); -- return 0; -- } -+ pool_count = mem_stack_pool_ring_count(ms->mbuf_pool); -+ if (reserve && pool_count < MBUFPOOL_RESERVE_NUM + n) { -+ goto out; - } - - if (mt == NULL) { -@@ -924,7 +938,8 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - } else { - mem_thread_group_used(); - mem_mbuf_migrate_dequeue(mt); -- ret = pool_get_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, (void **)mbuf_table, n); -+ ret = pool_get_bulk_with_cache(&mbuf_mp_ops, ms->mbuf_pool, mt->mbuf_cache, -+ (void **)mbuf_table, n, pool_count); - mem_thread_group_done(); - } - -@@ -935,6 +950,10 @@ unsigned mem_get_mbuf_bulk(int stack_id, struct rte_mbuf **mbuf_table, unsigned - } - #endif /* MEMP_DEBUG */ - -+out: -+ if (unlikely(ret == 0)) { -+ mem_thread_manager_flush_all(); -+ } - return ret; - } - --- -2.33.0 - diff --git a/0345-sk_wait-fix-lwip_tcp_allow_send-coredump.patch b/0345-sk_wait-fix-lwip_tcp_allow_send-coredump.patch deleted file mode 100644 index 95cbae8..0000000 --- a/0345-sk_wait-fix-lwip_tcp_allow_send-coredump.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f0e0a9cdff414f1089173ea86e697ea3118623eb Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 23 Apr 2025 16:34:08 +0800 -Subject: [PATCH] sk_wait: fix lwip_tcp_allow_send coredump - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_wait.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 816f340..d9db582 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -366,15 +366,22 @@ static inline bool NETCONN_NEED_RECV(const struct lwip_sock *sock) - - static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) - { -+ if (sock->conn->pcb.tcp == NULL) { -+ return false; -+ } -+ - if (get_global_cfg_params()->stack_mode_rtc) { - if (NETCONN_TYPE(sock->conn) == NETCONN_TCP) - return lwip_tcp_allow_send(sock->conn->pcb.tcp); -- return false; -- } -- if (sys_mbox_valid(&sock->conn->sendmbox)) { -- const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -- return mr->ops->free_count(mr) > 0; -+ else /* if UDP */ -+ return true; -+ } else { /* if RTW */ -+ if (sys_mbox_valid(&sock->conn->sendmbox)) { -+ const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ return mr->ops->free_count(mr) > 0; -+ } - } -+ - return false; - } - --- -2.33.0 - diff --git a/0346-mbox-fix-mbox_ring_common_free-coredump-when-rte_rin.patch b/0346-mbox-fix-mbox_ring_common_free-coredump-when-rte_rin.patch deleted file mode 100644 index fe8c61b..0000000 --- a/0346-mbox-fix-mbox_ring_common_free-coredump-when-rte_rin.patch +++ /dev/null @@ -1,52 +0,0 @@ -From c9285237af5d95fc4014963ab9fae2327a0bd265 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 25 Apr 2025 15:09:27 +0800 -Subject: [PATCH] mbox: fix mbox_ring_common_free coredump when rte_ring_create - failed - -Signed-off-by: Lemmy Huang ---- - src/lstack/include/mbox_ring.h | 20 ++++++++++++-------- - 1 file changed, 12 insertions(+), 8 deletions(-) - -diff --git a/src/lstack/include/mbox_ring.h b/src/lstack/include/mbox_ring.h -index 2e3ac6a..893c636 100644 ---- a/src/lstack/include/mbox_ring.h -+++ b/src/lstack/include/mbox_ring.h -@@ -85,12 +85,14 @@ void mbox_ring_common_free(struct mbox_ring *mr) - if (obj != NULL) - mr->obj_free_fn(mr, obj, true); - -- if (mr->flags & MBOX_FLAG_RECV) -- mr->ops->recv_finish_burst(mr); -- while (true) { -- if (mr->ops->dequeue_burst(mr, &obj, 1) == 0) -- break; -- mr->obj_free_fn(mr, obj, false); -+ if (mr->ring != NULL) { -+ if (mr->flags & MBOX_FLAG_RECV) -+ mr->ops->recv_finish_burst(mr); -+ while (true) { -+ if (mr->ops->dequeue_burst(mr, &obj, 1) == 0) -+ break; -+ mr->obj_free_fn(mr, obj, false); -+ } - } - } - -@@ -482,8 +484,10 @@ static inline - void pk_ring_destroy(struct mbox_ring *mr) - { - void *obj; -- while (mr->ops->recv_start_burst(mr, &obj, 1) > 0) { } -- mr->ops->recv_finish_burst(mr); -+ if (mr->ring != NULL) { -+ while (mr->ops->recv_start_burst(mr, &obj, 1) > 0) { } -+ mr->ops->recv_finish_burst(mr); -+ } - return; - } - --- -2.33.0 - diff --git a/0347-sk_wait-fix-sock_wait_common_free.patch b/0347-sk_wait-fix-sock_wait_common_free.patch deleted file mode 100644 index 976d7c2..0000000 --- a/0347-sk_wait-fix-sock_wait_common_free.patch +++ /dev/null @@ -1,62 +0,0 @@ -From bd6149bf56dd26a67f835be5b4bc4d36ca8bca96 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Thu, 24 Apr 2025 10:03:25 +0800 -Subject: [PATCH] sk_wait: fix sock_wait_common_free socket: simplify calling - free_count in rtw_stack_tcp_write - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 13 +++---------- - src/lstack/core/lstack_wait.c | 5 +++-- - 2 files changed, 6 insertions(+), 12 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 9eafc22..aff9d6d 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -671,7 +671,8 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - return -1; - } - -- if (unlikely(mr->app_free_count < 2)) { -+ if (unlikely(mr->app_free_count < 2) || -+ total_copy_len > mr->app_free_count * TCP_MSS) { - mr->app_free_count = mr->ops->free_count(mr); - if (unlikely(mr->app_free_count < 2)) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -@@ -691,15 +692,7 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - copied_total += rtw_stack_tcp_write_one(sock, mr, data + copied_total, total_copy_len, flags); - } else { - if (total_copy_len > mr->app_free_count * TCP_MSS) { -- mr->app_free_count = mr->ops->free_count(mr); -- if (unlikely(mr->app_free_count < 2)) { -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- set_errno(EWOULDBLOCK); -- goto out; -- } -- if (total_copy_len > mr->app_free_count * TCP_MSS) { -- total_copy_len = mr->app_free_count * TCP_MSS; -- } -+ total_copy_len = mr->app_free_count * TCP_MSS; - } - /* write bulk pbuf */ - while (total_copy_len > 0) { -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index d9db582..d0e8d82 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -307,8 +307,9 @@ void sock_wait_common_free(struct sock_wait *sk_wait) - do { - wait_stack = false; - for (int i = 0; i < PROTOCOL_STACK_MAX; ++i) { -- rte_mb(); -- if (!list_node_null(&sk_wait->stk_notify_node[i])) { -+ rte_rmb(); -+ if (!list_node_null(&sk_wait->stk_notify_node[i]) || -+ !list_head_empty(&sk_wait->stk_event_list[i])) { - wait_stack = true; - usleep(LWIP_EVENT_WAIT_US); - break; --- -2.33.0 - diff --git a/0348-socket-fix-stack_udp_readmsg-return-len.patch b/0348-socket-fix-stack_udp_readmsg-return-len.patch deleted file mode 100644 index 4c82756..0000000 --- a/0348-socket-fix-stack_udp_readmsg-return-len.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 329cbd6b63b4954c01caf9023007557f5efe7b27 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 25 Apr 2025 20:37:39 +0800 -Subject: [PATCH] socket: fix stack_udp_readmsg return len - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index aff9d6d..4c524ab 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -483,7 +483,7 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, siz - struct pbuf **extcache_list; - struct netbuf *nbuf; - err_t err = ERR_OK; -- uint16_t copied_total = 0; -+ uint16_t total_len = 0; - - LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(sock=%p, msg=%p, size=%"SZT_F", flags=0x%x)\n", - __FUNCTION__, sock, msg, len, flags)); -@@ -506,11 +506,11 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, siz - - /* let not free inside by MSG_PEEK */ - sock->lastdata.netbuf = nbuf; -- err = lwip_recvfrom_udp_raw(sock, flags | MSG_PEEK, msg, &copied_total, 0); -+ err = lwip_recvfrom_udp_raw(sock, flags | MSG_PEEK, msg, &total_len, 0); - sock->lastdata.netbuf = NULL; - - SOCK_WAIT_STAT(sock->sk_wait, app_read_cnt, 1); -- SOCK_WAIT_STAT(sock->sk_wait, sock_rx_drop, copied_total < len ? 1 : 0); -+ SOCK_WAIT_STAT(sock->sk_wait, sock_rx_drop, total_len > len ? 1 : 0); - if (get_protocol_stack_group()->latency_start) - calculate_lstack_latency(sock->stack_id, &nbuf->p, 1, GAZELLE_LATENCY_READ_LSTACK, 0); - -@@ -521,7 +521,7 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, siz - mem_extcache_put_pbuf(nbuf->p, NULL, extcache_list); - } - -- mr->app_recvd_len += copied_total; -+ mr->app_recvd_len += total_len; - mr->app_queued_num++; - if (mr->app_queued_num >= RECV_EXTEND_CACHE_MAX || - mr->app_recvd_len >= RECV_EXTEND_CACHE_LEN) { -@@ -534,8 +534,8 @@ static ssize_t stack_udp_readmsg(struct lwip_sock *sock, struct msghdr *msg, siz - } - - if (err == ERR_OK) { -- API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, copied_total); -- return copied_total; -+ API_EVENT(sock->conn, NETCONN_EVT_RCVMINUS, total_len); -+ return LWIP_MIN(len, total_len); - } - out: - SOCK_WAIT_STAT(sock->sk_wait, read_null, 1); --- -2.33.0 - diff --git a/0349-sk_wait-fix-lwip_wait_foreach_notify-coredump-at-sta.patch b/0349-sk_wait-fix-lwip_wait_foreach_notify-coredump-at-sta.patch deleted file mode 100644 index dc3473c..0000000 --- a/0349-sk_wait-fix-lwip_wait_foreach_notify-coredump-at-sta.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 1ff5ffd3634c61c6d6062b51d418b41b3a6a86d0 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 25 Apr 2025 21:40:16 +0800 -Subject: [PATCH] sk_wait: fix lwip_wait_foreach_notify coredump at startup - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_protocol_stack.c | 1 + - src/lstack/core/lstack_wait.c | 3 +-- - src/lstack/include/lstack_wait.h | 2 ++ - 3 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/core/lstack_protocol_stack.c b/src/lstack/core/lstack_protocol_stack.c -index d375ecc..8ff6981 100644 ---- a/src/lstack/core/lstack_protocol_stack.c -+++ b/src/lstack/core/lstack_protocol_stack.c -@@ -425,6 +425,7 @@ static struct protocol_stack *stack_thread_init(void *arg) - stack_affinity_numa(stack->numa_id); - } - -+ lwip_wait_init(stack->stack_idx); - if (mem_stack_mpcache_init(stack->stack_idx, stack->cpu_id) < 0) { - goto END; - } -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index d0e8d82..42ebf05 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -72,7 +72,7 @@ static inline struct lwip_wait *lwip_wait_get(int stack_id) - return &g_wait_group.lwaits[stack_id]; - } - --static int lwip_wait_init(int stack_id) -+int lwip_wait_init(int stack_id) - { - struct lwip_wait *lwait = lwip_wait_get(stack_id); - LWIP_UNUSED_ARG(lwait); -@@ -191,7 +191,6 @@ void* kernel_wait_thread(void *arg) - free(arg); - sem_post(&get_protocol_stack_group()->sem_stack_setup); - -- lwip_wait_init(stack_id); - kernel_wait_init(stack_id); - kwait = kernel_wait_get(stack_id); - -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -index a1d35dd..58da126 100644 ---- a/src/lstack/include/lstack_wait.h -+++ b/src/lstack/include/lstack_wait.h -@@ -110,6 +110,8 @@ struct sock_wait { - int sock_wait_group_init(void); - void sock_wait_group_stat(int stack_id, struct gazelle_wakeup_stat *stat); - -+int lwip_wait_init(int stack_id); -+ - void* kernel_wait_thread(void *arg); - int kernel_wait_ctl(struct sock_wait *sk_wait, int new_stack_id, int old_stack_id); - --- -2.33.0 - diff --git a/0350-epoll-fix-do_lwip_connected_callback.patch b/0350-epoll-fix-do_lwip_connected_callback.patch deleted file mode 100644 index ed88faf..0000000 --- a/0350-epoll-fix-do_lwip_connected_callback.patch +++ /dev/null @@ -1,212 +0,0 @@ -From b872ae2d9b0aca063e14aa0648d13e49af494a75 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 22 Apr 2025 15:41:53 +0800 -Subject: [PATCH] epoll: fix do_lwip_connected_callback - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 46 +++++++++++++++++++------------ - src/lstack/api/lstack_sockctl.c | 22 --------------- - src/lstack/api/lstack_wrap.c | 25 +++++++++++++++++ - src/lstack/core/lstack_wait.c | 3 +- - src/lstack/include/lstack_epoll.h | 3 ++ - 5 files changed, 58 insertions(+), 41 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 19cc9d6..1a10e24 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -219,7 +219,6 @@ static int epoll_close_internal(int epfd) - sk_wait->type = WAIT_CLOSE; - epoll_cb_free(&sk_wait->epcb); - -- posix_api->close_fn(sk_wait->epfd); - sock_wait_kernel_free(sk_wait); - sock_wait_common_free(sk_wait); - -@@ -259,6 +258,25 @@ int lstack_epoll_close(int epfd) - return posix_api->close_fn(epfd); - } - -+int epoll_ctl_kernel_event(int epfd, int op, int fd, struct epoll_event *event, -+ struct sock_wait *sk_wait) -+{ -+ int ret; -+ -+ ret = posix_api->epoll_ctl_fn(epfd, op, fd, event); -+ if (ret != 0) { -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn failed, fd=%d epfd=%d op=%d\n", fd, epfd, op); -+ return ret; -+ } -+ if (op == EPOLL_CTL_ADD) { -+ sk_wait->kernel_nfds++; -+ } else if (op == EPOLL_CTL_DEL) { -+ sk_wait->kernel_nfds--; -+ } -+ -+ return ret; -+} -+ - int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - { - int ret; -@@ -278,22 +296,13 @@ int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - __FUNCTION__, epfd, op, fd, event)); - - enum posix_type sk_type = select_sock_posix_path(sock); -- /* has POSIX_LWIP */ -- if (sk_type != POSIX_LWIP) { -- ret = posix_api->epoll_ctl_fn(epfd, op, fd, event); -- if (ret != 0) { -- LSTACK_LOG(ERR, LSTACK, "epoll_ctl_fn failed, fd=%d epfd=%d op=%d\n", fd, epfd, op); -+ if (sk_type & POSIX_KERNEL) { /* has POSIX_KERNEL */ -+ ret = epoll_ctl_kernel_event(epfd, op, fd, event, sk_wait); -+ if (ret != 0 || -+ sk_type == POSIX_KERNEL) { /* is POSIX_KERNEL */ - return ret; - } -- if (op == EPOLL_CTL_ADD) { -- sk_wait->kernel_nfds++; -- } else if (op == EPOLL_CTL_DEL) { -- sk_wait->kernel_nfds--; -- } - } -- /* is POSIX_KERNEL */ -- if (sk_type == POSIX_KERNEL) -- return ret; - - for (; sock != NULL; sock = sock->listen_next) { - sk_event = &sock->sk_event; -@@ -412,7 +421,8 @@ int lstack_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int t - maxevents = POLL_MAX_EVENTS; - } - /* avoid the starvation of poll events from both kernel and lwip */ -- lwip_maxevents = (maxevents >> 1) + 1; -+ lwip_maxevents = sk_wait->kernel_nfds > 0 ? -+ (maxevents >> 1) + 1 : maxevents; - - start = sys_now(); - -@@ -555,7 +565,7 @@ struct sock_wait *poll_construct_wait(int nfds) - return g_sk_wait; - } - --static bool poll_ctl_kernel_event(int epfd, int fds_id, -+static int poll_ctl_kernel_event(int epfd, int fds_id, - const struct pollfd *new_fds, const struct pollfd *old_fds) - { - int ret; -@@ -575,11 +585,11 @@ static bool poll_ctl_kernel_event(int epfd, int fds_id, - ret |= posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_ADD, new_fds->fd, &epevent); - } - -- if (ret != 0) { -+ if (ret != 0 && errno != EINTR && errno != ENOENT) { - LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d, new_fd %d, old_fd %d\n", - errno, new_fds->fd, old_fds->fd); - } -- return true; -+ return ret; - } - - static int poll_wait_kernel_event(int epfd, struct pollfd *fds, int maxevents) -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index f53b4cd..856b24e 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -455,28 +455,6 @@ static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, s - return ret; - } - --/* for lwip nonblock connected callback */ --void do_lwip_connected_callback(int fd) --{ -- bool has_kernel; -- struct lwip_sock *sock = lwip_get_socket(fd); -- if (POSIX_IS_CLOSED(sock)) { -- return; -- } -- -- has_kernel = POSIX_HAS_TYPE(sock, POSIX_KERNEL); -- POSIX_SET_TYPE(sock, POSIX_LWIP); -- if (has_kernel) { -- /* delete kernel event */ -- if (sock->sk_wait != NULL) { -- posix_api->epoll_ctl_fn(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL); -- } -- /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -- posix_api->shutdown_fn(fd, SHUT_RDWR); -- } -- return; --} -- - /* when fd is listenfd, listenfd of all protocol stack thread will be closed */ - static int stack_broadcast_close(int fd) - { -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index e22937f..8339750 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -378,6 +378,31 @@ static int32_t do_connect(int32_t s, const struct sockaddr *addr, socklen_t addr - return ret; - } - -+/* for lwip nonblock connected callback */ -+void do_lwip_connected_callback(int fd) -+{ -+ struct lwip_sock *sock = lwip_get_socket(fd); -+ if (POSIX_IS_CLOSED(sock)) { -+ return; -+ } -+ -+ if (POSIX_HAS_TYPE(sock, POSIX_KERNEL)) { -+ POSIX_SET_TYPE(sock, POSIX_LWIP); -+ /* delete kernel event */ -+ if (sock->sk_wait != NULL) { -+ if (sock->sk_wait->type & WAIT_EPOLL) { -+ epoll_ctl_kernel_event(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL, sock->sk_wait); -+ } -+ } -+ /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -+ posix_api->shutdown_fn(fd, SHUT_RDWR); -+ } else { -+ POSIX_SET_TYPE(sock, POSIX_LWIP); -+ } -+ -+ return; -+} -+ - static inline int32_t do_listen(int32_t s, int32_t backlog) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_KERNEL) { -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 42ebf05..7070d3f 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -392,7 +392,8 @@ static unsigned sock_event_lose_pending(const struct lwip_sock *sock, enum netco - switch (evt) { - case NETCONN_EVT_RCVMINUS: - if (sock->sk_event.events & EPOLLIN) { -- if (!NETCONN_NEED_RECV(sock) && -+ if (!sock->errevent && -+ !NETCONN_NEED_RECV(sock) && - !NETCONN_NEED_ACCEPT(sock)) { - event = EPOLLIN; - } -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 99a7162..c6d2eb3 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -23,6 +23,9 @@ void poll_destruct_wait(void); - - int lstack_epoll_close(int epfd); - void epoll_api_init(posix_api_t *api); -+int epoll_ctl_kernel_event(int epfd, int op, int fd, struct epoll_event *event, -+ struct sock_wait *sk_wait); -+ - bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking); - - #endif /* _GAZELLE_EPOLL_H_ */ --- -2.33.0 - diff --git a/0351-sockio-fix-rtw_stack_tcp_write-wrong-copied_total-af.patch b/0351-sockio-fix-rtw_stack_tcp_write-wrong-copied_total-af.patch deleted file mode 100644 index 09dc616..0000000 --- a/0351-sockio-fix-rtw_stack_tcp_write-wrong-copied_total-af.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0f38dd2b397cc84bfaf1eeac358ad2a916998d73 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Thu, 26 Jun 2025 10:30:45 +0800 -Subject: [PATCH] sockio: fix rtw_stack_tcp_write wrong copied_total after - append - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 4c524ab..8640931 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -683,13 +683,15 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - - copied_total = rtw_stack_tcp_append(mr, data, LWIP_MIN(TCP_MSS, total_copy_len), flags); - SOCK_WAIT_STAT(sock->sk_wait, sock_tx_merge, copied_total > 0 ? 1 : 0); -- if (copied_total == total_copy_len) { -- return copied_total; -+ total_copy_len -= copied_total; -+ if (total_copy_len == 0) { -+ goto out; - } - - if (total_copy_len <= TCP_MSS) { - /* write one pbuf */ - copied_total += rtw_stack_tcp_write_one(sock, mr, data + copied_total, total_copy_len, flags); -+ total_copy_len -= copied_total; - } else { - if (total_copy_len > mr->app_free_count * TCP_MSS) { - total_copy_len = mr->app_free_count * TCP_MSS; --- -2.33.0 - diff --git a/0352-sk_event-fix-rtw-epoll-wrong-event-notify-and-remove.patch b/0352-sk_event-fix-rtw-epoll-wrong-event-notify-and-remove.patch deleted file mode 100644 index 7abee40..0000000 --- a/0352-sk_event-fix-rtw-epoll-wrong-event-notify-and-remove.patch +++ /dev/null @@ -1,349 +0,0 @@ -From ad2d26c2a9316829724adbf5ed7e201ff85ae7a6 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sat, 28 Jun 2025 14:59:54 +0800 -Subject: [PATCH] sk_event: fix rtw epoll wrong event notify and remove - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 69 +++++++++++++++++++------------- - src/lstack/api/lstack_sockio.c | 2 +- - src/lstack/core/lstack_wait.c | 53 ++++++++++++++---------- - src/lstack/include/lstack_wait.h | 9 +++-- - 4 files changed, 80 insertions(+), 53 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 1a10e24..d39002b 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -53,46 +53,64 @@ static int rtw_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint3 - } - - static void rtc_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id) -+ enum netconn_evt evt, int stack_id) - { -- sk_event->pending |= pending; -- if (list_node_null(&sk_event->event_node)) { -- list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ sk_event->pending |= sock_event_hold_pending(sk_event->sock, sk_wait->type, evt, 0); -+ if (likely(sk_event->pending != 0)) { -+ if (list_node_null(&sk_event->event_node)) { -+ list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ } - } - } - --static void rtc_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+static void rtc_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, enum netconn_evt evt) - { -- sk_event->pending &= ~pending; -+ sk_event->pending &= ~sock_event_lose_pending(sk_event->sock, evt, 0); - if (sk_event->pending == 0) { - list_del_node(&sk_event->event_node); - } - } - - static void rtw_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id) -+ enum netconn_evt evt, int stack_id) - { -+ /* call sock_event_hold_pending in lock to avoid unnecessary events: -+ * stack: mbox_enqueue -> hold_pending -> lock -> notify_event -> unlock -+ * recv: mbox_dequeue -> lose_pending -> lock -> remove_event -> unlock -+ */ -+ - #if SOCK_WAIT_BATCH_NOTIFY - if (likely(stack_id >= 0)) { -- lwip_wait_add_notify(sk_wait, sk_event, pending, stack_id); -+ lwip_wait_add_notify(sk_wait, sk_event, evt, stack_id); - return; - } - #endif /* SOCK_WAIT_BATCH_NOTIFY */ - - rte_spinlock_lock(&sk_wait->epcb.lock); -- sk_event->pending |= pending; -- if (list_node_null(&sk_event->event_node)) { -- list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ sk_event->pending |= sock_event_hold_pending(sk_event->sock, sk_wait->type, evt, 0); -+ if (likely(sk_event->pending != 0)) { -+ if (list_node_null(&sk_event->event_node)) { -+ list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); -+ } - } - rte_spinlock_unlock(&sk_wait->epcb.lock); - - sys_sem_signal_internal(&sk_wait->sem); - } - --static void rtw_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+static void rtw_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, enum netconn_evt evt) - { -+ /* call sock_event_hold_pending in lock to avoid wrong remove: -+ * stack: mbox_enqueue -> hold_pending -> lock -> notify_event -> unlock -+ * recv: lose_pending -> lock -> remove_event -> unlock -+ */ -+ -+ if (sock_event_lose_pending(sk_event->sock, evt, 0) == 0) { -+ return; -+ } -+ - rte_spinlock_lock(&sk_wait->epcb.lock); -- sk_event->pending &= ~pending; -+ sk_event->pending &= ~sock_event_lose_pending(sk_event->sock, evt, 0); - if (sk_event->pending == 0) { - list_del_node(&sk_event->event_node); - } -@@ -100,24 +118,24 @@ static void rtw_epoll_remove_event(struct sock_wait *sk_wait, struct sock_event - } - - static void rtc_poll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id) -+ enum netconn_evt evt, int stack_id) - { - } --static void rtc_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+static void rtc_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, enum netconn_evt evt) - { - } - static void rtw_poll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id) -+ enum netconn_evt evt, int stack_id) - { - #if SOCK_WAIT_BATCH_NOTIFY - if (likely(stack_id >= 0)) { -- lwip_wait_add_notify(sk_wait, NULL, 0, stack_id); -+ lwip_wait_add_notify(sk_wait, NULL, evt, stack_id); - return; - } - #endif /* SOCK_WAIT_BATCH_NOTIFY */ - sys_sem_signal_internal(&sk_wait->sem); - } --static void rtw_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending) -+static void rtw_poll_remove_event(struct sock_wait *sk_wait, struct sock_event *sk_event, enum netconn_evt evt) - { - } - -@@ -284,7 +302,6 @@ int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - struct lwip_sock *sock = lwip_get_socket(fd); - struct sock_wait *sk_wait = epsock->sk_wait; - struct sock_event *sk_event; -- unsigned pending; - - if (epfd < 0 || fd < 0 || epfd == fd || \ - (event == NULL && op != EPOLL_CTL_DEL)) { -@@ -316,10 +333,9 @@ int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - sk_event->events = event->events | EPOLLERR | EPOLLHUP; - sk_event->ep_data = event->data; - -- pending = sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_RCVPLUS, 0) | -- sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_SENDPLUS, 0) | -- sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_ERROR, 0); -- sk_wait->notify_fn(sk_wait, sk_event, pending, -1); -+ sk_wait->notify_fn(sk_wait, sk_event, NETCONN_EVT_RCVPLUS, -1); -+ sk_wait->notify_fn(sk_wait, sk_event, NETCONN_EVT_SENDPLUS, -1); -+ sk_wait->notify_fn(sk_wait, sk_event, NETCONN_EVT_ERROR, -1); - - sk_wait->lwip_nfds++; - sk_wait->affinity.stack_nfds[sock->stack_id]++; -@@ -327,10 +343,9 @@ int lstack_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) - case EPOLL_CTL_DEL: - sk_event->events = 0; - -- pending = sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_RCVMINUS, 0) | -- sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_SENDMINUS, 0) | -- sock_event_hold_pending(sock, WAIT_EPOLL, NETCONN_EVT_ERROR, 0); -- sk_wait->remove_fn(sk_wait, sk_event, pending); -+ sk_wait->remove_fn(sk_wait, sk_event, NETCONN_EVT_RCVMINUS); -+ sk_wait->remove_fn(sk_wait, sk_event, NETCONN_EVT_SENDMINUS); -+ sk_wait->remove_fn(sk_wait, sk_event, NETCONN_EVT_ERROR); - - sk_wait->lwip_nfds--; - sk_wait->affinity.stack_nfds[sock->stack_id]--; -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 8640931..418311e 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -1461,7 +1461,7 @@ int do_lwip_init_sock(int fd) - } - - sock->sk_wait = NULL; -- ret = sock_event_init(&sock->sk_event); -+ ret = sock_event_init(&sock->sk_event, sock); - if (ret != 0) { - LSTACK_LOG(ERR, LSTACK, "sock_event_init failed\n"); - return -1; -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 7070d3f..4714742 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -256,10 +256,11 @@ void affinity_bind_stack(struct sock_wait *sk_wait, struct wait_affinity *affini - } - } - --int sock_event_init(struct sock_event *sk_event) -+int sock_event_init(struct sock_event *sk_event, struct lwip_sock *sock) - { - memset_s(sk_event, sizeof(struct sock_event), 0, sizeof(struct sock_event)); - -+ sk_event->sock = sock; - list_init_node(&sk_event->event_node); - #if SOCK_WAIT_BATCH_NOTIFY - list_init_node(&sk_event->stk_event_node); -@@ -278,6 +279,7 @@ void sock_event_free(struct sock_event *sk_event, struct sock_wait *sk_wait) - list_del_node(&sk_event->stk_event_node); - #endif /* SOCK_WAIT_BATCH_NOTIFY */ - } -+ sk_event->sock = NULL; - } - - int sock_wait_common_init(struct sock_wait *sk_wait) -@@ -385,7 +387,7 @@ static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) - return false; - } - --static unsigned sock_event_lose_pending(const struct lwip_sock *sock, enum netconn_evt evt, unsigned len) -+unsigned sock_event_lose_pending(const struct lwip_sock *sock, enum netconn_evt evt, unsigned len) - { - unsigned event = 0; - -@@ -421,8 +423,7 @@ unsigned sock_event_hold_pending(const struct lwip_sock *sock, - switch (evt) { - case NETCONN_EVT_RCVPLUS: - if (sock->sk_event.events & EPOLLIN || type & WAIT_BLOCK) { -- if (len > 0 || -- NETCONN_NEED_RECV(sock) || -+ if (NETCONN_NEED_RECV(sock) || - NETCONN_NEED_ACCEPT(sock)) { - event = EPOLLIN; - } -@@ -430,8 +431,7 @@ unsigned sock_event_hold_pending(const struct lwip_sock *sock, - break; - case NETCONN_EVT_SENDPLUS: - if (sock->sk_event.events & EPOLLOUT || type & WAIT_BLOCK) { -- if (len > 0 || -- NETCONN_ALLOW_SEND(sock)) { -+ if (NETCONN_ALLOW_SEND(sock)) { - event = EPOLLOUT; - } - } -@@ -460,11 +460,7 @@ void sock_event_remove_pending(struct lwip_sock *sock, enum netconn_evt evt, uns - sock->sk_wait = NULL; - return; - } -- -- unsigned pending = sock_event_lose_pending(sock, evt, 0); -- if (pending) { -- sock->sk_wait->remove_fn(sock->sk_wait, &sock->sk_event, pending); -- } -+ sock->sk_wait->remove_fn(sock->sk_wait, &sock->sk_event, evt); - } - - void sock_event_notify_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len) -@@ -479,22 +475,18 @@ void sock_event_notify_pending(struct lwip_sock *sock, enum netconn_evt evt, uns - sock->sk_wait = NULL; - return; - } -- -- unsigned pending = sock_event_hold_pending(sock, sock->sk_wait->type, evt, len); -- if (pending) { -- sock->sk_wait->notify_fn(sock->sk_wait, &sock->sk_event, pending, sock->stack_id); -- } -+ sock->sk_wait->notify_fn(sock->sk_wait, &sock->sk_event, evt, sock->stack_id); - } - - #if SOCK_WAIT_BATCH_NOTIFY - /* Only allow stack call */ - void lwip_wait_add_notify(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id) -+ enum netconn_evt evt, int stack_id) - { - struct lwip_wait *lwait = lwip_wait_get(stack_id); - - if (sk_event != NULL) { -- sk_event->stk_pending |= pending; -+ sk_event->stk_evts |= evt; - if (list_node_null(&sk_event->stk_event_node)) { - list_add_node(&sk_event->stk_event_node, &sk_wait->stk_event_list[stack_id]); - } -@@ -505,6 +497,23 @@ void lwip_wait_add_notify(struct sock_wait *sk_wait, struct sock_event *sk_event - } - } - -+static unsigned sock_event_get_pending(struct sock_event *sk_event, enum netconn_evt evts) -+{ -+ unsigned pending = 0; -+ -+ if (evts & NETCONN_EVT_SENDPLUS) { -+ pending |= sock_event_hold_pending(sk_event->sock, WAIT_EPOLL, NETCONN_EVT_SENDPLUS, 0); -+ } -+ if (evts & NETCONN_EVT_RCVPLUS) { -+ pending |= sock_event_hold_pending(sk_event->sock, WAIT_EPOLL, NETCONN_EVT_RCVPLUS, 0); -+ } -+ if (evts & NETCONN_EVT_ERROR) { -+ pending |= sock_event_hold_pending(sk_event->sock, WAIT_EPOLL, NETCONN_EVT_ERROR, 0); -+ } -+ sk_event->stk_evts = 0; -+ return pending; -+} -+ - static inline - unsigned sock_wait_foreach_event(struct sock_wait *sk_wait, int stack_id) - { -@@ -523,12 +532,14 @@ unsigned sock_wait_foreach_event(struct sock_wait *sk_wait, int stack_id) - sk_event = container_of(node, struct sock_event, stk_event_node); - - /* see rtw_epoll_notify_event() */ -- sk_event->pending |= sk_event->stk_pending; -+ sk_event->pending |= sock_event_get_pending(sk_event, sk_event->stk_evts); -+ if (unlikely(sk_event->pending == 0)) { -+ continue; -+ } -+ - if (list_node_null(&sk_event->event_node)) { - list_add_node(&sk_event->event_node, &sk_wait->epcb.event_list); - } -- -- sk_event->stk_pending = 0; - count++; - } - -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -index 58da126..8ed2e93 100644 ---- a/src/lstack/include/lstack_wait.h -+++ b/src/lstack/include/lstack_wait.h -@@ -67,9 +67,9 @@ struct sock_wait { - int (*timedwait_fn)(struct sock_wait *sk_wait, int timeout, uint32_t start); - /* trigger event */ - void (*notify_fn)(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id); -+ enum netconn_evt evt, int stack_id); - /* remove event */ -- void (*remove_fn)(struct sock_wait *sk_wait, struct sock_event *sk_event, unsigned pending); -+ void (*remove_fn)(struct sock_wait *sk_wait, struct sock_event *sk_event, enum netconn_evt evt); - - /* dfx stat */ - struct list_node group_node; -@@ -117,17 +117,18 @@ int kernel_wait_ctl(struct sock_wait *sk_wait, int new_stack_id, int old_stack_i - - #if SOCK_WAIT_BATCH_NOTIFY - void lwip_wait_add_notify(struct sock_wait *sk_wait, struct sock_event *sk_event, -- unsigned pending, int stack_id); -+ enum netconn_evt evt, int stack_id); - unsigned lwip_wait_foreach_notify(int stack_id); - bool lwip_wait_notify_empty(int stack_id); - #endif /* SOCK_WAIT_BATCH_NOTIFY */ - -+unsigned sock_event_lose_pending(const struct lwip_sock *sock, enum netconn_evt evt, unsigned len); - unsigned sock_event_hold_pending(const struct lwip_sock *sock, - enum sock_wait_type type, enum netconn_evt evt, unsigned len); - void sock_event_notify_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len); - void sock_event_remove_pending(struct lwip_sock *sock, enum netconn_evt evt, unsigned len); - --int sock_event_init(struct sock_event *sk_event); -+int sock_event_init(struct sock_event *sk_event, struct lwip_sock *sock); - void sock_event_free(struct sock_event *sk_event, struct sock_wait *sk_wait); - - int sock_wait_common_init(struct sock_wait *sk_wait); --- -2.33.0 - diff --git a/0353-poll-fix-do_lwip_connected_callback-not-delete-poll-.patch b/0353-poll-fix-do_lwip_connected_callback-not-delete-poll-.patch deleted file mode 100644 index 2912a3d..0000000 --- a/0353-poll-fix-do_lwip_connected_callback-not-delete-poll-.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 4931694a535c2371645ab58669e80a6a204a1dd1 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Wed, 2 Jul 2025 09:36:12 +0800 -Subject: [PATCH] poll: fix do_lwip_connected_callback not delete poll kernel - fd - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 73 +++++++++++++++++++------------ - src/lstack/api/lstack_wrap.c | 2 + - src/lstack/include/lstack_epoll.h | 1 + - 3 files changed, 49 insertions(+), 27 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index d39002b..949e10b 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -580,43 +580,62 @@ struct sock_wait *poll_construct_wait(int nfds) - return g_sk_wait; - } - --static int poll_ctl_kernel_event(int epfd, int fds_id, -- const struct pollfd *new_fds, const struct pollfd *old_fds) --{ -- int ret; -+struct poll_kernel_data { -+ union { -+ struct { -+ uint32_t fd; -+ uint16_t fds_id; -+ }; -+ void *ptr; -+ }; -+}; -+int poll_ctl_kernel_event(int epfd, int fds_id, int old_fd, const struct pollfd *new_fds) -+{ -+ int ret = 0; - struct epoll_event epevent; -+ struct poll_kernel_data pdata; - -- LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(epfd=%d, old_fd=%d, new_fd=%d)\n", -- __FUNCTION__, epfd, old_fds->fd, new_fds->fd)); -- -- epevent.data.fd = fds_id; -- epevent.events = new_fds->events; -+ RTE_BUILD_BUG_ON(sizeof(struct poll_kernel_data) > sizeof(void *)); - - /* EPOLL_CTL_MOD may not be any events, but why? */ -- if (old_fds->fd == 0) { -- ret = posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_ADD, new_fds->fd, &epevent); -- } else { -- ret = posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_DEL, old_fds->fd, NULL); -+ if (old_fd > 0) { -+ ret = posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_DEL, old_fd, NULL); -+ } -+ if (new_fds != NULL && new_fds->fd > 0) { -+ pdata.fd = new_fds->fd; -+ pdata.fds_id = fds_id; -+ epevent.data.ptr = pdata.ptr; -+ epevent.events = new_fds->events; - ret |= posix_api->epoll_ctl_fn(epfd, EPOLL_CTL_ADD, new_fds->fd, &epevent); - } - -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(epfd=%d, fds_id %d, old_fd=%d, new_fd=%d)\n", -+ __FUNCTION__, epfd, fds_id, old_fd, new_fds ? new_fds->fd : -1)); -+ - if (ret != 0 && errno != EINTR && errno != ENOENT) { -- LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d, new_fd %d, old_fd %d\n", -- errno, new_fds->fd, old_fds->fd); -+ LSTACK_LOG(ERR, LSTACK, "epoll_ctl failed, errno %d, fds_id %d, old_fd %d, new_fd %d\n", -+ errno, fds_id, old_fd, new_fds ? new_fds->fd : -1); - } - return ret; - } - --static int poll_wait_kernel_event(int epfd, struct pollfd *fds, int maxevents) -+static int poll_wait_kernel_event(int epfd, const struct poll_cb *pcb, struct pollfd *fds, int maxevents) - { - struct epoll_event epevents[POLL_MAX_EVENTS]; -- int num = 0; -- int i, fds_id; -- -- num = posix_api->epoll_wait_fn(epfd, epevents, maxevents, 0); -- for (i = 0; i < num; ++i) { -- fds_id = epevents[i].data.fd; -- fds[fds_id].revents = epevents[i].events; -+ struct poll_kernel_data pdata; -+ int ret, i, num = 0; -+ -+ ret = posix_api->epoll_wait_fn(epfd, epevents, maxevents, 0); -+ for (i = 0; i < ret; ++i) { -+ pdata.ptr = epevents[i].data.ptr; -+ if (pdata.fd != fds[pdata.fds_id].fd) { -+ poll_ctl_kernel_event(epfd, pdata.fds_id, pdata.fd, NULL); -+ continue; -+ } -+ /* may be already counted by poll_scan_lwip_event() */ -+ if (fds[pdata.fds_id].revents == 0) -+ num++; -+ fds[pdata.fds_id].revents |= epevents[i].events; - } - - return num; -@@ -635,14 +654,14 @@ static void poll_prepare_wait(struct sock_wait *sk_wait, struct pollfd *fds, nfd - 0, sizeof(sk_wait->affinity.stack_nfds)); - - for (i = 0; i < nfds; ++i) { -+ fds[i].revents = 0; - fd = fds[i].fd; - sock = lwip_get_socket(fd); - sk_type = select_sock_posix_path(sock); - - if (sk_type & POSIX_KERNEL) { -- poll_ctl_kernel_event(sk_wait->epfd, i, &fds[i], -- &pcb->kernel_fds[sk_wait->kernel_nfds]); -- pcb->kernel_fds[sk_wait->kernel_nfds] = fds[i]; -+ poll_ctl_kernel_event(sk_wait->epfd, i, pcb->kernel_fds[i].fd, &fds[i]); -+ pcb->kernel_fds[i] = fds[i]; - sk_wait->kernel_nfds++; - } - -@@ -723,7 +742,7 @@ int lstack_poll(struct pollfd *fds, nfds_t nfds, int timeout) - } - - if (sk_wait->kernel_nfds > 0 && rte_atomic16_read(&sk_wait->kernel_pending)) { -- kernel_num = poll_wait_kernel_event(sk_wait->epfd, fds, sk_wait->kernel_nfds); -+ kernel_num = poll_wait_kernel_event(sk_wait->epfd, &sk_wait->pcb, fds, sk_wait->kernel_nfds); - if (kernel_num == 0 && errno != EINTR && errno != EAGAIN) { - rte_atomic16_set(&sk_wait->kernel_pending, false); - } -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 8339750..6523dc2 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -392,6 +392,8 @@ void do_lwip_connected_callback(int fd) - if (sock->sk_wait != NULL) { - if (sock->sk_wait->type & WAIT_EPOLL) { - epoll_ctl_kernel_event(sock->sk_wait->epfd, EPOLL_CTL_DEL, fd, NULL, sock->sk_wait); -+ } else if (sock->sk_wait->type & WAIT_POLL) { -+ poll_ctl_kernel_event(sock->sk_wait->epfd, 0, fd, NULL); - } - } - /* shutdown kernel connect, do_connect() has tried both kernel and lwip. */ -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index c6d2eb3..94e872d 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -25,6 +25,7 @@ int lstack_epoll_close(int epfd); - void epoll_api_init(posix_api_t *api); - int epoll_ctl_kernel_event(int epfd, int op, int fd, struct epoll_event *event, - struct sock_wait *sk_wait); -+int poll_ctl_kernel_event(int epfd, int fds_id, int old_fd, const struct pollfd *new_fds); - - bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking); - --- -2.33.0 - diff --git a/0354-sockctl-fix-rtw-broadcast-close-and-shutdown.patch b/0354-sockctl-fix-rtw-broadcast-close-and-shutdown.patch deleted file mode 100644 index ed0d99b..0000000 --- a/0354-sockctl-fix-rtw-broadcast-close-and-shutdown.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 930c68e37f09c0ad3f5e56ae5407ad397afc48cb Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 4 Jul 2025 08:58:03 +0800 -Subject: [PATCH] sockctl: fix rtw broadcast close and shutdown - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockctl.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index 856b24e..a224303 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -461,7 +461,7 @@ static int stack_broadcast_close(int fd) - int ret = 0; - struct lwip_sock *sock = lwip_get_socket(fd); - -- while (sock != NULL) { -+ do { - if (POSIX_IS_CLOSED(sock)) { - ret = -1; - break; -@@ -469,7 +469,7 @@ static int stack_broadcast_close(int fd) - fd = sock->conn->callback_arg.socket; - ret |= rpc_call_close(sock->stack_id, fd); - sock = sock->listen_next; -- } -+ } while (sock != NULL); - - if (ret != 0) { - GAZELLE_RETURN(EBADF); -@@ -482,7 +482,7 @@ static int stack_broadcast_shutdown(int fd, int how) - int ret = 0; - struct lwip_sock *sock = lwip_get_socket(fd); - -- while (true) { -+ do { - if (POSIX_IS_CLOSED(sock)) { - ret = -1; - break; -@@ -490,7 +490,7 @@ static int stack_broadcast_shutdown(int fd, int how) - fd = sock->conn->callback_arg.socket; - ret |= rpc_call_shutdown(sock->stack_id, fd, how); - sock = sock->listen_next; -- } -+ } while (sock != NULL); - - if (ret != 0) { - GAZELLE_RETURN(EBADF); --- -2.33.0 - diff --git a/0355-mempool-increase-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch b/0355-mempool-increase-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch deleted file mode 100644 index ed3c4f5..0000000 --- a/0355-mempool-increase-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch +++ /dev/null @@ -1,26 +0,0 @@ -From f807fda71067c85f436a294746afc4a56aebe8fa Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 4 Jul 2025 08:58:37 +0800 -Subject: [PATCH] mempool: increase MEM_THREAD_MANAGER_FREE_S to avoid poll - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_mempool.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 70ac8c6..3f447f0 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -27,7 +27,7 @@ - #define MEM_THREAD_MAX_PATH 32 /* cat /proc/sys/kernel/pid_max */ - #define MEM_THREAD_FLUSH_SIG (SIGRTMIN + 11) - #define MEM_THREAD_MANAGER_FLUSH_MS 100 --#define MEM_THREAD_MANAGER_FREE_S 2 -+#define MEM_THREAD_MANAGER_FREE_S 20 - #define MEM_THREAD_MANAGER_FREE_MAX 64 - - struct mem_thread_manager { --- -2.33.0 - diff --git a/0356-sockio-fix-callback_tcp_send-output-too-many-at-once.patch b/0356-sockio-fix-callback_tcp_send-output-too-many-at-once.patch deleted file mode 100644 index ee77df0..0000000 --- a/0356-sockio-fix-callback_tcp_send-output-too-many-at-once.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 0199d6397ae4f6c6fe76ed2d741f3b0e72546af2 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 4 Jul 2025 08:59:39 +0800 -Subject: [PATCH] sockio: fix callback_tcp_send output too many at once - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 33 ++++++++++++++++++++++----------- - 1 file changed, 22 insertions(+), 11 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 418311e..05e82d7 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -964,36 +964,47 @@ static void callback_tcp_send(struct rpc_msg *sendmsg) - struct protocol_stack *stack = get_protocol_stack(); - struct lwip_sock *sock = sendmsg->args[MSG_ARG_0].p; - struct mem_thread *mt = sendmsg->args[MSG_ARG_1].p; -+ const struct tcp_pcb *pcb = sock->conn->pcb.tcp; -+ const struct mbox_ring *mr = &sock->conn->sendmbox->mring; - bool output_again; - err_t err; - -- if (unlikely(sock->conn->pcb.tcp == NULL)) -+ if (unlikely(pcb == NULL)) - return; - -+#if GAZELLE_TCP_ASYNC_RECVD -+ struct rpc_msg *recvmsg; -+ if (RECVD_UNSUBMITED(sendmsg)) { -+ RECVD_UNSUBMITED(sendmsg) = 0; -+ recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -+ callback_tcp_recvd(recvmsg); -+ } -+#endif /* GAZELLE_TCP_ASYNC_RECVD */ -+ -+ /* If LWIP_MIN(snd_wnd, cwnd) limit output. */ -+ if (pcb->unsent != NULL && pcb->unacked != NULL) { -+ rpc_async_call(&stack->rpc_queue, sendmsg, RPC_MSG_REUSE | RPC_MSG_RECALL); -+ return; -+ } -+ - if (get_protocol_stack_group()->latency_start) - calculate_sock_latency(sock, GAZELLE_LATENCY_WRITE_RPC_MSG); - -+ sendmsg->result = 0; - do { -- if (!lwip_tcp_allow_send(sock->conn->pcb.tcp)) { -+ /* Not output too many bufs at once. */ -+ if (sendmsg->result >= mr->ops->get_capacity(mr) || !lwip_tcp_allow_send(sock->conn->pcb.tcp)) { - rpc_async_call(&stack->rpc_queue, sendmsg, RPC_MSG_REUSE | RPC_MSG_RECALL); - break; - } - sendmsg->result += rtw_stack_tcp_output(sock->conn, &output_again, mt); - } while (output_again); -+ - err = tcp_output(sock->conn->pcb.tcp); - if (unlikely(err != ERR_OK)) { - LSTACK_LOG(ERR, LSTACK, "tcp_output failed, sock %p, err %u\n", sock, err); - } - --#if GAZELLE_TCP_ASYNC_RECVD -- struct rpc_msg *recvmsg; -- if (RECVD_UNSUBMITED(sendmsg)) { -- RECVD_UNSUBMITED(sendmsg) = 0; -- recvmsg = sock_mbox_private_get(sock->conn->recvmbox); -- callback_tcp_recvd(recvmsg); -- } --#endif /* GAZELLE_TCP_ASYNC_RECVD */ -- - return; - } - --- -2.33.0 - diff --git a/0357-sockio-fix-sendmbox-full-return-EWOULDBLOCK.patch b/0357-sockio-fix-sendmbox-full-return-EWOULDBLOCK.patch deleted file mode 100644 index d6d8e13..0000000 --- a/0357-sockio-fix-sendmbox-full-return-EWOULDBLOCK.patch +++ /dev/null @@ -1,336 +0,0 @@ -From 635e86630da1ebfe5955b1598f8adb5a9d547a2f Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 4 Jul 2025 09:00:42 +0800 -Subject: [PATCH] sockio: fix sendmbox full return EWOULDBLOCK - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 34 ++++++++----- - src/lstack/api/lstack_sockctl.c | 8 +-- - src/lstack/api/lstack_sockio.c | 83 +++++++++++++++++++------------ - src/lstack/include/lstack_epoll.h | 2 +- - 4 files changed, 76 insertions(+), 51 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index 949e10b..a07968a 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -439,7 +439,7 @@ int lstack_epoll_wait(int epfd, struct epoll_event* events, int maxevents, int t - lwip_maxevents = sk_wait->kernel_nfds > 0 ? - (maxevents >> 1) + 1 : maxevents; - -- start = sys_now(); -+ start = timeout <= 0 ? 0 : sys_now(); - - /* RTC try to recv polling. */ - sk_wait->timedwait_fn(sk_wait, 0, start); -@@ -732,7 +732,7 @@ int lstack_poll(struct pollfd *fds, nfds_t nfds, int timeout) - return posix_api->poll_fn(fds, nfds, timeout); - } - -- start = sys_now(); -+ start = timeout <= 0 ? 0 : sys_now(); - - /* RTC try to recv polling. */ - sk_wait->timedwait_fn(sk_wait, 0, start); -@@ -861,14 +861,17 @@ void epoll_api_init(posix_api_t *api) - api->select_fn = lstack_select; - } - --bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking) -+bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool nonblocking) - { - bool rtc_mode = get_global_cfg_params()->stack_mode_rtc; -- uint32_t start; -- int timeout; - unsigned pending = 0; -+ uint32_t start; -+ int timeout = -1; -+ int old_errno; -+ -+ nonblocking |= netconn_is_nonblocking(sock->conn); - -- if (!rtc_mode && noblocking) -+ if (!rtc_mode && nonblocking) - return false; - - if (unlikely(sock->sk_wait == NULL) || sock->sk_wait->type == WAIT_CLOSE) { -@@ -879,14 +882,21 @@ bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocki - rte_wmb(); - } - -+ old_errno = errno; - if (rtc_mode) { - /* RTC try to recv polling. */ - sock->sk_wait->timedwait_fn(sock->sk_wait, 0, 0); -- return true; -+ if (nonblocking) { -+ errno = old_errno; -+ return false; -+ } - } - -- timeout = sock->conn->recv_timeout == 0 ? -1 : sock->conn->recv_timeout; -- start = sys_now(); -+ if (evt == NETCONN_EVT_RCVPLUS && sock->conn->recv_timeout > 0) { -+ timeout = sock->conn->recv_timeout; -+ } -+ -+ start = timeout <= 0 ? 0 : sys_now(); - do { - pending = sock_event_hold_pending(sock, WAIT_BLOCK, evt, 0) | - sock_event_hold_pending(sock, WAIT_BLOCK, NETCONN_EVT_ERROR, 0); -@@ -896,13 +906,11 @@ bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocki - timeout = sock->sk_wait->timedwait_fn(sock->sk_wait, timeout, start); - } while (timeout > 0 || (timeout < 0 && errno == 0)); - -- if (errno == ETIMEDOUT) { -- errno = EAGAIN; -- } -- - if (evt == NETCONN_EVT_SENDPLUS) { - /* remove WAIT_BLOCK type */ - sock->sk_wait->type &= ~WAIT_BLOCK; - } -+ -+ errno = old_errno; - return pending != 0; - } -diff --git a/src/lstack/api/lstack_sockctl.c b/src/lstack/api/lstack_sockctl.c -index a224303..906d228 100644 ---- a/src/lstack/api/lstack_sockctl.c -+++ b/src/lstack/api/lstack_sockctl.c -@@ -448,7 +448,7 @@ static int rpc_call_connect(int stack_id, int fd, const struct sockaddr *addr, s - - if (ret < 0 && errno == EINPROGRESS) { - struct lwip_sock *sock = lwip_get_socket(fd); -- if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, netconn_is_nonblocking(sock->conn))) { -+ if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, false)) { - ret = 0; - } - } -@@ -585,7 +585,7 @@ static int stack_broadcast_accept4(int fd, struct sockaddr *addr, socklen_t *add - - min_sock = get_min_accept_sock(fd); - if (min_sock == NULL) { -- if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, flags & SOCK_NONBLOCK)) { - min_sock = get_min_accept_sock(fd); - } - } -@@ -764,7 +764,7 @@ static int rtc_connect(int s, const struct sockaddr *name, socklen_t namelen) - ret = lwip_connect(s, name, namelen); - if (ret < 0 && errno == EINPROGRESS) { - struct lwip_sock *sock = lwip_get_socket(s); -- if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, netconn_is_nonblocking(sock->conn))) { -+ if (sock_event_wait(sock, NETCONN_EVT_SENDPLUS, false)) { - ret = 0; - } - } -@@ -782,7 +782,7 @@ static int rtc_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int fla - - ret = lwip_accept4(s, addr, addrlen, flags); - if (ret < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & SOCK_NONBLOCK))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, flags & SOCK_NONBLOCK)) { - ret = lwip_accept4(s, addr, addrlen, flags); - } - } -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 05e82d7..b5b203f 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -359,7 +359,7 @@ static ssize_t stack_udp_write(struct lwip_sock *sock, const void *data, size_t - mr->app_free_count = mr->ops->free_count(mr); - if (unlikely(mr->app_free_count < 1)) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- set_errno(EWOULDBLOCK); -+ set_errno(ENOBUFS); - return -1; - } - } -@@ -370,7 +370,10 @@ static ssize_t stack_udp_write(struct lwip_sock *sock, const void *data, size_t - copied_total = stack_udp_write_bulk(sock, mr, data, len, flags, to, tolen); - } - -- return copied_total > 0 ? copied_total : -1; -+ if (likely(copied_total > 0)) -+ return copied_total; -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ return -1; - } - - static ssize_t stack_udp_output(struct netconn *conn, bool *output_again, struct mem_thread *mt) -@@ -676,7 +679,7 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - mr->app_free_count = mr->ops->free_count(mr); - if (unlikely(mr->app_free_count < 2)) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- set_errno(EWOULDBLOCK); -+ set_errno(ENOBUFS); - return -1; - } - } -@@ -709,6 +712,8 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - } - - out: -+ if (unlikely(total_copy_len > 0)) -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - return copied_total > 0 ? copied_total : -1; - } - -@@ -1058,11 +1063,6 @@ static ssize_t rtc_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - } - - total_copy_len = LWIP_MIN((uint32_t)len, (uint32_t)pcb->snd_buf); -- if (unlikely(total_copy_len == 0)) { -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -- set_errno(EWOULDBLOCK); -- return -1; -- } - - while (total_copy_len > 0) { - if (total_copy_len <= TCP_SND_SIZE_MAX) { -@@ -1074,14 +1074,23 @@ static ssize_t rtc_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - - err = tcp_write(pcb, data + copied_total, buf_copy_len, write_flags | write_more); - if (err != ERR_OK) { -- LSTACK_LOG(ERR, LSTACK, "tcp_write failed, errno %d\n", err_to_errno(err)); - break; - } - total_copy_len -= buf_copy_len; - copied_total += buf_copy_len; - } - -- if (copied_total > 0) { -+ /* if OK or memory error, check available space */ -+ if (err == ERR_OK || err == ERR_MEM) { -+ if (!lwip_tcp_allow_send(sock->conn->pcb.tcp)) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ err = ERR_BUF; -+ } else if (total_copy_len > 0) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ } -+ } -+ -+ if (likely(copied_total > 0)) { - return copied_total; - } - set_errno(err_to_errno(err)); -@@ -1120,7 +1129,7 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - /* TODO: support MSG_WAITALL */ - recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, flags & MSG_DONTWAIT)) { - recvd = ioops.stack_tcp_read(sock, mem, len, flags, from, fromlen); - } - } -@@ -1140,7 +1149,7 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - msg.msg_namelen = (fromlen ? *fromlen : 0); - recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, flags & MSG_DONTWAIT)) { - recvd = ioops.stack_udp_readmsg(sock, &msg, len, flags); - } - } -@@ -1186,7 +1195,7 @@ ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - case NETCONN_UDP: - recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - if (recvd < 0 && errno == EWOULDBLOCK) { -- if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, netconn_is_nonblocking(sock->conn) || (flags & MSG_DONTWAIT))) { -+ if (sock_event_wait(sock, NETCONN_EVT_RCVPLUS, flags & MSG_DONTWAIT)) { - recvd = ioops.stack_udp_readmsg(sock, msg, len, flags); - } - } -@@ -1220,22 +1229,24 @@ ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, - - switch (NETCONN_TYPE(sock->conn)) { - case NETCONN_TCP: -- ret = ioops.stack_tcp_write(sock, mem, len, flags); -- if (ret < 0) { -- if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -- } -- } else { -+ do { -+ ret = ioops.stack_tcp_write(sock, mem, len, flags); -+ if (likely(ret > 0) || errno != ENOBUFS) -+ break; -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -+ } while (true); -+ if (ret > 0) { - ioops.stack_tcp_send(sock); - } - break; - case NETCONN_UDP: -- ret = ioops.stack_udp_write(sock, mem, len, flags, to, tolen); -- if (ret < 0) { -- if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -- } -- } else { -+ do { -+ ret = ioops.stack_udp_write(sock, mem, len, flags, to, tolen); -+ if (likely(ret > 0) || errno != ENOBUFS) -+ break; -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -+ } while (true); -+ if (ret > 0) { - ioops.stack_udp_send(sock); - } - break; -@@ -1271,11 +1282,15 @@ ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - if (i == msg->msg_iovlen - 1) { - write_more = 0; - } -- ret = ioops.stack_tcp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more); -+ do { -+ ret = ioops.stack_tcp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more); -+ if (likely(ret > 0) || errno != ENOBUFS) -+ break; -+ if (written > 0) -+ ioops.stack_tcp_send(sock); -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -+ } while (true); - if (ret < 0) { -- if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -- } - break; - } - written += ret; -@@ -1289,11 +1304,13 @@ ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - if (i == msg->msg_iovlen - 1) { - write_more = 0; - } -- ret = ioops.stack_udp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more, NULL, 0); -+ do { -+ ret = ioops.stack_udp_write(sock, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len, flags | write_more, NULL, 0); -+ if (likely(ret > 0) || errno != ENOBUFS) -+ break; -+ sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -+ } while (true); - if (ret < 0) { -- if (errno == EWOULDBLOCK) { -- sock_event_wait(sock, NETCONN_EVT_SENDPLUS, true); -- } - break; - } - written += ret; -diff --git a/src/lstack/include/lstack_epoll.h b/src/lstack/include/lstack_epoll.h -index 94e872d..844ef9d 100644 ---- a/src/lstack/include/lstack_epoll.h -+++ b/src/lstack/include/lstack_epoll.h -@@ -27,6 +27,6 @@ int epoll_ctl_kernel_event(int epfd, int op, int fd, struct epoll_event *event, - struct sock_wait *sk_wait); - int poll_ctl_kernel_event(int epfd, int fds_id, int old_fd, const struct pollfd *new_fds); - --bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool noblocking); -+bool sock_event_wait(struct lwip_sock *sock, enum netconn_evt evt, bool nonblocking); - - #endif /* _GAZELLE_EPOLL_H_ */ --- -2.33.0 - diff --git a/0358-sk_wait-igonre-mem_thread-flush-signal.patch b/0358-sk_wait-igonre-mem_thread-flush-signal.patch deleted file mode 100644 index e80b167..0000000 --- a/0358-sk_wait-igonre-mem_thread-flush-signal.patch +++ /dev/null @@ -1,112 +0,0 @@ -From f388e26bb66ee37fcfdb0adc357dbb4c98a03b64 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Fri, 4 Jul 2025 20:24:36 +0800 -Subject: [PATCH] sk_wait: igonre mem_thread flush signal - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_epoll.c | 14 ++++++++++++-- - src/lstack/core/lstack_mempool.c | 15 ++++++++++++++- - src/lstack/include/lstack_mempool.h | 1 + - 3 files changed, 27 insertions(+), 3 deletions(-) - -diff --git a/src/lstack/api/lstack_epoll.c b/src/lstack/api/lstack_epoll.c -index a07968a..0889f13 100644 ---- a/src/lstack/api/lstack_epoll.c -+++ b/src/lstack/api/lstack_epoll.c -@@ -28,6 +28,7 @@ - #include "lstack_cfg.h" - #include "lstack_log.h" - #include "lstack_protocol_stack.h" -+#include "lstack_mempool.h" - - #define POLL_MAX_EVENTS 32 - -@@ -36,20 +37,29 @@ static PER_THREAD struct sock_wait *g_sk_wait = NULL; - - static int rtc_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint32_t start) - { -+ mem_thread_ignore_flush_intr(); -+ - stack_polling(0); - - if (timeout > 0 && timeout <= (int)(sys_now() - start)) { - timeout = 0; - } else if (timeout < 0) { -- errno = 0; -+ if (errno != EINTR || mem_thread_ignore_flush_intr()) { -+ errno = 0; -+ } - } - return timeout; - } - - static int rtw_sock_wait_timedwait(struct sock_wait *sk_wait, int timeout, uint32_t start) - { -+ int ret; - /* when sem interrupted by signals, errno = EINTR */ -- return sys_sem_wait_internal(&sk_wait->sem, timeout); -+ mem_thread_ignore_flush_intr(); -+ do { -+ ret = sys_sem_wait_internal(&sk_wait->sem, timeout); -+ } while (ret < 0 && errno == EINTR && mem_thread_ignore_flush_intr()); -+ return ret; - } - - static void rtc_epoll_notify_event(struct sock_wait *sk_wait, struct sock_event *sk_event, -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index 3f447f0..ef8e7df 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -45,8 +45,9 @@ struct mem_thread_group { - struct list_node mt_node; - struct mem_thread mt_array[PROTOCOL_STACK_MAX]; - -- bool used_flag; - uint32_t used_time; -+ bool used_flag; -+ bool siged_flag; - }; - - static struct mem_stack g_mem_stack_group[PROTOCOL_STACK_MAX] = {0}; -@@ -106,6 +107,15 @@ static inline void mem_thread_group_done(void) - g_mem_thread_group->used_flag = false; - } - -+bool mem_thread_ignore_flush_intr(void) -+{ -+ if (likely(g_mem_thread_group != NULL) && g_mem_thread_group->siged_flag) { -+ g_mem_thread_group->siged_flag = false; -+ return true; -+ } -+ return false; -+} -+ - static void mem_thread_cache_flush(struct mem_thread *mt); - static unsigned mem_thread_cache_count(const struct mem_thread *mt); - static void mem_thread_group_action_flush(int signum) -@@ -115,6 +125,9 @@ static void mem_thread_group_action_flush(int signum) - - if (g_mem_thread_group == NULL) - return; -+ -+ g_mem_thread_group->siged_flag = true; -+ - if (mem_thread_group_in_used(g_mem_thread_group, MEM_THREAD_MANAGER_FLUSH_MS)) - return; - -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index 6a31503..946edd6 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -300,6 +300,7 @@ int mem_stack_pool_init(int stack_id, unsigned numa_id); - int mem_stack_mpcache_init(int stack_id, unsigned cpu_id); - - int mem_thread_manager_init(void); -+bool mem_thread_ignore_flush_intr(void); - void mem_thread_cache_free(struct mem_thread *mt); - int mem_thread_cache_init(struct mem_thread *mt, int stack_id); - --- -2.33.0 - diff --git a/0359-fix-20.03-LTS-build-failed.patch b/0359-fix-20.03-LTS-build-failed.patch deleted file mode 100644 index 540e401..0000000 --- a/0359-fix-20.03-LTS-build-failed.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 39557d189a97a30a63f76b16eb2daee9c52cbc47 Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Sun, 6 Jul 2025 17:00:49 +0800 -Subject: [PATCH] fix 20.03-LTS build failed - -Signed-off-by: Lemmy Huang ---- - src/lstack/core/lstack_mempool.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/lstack/core/lstack_mempool.c b/src/lstack/core/lstack_mempool.c -index ef8e7df..4388722 100644 ---- a/src/lstack/core/lstack_mempool.c -+++ b/src/lstack/core/lstack_mempool.c -@@ -13,6 +13,7 @@ - #include - - #include -+#include - #include - - #include "lstack_mempool.h" --- -2.33.0 - diff --git a/0360-sockio-fix-tcp_write-not-remove-EPOLLOUT.patch b/0360-sockio-fix-tcp_write-not-remove-EPOLLOUT.patch deleted file mode 100644 index 0ab7cf9..0000000 --- a/0360-sockio-fix-tcp_write-not-remove-EPOLLOUT.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 25e83b84417d5b609ea0d639a9a87d6602b101bf Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Mon, 7 Jul 2025 14:27:16 +0800 -Subject: [PATCH] sockio: fix tcp_write not remove EPOLLOUT - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 20 +++++++++++--------- - src/lstack/core/lstack_wait.c | 2 +- - src/lstack/include/lstack_wait.h | 2 ++ - 3 files changed, 14 insertions(+), 10 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index b5b203f..424cc82 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -355,9 +355,9 @@ static ssize_t stack_udp_write(struct lwip_sock *sock, const void *data, size_t - return -1; - } - -- if (unlikely(mr->app_free_count < 1)) { -+ if (unlikely(mr->app_free_count < SOCK_SENDMBOX_ALLOW_WRITE_SIZE)) { - mr->app_free_count = mr->ops->free_count(mr); -- if (unlikely(mr->app_free_count < 1)) { -+ if (unlikely(mr->app_free_count < SOCK_SENDMBOX_ALLOW_WRITE_SIZE)) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - set_errno(ENOBUFS); - return -1; -@@ -370,9 +370,12 @@ static ssize_t stack_udp_write(struct lwip_sock *sock, const void *data, size_t - copied_total = stack_udp_write_bulk(sock, mr, data, len, flags, to, tolen); - } - -+ if (mr->app_free_count < SOCK_SENDMBOX_ALLOW_NOTIFY_SIZE) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ } -+ - if (likely(copied_total > 0)) - return copied_total; -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - return -1; - } - -@@ -674,10 +677,10 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - return -1; - } - -- if (unlikely(mr->app_free_count < 2) || -+ if (unlikely(mr->app_free_count < SOCK_SENDMBOX_ALLOW_WRITE_SIZE) || - total_copy_len > mr->app_free_count * TCP_MSS) { - mr->app_free_count = mr->ops->free_count(mr); -- if (unlikely(mr->app_free_count < 2)) { -+ if (unlikely(mr->app_free_count < SOCK_SENDMBOX_ALLOW_WRITE_SIZE)) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - set_errno(ENOBUFS); - return -1; -@@ -712,8 +715,9 @@ static ssize_t rtw_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - } - - out: -- if (unlikely(total_copy_len > 0)) -+ if (mr->app_free_count < SOCK_SENDMBOX_ALLOW_NOTIFY_SIZE) { - API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); -+ } - return copied_total > 0 ? copied_total : -1; - } - -@@ -1082,11 +1086,9 @@ static ssize_t rtc_stack_tcp_write(struct lwip_sock *sock, const char *data, siz - - /* if OK or memory error, check available space */ - if (err == ERR_OK || err == ERR_MEM) { -+ API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - if (!lwip_tcp_allow_send(sock->conn->pcb.tcp)) { -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - err = ERR_BUF; -- } else if (total_copy_len > 0) { -- API_EVENT(sock->conn, NETCONN_EVT_SENDMINUS, 0); - } - } - -diff --git a/src/lstack/core/lstack_wait.c b/src/lstack/core/lstack_wait.c -index 4714742..855f2ed 100644 ---- a/src/lstack/core/lstack_wait.c -+++ b/src/lstack/core/lstack_wait.c -@@ -380,7 +380,7 @@ static inline bool NETCONN_ALLOW_SEND(const struct lwip_sock *sock) - } else { /* if RTW */ - if (sys_mbox_valid(&sock->conn->sendmbox)) { - const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -- return mr->ops->free_count(mr) > 0; -+ return mr->ops->free_count(mr) >= SOCK_SENDMBOX_ALLOW_NOTIFY_SIZE; - } - } - -diff --git a/src/lstack/include/lstack_wait.h b/src/lstack/include/lstack_wait.h -index 8ed2e93..dca22b6 100644 ---- a/src/lstack/include/lstack_wait.h -+++ b/src/lstack/include/lstack_wait.h -@@ -30,6 +30,8 @@ - #include "lstack_protocol_stack.h" - #include "lstack_cfg.h" - -+#define SOCK_SENDMBOX_ALLOW_WRITE_SIZE 4 -+#define SOCK_SENDMBOX_ALLOW_NOTIFY_SIZE 16 - - #define NETCONN_TYPE(conn) NETCONNTYPE_GROUP(netconn_type((conn))) - --- -2.33.0 - diff --git a/0361-sockio-fix-rpc_send-coredump-after-RPC_MSG_EXIT.patch b/0361-sockio-fix-rpc_send-coredump-after-RPC_MSG_EXIT.patch deleted file mode 100644 index 09e1faa..0000000 --- a/0361-sockio-fix-rpc_send-coredump-after-RPC_MSG_EXIT.patch +++ /dev/null @@ -1,335 +0,0 @@ -From ebbd5e477c3cdb5a561f79a09983b5beabb74c0e Mon Sep 17 00:00:00 2001 -From: Lemmy Huang -Date: Tue, 8 Jul 2025 14:04:29 +0800 -Subject: [PATCH] sockio: fix rpc_send coredump after RPC_MSG_EXIT - -Signed-off-by: Lemmy Huang ---- - src/lstack/api/lstack_sockio.c | 64 ++++++++++++++++++++++------- - src/lstack/api/lstack_wrap.c | 22 +++++----- - src/lstack/include/lstack_mempool.h | 6 +-- - src/lstack/include/lstack_sockio.h | 17 +------- - 4 files changed, 65 insertions(+), 44 deletions(-) - -diff --git a/src/lstack/api/lstack_sockio.c b/src/lstack/api/lstack_sockio.c -index 424cc82..ce22134 100644 ---- a/src/lstack/api/lstack_sockio.c -+++ b/src/lstack/api/lstack_sockio.c -@@ -443,6 +443,11 @@ static void callback_udp_send(struct rpc_msg *msg) - struct mem_thread *mt = msg->args[MSG_ARG_1].p; - bool output_again; - -+ if (unlikely(POSIX_IS_CLOSED(sock))) { -+ msg->result = -1; -+ return; -+ } -+ - if (get_protocol_stack_group()->latency_start) - calculate_sock_latency(sock, GAZELLE_LATENCY_WRITE_RPC_MSG); - -@@ -922,6 +927,11 @@ static void callback_tcp_recvd(struct rpc_msg *recvmsg) - struct mbox_ring *mr; - u32_t recvd; - -+ if (unlikely(POSIX_IS_CLOSED(sock))) { -+ recvmsg->result = -1; -+ return; -+ } -+ - mr = &sock->conn->recvmbox->mring; - if (mr->flags & MBOX_FLAG_PEEK) { - sockio_peek_recv_free(mr, 0); -@@ -973,13 +983,21 @@ static void callback_tcp_send(struct rpc_msg *sendmsg) - struct protocol_stack *stack = get_protocol_stack(); - struct lwip_sock *sock = sendmsg->args[MSG_ARG_0].p; - struct mem_thread *mt = sendmsg->args[MSG_ARG_1].p; -- const struct tcp_pcb *pcb = sock->conn->pcb.tcp; -- const struct mbox_ring *mr = &sock->conn->sendmbox->mring; -+ const struct tcp_pcb *pcb; -+ const struct mbox_ring *mr; - bool output_again; - err_t err; - -- if (unlikely(pcb == NULL)) -+ if (unlikely(POSIX_IS_CLOSED(sock))) { -+ sendmsg->result = -1; -+ return; -+ } -+ mr = &sock->conn->sendmbox->mring; -+ pcb = sock->conn->pcb.tcp; -+ if (unlikely(pcb == NULL)) { -+ sendmsg->result = -1; - return; -+ } - - #if GAZELLE_TCP_ASYNC_RECVD - struct rpc_msg *recvmsg; -@@ -1105,7 +1123,7 @@ static void rtc_stack_tcp_send(struct lwip_sock *sock) - } - - --ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, -+static ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) - { - struct lwip_sock *sock = lwip_get_socket(fd); -@@ -1167,7 +1185,7 @@ ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, - return recvd; - } - --ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) -+static ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - { - struct lwip_sock *sock = lwip_get_socket(fd); - ssize_t len, recvd = 0; -@@ -1210,7 +1228,7 @@ ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags) - return recvd; - } - --ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, -+static ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, - const struct sockaddr *to, socklen_t tolen) - { - struct lwip_sock *sock = lwip_get_socket(fd); -@@ -1260,7 +1278,7 @@ ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, - return ret; - } - --ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) -+static ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - { - struct lwip_sock *sock = lwip_get_socket(fd); - ssize_t ret = -1; -@@ -1329,27 +1347,27 @@ ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags) - return written > 0 ? written : ret; - } - --ssize_t sockio_read(int fd, void *mem, size_t len) -+static ssize_t sockio_read(int fd, void *mem, size_t len) - { - return sockio_recvfrom(fd, mem, len, 0, NULL, NULL); - } - --ssize_t sockio_write(int fd, const void *mem, size_t len) -+static ssize_t sockio_write(int fd, const void *mem, size_t len) - { - return sockio_sendto(fd, mem, len, 0, NULL, 0); - } - --ssize_t sockio_recv(int fd, void *mem, size_t len, int flags) -+static ssize_t sockio_recv(int fd, void *mem, size_t len, int flags) - { - return sockio_recvfrom(fd, mem, len, flags, NULL, NULL); - } - --ssize_t sockio_send(int fd, const void *mem, size_t len, int flags) -+static ssize_t sockio_send(int fd, const void *mem, size_t len, int flags) - { - return sockio_sendto(fd, mem, len, flags, NULL, 0); - } - --ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt) -+static ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt) - { - struct msghdr msg; - -@@ -1364,7 +1382,7 @@ ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt) - return sockio_recvmsg(fd, &msg, 0); - } - --ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt) -+static ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt) - { - struct msghdr msg; - -@@ -1379,7 +1397,7 @@ ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt) - return sockio_sendmsg(fd, &msg, 0); - } - --void sockio_ops_init(void) -+static void sockio_ops_init(void) - { - struct sockio_ops *ops = &ioops; - -@@ -1400,6 +1418,24 @@ void sockio_ops_init(void) - } - } - -+void sockio_api_init(posix_api_t *api) -+{ -+ sockio_ops_init(); -+ -+ api->recvfrom_fn = sockio_recvfrom; -+ api->recvmsg_fn = sockio_recvmsg; -+ api->sendto_fn = sockio_sendto; -+ api->sendmsg_fn = sockio_sendmsg; -+ -+ api->read_fn = sockio_read; -+ api->write_fn = sockio_write; -+ api->recv_fn = sockio_recv; -+ api->send_fn = sockio_send; -+ -+ api->readv_fn = sockio_readv; -+ api->writev_fn = sockio_writev; -+} -+ - static int sockio_mbox_init(struct lwip_sock *sock) - { - int ret; -diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c -index 6523dc2..95279da 100644 ---- a/src/lstack/api/lstack_wrap.c -+++ b/src/lstack/api/lstack_wrap.c -@@ -53,7 +53,7 @@ void wrap_api_init(void) - } - - epoll_api_init(g_wrap_api); -- sockio_ops_init(); -+ sockio_api_init(g_wrap_api); - mbox_ring_ops_init(); - } - -@@ -566,7 +566,7 @@ static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol) - static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t flags) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return sockio_recv(sockfd, buf, len, flags); -+ return g_wrap_api->recv_fn(sockfd, buf, len, flags); - } - return posix_api->recv_fn(sockfd, buf, len, flags); - } -@@ -574,7 +574,7 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla - static inline ssize_t do_read(int32_t s, void *mem, size_t len) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_read(s, mem, len); -+ return g_wrap_api->read_fn(s, mem, len); - } - return posix_api->read_fn(s, mem, len); - } -@@ -582,7 +582,7 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len) - static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_readv(s, iov, iovcnt); -+ return g_wrap_api->readv_fn(s, iov, iovcnt); - } - return posix_api->readv_fn(s, iov, iovcnt); - } -@@ -590,7 +590,7 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt) - static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return sockio_send(sockfd, buf, len, flags); -+ return g_wrap_api->send_fn(sockfd, buf, len, flags); - } - return posix_api->send_fn(sockfd, buf, len, flags); - } -@@ -598,7 +598,7 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32 - static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_write(s, mem, size); -+ return g_wrap_api->write_fn(s, mem, size); - } - return posix_api->write_fn(s, mem, size); - } -@@ -606,7 +606,7 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size) - static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_writev(s, iov, iovcnt); -+ return g_wrap_api->writev_fn(s, iov, iovcnt); - } - return posix_api->writev_fn(s, iov, iovcnt); - } -@@ -614,7 +614,7 @@ static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt) - static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flags) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_recvmsg(s, message, flags); -+ return g_wrap_api->recvmsg_fn(s, message, flags); - } - return posix_api->recvmsg_fn(s, message, flags); - } -@@ -622,7 +622,7 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag - static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags) - { - if (select_sock_posix_path(lwip_get_socket(s)) == POSIX_LWIP) { -- return sockio_sendmsg(s, message, flags); -+ return g_wrap_api->sendmsg_fn(s, message, flags); - } - return posix_api->sendmsg_fn(s, message, flags); - } -@@ -631,7 +631,7 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t - struct sockaddr *addr, socklen_t *addrlen) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return sockio_recvfrom(sockfd, buf, len, flags, addr, addrlen); -+ return g_wrap_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); - } - return posix_api->recvfrom_fn(sockfd, buf, len, flags, addr, addrlen); - } -@@ -640,7 +640,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int - const struct sockaddr *addr, socklen_t addrlen) - { - if (select_sock_posix_path(lwip_get_socket(sockfd)) == POSIX_LWIP) { -- return sockio_sendto(sockfd, buf, len, flags, addr, addrlen); -+ return g_wrap_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); - } - return posix_api->sendto_fn(sockfd, buf, len, flags, addr, addrlen); - } -diff --git a/src/lstack/include/lstack_mempool.h b/src/lstack/include/lstack_mempool.h -index 946edd6..5e489e4 100644 ---- a/src/lstack/include/lstack_mempool.h -+++ b/src/lstack/include/lstack_mempool.h -@@ -10,8 +10,8 @@ - * See the Mulan PSL v2 for more details. - */ - --#ifndef __GAZELLE_MEM_H__ --#define __GAZELLE_MEM_H__ -+#ifndef __GAZELLE_MEMPOOL_H__ -+#define __GAZELLE_MEMPOOL_H__ - - #include - -@@ -336,4 +336,4 @@ void mem_extcache_flush_pbuf(struct pbuf **extcache_list); - void mem_init_pbuf(struct pbuf *p, pbuf_layer layer, uint16_t tot_len, uint16_t len, pbuf_type type); - - --#endif /* __GAZELLE_MEM_H__ */ -\ No newline at end of file -+#endif /* __GAZELLE_MEMPOOL_H__ */ -\ No newline at end of file -diff --git a/src/lstack/include/lstack_sockio.h b/src/lstack/include/lstack_sockio.h -index 265d620..2e4a8b1 100644 ---- a/src/lstack/include/lstack_sockio.h -+++ b/src/lstack/include/lstack_sockio.h -@@ -16,22 +16,7 @@ - #include - #include - --ssize_t sockio_recvfrom(int fd, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); --ssize_t sockio_recvmsg(int fd, struct msghdr *msg, int flags); --ssize_t sockio_sendto(int fd, const void *mem, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); --ssize_t sockio_sendmsg(int fd, const struct msghdr *msg, int flags); -- --ssize_t sockio_read(int fd, void *mem, size_t len); --ssize_t sockio_write(int fd, const void *mem, size_t len); -- --ssize_t sockio_recv(int fd, void *mem, size_t len, int flags); --ssize_t sockio_send(int fd, const void *mem, size_t len, int flags); -- --ssize_t sockio_readv(int fd, const struct iovec *iov, int iovcnt); --ssize_t sockio_writev(int fd, const struct iovec *iov, int iovcnt); -- -- --void sockio_ops_init(void); -+void sockio_api_init(posix_api_t *api); - bool sockio_mbox_pending(struct lwip_sock *sock); - - /* just for lwip */ --- -2.33.0 - diff --git a/gazelle-1.0.2.tar.gz b/gazelle-1.0.2.tar.gz deleted file mode 100644 index ad49dd50819937aaddf81b133df171cc0bbe6ac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1060611 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 z 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ȷ^%~>l-#ZBU+_6w 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

~S3 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

Fi{^dVO63 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

0jI&6dT6s0g2wixM9}&!9Xbur)wK+2w>lpfN@b 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≦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

~&%&ftH^uIPtrz%ly-B0p?k_L#FMb=DU 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

pA=lF0uRi1v+an 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 !0hpd0AIZ!D)<=%&xH_|J*AFzF5Qitii_Zp}zh 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%0AB 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

|cW?>7+wEgLN5K2C1dtRmV?uNDd#H~FmztY1Q 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

{n8DeE8U2Y>|uBed$3(~U-0&Kyje%NK%qJF5* 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

  • q(Ycgq2laB)&h~dRz=v%E4MRL$_ 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%0A;)It0!g4k3{rPE6Xs$avz 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 z z#s_43$TipzsOv` z8-e+k(=f4@28f2{JiP6f!sFqQSZ&Kb^t~4|M61p6;6PZV{J-a=rLSS#6WqY;Ezf5; z+rNH|y8B3_-(cYR;ipZV`(j`xGOJnH9(CAAzSu?VFpFuvvJsc#7AY2j$

    oTl*N zWuC)~PyVB2f|iEo^CxQ5Or_&cnX^8E!|Qtu`a}FMl7?nQabCV=C!ZF8i4yLD1s4&M zuwd9S-mT(J52{fZHIQVPNG%OGiKcE0LR-Wx&BV(&_uSf>vn$F)Cb zdQa`^%tsKSkXbKs;Cr|$$bZgpLn>P595Va+dKj0sWhJ)T^+D6dO}_{Dhu}PoCix_V zF20ra+Z=Kc_Mr)t1?jCZlhjYuw~=M87W8#Oz*T02ooHV`vm-kZpZCr=M-wZmzf1!HZ{maW* zOU81ItE2^A?X`L#9~l1-mz<}yM!b0YkIZm%`;e}{m*Hypm0y%G=<`;ch#jKyYZ7ru z{9fM7?z1)uX>j>XHUmi5pC$CvVvmP6d}g7hGG1z4e3dK*XlDHPQZ*>#uol>pEbM9& zS<~x1MlJcSvoxhC692`TeT&*Fgf=t8T=kqQ`z?E8c5IDOs5xkBd=j#9Y{a2*cW3jI z6VtHtFUt4x!Wx5ZmKH|(e_IO8Cm!|La~{|FqLHx9@Z@ONnza$vNAtvDBqB77uR5HZ(bHw| zu%{Elp7WKld&}ICMmu@g3}QEr#%u8zupGS@#zXAZGnJD~cRJ^@S0z4RZKG<&miGqjE@!E1`4WfinVcOtPkekAXp@CnvtB#aRgD{^$WZgly2C!3vje+3 z${Ydx=j5!i)79(JoM$2<8eTUxPm|hq6<2muSFBq=s9JDciQT0uPob30Cxlq(Gn%1I z@q2kk&i69861mhm81xf`rKsEl=`*oS=-!h4?>&xDUyky%j!aZq5X%lJ_`_ZeJ*4nX ziRR^+_U=_!*e)^Y`ldbTPqDo)=X*lVSv5E_3>N-!x@WFyS}NKIL6!taR#_@~=sU6e z>v6IMy4AQbUa$!Ao%vF?yV_paOWShuMNrgXA?EVp>LY@NC-lLFW}8tHwe)Z)&i?=Zsz{*{XI=v{7>RQt4;6Sg{x0U-w=18V}cVOmG_u zh`r6>y(Ap$(e?2iXl@JF%EtR;8%i<$qF-b}Aa(IhOG)GVp2qHzSZBuHn!rfB=(+bJmjCS43hHn;H~hz9*xxPn(;D*qT)x=Y z9-)DbSFR4rc+Gu{woWKrryht#`EogUaInmoJTX^3UsXAI<|e=%JFVgOTcZm&4ux;$ z8u_SILy)uskOjA*Hf?LQznT2kXaQcn+?||Td{T(tBWdCD57wTN{r;(?Q$xXf?K#Id zhcE({`|76y28cUBq#m2?K9w5jI9I*9GZ1J{My*TR6BMvK?4w6Ik8C7;`Y^lfgnBlEXjy{am$CN62bTktn(ia{>5cWo z^Yse_nTFh#2mDqyG}9leV%vW2=e@6cXIZ-^D1~hMnx9?3l=?a?F#T{`ao`+)>EgP_9DfIDni2KoI;^PM|iW-b?V*guR@w-ax8^>rTESPdFrydsAU9@rtbXP$zc}`dx$HfRuz}(Zp^S6O{;Ztuc!iftji0O*z`im=u~sJ zi*ThIK~*;JOszfxxTht#~*{H{p8%9 z(h6TLb{vxC#}4npddiP|TK_ND4w;x6avhPY8w9Xz`5Hm;pM#Hfo3C6wc|tRBeR8PI z^V$K)#Q&7K<;>s|MDvX&bz?v0K*J25lTj@oAo0veA z&q;?(MRD} ztM09>qy3X{5q97vaWi;f9ZZ&Cm5wMaz(_Dn@!d=>aq`_9z=h0qz~xrE49@*pjFa7% zO!0rU)|t4oq~FonPfv+p6kVyLXp5pgr{(*jvCA=&gN^VmVlFcwsdV_n^sXTyJF|tm zD;kQT#V&gw;$^&x9>Df1JpUHizNvD#Q)@y`Xqt9(HT`N?)WWLuZWO@`EDAy4jKoop zklEanoxGNk<1thx}_7}q2cMf?;p*{=DkYrarCzT#lUFu zi>O}%RF??*E4=Q?ovyR&+?U_++XfyBf*Gh<#ASq!3kFK^ydm+h8b!p;l-#tm6p6=- z!?HPt(*gUgr102zH=WhiY%RbQ&cu>9W2^HA(eL`fma`sSoNTpgWxRQMm@}J3~LBJQVJNkG=xk&7;Y(h zc-&oiaK2<%CvQfDo&VW+U_F-qqINbDbhmT8}S;p5Rt7_#>JV zW*`#5$uFqQg2f4jrtu$pY#*@sfXiALZ|U98_<*Y(e!j0Xc)ZJNxi$SuYZFm(CAa4Y zK9R)B;z_iSXoX4$8FWCGz;W40>wFNXg?Bba%CB@Hhm}kl>`$;=?=2Bnb$Zr43#G&MU+_Da8c;_cn)rv)W(-n zI*)VL^l=LY&(95fIh)O&c~+hfl|zO_Fa|8fsYZA)g-0F>Z_Ia5M>d>JpU8HVe}ya5 zkxIBZZt#ae5N4qH3$_MslV2JbMtDXnC>0oJeWYryJqeSDghWAGvEbW%YnFs!cHFwG zD{FUxxp^E`JD3PVG!`thv|{Wb&5{U9RH+F23wtnfGjvuII~xWWmE$!MQp5@1N(aea za$$r}JY*6)lqk{)EsiTrT4#mNcH2ak!%6M}OG|Jvq;oGred=e1+H^_q>zDHm*Et~A zDp#MzLur1Yp*DY9vb;3*VO-~VD280r2w4Zm7sgAk@*B`A-VJSp{K2CWfeBrP@$ZdK zNh(eKUXy%@*B$nOe*NRYigAR;2ytZ(FiUnm@-gai-}2~2^qBh;ESDoaYR@touz3s=tgoTnEU2<-&&R`Ua3){5jw#-5yM9WeZh9S`7}a@A)35Fu_PmhTe69k zrJ5|`Ykb3`Dfn4tr{L;fhP*#H__SrK@}k{_0+OH&(@BLylZ#91CJf@}EpMQuON^l6rEtY1fdku!v#b>3E z;+mPl!)IUT1Vg0uj58n9a`vHIo=7n1be}#mb)<_P-xr{e2Su8#&L1k|2aC>=T8XFe zD#6fgNxNYatZ&zjl*vdYmHBxIh3Ir;T{G$}60Kyxg>oo~h_cXlx`C#;Y9DlK(x} za59nkM@Bes_)qGZ?IeV1oA}IIUnCncISH1ZzpX{ZSsqi57?dpKJI9`weJ)SCAtiw? zv_!ihETMDZvVqJcGEsluzqZsDkSqPw=&5&vLryFmJ0dAz#MQeZs{5X zB_)F?dYK@Ur;;SHdK)ypR)m18_lAvcWa9ePGh|sz!>3B`^eMa3#ntZlpT3e9d*3#q zy;tL63{1{>FlXD%dnz5zEiX8b!=}KuS`kig>e=P_4}~qON`*dtmm-vu@=?fx;gQ7~ z3G7#fa@Fy`Nt3-;Mf^72)q9dt)km=C9jAc7b7Fo}PS07JM5wGk|3!NBkBwK*xETjt84s(Kmi5u*k^c6&m=?sx0Q$CwV*^M`@hsFL7AS>oLU` zBt)_kT1U^rTcUAA5=Q{Ro08HeyqYC@f>QDs(-S>dNlny&;*~zw1BPb=cpn7LY!X}` zuDxPVG6EZv&9h6n!lE)NJ-)UHhQhxtx^0){y3Kti7|04mh7;!7oFAVQfV=({QV3ca zgyLU|I7;(>P!s8l>YOl@PXWs7$?^<)wmKNee}i{nFsvb_vC*Od4MXG~!da@nd3A15 zpUVriuqGJT@a`NJPlBERQ(%}wKt9{wCM%JK#jnQ^^_9d>mWlCSt>B#X?#}LY@CQY) zEv^!TG{kBJ7TUWVMm5`g&*a5cPdU$i(Do?K0@5uK)VIt^BESG4d!TLsrn}J}VBz34 zJO+LilRAfLTE7# ztQJ%e*9F(i{W;c!im**Z_wDjrNk{gBn0KS@7_goKLoyhFU{Vhj$|reM<6yFB7N>G+>gzX0Pv1x?kik?{1KaDv|!WoG!_k07Rxzk$}$ef37Qb%3$0*S4g} z=L;#M^AKUwBf<2Ez;!TtbDxJ9sz{}2aMm)xa~~{>^ke@d9*?zn^U5u=Ubd$s!d2}R zdv;Yj@gjzi;3m(gCmH#Vsj}tViU|IPjsp{k$7hJsADF&s{SXtgUXo<221}otwN5au zBK!>Tc;v+I^VNSy7@C+9_B*J$p#S(T{dwBq|ZT~UZj3^ywl3o4f zP8$#6zD2>QGntO^r_`lPKYC&oBW~K-_6m-~ifX1=$@5IqkxsPJAZTDs#_spqAl1ZRh_H z29cn(dSUH|qmn*fZuQ4?_1lW0E+ts&I^Dw}wsk1*fI1>`h6d?Mh&J4=DlG=j9wDKt z@~{DZxVj+@?tF~saqNlD^lc$e5K5?WsiTFOG4K+Tvopd;`X~6PgCtbasI%55xrqgS zX*7U7eAu(%gBw6#(r!70T^0eNP3A;_e=4$DOMfx0#z}+(ehBuhXGdhyrcUD>z|IJG zGgL$2*QyW3r*Z-Is~&caPa(0A6CYsQr2}*fCsA0tG?s_vZ!u0+H|D#tu1PnX?R^XuC-G9e zl=I1phWzfW_ZrD26iuzFb4t8~8(!D$fj2>OT?voqCII|h*=Rv1$n!jdYqC6pSNo7! zb(K_4GKz@ApI8NDftwt;dnnF&fyl;{K~N!81ME9_jX#&%tDNXwHk$moQbSn$FCcZI zosV6B|CbORxu9c)V$61YB1>`SQlkz<^B;R6qow-PD`V zA?Q&0UToMf;f*CuMQg&6nQ>VXDBh;V0twk8m3QZ*fYDrH$G=8VB&{%v;q~H^Qla_o zD_($8GJ-~0w3agWXCpRDgPyT_^0#DGa&>5pz?pbf!Nq#X%evUI$`X3O4(0NCzetfw zEayB(QZc$yTG$8Epgh#Tuk>S?U+VrE_pQCqe0T{&RpCVbh11air!CK>lc2HdZE#DO zGo1RC<`XWBlry|Sq4we74o6q7aoxwfRJR~?)b1<&SuI|LQIA8#PCO4qxcPHEsHx-v?MIQn zr*InL3YfafDs{J_+axbGgrp^r{6cDGdf&9P-nO`FDlok5tmVU-#7p!9u&{QE^(hQG zi}MTfd`OQ)SsXD5CI}I#4ygF=z1uWC_&f*~C1Z0c(E%_4T+1r7h3z3{`tlD(AiDzi$F2ACwB& zSQD7&b~c>+nX-_oe11Up%lQ+q{lwyC=0tjgn`C=N!!cxN9KS7_2THZ-(meq6siF-; z1O|_AK2i=YxP?NnNuPShl>bAG6diK%Z#@VG;v?Q$KvRI!8{nzdx8BkM3?r`0r9RXB z>Hwn%ikCyHs8y&w4lZsL*F-j$L{Ep8R7!HoVa0n~?G4y7G2Gx{or;rPsKzl#HwENo zN?wwx9N|vWAf_%NZ5erOxTFNu4f1TxCK^rto^km*VW7~xWf9<%fd%X}zfQ3$BrYWBrNv}vlEr;o#HBX^ zO{yvtn?_tZn7S&&JTRkI6Hk=u!t$!6*ummo1AM1S#cu0l4WJSCN%r z3e0=4f!k@=gPd#dp~x9w15Tx24FO$J`wF58R*U#x zLCbkX4lnhvV^CR#Yij*YE?c+I!09)91DW;5!>#Xn@d4-|YklS-i_<&fgKxAA0?y65 zv2~lryWt=wjrj=X4R9+v2y27tyLLE?-A-83A;>GZQSLb;7xUQIAg|T?Fx}6l@RO96fP9f<`d}zty?7f7Q zLO(Wz+_Y|lGuf4g10x;xDoU=3APNBHTr$`JiL5`QTlb;+Y#(c2z5`Eew#vtEQhYqP zoH$XKoxq9Mh$N`5s!ZgB7Cf~ITct8C?!;=O#jG(3LKb!jt=8uxye4tvz0=odL>8u=*0mgCpJzJ^dlS zIzl0gvu!bU6Wx{qOM5wGXy&yCL9Qo%)a_B{9jy+E1TXj7^;Tkh!D+YB^1U|0r^B&I z!NmUjb^ZZ8a87I`T^6py@JwQ;xd)Tz3aJ&}-xh_H(q{ooCXkZp4BmP6B@F{kQLzYy z7wJZ2&vuBof?Q_Px*MCbIf{R-VwyxyjG2Ex8>wPC&a`poJRD|Gq(-1&uCf2haqha* zQq6K+A*4m0NghmKU>TmiAqqGj1y`RQKkRv8nf#c{Upe+jfp?XyeasK{5V@2KUs^YB zOSZ4mFL_k^{Vdk=ZU+!9sYp}QPa;a)WV;u}B#~$thsP=-RO#Xj0J%@5;IC*;0p88#pPGqKY1>8Fb;04db z5kcI)8y*)$C8qBY`S<)sQi(+(N1T{0vfTxNyf9>Ln?YrfS+-4jkQ44l6QS-5;tAQX zXdUx|tSxSQfSJEp?>m@4fKNb<@6S>M#jP=w>3*x9OPth|9P;Ezr(ls^wcySIVn<*m zE4P{k>w9yf2pxsT6&#cP-F3Hl&k4tfFsXH3Q$)d)Rx4d*5mftq>CEhCRkn25qJh9; zNloVV_M&`30}hsZILGJ+@pvWJuGJ6;Ez(eX)gQDOiKioaFy)iYvIyZAV33wG{Vh-{ z!&gm)|Bl(}n5Y7o)X!F8Dm`9=4lM-HACdhi`9UDYEH7 z#l6U5O*R83MXIzIWW(Y^ALkjJh>XdWGU#yrcxBH6WV`1^>y9qc|65i7E{nXvOps!v zF8@giquQEMCuoTt^3<GPjS;q58LHjfPRir=@Y8yT{ZL7k(>;?R4XFLi>^hZ&dv!Y8MM)A$ zxfOK|N|{5n+&&Q#ILm0j7!yPv%8Hx9TS+`)3QVPN`PQq_!`H!l+b{a4W|YtCTOEk?*F8cdj@&wjMz-GE%gx{*Z*}YfPQ6 z6KpK~i15LiIOSua>g&Z(Qg0Ueq`_x_aDQF~TOm(r7QJ>#e(kH$2Z$x_N4 z8Nk>vJbxl!(uFt*6COd~8Fz)>+XfLlieg2_` z$AM@XMdm7&0sEdM>AVo~Z(Y}O)PAL-Q zJi82!=+*J4I@mc0p>f7d>DO?!;0IjIWe2lXgdT!l z1*I%f_uU3@G7>KCr$>t#F=|0kaGwh6%)~RCcMRMEh>b71#x0Y_Kk#yC1ht&aT9nQI z)-NfMpkgp$K>}R>ym;%n?5oXqV>|@+K}`0I5N=4)p!MuzNI%&4xk^hkj+g8!5!9z| zJM%yn006!i^a>iwOklKbB)@ldSb3aT8gnifDxu38OztEyH>pZYRGn-r@}IEg0p^8K zy%#BV#EoyE8p9RKJw^q09LS8RFgB>+E8vVB1;G6!8(u^s zKM=|}t+(sPd>Y;wypqk&(-QKPmivQc968dp-;4BD1Q`|)79cVlTtIm&!Wc?4959%n z&V8w3!?>S;U~l177Ghwr_Yf+L>n!&YntD|pXG&2R3C%AO0twkZdIq;3rV#=5TYf>} zShth$PVSEKRnuXrrNe^adTR5~I%qdtS5H%4h>-5%L)6o?ak1#@Q6b+MM}L81kl z9EF+kGyCvWtdo-3oK#L8)fhEyoW^Ka+E2c(3Z_UD13c9PQ|N zCn!DyfITFygwK=^&YC`OZ=8ilbg4*!lj)I!l#B6Y6BB^<)HO-rOg+|s)x}3zCWDP~ zans@`lRyC|h4t64CLY^>mE4hTNNe()aae1lGIiQwHL=W$#dH@Q$JMSEB2s(qf%OPq zFWs(Iz70&3h8!NKRzMA7WMkWG7+HAbVVavOSLc0 z<|eWQ#uOWEm8db#MlOvu*N)v!X5gh1Ft@C(t_MhFYF(nw>=p_o^BV+(9dlB7?3FcJ zD!K1tWQE4P0v=b$_P|t?Y~wr-P>3Kq>TvcqEh%vBU)-?24Kl;$Kd5fCvqgqm&%6p0m>H#3?B z@T?5ZEats7zdW9!d^4IX5RMBWekz~&@THUcV`yvSG%Xco#kA;sPM>$4*#6#&!r=FhAzJWhB)v1L-p zy|7pDPneu!)E38<^nVR^K#HTPjCe4N1g*ZIeh{{s#AAuYe5feMmiCAnGGK#l<^4mq zGC4&Q8#HbOM2*d z$uB7C&_1JV=_;UNIA?A((TNq+7OMvA2swS1IU>BanAcEW4Y`zuC9f`PLhY8mm8N1|^mx?83-kmw0HqzZ5>Z|GR*GS%C$ zAa9o*e%aVW{shr)RqXMD5Lu)8L6J9`2IEEX?G+}CB`Z<7qZ^Opp)5_tEPBz!HeB9E zG($k*j!*;)>8hHd*+ncxX3qyj;2u}Ef>7u==BU4u0;H|3v(ZW4xW{gZGt+Bk&)<>; zq@}Ba6w#fPYH01(<$!oaGpYlyF9t5JafX!28v6L;tCqV6SY?QaE^g7wnxKgYZ~U+o z0+>wlnP$}J*(thogF$kfWxoB?HqV5C-(yFj zN099W?WJ=*_5Ik##n=aU9xkoy6cHX~z1W)Ol8D*h394M`a;vauI@lN$J=>V(Xn`yFIXtpCav%RNwd=nW~AA=<(9VpK*+$u)2p zEiqJd&AFgpG)kcu)-o4VrlFMwb2gB&dSfsh-}_&5B!$Qx`K(`M+2zD(yfLJU{w8H~ zuFq?rP~Eu&^fTG-IYr{sAJBIkF0o?%>~x^WqF+Rm*W6z0k;JQr=_%46_Cc?Op>$sJ z+hRt&QTbcpAQkgBuS)hSiuMb}2;wAos|?ESnjM|1VM_?f-oa+L3HtEfJ{b3mCRHv` z&gMAq3z>sSy&n$v{jEX&QK|QfA{(Zr{UcREetEtBs7~8kFqltGjC^m&4?@w1g6h*G z_S3fiF2wtrjQwNMxc&~;|1MkGTYssD^f7t9f0A3>FW;1~Zou%L>ny7sc$K!j6WXGq zeg%(z*YWMGi%?89+>aSz&r-|JwC(M*3lDhz7lm&E@Zw1KVHE|T8%_G=-~(3XZ`2&# zNW2gJzhKr7K!A#9ecFUX+p^d#`rwE>W&?ghKRXNbWLeg``ebKYS^+fFN@%;{5R^q_ zkFWH}1J?(?9(Iq89Q0>(lJ1d+psxPdQ)|vYa<7DJz9p*R zsOO^X9o-k{r$)VWW~I*LF~{SIDe55h&dLNcOHeQH>pkb$;QeJGE#;SRCnQc&tB_Hd zzsUPrnuCX_kJ`k={UUnB3;r!WYL)9!M@Zldr&Hg*S-W@2r)`7MN=Wg{zjcZFtg`Ui zCC>(i!XUd)@vlA=uw8(Xcn=**``{MKC|IBK1F38Gjve^P~5lt98`HGLib5zYew8 z8}QVxswjqiv5);c%jPF>Ki6ZybtQ}QkG^*7r&IUO@7o*uul2IZ9}g37@CDi`YG$y82;K9%8)U-co>($f7UW+L+-499jvt%Z8Ajy{fh zDHHn8#7#&Jx+f~{8H1_U!lNqc*&XN)!758eqzuSpTrq<5t!i^lCIWGL(|@|PL5G0& zzJ7172J;Eiq?ecDSx-vdcPS0f?wR1?yca6qCU|E^V2-$x?N1(Kx;hQZRy;ocS`sWd z?2(jkS?Y0eDJL>-$Jf$g@08dC&HzZg;?bpKw|%)LAn zLtR_n&+>s^@Ebg5omEj`&8}q9N*@;a5J$ez`Ed)+WEx*cIS z(}BBKOY&;nvUWo(i6)muZRkfPb21n}hdb{5y{?PlG(IWa1q8}hS0D@*$*NQ7bL@YH%;Xgy3#@0LYv%{$Fgxl z4YQ{$V;zN9j_|}*XGli8OWIj4eHr&>Z&~s z>Rd|(xo$7^XCbY7@I5d~QTqW2jo+*KBQpb>qx7}sE1?t^}AeY#Qj4XMb`E)$Bv-)V$cZ-I4 za*>vl8CZecYy?@+p)?2V>Ig>yMgeUxGW^@HBArp@PtWa}4Kn08zrh*Il?I_LgVJ+> z{Ozxgsk^I2CSKy=0Nq$vXmnXF=_v{g?F}}RN!Fe72|pGZoGWpe`CNEpgQ;w=p{fh3 zTx*c_*bY`QydEcy3c8@F>JBc}HJ{Y`2|tbWKEq zkR%?j9hhvFA09VbFJBB6{R{^uga!+QdoRO?C2q7$#0Up#lGpLo23~Sm3&>j+VNNVP z5&YuAx^PflOSH}y`ZaMvzD`QlzzZCEB2jUsxPL_|j5rEWT9RB*aSI}rObre>N+qz9 zdh;-C|1>nfnaNi}57}}W1+YlmS6f=_``(_N zaL7C)A;xo*oMo?2K8$E2N^Qhk-OM0Hj$`22#+Nz!+}9Ai8@biypSj_ey zm3`x(oDZrNVUkye8=i%p-i z`9#C#+Cir4l8~!h@_v#ytPu^z_US?$KQR@N{fTI<|Ify?x{N0M~P zx$;YMkhdjHamo`!T1hd+qP)SxDdMS?*|sR$%3!rU!V3iKsv^0~HCHf>GfucVG zk3&9?z+xa_Xm;F;tpCLA@mxahSs>{3#1t2H{9WTxo5xSXXSvS;bxuZ~hpt-b`kaT< zPi{TWyLE-@ra>}{S4!Sl(EMuqX%E2!|9D4NJxRwrAWt!^TlBaAnVy5?9 zKHVy(O7o?l(6NeJUR4IZPt;Ky7w`{)HJ0&&XAfi|X$b;&JW1{f(I;%J{|&*~LDtJV z())oy8Y2nHRqpqI9j9H5!!gZisL2;?h8T0R6B2G!vf`zBUgGhMsAzlEF-F2fjs$KF z_qNN*-7(s3GyKtZj>fn+ldpo3i(Fv8yXxYd<~>QH`*X zyphd$FuhfYmXrA=zW$}^Y-Wzd)#x*OtYEoU^zz&dq<`DI!Dq&XAU2+XN2Xqgi(M%5 z+(ocgm8Gv2El*G-I}YB`&%fY&dVn>M96{0xqMT-ban{smVIv3WpEuu2kSq$qk9oCp zg^WukY{<#CGM>Bahy6k{G>TQ6?9GBs=%16XPJm)9;1})SURfLyap-f3gcsk}OXndC zC~HlYBkzz(Qq@*7>ua)&kO&+zvr}ThbX0yNvm$8cMgw@Q}W{IWgt)5kM7;&n|4z9U!cUhxlSBikh zY|(TG!Uf&U9YWK#1h!MO98^W^ND5D?`t-vnP&=ZoRv=%KKZ>P(QmPw-q3|xi@|Q=^ zLcvp@X@gUQwEqaD;$l|F)`owS|CStvgeX^+@CkCAR2R#a*!s*tjQ6s@Wpke9l%FUC z#?7gsx&?L@G*D2Q^?I2Q2oX+8oP*F4N#-2R_TiQReW&{v*S5?zZ(3S%7%K!dMD3I& z;Oe~_u@Z{t@d`RlA}0p=nRI5L6~&{;E>u4JY5+kJ7gGkjz}tB3hA2kOAkR8NTc(6a z{z4bA9~?#!7Gs|ngerHT-u1HvqH*8XFsK`&RdmS8gh)F`j3(68Cf5R@X(Tir*YzlN zytl-d1KR9f4?&hX*0pVXmkM(zae}e-+yu~UPep3@-xZ|LJHL+Q_=))@Uv27`PcXnT zy`H(cM^{K53m8YoN5z$RscKDJ`CvaVKJMNXBABEv$8att>DygP50vUBubF)H*n^KR^de4!OHj2`^q1bpU><#rpKmk$q81Q~!O5^thm ztWZkG@{j|z>h+8?&w#Tk6R8Rd7vUAcX*)N$Vc2j&Ebyd!NoxZmX%0fLx2t_l;yYwI zPGrT%0)0tlmnVPyh^c?CgS6rfU8r%iV%29o|UZU>@0%oZmSF(huzbPQAj`z8h1&LcV zry@ku9X!>|N95EkM^x;HJOBWTqug;f(KZoHmaukA>Cxbj;fTxiF??*D?d{&(~g zSgz>#dCWo88ueyZ{nrYcefYf%{C{|UKK9jjb!6KW7vd6UQ+J4E#UJ&IUYmwS_;9s) zxSxjrqD6_ic~WtZdhY>$pP<~j!O!w3!`u7N+;MUyyPUDrG?rIM>Wn_1? zKw&3vccZ#$eM*RK%4m0@+Fg1lT|q8k(&;(uPh#=TLz4q$$JHwZJm`P{4Z9JMig7!S zs+~O+3x4ia+q*8~&ayy7XjC$Fj3 z^9FGaq;V^de_MIAY9Fv%V$u`%LO4>@UG$44?b0tsPLzI?RPoHp{aw7_+gAKTl4 ze?x$wz5Gkn&T<|{g6C9fWKinn`=4Xn-)wxKu#}wp*)WQFn;?2gtTJ|Q^ZWU($L|0~ zK)An1iM~7ceaJnzX$p-_&wfg4e+Tuew%x~-n{(x-0^u`8exBE;=NCWa`SSSPH9%Wk zN_|FH`l8~JfBWFiy$h2AwMQye=gQ~VRmeXFb${X#)xI6)N=XTd(L26m_NfN^@B5~s z(i1$UKVDycrAFQRj26QMGVR@95p%ZDXsLQ?d5yYxJ#6-!Bo}1rw{bmOawqr$Uwpi? zY^kQ`YEl`sx8EJbGh~ag^`1=fccCa4iOO>Qs!SuA%gAKzRRtD3oT~I*?|?$VX0%{KQPX@vtoAF>C`YK zUYEFF^Ly<;x$^F2^N2)F@z+PI)GMt}E#$mvpUvIEd!E~u(h%$g-M?-49HLCbIt}j( zzWz`=nn6|WuOZZB%xl52i(h8rZtbQ!2k$Og9Sv4H@tc-EHBBxiPL7OE4)|5Rwlquh zoGaDbm8KpM{oWriqWMR+AGrI&-vU;(`W+?gU3kprT(IUp8h9!%lZ+2tQ#sA=eQ<%g zxt~Jy6W=2>D!))~jKmpI1y}2}wSeUfp@v8?V7rv6Gm znK?`f#cg;6RDGHP+-rH|$30o3h0UR;+jXzyRjx3bR*C%)Y;@wE*6^@p(xGmnIbg1? z@rw`HXhhoU;d2w4im!X0`+abQ^Z2?^-TC@U`JfN;U0M? zr(IFc*53Q$SMaZ%_m4u^zcZbBUdRpuIoGJzk$Qp8Kp_3zMM1V&Rmr>CSzCK2H&}^n z))PB!{{C?dj>Fe$&3eS-J@xQ~o6xXDrg3r4dSct}Z%N=;oGM@x>dh|n6MMJ+)Sc59 ztXS!X`j_WXZ!ZH;Pf0K{@B%#ZHHF=E{3-V)Z4Ei+FOV?&)jUm~g4-U=y1%!#w{{8FJIZeEmyA>1QBi^e+dm7g<+X*T9 zDTRUk3tv(f7(i3AHG{T)Qm+kNq~5;tc3u_;{Fx$; z$q@vGMi{!gVa|Qy)6e(!d*Aba&pFq7&h?*5F9z)@QA~_h&CB8?IJe6Q=xW zt{$!+lFTsHCjGAO4-aelEbR(K^V;zVP%2-xrh5H$3ZZrA?%-POJYYO2^#eK-kf8r+|N}27a>Pad5P)0B6U+ zhhc$Rdv@j?*IK8?M2K+qr)uS%9L5J=xrGpasm08$E-%av3k zeWlkp4z@pv0k3B|nLNC{eziF{E4z3(42my1t$vvN8|gE1<7J||R@Pm3LJ2m<@$|OG zJ@`b+e`u83G0x?>$R*+&vVXA;odu~Hx}@3;4l12JI`tIK!26$M?A}-`yG`0yBbJEc zc)!-*jxnt*SGLp~v5in_{j+T;o{J!F)dlU{_)bWM{rA&Iwqilg&0LPy(svF8Et_f8 z-u4l_#ClpNUdy4n0y#0o9;dzcZs8wFb?cTW6&+o2>*Wg=d$5G=8YXJeld{HY#^31t z4>A~aArObDN7=^6#;bN!epfVkcqWkFmm}2W_JBa8V_;VuHgna_#bR%Z0nd|;ijC<1 z^3oKA{e9+Xv~*uzde0YAQKP5IG*|=#b?}5rLyL5{HhhBZNs%Ln%6{(ssUzvsLJ2Bn zW}V7}?8OmgfEC5p=v$cxUk4drxb*B{d!t&3?HgNpsi9f&ksKMHIwIJL7HtF9PHIg} z!TmDk_mHY&{uFm-r__%#&<=UAbl03EeMxXV+y@*3!L822GCi$Zf}P5{i`p-v2_ysu zwxZTPxv>xqQebI7x+FQpmXx3!{5|+EKE=vgNRyc+se0Bo-YQmXVHwV6m|fO;A8*fi zY`f3$Uo<_2=h+X{o(gd6uPtk=+uu{D)$*=VgAJbrM-Kjn=G9{kAcd1J^Z4(1Z5}*!#-Q#>gB`ih92|@5a6yd4yyU zm*VN$_=^|)VTVZ;7a%MVuX#kNOI(L*%PV~4TklZ8fvZov)JKz2v{sNJ)tT+N3quwP!{fj{kxZ|NzR%Q zf5aPD=2=hLBzZWzyjT<<{2WDMskMcb(eXy`<#hV4n$h^YWQZ+zN2ZSZ5VrT?z6mdr z;0#}Bvwh=Frf_ibeAm6?G(@B~@VFfXb8Rw@SIW;fE=8UDL}bIQf@@5my971VQJzBb z?l0A=qySZ9^7>Zs!uz7j+XH`_T6$S2#l%eK(jD;H8bPP8Yw_GH(Ka)duh~eqW`Ssn z=49ZF*`9y@oA%Pd3nNLT9E$?mL)SOX4v)FnhMc3QY3WIk<+(V4 zcTYvptHA~hK)Y63oK-SdN>vZR0Q=njRaKmsY*7CjC1c8f?IKB|9FGE9oF*BK(fmq7 z1HpXGxtnkelRPJuaPDuseX*#vPP8Ij^+(3sT^tOtFms_JfG$t6o(PHxN{S@<)y*IiQ*HVC1Rw-PaD2`VRM%W`|?=T za^-lhFjLkJvWQV_60^McC0ihF?0Ap3>v274TMm2f!Kq}7p^$?Y_w7Zpo5ZS&k#Ln1 zvDlM3R@;<}`@61cgobe)PoX9ohDq=}t)5dZqolLNGOnR=xdJom?xFxpsIKefc|v$z zM~+pf;6rCYIrfVTnplLFnTGVKdI_aClL5&4J6@SVu z8&!y+`b#>wWL=dl`+**~>$=P0MV`($4>VjUD!F{A!_lDDaD*1lPM;FG-laA-_U-#= zq0jX|gu*-M+ry||h^G}PF(czQd zPnkcAdbaNV+F;$pEbZywJqzG%INh-AhRStr)F?Ur=2s*|=GIE)rRN?#15p%n3*E$ zPQZFlqmt6E{CK^5IcuZ%Jgz@Gl5G7XA>`6VeOz+XNkzAvO@r!}8W+d0^%U(schWvd z7~xV)hww}`d&rg!V8Wt`Hx;`uLm1E3?CBzD%l7Scd-u^RU10RR<+hP;JdX&WXZd!O zn)CZ1j%8KlygWv=hUK>V#GO|xFK@sbF%iG`Zp7oMHP@+IQ;g87{eREZA2U=sT11*1ew66Y>ea z?sV7ku%OlP+NgO5H6c(E62tnlS8>xe9qZn!AOQnXrXpF69pvUQJizf9}RpoUn6!+}L6 zZohL~lBcW`Pk%eis4%2qRJ8H3u zl9wNWK&@C= zj@^T2K}%5iSPI(lC70SZ=xMNxCmdccK!aI%yMW1g2n+h-Ve$|BB!Lcp2AML-MSQg6 z)ZM2iE=B9M-JR22gZ3W^8n_>c?Wa~ocXZiDzPV%}lNw0Qhy1d}!7%-BJ8ff#)SJah z$av{)9Z#hrPO%gMyA;hRu@Y{wm^~U53G-XazYHRcGom3%wIh8o|1?J%cIdKJ3RvT_ zr-n;q+>dr^sMYz^XQw2YIQUEiO#~hhDE5tH0-&tyL~-db5^)lVW?1@oHK}JmEQ{+X zHz0+taOG_H&?v@zIO#e!eeU>+2*TmT*6)`*og_8wEwYkPdG&95?1ly||Fk<`nTg7s zP=Dan!V=xfgt24KHi-X%_#NgQ>xCCA26ppDN-PrQo4GIT$jt8-?AVsSF?&er=Q3cB zQ|!iaWVCV-7O5EFx1RS>c-myHDc7of8TWkSj9P4em9I2;?+l~z@sssxDDx=ZR&#~q zuNmGX`)>3#Z*|I#y@@?XBG~YEK4n)etWL)sN5{g-1$eBx1WKOnQKgerE3~6&cvP*u ziyp4Dv^TaKTWc|n7Pj8*RAzX_#{?DoxIb^7udS%SodqgScND&N%`tsw|GP{qw5WtnyXCBi#*jM?_kM|?mQw?=7+Qwq^NASQx`K@$ z$FfQ+SgclG%EKb}_k3l{4+X*NVdv;#KC#aNX7_KCi!kskOr{zb7PxfWi6xS?#a&A3o}MTO99$R+PX$ z&Imxh*SpAMnJ*KbNbu(!iIPO4=f7-fm!Bt}XX`ysJ=W;zEsP zZPHBk)HXsOrX8)QeghK?US`!HTGU$S>l;;a>X-EJ=!Gd=2+rHnPu90<*d^yYr4gg6 zs^ST^F=fk-HDf|n(D z)N@|R!&t{sE7kkz)NuIlJMW5?g%%`BxuyZso0U2SSS0Mr?xE_IoZ@#75c3_6rT%6? z6%_#Nx=uLD9%kDp@O!Y1-#8Y>dICwij!J4Cal;G|pKV?Nn44`k(^WgqmV~{q6$(Uu z*>`j`xihZ}WiB$pdY=?s>S^(RYORS)jaJr@E+8`0j-BHhb#C5IhI5>!{T8ka?~=rA z$o3Ha${7^-U5Ug_=ju`d@&4F}sm`yn+SCN9snH*SVFeFN{&?XU*X*HPZkr5`@CJj8 zT3y&1eycs-;jsLd24=V%a0bKtY8)wS#RS-2w%dEG?~(qplDCkW-9nY(pG;H~9a`o8 zs&}c)nv110SFLSY1&D7d+NJgxn7eB zM0l?j&@hdml#D{A6rSmlNDXDs8x)SRI&E0JOUC~Q8-bMboLv6G<2 zK-zW61f9F65?a_=gMQ+Vd;@v`kFa zOj6U3u~uKoUb(wpWPd#|z^mb5kFs3yZ5sH^IT#NKRpVBtC_~04lgDN{G})E;kxI1P zj_x1fB0ZH@7b?y6%*-yfkBkgAQ#wU$Wiwv0#@hmYb?P|~a5~vU*y3=<$A)G0LyB#2 zu5^oD8}hHHZzQvm}N%eGMTFo#5hD7MUsPpm;E!Sp2o(O=16`*&9|B1v)QAjOS9J#Bx_V1lb$|IT3k z7QCUbHrS~7%LyJ1mx9#QdWi!2eH?)eQo_d~k>hK*9PhyF;m*-G|8~Q^n!<7io^HdX zljfxmb>n3sL~H3L{6QidOms7~f`r~XN7suj%zJ}UWYZu+Xkf$gHNCx6;`N%yLtx?* zXZNjWJ5O`*RmJ>Dc=^}{yxKc~N0Q;D&v1k5BP9|^+aBkWz}GBNfBRZ`-DF-WdluJ> z$A15$voRZJF!iI`n?;%~_IiI2;97p(-jh$U-v(N9eLH=u)o)+sE&?~2w!H88Y)nV1 zoaAMobq?Mca9bKFuAQiEhW+Atl^0AAkA~Y3FY@%*AH~A23BL{B+s61eM1+~WONp)p z?5MVHYFkZf)*v3I>+3a3PWQ9W$KZM(N@GT!HCil4hzywP7EkabF@C!3p^2J|g$jHd zA13sqsKoU^RoW6;|uRhUQ12Nz26o@RGxvWBpmOCY97R^oRT8K^t7P2;18~!<$nfO zRS3k4wLG(x_u|+I!q#1X(p;~?=;2(i)))frKwjNg9%i8xhxBKO;|aZ=N5b+Snimqo zC(!=#ca6knklzz5|B+LBOb}cVxn6?XzufjlECJfrcsc=Va@rp$_BuQ=_{Bu-4^o)F z7D{hesD$a%gT((41SrUn%70xo8)F9brym|E93d?M?prs=6j&_nBCU4?>F5dins#d{ z{$NM8!+_WM7t7s!0xrNPx6Ld{VWnNhPp6m{QXdWy(sJL<0*Tn z{)el==EG_$aLYjA@vOJ7=dQ?g@2cJ?A+BZ-=RAlXhy!7gJ-kIW;j7)q$oT#%)4#8E z1b}x_Sfv2-brR)(fA(}>uCR3+<@WV9{h=?y72ezKv-QcnE0Nnh)<^HoXaCBajiUeK z%)R;8J+S(=2`ln-M`U1V-Y0EhLKzK9tJ$eS#(d{#9TxF_S(L*Qu|^wBAErSxBeoIl zXOwTj!vYn!^wp)Vo`)lNr2xU3+#QP>UwEfe{Jag+=&qtNb0syf{r+lLvT+2 z?D`f;uqid}_&vSgRfVMytVPXeGi{Tx9=DSLf@Y~X?)ZKcdbI(4v=_hJpuXcs6 zx~gH?x!&uuXVpV|L$eo&-uvkLu&W7Onbf$cquCQ8Zz@l(@C5TBm`DF-?pJIuNQ2J2 z4rXR!M%V~qut>04YV$DRnde$O1UAn1=LWOma|n2TWIo`N<%S`b1QAT3xb|c2p_?+1 z`oqr3A}(EyoL7o{hlIs=g_nD1n%p^yDL;k%^|ib+8+ABxB~ z#l;9;nKC(F4h0!64(=Fe4XTX%wdcRhulC>dtB5+W_a%4sYuQK2P@{-QTg-os%uvn5 zb4e-&R05bC;@eS7LDM2@R9j7YVcy?F@N0et;~7+yMvh=xYRND!4V5mMXh6E@{#l?x z=7-960PL6St!lW}f#18S_djf7Ca(SJ?UDwpeE*V{kEz2T+K?t=`NXVG>s&gliz)Jx z!e2Q?vQAys*Qn^V8-3Ipa~CpZUfnJYiZG%s2`H;3;2Q;xmD#;dlq za?kN$v%@;Y1jE_?EC`RS$j$b{=zyHpUUcH@RV$vt^kF6|Nrn&<40|gglwC$mC%gXaN$Jv%vvPSobrcr#MBtyInW%r#vu7Wkk7^rMT7g*M4P%_h`^W6f z7F4aH!H3JYYTFx5)D@+x$PrV7)tfE!&H%D$N$}?!=}hQV>`t8w?tTnb zrp1vU)32M`_gqUXeq22rl%N)CCMQqkvzUgscGupevW}XRkeDY$ruqMx&C|eaw$%Hk z6e8?47ci_g`ZDvo_IDRrhaSTkixt^Tl|LtvSwXGR%gsWU*lo9`&)R{x^bR7quRTzU zD%w!)#cX735)2qWm`&ryp{X~WBT#9tq<*7N+n58j#R+GvB|+)df2mij+l+JZ{mx1s z#Vm!BN7)Ab?`;pYl{iM&rerPL<^G%?Z|v2hqZ&(%JG!&O*K(^2eQR-Fals%p#_aGl zyMA4DFSEbZJ{*>Rj4hnnZGd;asf=V7^h23g!ih7oDA)E!$Gzl&I8 z{kxKV<2y(e037l1nVKuu%ge<H1w*NEkVPECCMe?5{tHmR*+wh66!<{2{Ic9JKkMUJp3mWHsw^F7gpi#H! z2S&kJv$tN=OVfo}sOi;@PUR5E%A;6^S+>x-%52=-_^Jz#Jf>r=vZ_dGn}63LcU}Zu zIEMPth@o&pCVD{dUC)I*^lvT+&@&F%GZ~{)90v>at>wqURoy{GDj*R-)GM}59O)~# z^zg)1g@zVKj>JC<|30b5tI=&5)^BQx>In*oJ#5a;vY)hw z@MkrxFP>~zws2>7ZPb^HlW@#1gjF&8%iCUG$$hu;Q_sfi$V*GDE@H8)%CK>)-z~+p zw{}B?y)@R!9D0(%{+>IPy}(VNvt}YER+4*d*fuVm9(<0HAp5VDU!Sf-4P%RGn#@(> zsI(<u9g8)XI$wj~+G270l6=N0XL(N5X;o`h$GF(xlvA68RuZW6s~ zL@y8bEXXpwRVb#|e@IvqU)nh$>CjXCfWNAM$Ve>ARzedC_R#z_RI7eq^snbOA-BY` zhIB(d#{Wnd@B4Iy@1GY!QjxB( z6s9)p{AH`@G{!;eq`RIuGl5`f`?E!VFb(I!$1f zfSs_A2V7NNsI7M3(u>iIcSX6mi&t-;uQD5TIW$MKAZh<_OdvZDZpCdI`i9?x1^<}k z)k0Jk?MPp^SeWt}5FB+;yuFd3n)yls{rXBBv!O;fgsIx0|Aer!hDFn!di^y%3<~Lo z^{H^dG*sBaAH%E_f#HF#YNtu3oGqKApbhT)eLQ1{D1Bp*;E`JhMEf?|WPwT2Rl%hlRYwnQBX1nX`>W1^Bcb zm1;t&qy0xhjFUVUTKzR=0+2K9Ta#v!3}cW!kI5>k6k+y#KV6u$I3-D!y#g#ubJeK}H(4+y=vp zcJBx^Jz4K~ZL}*fB&`*usP3_WH?h~jMH4t4>gK8=q!N!`cUdM-wQ3)^OkLZ*HdTmM!&Mot zswPXQWjp*dsdv3nC8d(tRbc*fq{zB@&NlJIKLM%ZKLBZvT@++yfILBCmEaA^QWF0SDR;HM`T%fz8YNLZ}jhExx~)fuwA#H#YHV+*b8QEAv|3)?CdgpywuRm8ZReHV@nf={)2xS zaais3t&!5dPm{Jilxhct)AFA7ucf74xf3WwSmo@mbGljgqI%23siWcZDD@wy$+i^3 z$~^|y^z*`1N1Z|eOHW@+P+)WCW$GlT`Pj?6w}AdXJ7pvX;1!V~;<%`&_k$ zj>1d)9z1xOeR$6qy{p!I?W-8_Va$}$gn73QS?2ecbpdlT1(T^-DzFfQFvl7xR26@O z46e^~d(&@gM+jFQQKvRXQpd233&nT4>sdyA`!(@*FFx+8PC|Pj1}hqjG1_ublXT19 z?6Z08#&caGce4$8A_O;H7tGW5x2_2$;=F7E>2;5PDsCWfB}7i2-Ly zwSQ?~zN{hR(rF&DE|HK&QsMENLKy=JwT!RY^>KZMA(E%!sIaE!(%pWvjoZ#DpP&FN}JFVxAmL3^p>(Y7sMx#!JsNI_zL*D#rw^Rh*kEz9s$#jYeX zYQwUNHZvh1wJGOr1RBTVhw>cOI-$F6-$v6(O}h5%Z9R=GV;NwT>mOmVn+-C_6T+Pp zwh`cji3~a~{Bru*wN@&!k%oO_si`W`1Xeovt*E+yRm?r2r@X3HsB76^((rux-vJRU z#P%`+Pv_}J#1&7IEmJ%miEdYK7-I$e_pv&fU&ll2b$n-aQ8*G+i#>JjW?kCt5O((= zV~8tjf1IM~!R90?PeWWfU4SSR$j{$%xzHerV8-&-xKMj#+xT3ulA}_<`o;I2UDiz3 z5{#!fllf_n?U(`d&1&1|(*MytxaSN0x@)9SRP>>X;2X%Gt=oW+LZNmw2CQjfpKoBa zav)7Was*8W%!$)nb%3Wm(Zr#$NkNwpj8@+17 z*=H7wh$`*(xzw7nYP2?M3!J>)U#$)ZwPdteQ{-gUJB-+5?G<9Bby9cT zatbA+7hj95vv1)jG_aVjPr%9-*tcz8j~^y>;E1}YVb31~BAks!gzSW<|-s3CfP z+sl|(x5m$|7449vHZa5oV;zAe!WgwkY0?)ujSMZF$!6o~n?d5-`3Mvh> zn$MHBiF*z?(#urf8dck6LE*-uNAGRJ-wiKYoPP3}v>$gmaxy*6*f^fp`CB+7(`cM- zJ2LGvp?x=o(dk>wS#8eVBWWeqK(S?cjw0?+BM*Y=+km-{Y1H{HpfS(24@Gnf*Ph}b zmJzN`blLS0^X{{n9dOzdm-(e)#9_17{s635NZMUd@ao`n`G@V+KhbhrD84E!xy)mZ zBCZTt^F^`FN=~16`Yo=aU6!Nk_VMHVhbnW= zowCbeHL=4H>VyY<0*MpaD_nn%MB?1~#o>8fXN?Uqd0pJm@wSfY>a0R|@XOj_d|F;^ zLe<2n0?QcK7P_t?;A0eu@i-%6-TFOFex%M^gnA=pn@rOSBkKF-amMrHVV}X^VwjDx4PUOO{&%Ggv7N)6rAG}8JtC4E z2_umV;rUSO=cQMeoE=)Mhi=dIgCKV+|2Y(1f=x8|u=bjegd0lg#w;*nt-!uh+pJ{2*Y2?;f82ErNDRc0miyaGu6$c&4W}KrK4AEkhb45Y%J7;tYMI50EcGkaB#ub_J+bn zUz+3UawK!-lunh_sQ|#|45X{&?np+F3MeU zdj)&QC-+|@`2U#dmZ3q*qD*?>)XmhLxfcn&+ z(@@lV*|yFXTTKY-b2*FD7jqAf8HrQEJx;SI*7U7%>;LTfdv90yG*uZJ4~y>nEs^}< z#ZZ}eu~Pg?hPh$*Cr&<=s^x{U1`dT$X9M0Pt=KPrO79S}IIhp;1-GBAWxYk1Z6(D( z-uD{W&Po_b2GfbCz-Nq8pgv9n@b+9zLas zRf(_REA7J^r-lG3{e#PI;0It{+SfCu(9&OsjT>m;WOQ9osVWg@l6EnKufHc4c)3+s zIRd%cpK*=5uKB|%!xtsO@^u6rzm@sJ^2SAts>ZLJMu=s(;HAgvos~wnQGhETe~7SN z=UrHiLxe5KL?lyJ1Xq#J)%zz!riH&|=r5`^neF_)1P{OFK=G%QagP_fR{qi5rdqvk zLHU%)<86}IHP}(Ksfgi4?$b>ZmLE`dp-#T0u-d9BkN(fABY*AZ zjBfGYgjpah^XiBN%wSr>`ci;^ws_Mmmq3+M*1f@4zWI6<4E%*c@b@%aDekGPq|>q? z8UPB89r`!40ijP6;f1ZcPQbbR&i+>AH9y_b)%mtCQ~U9ZJL~jR*SAn!cPq${WCg6g za0u`}*%0GxFyrpjsHX+}L0U{OT>RHL0W$w}gQwutf)ER-7ts#(WK^t68@0@IUUNe! zuktxZw5%@^o;8F1ylVXp+%4tErT?>6<-j4->!@6;0c0i+;0F0duSp1h-CKP!0V&QT zy1;j3Gl8aA0&Zw2VLUSH6Qn2(%*j>eI2M5m#Ruq!ervD&Pxme3ioFi=1Dm|gR zSHRoG`NQDT&a<9O>O$bk(JbQX7%g-+Q20V0Tnk>y@T9MQr17ybxT4)Ce1Ieud9C zB6Y6dL{dQq!2(yOpQxz2o1XU+1zfK(t2mLoIcpQXXcN0&EN-yt^RMd7h!k>LSqG1J zGWn3sc%5&yJuO;g5d=jE5(2m|24AJFK)tW_9ipYc%?=v%R~Jyk#gg@9VYA~C3Np`w zK{l)j7I6DiTJbf9!fiK~xd6OJ@RN2dIbxYus6^O0W|I)XQQ!G}$>rtdoIaEJ^e(uo z0z6h57;xIS?a4a5^J_0dUUsV2+56=c`&9RNkjx-$*1fh@fXjR5p0^FYaO0*M6G#g< zs7rZSxw`Dp_T+jCLDWIy)u1rn0?(N07ya5d^1d%{mL=aipj_$zwP&r_N`3{dZi+yM;SsDB*Ui`X5-HrFC7Gps+Mn_oap|pXw1ilY zyIMGTC_Yc(=E>r+fyXWZ?pu+xCOR_F0pgug@21mxh@WJ{R|xf^n?9iM9W3eP29F(1 zCjAcMM;n_2pNcIh)94sdb$_!vK2%*Phh96YJK-F&$@8LEb; z&AYlza7<&rHOyvc#%44f3lJhX_ex-6hFCLG+EF2=*&f{xB4C{K^Wr(simD8O6k>d zz7D?CbX~{0Ku}jhWxQXilJ4!aq0I^$jTr`74=AVHv|QONIn!Fkk`u7q2j~BjEY0TE za}cRZ93O>EwW4#|;k z1{vmWN?&u8jpY!kTPTGyapy_m5-C%KhW~%@F(Y{Mh~RpK(*L$C{J-t7N*xVMknfi= ze7*lWnL~-`|26N7xr&+(HJcq3{`ctY|AUY5iJa+;1^vp(`0w5!;om62{PhkO^*4+3U%qqd0)6u}6#>X0QRlkTa?cvv1e#dv zvB-Gs=|Vs3VJ*`4sDfKA6G3LAB@h@Hb0D4HfI(EppT?22?gDo4Yrx4uw44=ygi0q9ude;w!4EmIu#Iabl0hjl5-QNB#`=IY316UIj(ZNYEIfJmI-U0D#9G1-Aw+fnG;wKk=kE4w*vfht``ez_BpGuc9r($7f4$Nc=wRTSnapbHiVJhvl&}|?@GI!Fa`Kkr@7-LaHwsK-klb}l z=Ri1VaJboqWdGLo&Zl6IC#l3|U3Vr-eXV`DCmOehw~0$k91 zi$9qri4uZ&z_gvGuRNJoP`Dii&bTeq9$k00cVU2kTcDteXVzn1ZRp(*=?F~6!K@;1 zWo$xGud!kS^$hbx#~O1RlIC4-(>OKqFt{knI)1Oin?niEDW{cI>5d{ z*#}d~RN!mEzWQ3QSL-uhb#A(YmyG)LdkNF!HmKMkpX-6GH%Zj`QPaw8I!!btqlX3r zTJ|O5+xMcxJ|%)eNVRO8xxGA8$5Rsbl@y5am-NbYdBjo=!&0aBG*8nnV)dy*-I5yn zq1IFp=AQhYw-54|5v0m(p5+D#>&v4DM@xcFj<3F6mA`C|d(+Of!IhtyXP9n#xUF(J z_>OIOpv$tW`i^^Q-;w-w`0EYc-Y<^UdaORYyI!`IfZfV;z&yH>cv%;mRnjgU7u>Di zZktJ=tX{xMJh?YMG*lpIo*LfU6Jx<=)?ULBecfK8C<2LX9$V`W_h;aKlbpH+@Mw!A z8pC=U`>#IAR>(bv8IN+Py`a_CEg3IP)riU}GgU~g2xlv@D(C!|?$kiYrp`RMZ@-&V zwol*kXUUuQ*}XFF<8X(7U109+TcS62A6A2}3DQmKc5cYoxN02VJ;MBiwTUrQ8GraN zc1U^*&*EsER;ED<7mJnFa`15oJ4SEcn=d1rb&a2LBztZ<(~atB#dZH0FZ%Fwm`A@w zETo}|C!YNZd+`*XZ26-t37-xw8Z7&lUE@dBy0p2RR55<4Z) z)84(Q#y2%>HmG#wJJ^O6qwmtTOmAc{689&P^ zwoo^ypU_TFeSvVS6EI~)m#~g)RQvR24{jS7Ec!#t;cgGY*1bNtd+Q<8Y4BBRxC`BH zx!>;#K0;od_+?=?P=MzAeDk6^&bu0ei$&N-OOD#AFl%tLL!1jUmEY0A&sLk}m!f~+ z44Hwj+sAF*t8A1Go5rGC##c@2s=QrXZ%Q!ogCEi|aPu z99v6`TyLsMy4MH&HBjAQ`KbC+)(!Wh<82FLy2{wz9L}@J5~$9N)v&tFb|0zMuw091 zWzZ^!3etf@A;?ayBDAo@35HdR47I<`F2%G@)drikMn#$sa9uEqs4 z#10x7)Wle684Ier*}`u2S1VAQbUedK>>@{DoX3XPV ze!4VfyH>iAdryi=c*izW2WC%*>MD2g->eCrL#?cub^>~Zu7=`(cjwc($-UcGTmAjI zr;N>~C(S3URzg>P!ZoK?$AI&TL`>+OU+gOido9K5UOrOQzqV-l-@ciVefRq8`Ru$c zxN92`h?wg~oO_?oT3w9;QUcqccFxM=JKE^ec>4(Hm#X!g?zAN)B36XYV&42@xm3HK zgjtJN5U#DQb!7Csm}B)uNCExy+OI|o=@R02j~do6Tx&Fn`1#x8+nZ=zUBwp=#6*8# zvDYC_3SuiGa^~W2_N*|`dvE)KKQ&Z$(@^d9Z))*t0;7IjSiL9wROo~{&WmaP>_G@H}z_PmIu+z8a*{jatO=?Ttn?so9k+|#>e z`Y)G4PD@y#83oq)uHvZr%+S>mzI2X)Rq? zS^_sethl{q;O_vp217^6JBOh*!fBrSPQQ*cL~+KBy1eBoJDp79c2MBV`k(^Ods?lY zexkVaqf=Q}X3A<)3o<-l5_w>C^ego+q^1GCG5U=q45B0%YFlYWQitUpLIGze+xOWm z83%8GNT7(jaUxL9R>Yk&KK&gR&iCeRmt9Xy2*{aL9$BtBwgFOM_P_5%@<^G+SEayW zXrogkB!Fmj;SaEdnbC&67WPOvBS?+BJgDuxFka#9BJ8MpmCJb|L>9weWnoDFw`$mn zD(iCq3*LWH6%{`ewQ;f**z+Z7OitfkJthB@wLlfARP_3%z6zPlTx~*N$bg8(_?r=u z5VR;P|J%zoHMlv43(GPgtUzZRI>Bbq^r}!UqI}oUeHULQpq~_}r~^!Kop4`XpW?fT z^!-uoL#F#zBm)6-sL6D_qsCesWnK*2GtxMv{TujM0#d>{XVWU63c=<(@O0a2Zhjqq z-}^P{YmH7&-}lqP5^jCN@O&@T_-)Z6_RgBvWjc*;h-;J8kIMr%#V^V|78J0Gu=Rj% z50itktO{%$r{2#Ix8cJRk`?o9E7=ZhhvV?!%Uz#dUmxoFYD6CAL+xYRh#sHD!EV5A z50u~AQ$1S+6mPs-*p(OedOf?xqv=eL5E^?0XsBNC$!0Tn%S69nq@dGzWxo-IcV{IN zPifH?7o@kCb_8meUj234_1s0=hF2SF^l%0XyTF&r^ni&bQG~7&Qvwp^Fux4T5`g^h zWbKs!aA=9Dg;u8N^KAgTi^Y2-B-mEYG54M_F(JJH`@RGDSvg*5i^FZj?VM$-6%cOZ zl&xTt-KX7ObM{HW__2Ff{^YRz`02#=SVu=IHd6QlB=?Ta!wCMZr?D4=F&%q-H7Ru{ zC`j_6EVpC~?x)CZ%+yGhKOLQI!pT$mgY5)gjPucea3JeZhPl# zBjzlFRyu#yt|JRaZWBko6B1IV2vCM-vHou5mWIVlP3x6j`MtOF1cq9d>LYzMu}io} zKd~3skx~Oy6~>6c8BUF_id4h-_dhKYs$P;BA|c5>W4X2C`pXL6(0eh!RU~$J1Bo3} zFSKj3D2Vj3yS7t#rL+g$Jb;mhcHM=)d?V{gQ7fXC>j4tEpVr-<`#X8}0f0#g#u5(! z9SF|6D0Lj=_{rL1g9?6}UFRXf{jl-a%8JzU0B|RLyC>Pgf8~S*UQ6RfxB;~e?%o-9}sPy86s;zGDZTc1RbsZ zEyU`#>Z!_xr$}FA2T2CMO-0_&gHbtRla-m^%h##SrVi-6uf@s>l9Ebn8Btv0)oG%zkl?N z$|Wx>PS@*HO{0tT(QlTD{+dN`>N@0G%}ynixsi1TXfc)d9<8_C*f&sH+v0E^V(5}z z-@y}`P63`UYpd_YzV`4kH>yyIFu6mUzpQ?cA|<#izHV!5#9o5%iJ$P(1>Q3SnmyvN zTOhCQnar12b|$QIpr@p%;3QU~?XkAdaO{e?xO;RHB#{K8&B=x}%QiPgRPUJEfKlg4 zhgO_zww&b(+|y$PFvI=@VzS=wqe|NoQE| zHeYIH=OJkzXlX}?!Ca75|J;NBiC=ceQtXtkNGtL)EzAF3`j1F(G26U3$-->%|E2#n zB%QC6z_DoipBl3NgAo-fk>=UyiIZblXsM$Bw1 zPgpou-&h;6npx_b7}>KfH-1`%Cmp8Q|d%m3!(Xz!qJ2UKZiZSC;ieeQqs{GXlsf5|IY zURDbA0U>x)A65FfxB?Q=jU3=V5;6eLk(Ms!#eg3->=mR$k%|V0SAkz{n>>5<3<;?; z66Hc4%#Pl-d9H4cg!HHl{C}g%I_C`%l9-3I_%kIJoz2E$O&l0r_2rc|RBn5pX0{y@ z!b#{}z;;9`GdyM(#zh#;)!A;!*{Nf8Gel29qFo35b?IB=kg^$jR^vX5XTi?|zb-cw zdD;$aaJ2O$@t&8%CLqO^h);lL!|;3l8Ssbgk1^>0zsMGR`vo$E_)AJ3OyE)U^Uvab z^WD+3M=OI=jI69^RTu7Kh+TNs72m}U;DQCgRVyB?UZJ(lby6ziQN5VWn~warG{NhLPA$Di29nEu~=4Jt9;essz&$Y zi4;NiJZ1pZBwJ2Ybf*Y;5^h|gAy1bX^)gXV%-y*mc0nVTVi6x7-x90Z=DIOa$>^eb z1CeM*r6bz@0Fw?Q+G4tHBug&UYISwh>10QrRVsqm^@`8K`(WiYg5P#tT;|1#2S-II zmXlTEXu=meQ30YK9dzt-`$hX>&d)#zs58p)F(X(S+??Ol6pH=e5d<8aL<=S4?=qw!t3H1G z_)`%fVkm4j^!OY=5to-~Vu4c{!FQ{PyB5ZjTU-$r`_QU4-I&!%B|1*qGn)YjsC(5u zVOl;@1*}-NdULY6zQ&FP`Tm_Wi7!k2iOVV!u~R)UjEzcF{xv*FWC)X-hSIosh~k<}Fy70a=0 z$^6b*Y9(IA{Ru{=r>9Mq%HO})Pu)W!tyvHEoqQydlehc0AcjKhU5%rEz}|AI_e7-d z)ygtDt~h4gETCr70nTR!t9YGuq9_k!0uj#Zqs-M=PpxNW8(e=($0L*6R2UzcKS6$o zKxC(S?ZJ1()6*%d$xDN3NFSsJxG0lGiasvZXKXuw?p{j;MUuULylc>?7;ITZMX+##4 z2wsBedRN{-!9A%#i$xv9G6<@~)Xsr(Ab+cKT-PZ%67}J;o%e5+va!*9C+d&vg}6NS zA}J;!fPoVZAn)B-es2=PL*viY z!X76!)v`Yqx}#ZSIrq}|AL8j&i0mdv;#O;`*=SO5*K{9k&mu%gx}Gfr&XfcMsJRYStc+3at40;Ro2T;%B#w1VPX!;C1M{Thws#3o;QVjHbNXnnBLN zpl%{7J-r){X#Mr=4J*MLTa1KbfZ_=`_bTJk5$bAL)hx9}#l@Md!-|h3NuBYw+cs-! zYf10BTwRo3u7yYMy)rr^XL!09y`$x~L=VCCFX^HZa%IWEyae>@O*yb&qU zc54494F&5d-jsJ7tM1XhxT#HtEsF;(#=J`nPwm~?F@}^YgU7dCOZ3^?GQcr746qTb zxr@Ql&Qeiy(yU*Rj=p{C{>LC`Q6I{lhdjE7tINh?GRaStVs)G zpu0bj$9-8O=r{nBU|MM8Gxw# zw{JEdTu9WOg$e5G?;sE-@W|y@+*bb;Wgff-H=c=%2mbVn=P;@3jXd@*p^^_Gwc_)~ zyD?`!I5!i-6^ja2(_&P?Vi6O+(;L*?G|s9w@R)7^nW~_5(KZumoi80{STpHKL%G zjxBe-o;-vr>SsWCDQ?HHXxlkYa9n)jse z!DPEX@3TTqoW{>WOeNYNx_&3^>jP0Fa|U^2U1Tekf?QHTHvwlnmAf~7o(vwUk*IO0 z5hShWi!`9)PuYqeP>|}2+*BbReP}3}W}|X9t!0hM#n*QcyOj+?C4xvBeWvGT$5ZT4 zN?clR47UQ_DX%p5_swd~K_Ah#i9qc^r??#=okyWYrp6T0rSdsTe<@8wIfYg{hi6nn zS#J^jIXdc=fYy8MI)~k_0c$rI-y(wF-&~Fm37}ZM&Hb~ky)5_9)(t~7HQ6v_jNE%# zw+y9&o*pwYg;9YlEy^?5=;C4SxFk#%zUQ11WxsbAl^OTN!PCBca`xgZEXRDzoHg>H zh`am`x$gPm*zn8~Qn}pVA;86rB_5ULRC}r>iOfh&=wC~PRD(EO1rbu`sTXnFOr)aTqz|dm^IkC-;woyyLBl4M(j{R+ZwysatSBK(ku}v9$WlJx_ zV2bm(b?>YOPes$zb*^cFFX-jtuRePB*U%r`q-(8xU9(h@P{V_KAH#c!k%^)z@D5|h z+hEg{1&?n1Z}`Kp%$gn#nQp&c(72!elQ0kE1btqc5|qT~ol$A!(PzkxoMR7He#ooh zFv$~ielY#6>!>AifleTPlhIEyb^lpdo?SA9i<+34N!X_Uvgpqn>DaAKQ=Vx*#r^R0 zOJ7Io*+c|U87igWzawY45cYqFg6d4-+u=Xyb$M2c9A!&ckzNvnPVUbn;KZ3E9IO9S zSSCnK#;5ZBjI+^$2a%2_!%-|%K1 zGfH!QX?zg36ZtOll9zN@Z1laU8d3PBzE@|@drN(CJO$>3Yo3XFTVS7}8aEF_%ZROdG>D)v{6sLs(vZAqqi)L|2;q=p^#C6DT`) zQL}*3^^CJbFP*}K5?2Gc%ZLDHkABbf_8l9pkr^xuc zcm#0DRhx>j02>`g`o$Pf_Ic#Av|Sq2R-5s&>gl&{JbNx`ljgWS+OKWR6yxh6ZW2ig z7szK0e1C$6fr6KRJNC58jZ#r4Uo5bTR-bhqFS#b}ON*KWlR&qd?qEJETu1!-w=KE! zMO9|GT`mWMC0`T=Q^fLpVTm_g?m~Y_Kog?|I%{11tZu))(VQ)^ZS|vg6 z_Ih!%Q?=0nJ7Z}C*dK-#$|yC8;Nak^6eDf5&f63Zo`s>`iFH%2waY|NbAZdC-x^X^7RnMmG3RuagG7153qGHdHkNo_TH4?PZ?lM^^;t=TC7_R3ydt zXDT5u^E+#1X2F6_6D^PBQp<+;aZs$9tn+Z_`ku$8b$%fc_G;+b4D40WZFC!HBit=j zh#V&*A(eKa9;7VLdclbz7}+zI0O&oW)+?o zQQL2(liVqwZeLRlHK$an`6+6udjB2LRB#YM`aN+%gGLG!5&m9Rj@Uc54WH29kf=mF z^D$D65sAUYRvRsdj~%+=kTD-=jflWEzaxbpV0712Vw4ZU;2{l~UN-i>Ql)%_{@I3x zQ%FgiE=+H3iCmUKJoO0@KB*isg#l^-dZ*bH6mcp{iteLF{y=>E#wZ5KzD}dt=@=$U zZ3#Sl$KO!6z&wnr(rTKI%p`rfZKTV*v)C7bV~NAI)Q*pLJ})HxQ`ENIFTe%kON&<$ zmWnDe%=a5+$UvpMX$C=cE6K^t5B37p4#6EfK$)5z^VCJVQn73rcJnf}7}r9ze8koQWvaS^1&}pn*8gT*Fiwq9Sg8U&Gy|I?<10tyoRVV-|+O1NX!z zF1(XaD6vy$ms>w6*03IW#6E9YS^rFe3T0%X{s1T5m?;!Z(%{ag`vAM2%2{=BaDXSI zIl1UK{QNV%jDauV&9*x~+{Y>*s`8qH?khjCBNMAVcmbuU1S5`0oF)x7?7^$y1W`2q zOIJGlmrAc+zjoCOkWAucsVgbWJ6qY*&oviLU$JRXzOq zmblV!eZQhR?$O+&_D7%Jw6olwjs0HGZExG!;cU>#qoQ))B{rl>FJH5c|Ix64KI!ed zv7d?5GeWl&QBi_}1Yat6B+uzll%Qhq@V!w0e1^sQdiS^v9?Lhu{lcY}n-deO+s)-t zTqQO$+#?ULuVinM1od{o2>O$F?RAi=!$L#%ZE2@$zUt{5c-)xZz8{5r?*w!HsMtr+=;r5XE#wrj=(gv5pN;v8Gqk;G zj)Rz5wqFRoW*#(D5Jje#5jLt=j&5?a<@=tIh?C;Yd+YrCi-wOu19ESW9A(uyH4Xci~z|kB&C1BKLH(su@(? z1Kv{n7JSGW!qjADn7Z!3vD=~SVR--g8{}Ig!dBgzlWuzL;{hle>gtE5H)eT2Z)!>| z(Buq_ct~b$OXjIZ;CD8eLA32%^dtXQd7m2!3MlC<+U+K0t172uU!j^C;9Zx9WJUI} z5?jmtm5@_f9t!BX(o+;QY`TWdk1J0k5#>~3_a>vs9kmOn03RQ8_R_UBIi7z~+x@oG zRIdkbsb~S{`-9y2`cIxhv0Kh$;}9o;V;VfywF)lI#q`FGW@pQN6BM#45NvYh$;lttrG8Aw0zII`vqhWYci?tLm|ZlHBWPLg@1kF_0>VHQGd!JL?F|_)cUww_8!+E z3OK04Y(91(sxF;D1eYS!pJ*47*6n{ak5HG@xkdv^6F>uVugDH>eW4W8$~ zlgM9Bd<~_TGk+{^P4II#S7|Du-U0j3P8W&tU}NRmTnh92_qfKw$HKxnX870e3YVU> z8ii5SB}Gunz52(ayEv$Uum{71n$=8(UDu`@OW1kg^Fmg(ibCw2TD{Ze z#!RDoi%L1OW|bNc-dQa6#8jD&Fd*FL+k-!kYP|<@XXPf)DjY@?H6Xg)Tp7%GRtS`= z`r2+kEAtqUM~Shqlcu6!Lz`o!2Dr<6XrvX-{O*o7xbAD|rQb1MA1&neINA9*-Rpt4 zJZ{qcX5D;goFN(RHir+G51n`7CF3Ydu9Ra7(8=*+u|VI1cT$x%4|nFo>b((7^(%KD z;{UX2eBX??nmjw&T(@exxbR?PVtQ!aXEocj=^Ok0J-S7%4c5`xNbj^SP+;D&u}2bh zmAU@?S486-x+-@xiD-&R{Ca>GyCoQxP8@~tKF>^zE!^VgS089syq%q$R>LFW6B8q; zqs{U1?9A-!dzx1yk)(oUKu2LhWRoj55CU}85tCz*A()N?#EtKJ_b>Qy6Ca-fZu)L$y{wU zQy~WLQum0CWUhoS$GSglv%gCnf1+i35QY#g=-nh9K$9znt&%+n!uz^sC!*8Sfshw)DcZGm9Y*aOVI(bYN;$fbji$N1#cpt-gNo z(KK$)Pg}OM3!f}o$W!Ivya@OnjkP1yquF07c{kR{r!iv^23HC+Kp~pW9wu# z%deqc*|NzGsvZCVlm6c32r3a%sp}75202-vnBQ&~?VttS@y^c;_0;wDB-&9IgGV1v z?t!zX;a*Qj=;lgJhm2p2yq{B2&h^ZRop1Gvu^bS{BsN2O7d30{gM*O8v;$GFMbOc?<> z14K6Src-+q=E$$I+Bf}jW4{r~0h)HYD11*-!tuI#lCOkvKoLhdjTsq|V{rG8>_{w} z>nF@@7g+`4JZyzc?ve-fF+>OZXb=S7|j>M&%tmkojP} zV#`zhF$VLH>#y7lFo6OJ8i6ZCIku{}8LZ`wxc1Y-?EddlKkdBgAe0lVQwRLev+xt1 zYZDw>ySL02YCQp>O@mr~=i8bc%@Uw9sr+`S7$3WLYLYUra^UH5uj(P zprU$L_Y^}z$Bsid2gBMItlT_!pD|YDv9IOi#9lO}U*Y_#Yj47AbN=(jFNx^ z?{;8XlIiQ~d-Hs&ej79=+%7wM{0=Mf@`^1Jm5@Sj#FdUpvCd_bjm;DWmE_p>G_l5) zNlyn~P>p_XPFtCm;2(pdgn~|#dkMnG$nwZs+!E|aJ2o{nHMjeb1!TIe((`04u*&^- z>vNW95_*h8DDHTFB9A3BMR2stNTzpSpvnZAGCq_kWBKhph12Pt5#SoiinQw|61Z>} z#}t}9PVFE-V3REDJ+rsJ-$-uS8_T>89rn+TBpvUjj~0+|eGz!1;;^b9Pi0O7h?g=; zL@VoM{Jb~DC%|;wnlcSTwPRt|b66q^0ziwlXxL`C=6!74o6 z`RCUg=NsivCR$qB98V4aEDnNm?>@6o>H1{#UCoY35kP5zq|svleAz@UuOG z=eN%}?IPwkLEO~-xTB+k_5N^c0E*|u%3NDu3$A@NsgLY**rUxYRIWhn(eDR{J%5qY}%Bo0H?nlOCR~<)fIz5<(|njNQOL7S^LY^F4a_i2 zKrm=inNlabU5{GaTI=#6XwkMN=P3LbMqSSGB4eiNaE61bK~saFh<-ETyB<9T=1isx z9+(dd{3PsoHatH+UjPiDP9&1$Y|}I|J^3D*Guff|Ife*^VAp*ZImO0C*VvCZU9Z*s z+#=m(Qjd8fJ6u)=+ZSgQnbSh=2`zB8Z~js_3v`_H69CgpvClgm_-iteS1IFs=(-wi zG~Z)B)PHu6Mly4zkdKdn$GGMKMcZIzrj=x-(|)laT5 z>#-jW{oX0u*SERyq@PMEqDC(6GPi5H9uk+XQ~N8wQcps~ZvPviDWeY=>VR*V<5z{nn+0bplTr9cg1SVes1iQHW5 zUAzGF(&t~MdqO8o=r@J)zhOQzn;FJT;3`GQSG_}qxt(BshvDGZ02Sj9^8xm)n6`JQ z<-m+TcmGN@Rc<1eiY;|Qi>qj0U?5Ml8Y6zRIhfIf!qE_bPN_my?+jzV>#^ASajYyJ zPk~_5`bSU7ZHmqL>HP^dx>lZyJ0Z1q{qCafo!+59#>T}?7so~|{xLMj zzF$YExBdb+~oqLcXBqEsPEX-nbC_8_`|n=xbTdv(evz5N4Kn$^~-wZ%Q& zjKy$W6zmoZWNaTSpiuop z`JMWXsv-NnB6Bk`>py;ME$LLZrl&I;tDagfI$l70=05`iaG*X;0f4YQy$830hAF;K zQb-#jzmUFMeaPAJQa-&kDuCK>US54=y++Beud6T;U9E|^o`MJoosM_q8pv7 zd0a&7VcT)6pmT%~G!^1J^BqoQ9%+6j1e=m+p38AfNsdQURMJ0am%K9`J&AzB*o8)) ziNTj%6j_W+(5>QfrwvU9T3}NJxRCRA1q*SbSH}11oQ@u1Jbv4s^t45+Pr~ALp@=>z ziLlp{Y>L2YzVco|^IV@LCQHgw+tzB;7#jaW)mAr^LTu5Xkz?}E^T4wWITYsHSB!ukxg}#h-74Gv$r!Cz8&!zH00Wp@=`(wP zkE8ubdRFF)ez8-UiMC9(pv`}$&_h- zul``N_~_|#W9BtHu#CR_g_c_Ya0ozAz~@Uj-MoG0*|7b!$Iomi=-c{2Ru=Z`QV`|# zyhF({UTnQ#y&xkqsu1-WBlzW)3Lcwz$=Wqvql7G1Tg6EmIqZ$qcMl;gwBnvppzEVg z5oDtrL>C971PN_Q{-zSE;e_X6ha;p+b@XKegze(L}@NK zuvkc+107w1Gnh+>Ib3I|y)@Yxpu%b&ES8$M{E_|9vEc>?M;lZDFywyKaC>i=s|eY* zrfgTvT_f+p6_o_&{(R#O-S)f1i;8awLWsV3DiuZ1{j6BPf#9SF<9Ud3IshFV#scuX zF@QaefZ&UffnjfNp*tGzJ9~S3%Z?sft3UAKQt22O-F4)0wRDL-N<~N)HHhgR=6?Dy zykMv+|DGHf7ayBa{3f-yp#Ef)<>(h_tn3S0sJeCR| zx=;uGF90W;wx)zfdrtS4EjPwWM;qOpXPW^~!wpQfdhO5~571b3tD=8opW$Pj?nhCL zVyP&tCiAz@`d`NYhyKl1XT5I6Tb2O<0WGoKUoi=Vy&7J9deRaS8tPYwu$gbazy3YV z@A7EU+R7;4;&eGRHs)})oa_Dl`L$VZb%s#nyQljR5u`@WLqGiFkayXE(OkPv#AD@< ze@`Zt9dxAt4w(!+shm8f@bRd%+~||}PC}|9x9Po8T)3{k z&+oidfy=C+R;<%lAQefjfkZyrdZ!Cc0 zND&rhX1UX~_FWGiJlJ^Fz874TbA=j7CF*K54s8k|w@)aYNNqiI|}w*%qYg{QG`R&%rCdaUPOH*J;Yxl=C`T0L5*ISKgtOMCzca03XH zEc*y{YtA{yDs0hv@m8HcD8u z>uQiLFOO$ODg1wfJr-dioNe>p9s48kIdDb~IE_ldznqa3!q_T#tO-IO~m=p7q}E z=dt3#&>*#gccQLO)$XHwcst@V;$YcJBeOpJW1i4+B{rIs@{`xMww?eNFy02D7x5`;du6KYG>nTehUz|AwZqwU%4 z51zTXxmWRd^wsxF$~RAV3_a7C4PVidOpJGM4Z%!SU*^-YeUf}RI-C;sRNaPFpe zew=DB8^8Tbynv=N0hvUY!@0_ryj>GaCb}@o$-H2)o+Xu8KkeARa3#3aRHm6r|G*dB z8Wk*`H*y>IWDoBP`2)QB9`BPaX|v^Wk$uUr!~>6n6|MU5p@tb!8VdPK zABHIR+&+S)?2*Iv+BzpSC&av~E3&-4E8?y@@~+bdk>I;G;+yVg7`K`ur;X>U79Z_E z?8X3$vK>$%)DRIFS?zP{-h`^I=VHLapD#TMt)E1$E-YAkYSVPa(Cs$8{VAoRz~@{7 z@wVQJu?}!ieg0Xzart2N$7rdclw54xn{Le6cTYqc|=Nawy$5&1+Xe07ph z34sm7r6I$lD7n6e;4tc-m(}%^m$5_Romuz&H?7aj0-jb{95uA_Kn&uen=0oafEcz( z?|;mJl~mlmub?jJdnzmw$8xyIG}`re*x&!QH`rl+#SU;AJ18gG@ow+_hgyOND5psNaabxIME}p%^>*~~`SQCJ_sDzx~?Ck6sbb_4k zKp(FY2T=Oo32=V|L>^1Et2T%LVgQI}`+PxAz+01e?LGJ@JI1hFH=n1xh^SZlB4C&D z@*{KD1!-wSnX#w!>Sc4;@Bj&Ot|JOwh9}}2;b9ScOivvXt@b-{v2XR%9E}$1Zd-k{Az0P*z8vWcCpvB=XBQkK^E#n$p>40%-=1l#G99GU z{eY{MO_?4XI*qoQ=rjmFGOOcj7&+$f8>xPAU z7N>Z6#IEE`2?c4ll!F)DE@2)1fTbnFd%)6U3PiNDKnUlyvo-7UeNgYcPyEAP1_mzX zf(N|{SlBvf_)os#GO6hSu8>7Q-$1!D!$uKa)hSx%x}Vi-(js(w9dPJP;m?J&y#14x zmzGpcg%OT(Pd`Mt!zCrUd-Lgd>^9BYd+O0K;x-lmJ?weRFW~Yy(`j{O6eITar@1A;lvy(>2wj@S2B7IMRefl zj^!$5Tl6PzZ4HH1eMbK1qUdw86A4`yCx(aFA1W^{i{Z-vqgW9K}T$ks%p?xID;>k?+1Bx;0AS-HDtFi!M&ul2@PQ_9wt=wMNU)0F3`!z<(o+Fsae`$M;D08j!s%`xntIL zmYF~=YKT(}_YrvlXgD$Wbj2Aew?mNWJuV*#aL6sJ7dJmLXV7EP+nw)d;in+vmZS0& z&*6cK)J|5bA5HPb4hmB~FHCTCve9z1z0D!6lkKzyE=_4JeF=7&i;HnO7g^iK78f0M z2J8hoR^|G-d>)AE408TV%PNf;O&!03~wLSpuzg8x)mP+K) zX_M#qMlWmgK`Gr;*?Ypt08`}mr{_9f{G5#1Qk~A~SGOYgcO>xe9&0%UVUA)9I^}Bf z*XjXtcHqGyvZ_Epn(*^uU#k0qC9Z~eWLAPqG!L#Wd;AZNw`b9+kYDqN=#^-Y;!W)a z7mYkqc~_QB$=D4&e)tp5Tidd$E4=ihY$~{F6uTpBICxXC#{gQ5B$*zo?y`%$ zcq7$JYIZJsK0IxoqIQ^pru9B*vT|3tjLFAqYneK>+PWA=yTNpEaRem=eO>}U1GnFE z9=7}2Vx;AMTS-QzubD41hL(jwyefZiWR1^J_-QpTbVe|AMk1S!A=HWZ*$qA!v3@dv zRarQN=ABG%sY{7o+yjf5;*U2wpR91BH!~M4r(t=XLPMA2jEzA*bX#A4n(zI5EMDlP z^n3pt!N>CH&lFXZR$>SGPile=IcM+|Lvgc9o;ZC3;)wc-E{%Hki<;t4rK<`n+9({# zQP7EYQH^@PkSUjec<-~NUv5q)^$CVx%Mlz%!yhm*DA*i>tB@(;{x6Ytt-y~z8|*-F zvfQWPzr1vIa@j$Gek+N5`%do)W1K)>%Dv5vpKX^&#$seDYSPMsrep-dpAsb_cok0l-_HkrR2o*4x@upkg*3>%c(KQKv~17x?Abt_nx=N_ zcN@xWe8swxUIu=4kDx%8@|o8XJ)a{5H_r7Ut*l5EX}7DR8U&y_NG}UKKPEyVDJMCz z9=D&1-5e1iXM=|ka1;PBCkmxlCz=kG(83o(*ZVWk$T2Tx7t(Io{rFJyz}6r*W(U7O zvfgg-1yu96>6sF#POSwG78YeXN49~1MQ9d_WDsVw0h+_Md6#5lMQFatc%vdMwUB80 zQ_P&ZJpi2Bf{=YU!DbBVIBz{r`kL(=~yOkdyEQ$+BD!x$YvleuUH!NH~=RGz&YJ@EL;Io4ia%J6NL+xO*4Z)u*nen#Ds~S z^2I`RKE4d0(Q+K?VHoNLm4A-+^Us9nVYH<`N%Oz$@jV7&fvyZS8+QMIOEvmW`9 zeP$?r+s(eFrif7foFY(TeJ79ukZdL3QnC5R8WXee^VHtWi{a%Q+_(h5{&hzck0E~Qs`B=QR zgR*As9V*e151JMS?8O18ckqx{80hgQ2a@@hM}O2gu6yXV4g#Un=DJ(y3|{K98a4C9 zS9kIb21w*SyBQClHGOn_(RGAVyD4<_wc|c)dhkQr#{4#<;OE%uR4th@6$oP2%2npDk5gs3nylvIBa=p+=2ZHzE>eSo{p&+AyWxHUEB+g^qz8uU)a4>#v< z9p+B)#qH-;AJ&IQktF;_u6jsMaQ%ojPIlo|J`QWctFG^TT;feI^7B@PsCCmXE<%i~ zs41R*!KU=PW%%M=o#TPJ1|Bd2TOG&4@OL#auA9Kp~_5d?JYn7R$ zc68wy%VzVom}XrCQ%3Q4UY>LDg0eXFmsTV?_(P>FBGBF zx*r#TTi3ud3~<@uSs)T#|7Iw4asAlv8ymfMc4p{MdL%Qjhj>Bmbh|t+-BaVOG zg`RD$Q+xhgrzhFi4Pd=+cHF0t6aEs!Ptl%8?h_&(BZ3iA{iZwWXYzQX`|(uX3mKVx zn|0&<1a%J&4|&ZS+oc6-bs{*#LKad|5A92(*GJk|E}J^7G9OQNjO2ss^Rd{aAs((F zklzg zbw+5#TBYae+03j~#o8B+l}4p%v+tk9UYwe+2&9O9BATUlnCP8f`_Wy1=UF%p-lFB)v;`*Z)sH=Zx}S>u)!rh zh<-bkB2xprZtO&+;)4C9=eRvP-;+*In@G0D8-JV~I8+l;`rbM4AlTQN!BD|me@sHa-CkzgAEu_z zJQglkFW9~2w_%~n8_R??I3?&c{76bDbu16iqb@g@kajH52FPRiZ2~ep2IfN}>KEHn zRp;5V6XDbK0*X9l-uQTw@S9e=dp`n1E8;SHsVM#VBRHRRV|);O84*rEf>CnnbXbh) z#4p(2l|YJzT{8(?CR6U=Q6uqaIv8bk_c*pHkwB)HVaCjHz74_tKptb8b`JxxGU|g} zkBRZ2JQQ~<*t&C~g>>3Ofe|i<0~bZuLxM`vY$$|c2lnqMRrr- zQfq4iB@+c1%ATt@0-Gs);V4zzt=*hY$SMp(A>dMak>&KpI3ekq)Y7PnM3tg~8PTA- zZ*S*4Kz~~>UJmZ`sWv`wKMRb<_;5xmf#$31ahWj9o3y2lV~2})6R${fdRukME?1jR z2#>Ph^NNSVZ8|V3#D4dvJo*RCWNpw}+b~}$f}@`s>d>EGYocT0&_y}lJeF6sFzSd9{)EK^NX~A6ee+yoyCsD42^<#9jEr`;v7VgFJo3rk8}2d#uds(_+hA zHD!rqI{~BbKjsa{@Dxs}05u5%T0Fq=X*pK*K#Tl=z5f*DgY?BHjp_rWcL!IVp5Yma zKe8ukGi5f;V*8!=FW*P@G@8K=YN2Okr`d?G$!lTPHEc}=sO^W z>75T_xIR8y0+c-By@+y4MxrYQ+nUvGe}a<;l*R)A`Y+UMM=y2Xk}n&sEm5R(|);y!89b zU`5(s&ak()7o}=AX>ZRCuL>w{GKNuA34E-94xdPrVI3KQ!GzlM~ z;ISOUMEfi%KR4;Htt}?@^KU5?H#5sk&R5+m#7R}2NpoZI(IA-0( z14*keF4OPiljSCI@`^WLP=?z~U@Blq4{~SY{PKAAyh+QwU~zI`N-kAsvsrWC!}7-w z+}7n3x1!+fq&@Ifjf(l3wGzt%$q>b?m%H5L{s)!|_>1mnsmXnPeV@6x=@=NwsAXbL zj!AWNPo{1i8xMVvhNfDk*l*o0VLer9^EByCIBacNP%E^Wo%qs%j6FVr$Evd-to8tn zS(t&acz)ghaRYHQX{{sWcQ~S|3wYy(?Owb#lWME!wZp(iBzs|-9`piVH|habjduWT zK$5>C@zo$0(D$|oGU2V|Z;=&%tet*-y-^JI#gi9%4V{J^N>%gL#da1%j)&lSY+#h- zS3&StV*?A5HT>BnE0}+~x;nQO<{8Bi`)ua$mTcmy&#g-x`AD1NwUKpKu@2|yW^Zpi z(zV*i23C6d-SckyugNHyz3Z9R+-0Nj+B5`@-LeuKGid4$l9IWOei%n9zb3S)G z)#T~U?{<(QoH1Etxo>g`;N6+KG)uzo ze7=71%=K=oEZz6HuOSU!B5V2TCk41iPE&XA zW`K?N`DV4F@qLOE>j`SUXoni_%R|*fZp(>%leh?alFbz-@-KOwW(ZLV6J4fnc}JJU zoN7MvUF~h(Ud>dPMIXOE`4CX@4kwFI_fhdGvxFbgYqfzCQdi~kce;87&-}!!<0NBs zywp3Xzi>a`(e9ZG5r=z!(f!Rpo5eWB5*#6fZqHPjlmRsA1^ zoe2-_JScf+nq&6)bYpL^*Dv9LX#tpQ6nBsAhK z)T%-=biFlGv373pJRFyfFr(*u$n?ibmw85b3@lRy&-=>E)U|Wn^}X?TB#t@Xw&i&FBjv|AW@gm)tuca)uxENqs(Z$)}|@HYY{y6 zNe`5{6C(nENDi^Mo8!OaFE=F)2im^WG`=m$Bmd)MdW$uLtYb78vks- zNU&bex%OYq1->lC%tz{_c#Qqzin29K;`{o`SFap?gb6($r<_Lq8ZI1N`40-p7zkjpaQtP2m!;85Svizk? zBmiDJ2$fJi?|h(j3l$80F5MR!Tvf!JX}+sxa5$|FW$MY?QBwy$O$sBQ6&`&9IH*hB z;H{iaOb3S5=X;5FC(4a_V^1MJt3}-3nMyd1e%@6s5>eRByPejV+ud#G3Dgl&f`O2z`YYP zaBr4(p4f@JhK#H7a~@_+&yIl2X6YDxquXJga9j;U3_ZR_1sxZgWZRT6r_R&%G~k^sdh*qOEK>J?EWk_}GSKHO{6vVkc=$<_|;2 zs9|`QVx3&#RN5nv7`C0NB#@sG3rPg_qA%ad-brtDCg9HFoDpYXla%&cWTV@kMr1$T_Y!ZkkbK|GPS%KYRqx?2pe6BDxdlw zR1nJItKj-DWSg7V?}2Nwi0x(&NAi&Tg<-&Vb4ihmx%!28kEDT7$kE95^5pf^BXzA-Q4HJjq%1K_zk% z57lv4^fX&AyzeHWb<66hmwXcA@mm<9YS95ij|jt54K>X>;au!iIKbRoxaqhB? z?WNkh7A-8aK8TO$#S!&wUX{;q|MhpBpCI$+3tFeW&f$y+&#bE`_ynjphbg8QwVoan zl|F9sykBcPyHi_iKCAXNLOfeGIi)`PscKO$wkPHBaBVbyG!W{PjicmHi*MLLLo5d5y zo__DYyJtB+M@!vb2qbtHvj2Y2g=$8NNLY(76P@XiN1whYK5|Rshr7u$SjW-#65f%= zdVP6&=VhSp{=ylrDk0U~eqPljc3a_`Y%Huxv5b_<(!89mI+6E2?jqJvd|ULC&zA!> zOK&FArM!9o6X4s+)!l44X86z5V`QtmhM4Q=_q}MVX#c} zc8V+>Y~VDIvfaL4?S+fCXenwMN0(Dkc--t=gZ8Qtk~Bq3nP%6Y#H&wsr)?sV z7@$SPUl=5*M7-3;i41%##0&;K>5c~~_KX(W~7Y(8jO=kqZ zit)!+L!@$wimF=t?o9$F)ttv_D(C#D`DLom^pE|ot^=vUy2rEmfwS;4G!j0g<5&B0 z>U-Nj5OYPGK$!9xh#?XW)b9_*g2f=GpEo1Un~#=Ly+=LIbyHLwbOVv9-V9PhyS;%n z6ru$ex%iXU3A!DWcwesTMk;;9oQ@MqXB3~5NM|Ia2x5s5o=0azLJht<|IUb5q2#^a zNx*jY%XkIvEfFys&kJjTt&6X=g6>BZ0Q5ZP9?(@&J3$*ng$>G6QKE10Ur1gw?ZQMt z8XpzKL6DD$yb`zDu9Cbr#!4d>bl>g=c(!ftlXUq*P?`z68!uRn36Nd!5$C1QsQrC@ z{d15EJkn&hLI6WlfDBW67db6G(+4O zk%b$6^8WjQ2*YCfBjUO3vCUn7_lRbe2)K(ERg*rtw|0`S&PM|%#?`V;ssr=J{+A0M z8#xP0eW-w&f>{4#mpH+K?bcJ>kongNO zZTbGq&RsQIHMO~<(ymTj8S<*VWdSYS4KDxLsY*zkcjp5sv38vw<(S?Nn=u%l?;fMh zd8IfA?zVO!D1>h&aX677FF$g{@fQ5*JXa0(zW3DHWpvI%u1K&=XDvCP2>JE@^LVv`)ga?@Ml+5>if?6y$Uu ztZK4FE{;SlymoD_vV&Q=y1en^eyfJexj*gYbB_QQ-p6(G7@~KG80)?wlxmcE(#jsq z<2G9}q24z^=k=oXfbycxjJ-fe!!X6ODbj*2`)wjhyu~;jBGe4LS-;jA-l5ZJC#>7H zVcs>slew_wI+*n6swIOxe|xg-Gq#i=Nxt%KqW zp1;8mJP=%iTW|>Ot_c=Ga1BmycL?qf+$E48!F6$W4Z(GBhsAAKxLxwStM_+Tckk7` zRabXcw|_*Ihnb$9p6<`5XQm%++Ju0Q)dQM45{i;v<@q-|c1f$B2BO4SB)&^Ut`t#G zq3phTiLn00xFd>g+5I*~O9HWi&rKI=z=72!Zh{b{Lt*1VC4&=TeQ_ZdxORK{5Ihf& zjBEphR?t7T+&cHF5PL1!qfq5w{&zga|E{w+L&2mFt@FM)xqEPUB!~%uJuu%txz)+)t*TFu*2|gpIy5AjaH){eb=M{Ow^}7;t_03kA;8 z08mar1|~D>i{7u$7I@8u@km6x>XfqhC#9UIT>}38{j}8P4Tzx-TkVN~dN^PQT3`qY zlvyv-SxvzXfL$L}b}WXV5t3tbkEbUknHI>#z%IVe`06Uy*;Rz0=~o+vY;SE%`|2{M zFfua2jx=_N`hj~Ra9wq+{YggBk4^fcOFAC4_>p4*l9@FZ**hLKcGnGH*@aYg!-}O+ zGa9JA!U;Opd%|oNYRq8g+7%QPUAkzMuLIzb^}a_%M(Uwp*Ou!7V3)DC(* zd>d?+%oFKVt}l*OTIT$oAnvep`}lZx4?RrVdZilWPV4PX+aFc{=6!vAY=uzHUES^r zzIT1G3!}vYD7&~{;zsdSmZVtP4PvAv>0{01lWy?j2zEbo6MGKvJ=inMn*OpauUi1+uxmUU$GelJC3BV zK0?01!5_gO{lx`jrc@ImjN;_y*WMDm5W44t(XjcOoYOR%y--zK+lpQ#=Mw3~iS-FH zJNrbreemPu{*<3@R@fmE3yaHHT>XJA6Ubw z(;~u62Y@3cyl;1zCI0eY5YlU>02zk>Ypq6yAG(`bhgnh9+x8VyDf8a;`_E<` z5^xnZvrug!=YB?=hC&3%4JY`c5>*d1K6ik4HNPXz=Hu)9(3$9W8%+Hf2rM(67duU6 z!)M>>M+6+?OhTwn!|5a=!q4BszliToM(0N0H@`hyZ!j6a00cW)o3y=*d3hg-?fVAd za?=lTHD|Z(bgZ@6_{05paT_x7P{9IQuS&1FgGz}G@v!@NqEKj(!tK1gnn7V^;h9Zx zapY`y;hbQaSqYbg*p}M?3V)Z$Z6bu&M=che-ZP1NPKs=pf%1Ic7-`-N-;hQMp>RmoZp{LUxOg}OSmnK3ML+Kk($CDf223A*P zE?~8aBE`+zybwBrvo_Y>%J1X5^&}y z8YjKk5yK2Yb~s&=04g(w`g&N_X)$1#zD-vSpyV3*OnzSVrN_sR^Bo=@)TSnoUPhQL zR2qtbcBS#&Q#l}Xhw+3bNAgb=MT$?U3@_^(SV(^l9#qXW!Sj8*+qL8W@?(R|TnN%z zy*lQBC5w==2`Ba1I{i`m-gpv~MKhSdotJ?5}pa0-s|A}dYs zdVF7I*s&^u1>khBE7KmID^j6Q(WCIK(Q2@Kabg~v0W|M;R~6Y07fM7OSL`IBb$-+n zZc%~jEAewO(I1OUGa&;f!p2bH>rEkD+eM21+jdAO*~!$>FipU~@p6`jv`dpG=ex9P zpYbe#TEBTdvTak+mn3;JfoK6K=;frc6O(~m<)nG`a2>*AyRYjta_}p{4%I$=`t+3< zby6nFVZnIPxWpJC-hqlH?I=u_VC4J0v`qmCmJ~|0u@IOehJiHhqZ9hlU2K=ORyC1+ zbq7Um@kF}40>I>!P3zbCGLfNH=@+5y*n08`k|@H%6mK-J16ert9RBsD&jSIH(R`)f z(_YqY3QGed*H4eR5!9}qNxiOgavG~2`-TcY!z}#Rs2QI#6STA@{#(mKJe);?S*ij1 z6S-oz^vegzS@we6a0baD0k++FEJGA7JIryZ%S6I}%zU0O=Af|hpFe+2YvA<1GM1D4 zW`etf_2H8PYvQet55*^bl?S&2+XIJYq=nT#Ji)yJ{3$Arn7iRm$Md$dkC;n6_Q4>N znLho;*yl}Q2R@f@=f3ja%$$#O7wwEs#YE!BeVY@jVL7(*0I1y5f#4%-V2@J`fC zc{E7Er3Xcz)3vk8j+}^=`f6SROX3N0YVp$#E;*PaLM@v{1h^-~y6^Wctr65kDj@x95FNDQ*N--Awe zr}MJPT|y7sZ}3)(RR6wLHe~bj)FBCf2ju7#n*A%|Qth(8H2?_!kxjmyRHSU^ctIEh z+rz6_=J#8UeG*;{;oV_GDkTSruOXP%%G?rgXC3=Z1B^&U~{qyeWSNfv_(-T8&yg zE`?M6BQ8`drq>cb1&{zPX=$ub+}MhuRfR7g;AT9^pl~uzRb%J9xNWQZb$3^EGp}&2 zizYuxeuL>`wmdV6xo0~4G&+wH2ZK3ToKUM}6wU;LfPf=^xVm$XYk2~_lRC$IJ`8)p zr4b!ZsNB>Mn^l;uU)onNSY^cI#;Cy$IwNE8*g*| zBvD9?AGI<0g9l$IiI?yq8;FjI34ZrG-TApOcnvl+Oq0`a+bpmv>iT+ zH%C*yo_H_ULwldTxDbHf#S7SMf;^lbwXb0>56nTnw_ql(n3xLPUPf%FvGkD;!jgn(a-$?*T0NR|JLJ*VIgu|jUYolc;c9Lo`&wA<0I zL%z{jy+8W*ObQrauRHYUn<7w^JD@H)U0T$VPO)r7T#&pO|14?BJDsNUBVr*D-;7_a zz}0KH6gG}ziUx5sK1vw&pJZv$)&4@LS$TQoq$cJuu`=wAS~DGJBKpiCxW%Zyur9X@ z5ONruPEU5he=Sh1H|j!!5sh$jxxRf;Oi;M4K*0dO&GXQ_1tVp1=#qM~uZmRBp;D1C8MRo@*&aAYs6j-<$((qZ2GBA$`ZvX*E&zvL!G1%F(?!0=v zN6!KC>fno}`|;^%T=~B~=VIB-9gZ`$$1^vhh_PG`y3ftrz{APSB09*=ZC9p-Vfr$C z{L-BxZzH6A-g11jbz7|wpLlG%obgP6Jj#WOORCS0)ZEhg&{uC$$sSI0<0NPP5^#AC zJa=!v3}Dl*;i@&iJ&+h3YHKu4jx(~0c~(X%?^kNawpPzXcJuGI*Ce7kch@t_*QZ?& zX!nHwx<@R8(-%s!lM6$4LF3zOu|Mvg93^N;>#BX$^_fob=ve&}mtXBPCh$g_2=Q=k zp-q=h*Qa=Z{+WnPZvC;y1ehoP@?GisB;;$fphn-K+r)#$_HQy6qczx+Kh)7cz+PDB z%Oi7`g>qg?&4`5m^oDLobE8+0o$+qi8h8xHnkz{tE?e}k}czn;|DfO?Ma|(5s z#>Z)_-kgQGneU*tq~~e^>aS>?d#5$pPWf3l-$f3*x7^kP+4RuP<8nMq5 zWFxtovZTAs+lS3=L&$z{$kC+i$TUTyQCAHhwu4Ar6vis7nF8o%F$qiZ@|I+wmnZ^}vIo)_ch`RR|9R*%W? z(Tsi7A|i3uFMXWe4wz^F+nE0hAYZk~9o(>8X=s7m{;&)y7?HR+FsqD-^RIQ}$zPFb zYDe-NqA9oIx{sc$B5h-11HPpHekwcDhvxS6FM>OBkt^iy`D{f)i>)a~kcGs*mMKw? z;tL&^i~Oc135z?@Q+H=8i=V0R#`YJEpd>t@%buH*<@M~vK6H#iz&=#vXVQ~xu7@f5 z9eyjnOG^)RnQlNp!0%!nH9b8W%?iB|6+XM=suqrP@VEDqeD<^UyTUv?w(MJ}Sdw*a z#gDP2b8#QJFI0M>)H9!^`7I>%66x-R_7u&$&2lgRNJ$S zzS$Ocdst;<5tnwsobp%K9H?oXToi`l&+ak=8V zXp(_APY3if259qUX1|V?028p|I?lV}^-#X7tE00hChZPoue|1?M1+<&)Nht28k1FW zg!idijQd_aVPKu0;=XO%j`G%l8pKHG<6>kMDWMJlmpu4)6uzwN{L1-xvxu~CTsYgy z4~8suTLp4)i{aQbk5tXDYl%=cu=t%yibYHe`0CZGR)4-r@P?@JhYwE7cbx(7e&|Wb z$qUiMTo3cz-QCUhhUk8B@1dXlt3us)Y&X9%YQrQ^#u}#yR=u@~ozQFB<9%(bDwR}R z%66!(CMcU5V;$*DhLm%J7i8neZDIGu9}SmB!Vh6Z1sZ$8Fu@$(5M%b(w5mG$?q$Bb zBZzr9UIYbVKQG^WQcq5n>(}UNC{J0vQc&;#zZUvaT7;h~Vv-!+HM_=9E-YdVunNjY zYm9)h4kJ{<_Z79fn&9^S5X1+fiFxNvcCL5SA!&BwFuKIJQzyij=aW!F6k_A!t$ zUi;i_FhVpBOjzo`MFnZ50Nmq}@$h+C{Ym7jYu$5toull8k5bdpEKLStue#J8_*32u zP<6ve6Dqh*=F6=uaKlrr%2D_EFSnxn{4U?6 z4_+FC7q~Jvy%D&pMI(4W@;1=3B6F{6q0E{>E9CYszGS!6jB z=I>s@0+Q#un+BsEL7`h)O@#>Q)IM~kiQLj9rks8#k||C}Nm*=i-u3yd(%}cOnJQFz z6tmMW#N}wd8%^gD^}m^~Hh~oYq1eyL&OZL?f3_jxPV;nsSSgwuZj#Q%Z81&?+Wn@b6H;@2*$OWy>GVV?+xqL(0(+9gjUw(q6+M#YOuFr%yHD&P(yN9L3S4ilzugJ}F#JojUTN@DO zLH-<-$VXNpom#5$-8kTPwsyv|3;NIvUOxM4q$c;;;SZnGSYnFRp!g{EHJQz?^mMl; z4o8ySsec|HK?9X(V!Q#0>+~IN{AU*`P9B%O4iB4dwI@!B!LG7JrivZ+8U;64YlIb;xUEPv}On`Q{3gkDo4aVOaG zZtmlI-1Y`mMMW5#|GZ#UR#KfV(R@agiwtGty_VaF9nlvu`%~>F#&;yM+OF^4uaM_g z!}K9d(yNKt>^F8kSAMlGF$8k2;^MOKz={sL0nHrKy&-`OyG}wYseP+cbOcI!OqeY& z_AKTw&E_FXfWvF7%IC?e<8WX$nKW0)FhY%AI{|Oew6xk<9~&cWBtMJa(AyKHp|59p zXRV?AbpWG14NfiOYlUIul0@qVm{m-M8hv(B{gh93v^tis*k%>x?QhR_aj|lbUrGMl zJQWNDlyT6o?ymq?+YVDT8og6R8r9SQ>aAa&8<1^uy{ln25~nz6hhps z+Ib<%Y`EAu#OdV*NQxyp>K$Cy@H_a40El=VzV&VwJhOZeATHY z>z*@z$iF~=u8p@kQSs9=_&+R8DP9rO6Pm;v|^Eta2Qswp0)v-GJ!K{_e z-D5z1ofz2m|rWIpvzzfW|oNeYzm9EvDni?tv#^L zYD%m@N>w%9cBx?u5Jx67i`$|3@uLxDjx&cR0V{)u&paWQyvL@YTd^i)3%P!xEOUn+ zOyOrlC%_JSi}9>#sGHP*f`f9kBIWBFp#Ksy`1=TTM-aiz4K~;;a4rGtb0KE~6thJt z6hcm0;h-@2iA=tUoze77FmP&EyzYIL^JagH+tq>k zQ=0`Gz-hZlZv@J93Y34j_*A-a1d;G@(*uZMFf@GNqq_RGWCSHF(h0hs*g*ROWb)bH zUn``t-QB1aDpo@!yL;T7$OW|ff}4$Ugxtq9%5}^V=~Wt%lJJ1z98*Oq0BjmrEkD0@ z{dS)P0ye$9z!CduOk?Hl;cZf%o3hVx1kS4&>J3j*ajYdhLMdFn87u8heSKQ3|Ir0j zI~pMyG$srz8$+N`z;+;(>?%Ks2ln;~K(M0({D5M%;LJ)7tX7lNRH5gF@VBcdlDka% z_A}>`)wZRTzgmM@?d9Y?U2 zXkkt&efUtrVbVYU_m{$<{y6Ma79*~wYh5RikK3t+%QbB{+L;dEYg+|H#X2_q=J~E5 zWLwzzKd(#6r55+fl@|92SUsQmXfws(@o~Sm3aRRW!!^pc!pmDXi@IKbO5vkTh|r7^ zGat?K5b-2|cCCAFX=xkxDzvJ*`|z+<`l1Mz@+5+6<|_2rnlJA{{j^!W^j=1>w^!BG zaf1%Y`0TQ7w$FtcbFm#`yOd(Ag|voL0*lpl3E68PxxU6=(Z@f^6KQrcbaXh&=AkfO zmD9Z`4SPAq%Ai(h*PHT^5=SaBPSfz?h1vn|SK^T9w3i#v>QQ^flWd0V%d)Yg`@4OA zw*mbAP;A#yvJW=Pn@KeKe4b3U=gH!#F#IZ0vgjZaA9lB<5e84e((3k#f4gn zr5F-EA6m|(y&US7>AbdtrDh8-v17rPle z)+skPobrd&(%@v7xh`X*q2r~6t`p$=wymz|I&xxsYhRV*x zU;Brjs$;3V5UYJd_p`}idVgYzZTi}yb!Vh0ETu5m%#g!FYQyROA>8$zFbJ+Sfjg(2 z#l0o=N9i)`oj&XgisvG16wt3BCtIMR+a>|lk{UWEm4*>`5nr)O=6cS zKZqA-!iYllhJ%(Iju1MbKFcxaB;7(Oxa<+^+n1QaiQOxkeJlBz65IZQTq16ql*2c+$nIf8j;E{S`#i1j)} zd&$k#UIcUneS>lq55Zm~whtfbrlyJ(s=ovs@8!XXeh@f2=3^<)#AJ?;PP6=+e|HhS zxAD?EO-M4b@$Y_IBXx75(4KYYy?&FE*$Vbf3OlgeplwnA@1^cL%5R;kaQ6a45d#8d z$55|PEAg{rW7HY+H6RCqt(qB>6{}=@SVb6!RQEZ}9usk2!})uc$$qtFBWo%}V1r)4 z547?WX}4mbGsj+jYnqarnyfA3qA0cd>1#%CJ(xu}buWP^U^J45MGk+>8zEVBG+O6v z8lRojeIWeh=7z!Bjo}NHK~fb5UuH%|#`?wJ5zgP5m1M$}^aFAAzS%&!h|%o=ETXJAhU_dRceIYaoYHI-|J60=7k<7ngjbmDD9- z?N=nV$nKD;3fiFZG*M}0WfZF30^!cmw9LZ`J1+2}WeG*A1*7UP6tBf%5N|~hXOZ&t zzskRFX#S}cH3fJFWd>y$%N>^soX17b&>@;YY@G^9$B?c%IollYUb8RLxpyX}4519m zBO0BM39k+pAcQmpOZMRSX>jR5G3Bf1Pwiwg*&*IHw;7Gd%|1KuMSt55HYDD?x;bj7 z8O&o8a_nYO-kr}*>%*2FS;wBFtLodIDiXn9=zdSZLcr|XGz$DBmi%o+5&2aBJFm_B z8XR}`FbN9ZRCtxo`=g89Tz@b5S}X==U(&4Z%)`e}NG{ajQXS^3=-DBav8OU4I%3kV>ukvM2c`=3K2tDkKK*Dc_mYLR>N@(Hb5a7%P+es3+V6u@4I2 zpUx?N^V!R|ZY5_gv09JHF9DkpE5kBZkC{jATz~5;s9basIZ*+~$(M>?`IebZCUKr^ zvlBK^A@^8VCaDsq4wQ)525d0eM1n%W$*&USSTLZ*jgLvO2s!u)YH6!8t0mjN2vR}p zZWftu%gjy}8G*%CzkJtcyjDnw^VeHlz1>J+_O?3ZybCM}q5oy#EyQte!L0nD?oG&` z?G+4sZs7L}Zov}54+(v%h6>B3J1fR3JC%mkP-yJ)`%mro6&@=gtm{@LYV2}0wgzUQ zhNbHD9+s=kIG;Cv9#zB|vi7HZdTTI~BBizKUOz{uSB<)=UtsWkVWC#I3Q_IbC$WRQ zE><@C1slE#Hm_;MD_{fbGo%iGx6yd8EHDDBT8)KpPfPI^x*QpWd0kaGqwVPK$M@9F z9!te2+C@F%WNafgR@M9pvUz)f4&~a*3d6hNEqFtpuTX2RE){a0FIPZxq60WSi-2Ra zuxb{PJ5|K$ztX&DB~G?_Rs1Q;|L9n?a9G)V0kRa?PyhU2_q&bT>zPuGtSr-_x5`yX zm_j-mLiRGV#}@5^SisE>1k}$6a5uO_Tqu_ju#C*wG(MAQ&(2C&n>U z^&$8pWy17JQo>)y%RS!wCtNF5urWoK&37D62cNZ9wL&LFw6;jOVI#@3h0N9>LX;}! zIi=0rx$^r%i{nu-W|Hv%<}51&Acu^3>M^9FWzdQOYbt!bYo*1FSqxZV1Jr1#da%f* zskQ~7;b%P_Yqq4gb$) zQ{NQPMxs(-9MW=%vSGBT&Gjxpf3mPFS!wm0`u+R&1IXLaSsnY&!NFJHxF3LKB*Da_i2{`pSgXR132bAka?loj z>^}dMa_vgE1kQcBpd@_A?r@7)X?A&!{Y$z4mY!~Xhm1j51qY8bk16(GBo&5H|D`7s zmQg!`B5_ymG_*Zft^Da?RakK|@ZD}M?0}BjHf(cXw8Eh6E9}l)uHXF-((5;-QlaS3 zg%bw$fcz<9Xw7L1UuAt*MvBxTfM(a(z;l{#UD9<9WgQC$k zE%+15*plL64=aV6b%?h{vis!uTxG3EPw0HRis-oj0G8HS4tdhoG6>g%?jtDj zhFzmiVVXTL^oN)c6BFB||E(MWt~9&WrgK>=-d`Pxz>15)UNNnTiZ+c5r;#HiLf0V|r$>v?Vpx)~c8sf{9J*C|rYw&@9d z4J+$yW@hGgxu*)qBj;==m1f;I6Bct4~U9N8eg`Y9K4cRJ)g3G(e&~Orw zY?l2|nsIUq=E2wz1H(fiw?E{v__j_JDmhn6^TRIW6RJKA1j@)0d(>Ocv94Jc5C|A{^@EtW`lx6k5S#fXhfARzPI0_XN7B=VEEjLbvG+NJ9 zz>R4bh+uXHBQ!Fi?wYCcwOYCA!SI zTlm#kGmJ4B5cS6UY4#=s>k{9bH9Btk{KixZ+pFzs-uAzTU5`72FRF66%Y}fi4lVZg z_ph9t)6IkDua6d{%6E$**n9!7*n3cMEQ&+S=d`i(R1Kf&|8+sFsF7J)?VGeS%yW29 zIWSJ8MtS@Nj3iN&EyLcX;%;N{4)4M)y`aS&C`zbNh(tAfxnF|`UpybCI7j3T@onp!J-{IjgWOWn9puFE7Aq8M3=ZlRH$o(& z_dCdh+{%iyYt5T`LEb@os-0^DfNmqFX8R!4lA-qXCbw2IA z8R`WQ+KB~{Vs*ASp^S`7Tw_$V2aE~^aCSHCQLwSIS1xVlE;BM#cei;TZLx12brR-k zOSbUYJ{4uNcn{MuzgMbW3W2UvZWY){C4f({UN|$UM;p1>KSskfS~tfyvOpx6ZOKgU z`urxHC4(7e7PY(UZQgFBd7TwDOJB7M@ zgCz||!GVgSd2`QF&4um3{5Hp~}|53v9iOnIV?%p-aO< zg2;75oB|2;Z0HGYC)c3GZ4AJ{nJOWPP7oQ=C5;e98IAz{PGs84ow<$ypT^Lm2tW za~LQ$=Rx|469>+dYf z=oe1#)10CI)r=GDPG%fg^d2X@YhNTjuit|QKx-kD$GAFJ+dbu71PYVF3e_mRN{-72 z5n5U=sixjcRuNBt)@sbj;Z6wJD&a_i*KR6nwHj`|&%sO&*g9xFG#CZFtx@0{sxPPd`Qrmh%k9F;B&J@4?k`sz+>VQ$`> zhBVoyLpMs5uka07T)f&ZLPD|XNhy0>qEm+wrU6mRpq@k)dDl>V?5AZOLD=i2unp29g-IAJYPquV)(Eg1n#4Y!Jv zkH|Rl`}Z{d1D#q8fG0Dqk@Ieh&tA zq@d3~Okn?;6(o@_;iZOx!fay3<2j=VBiJs%pENwT(nODHv z_@VH#u9KCcOHc=l(d!N8tDi0BM}ebe1=)Cv%RUJh&HNpZ*$%X}ai6aF_4h~q7hSi@ zjZ-mJ?=l1`9i}9+dwcDq?5lZLc_v*&H~U-Bu741DxyGU9K3kT+Zcc zG+F>!l6fpY)bScS?GGV%-If}jeSkL zRsDT}-M|#l->zdv~#(KB`1-C?Eeq@?^Uw4AZ+$95H|-U0td;y6P)2QTGR$ z=;>(u6=?kRk_jQXH#0JNl}vO&nVgg%NcFSP-w|1@&=J}FWO*UAR!R|de!{!!g8&LE z2<^nAkN{S6p)biDVcndf%jPfPNS1j%hf(of2<; zMcasaoaV(@@2$4A+`!k4l9`Ze_1mp=2H0UwDfNJZ6^Q4avyF6gec&jP=1>b|QVP29 z&D}^5iZ1^1i{nqUk#`G4M;kxTM{Hjfgv0=~>XZ{G9B!>VG?OND==y@~5cJ_gr4W_*ml&XB8aH@%R@QLiV_e0mF<;Ban&o~cT8U#2J4Ab+ zC6}K2jEgE#vGI2>p{>p;F+2S%)9e~#0u}`~`q|lRWIitxq0LHyAvjdD>pUx{sc0Cgsy&^2zh+P7Goi+5F$n3xT)T_=7gf zmtf6;)DTM_a?wV6cV_1D1S_Ha{dR=aJGv;=Ozb`gSZ8rg-v&59F*^~Z-ge+QXK{5`^xYFMkM0`}D3{lRUjBINV3>G4AHRMkt)cxnv)47g%)0)?C4gJ>9 z5Ptfcw$r(K41mpG8?;a+S%1Wsc-(z%#x@E|p!V%gxiNnwG8tQq3MPq%lDId}o*fIY zRR|7w1q2pw;ft$`f(%Iri7)W?=ZuAN(fK95ll0iWl~xGpn+I)5wi9cApKQ65zOktr zyNO#RnN2Nk_UNjxFr806UOIZH`2}SepM^wy(#(9Gve^&Di;X|M%8kcY_=ehmYf5cD z_O+#X*PdC#XOL+kyY^tixJ6g>MB%_{-JL2UmhfQem;I|Kd~CW&e|+}BYH;t31?nV0 z7erzC%TC!&xdE|uu|N1>4%sz73@tV9(Y?YDpqu*YYmmxO+?zUG-Ua9c_>3P;b_KDt zEzOBW@;9;7;9i(IQc#>+1ewJ^N&fD5!^4$zxdX_q#gTi;Zf95SrS7`3$@W`h7- zQDTQkE}im(D(dKRDh}Hs8)r4xQ_YH0OYr@p=BgSm(pV&~EXgegg@3Ka4nXQ)6t-DL zv>KW`gj@RY)3bP*qv@X!ZZ3ab#L10*qc=oYTLI{2>6_97n4j2;+jq!noHIeG{2>*d z{myO^J~Lr87AtI9vhwA<3B@!U(l-W9z?FFFpfO#fnvJ9n(61**<#cGzm}NZ(>Lg** zazUW>=)9raZL^mn&RtPUmSXSnXS)#;>dNFZOPd7F%kDpBf2DXmI%p(|NUuRf424yb^3zEv_n%zKzW4kVVzCZ$&BTdd zt=I~FddQ`N(ub#(*=|UjZhaHl?$U90sVMy{{KsH8l^XL9OV?*O3(MMMdJ>lN3rxZ) zy9%h$FU3Fl9(AVX08K!$zqVZIh~4gQVzN4a^cRAFFXh9-JhWu)-7x)b%8{!YUH21M zbf^|laP-f#91?NZ(_9Tv4+Sj7NuNx|d8p6>N{poGX0&?cqH z3cFnnMiYS&e02?td%rQ_6F4-yR7WTsaPvGQ7|G@vP>v?I3Tp?gPq}G{5pXEot%-mV z&F(RnFOBY;M#lnun1wvM=c3zcoWqa{jaapJHeOLJBEh6U3GP1NW8oX1K12}MpR3Fr zSTL_A4Netj48EZ~AUYhX*&-|5s-pD9GSHY=_YVZuvV$E(^V6wjSsquHcN|ST{}x4# zG#)$%uqI96hxxTj^3^UGMa? z3R+RR*iKej_YY@=yYcgFVRr&UP)uNNm_K+ear<7YxGcQZ7wm?K+U$K}N5W|ut_!fC z=jD4jIxNI;F&HTnegwOT(B&S?Use|sGWtR2LDm^dpJgFqF9+rA`a1s2Np+Mz%S}@i zjJ207s0e3KryK>ai}J|s?*w6)%`x45l+V`mcwmi2x{nZ$ysL$3;hMPbHvv2KX4 z&d7{0rGVzd?M1vyxT6AvnBOw&?YwA4lz+z}2hV#CXladSnw;GrA7yECGWDd>)kd7$ zO5!`;wn0L5>#g)V>S!SM^Cb}-^C9>n%eJF>3kTiZ@}@j08YpKjw9Omool4Oyp7)pg zvjBU;IDnFmZHjeoBr7Xx`O=h+s@rVBN~2=|+B>x7&3q&lJ&kP1D(&*fw3W*nUPP^2 zt=e9Z3bu&g>y3~>!4*(Y9u(DChxzT9fwk)(ZSK~{;#75pa*`z4O$fgzNlo@AX~^@j ztu;`natI?TJl;B>ZoWEMs4W`H7Mj!V-laao!hVDze*N$8jmg!1)sX<31>*wQnDa+n zy}|A6ZMNwkWXx-sB>`Sm*5jGR)P1Qoe_+u2KVid^#ly?BGv6IA}sWV#X5ep$#2;$vdOp#l?d#Mg!0xZbSFsEPkcQ z>02L=l!SK(?C8KuFz&<~cxNoIMiW2-*CQhW+jWK#6Wz|350@k;+hc(*-AQUYUmW(= zyuo}qlC>c6bo1mv%dj(Cqa{9G#|S$#R2t6WfuxE`C2c}8iLZj-*h?18zrkt#lLNji z@8{3n6n4WC4O=W@ap^D&vV##Zb2GC$uMw1s`oX`^h|FnlnlW_Em?yK1>ci)*sl1SV zg+()rJqu(9V(-ySJ`qYp_#YTo2UbOIV*#z|%)V4F4I}7lx<&XA=Wrq#uq3&8aaIO8 zoq|hBO4?EUVRwowswt(>sg2*D(|Bpmi}?lk-3wq7>=bT<_A&L24dZ2`ytq*W9{zlv zsOLb8*Y_y~g<}cJFgRIs6`xt7(ZR_cJwwt`C0lUY*@5_D$hHFcpRlOXj5@bt9d~vv zoO>A=LV#mm`jngNoU#zWAt2k-EQi8dX7+F(zR|7t^+#;Fml~ubqN4?39C8iZUWEw1 zj6PuP{t1MW3@;SVUwRP|5+a(5=l+$bghZN9li4>NWiMYQO79&E?sxYJYXqaHGBGfm zg7%)4n_Wxk-oCxhqb?kCXiuri6PxmPz;xgL+t&`c*0mRYM;X}*S^H$Zi0SO?f4@)P zF*lS*?=1zZvWb}5+DUEh|Av0EKc*D3rVAL(b9Xo08s17~%UZfQcUDC|Qof>+=7K3ad~dQqP9ze?H#WNa^~=DkFsx0czF~L-MC&*|h3+@hzjJ-B z({<}m$~|QBh0TASWe;*z2&W$U*0Nad+HIbh9G_yg`9QQO%t%pfp3w#=iaW`4O^Q4HI2_cCl28)t+6$pK9Uf&Ml~nj9P3AFF%C;cgyKfu?V99l z!Trf>l%m0II7TudEu1OO)q9o8yA-n9BV5BKdh1b!mPYgB6@ItruXagagR8Of`)DS8 zU%rlD^KDj)|FZUZZ|Ze^6utuYTO{dgk?mWIwY zS;|K&RPUF;#_Uk=R_7jhwY_(vOzvMU_gK&f zr^n?;^Dh>t3!nV(eNPmQnwg_KMB)=10xY8qyG}bYIOs6Pd14~VhC5HeVYbEQkGq34 zLiht|dF&GLW`C;4HNwt?0wKART12p_@{G1oecWZ)7cJN zDD3wHvaA!a+pc~VdJ!qms<<05es$XZ@-qsR4h7B%lDJK}T4YO_z;6^5XNB|+(pbnl zYn)!`j1rpzaW_U-qpD_bFOcLzJex-)WTM|AM2UC4SIo3RRSV6Mzip-9ZMI+Tb+4G~ zXK&AO{1c?8r*{{2Q=gN;-NgyMDc4U9dz_co>!FX&3%Ad@Rwu+XhzEGhi0zK0q|Tt0 zFAqqD&&Egt;L?OXI3O>NjEd1!!8<#lp2xYqd1*@7ebht$H04er?txkp(30NNO!Wny zE2Bw3yQ$Fu`}0okDkJMvd~fpZgtpZVHuHxMb+ClV#YhSart~2c82!e$Fpe-A6<*lF z0LfA>opczJ;7oao`T%3&i0tN|4Bc${-IsN^4Ql4)e60L(s!7`y2)I$aTID{W9VY8S z*PGyh2ups^YoE#}WS;mcjU=!*z42?!EP>6#E&~OjwJ&%VbCtEuQG|>8z(U>GTaNa> z7|teBEgbo`1zy-nejPzAQK-uCk4lo zNoi{*<~vXlV8VIPZOIriQ<1dCcSe<>?G7=OK6 zM`kpQ(-|~7rsEjHqPf$kq0bM3|6V~MXsJm&SZCZMXCcVzV@dlP=taTYMfXYUKuhQ; z8N26r)kTxtw-h=5nC0)d@r%Y_mFW8gD6^%(8Ax`!0%gZnkvII7=ZEs4%9GHqL67`{iT^xmEriX4PaFI?u9!a>Myo zxYt^%%{*@A*NP)=L^x}ty*>PY-=wxfWRC-n>>&d35ggbQTY-R+APD{I+FX(ckR3g8_4wpjH_ClgQ#bzq$rcG!&P4b(CvUU6&Lsx>^LKSdw*?w9ON6 zL0RLYx8;7nV_E_ZKb?CY>+5lOxdD27{ar?Grh^TSj>^*AzTACczCBc7UT#^cAe#rJ zSZ}9uxgDOHxucqt4}XG&*4a4e8-dRApY{!YZF6q+%`b2@(*~7x30R8(IuVy!-8vsX zl3btej4hV%Nup3KvcMEL*(*qwfO}%BH-M1A|F<#@-)4Dj*8NhDksK3#7 z!Cr(|HFE|uDZJVP5A=sD$x1XP|El3M(%aXnNZnz z*Q$d;?duWtj`iGyhw!H%AQ{9{b{gW zvRSONYVd!0wBYT5>3mkYAj(cjDdtyE(bDO9k1Z6evNbklIkIlLiTXeKtmME-s4V4A z$`Ho0vam$kV!qTO*bG^}J9V4qw0O?uRF7W`U)r<(e2 zGPCBNDCfr)yIHP*%bL0y z8H z8%!`h0fAR~!0+Eo6VC1QP%EepZ(VP9a(0H~G};dfkNAboA0}ZAkN=PgI{-1$(+`07 z2(AmtK3>n0x3DnW>FMYk?5^?g52SNh7L5*y zx4F4F#J5@uWHPTTK!d=s&6X9^%#sykA-;l}0~b+qk#F55hH0zg;@SB57P=tnpgeFs zflk5Zbgc`z5Y{liBTLD2b%ULEMyr1*q~5>8xY!xHNKPykUI6$4i4yIGjvXSC4d*WBme$=#PMp|5-19h`K@x6Wv#`;b+_WL$h1#; zu&nLffQV9#@B*5^9iagRlj3=_GmB2$Ane`2$q4u?cPf6-Bz)tKx0{&$1U~0DJiA&e zdL(m$BF=`wOYalk!WM0-g5IiO52VcVs}u?-oWLJIv>-Xhk~WT7nDQ7C`Z#cdY}t@ z$5Wd42Q{4`gAfWbXkoR@`?v+veo@oo8Q^WPek$U9eOtZtI`?9C!X5i-1zM?tp|ED} zH^D&fqIOCOOYT3Nc}E{D96HKIWrPhzAY5d6E z*UpzDcHlaU)*-d9t|u2u>bZTToJp|qv1BrGOM;U6^H<;dOUExiKGq6Tu_J1rgQuvE z=PGkG3sGKyKU&pbE_qmaIQW9E>tRK64n$H%XIi%+%Aoxs<}IhtGSG3Y66 z=&YVh223B{_s35={==ZlTXPOW?qdrY_e{=8ecFi8rA&qBisID)$D3a)hky z)I4j%j6XEx1xj0%_%NDmVR}McF<&Lo5Z9VWk0dP!R-t)9=$b;zuT`^QOVc^nX-r5Z zDCm5G>*ra&@5dXX>`!hUMGQjAxZtDZrYRutFh;(3_sIFhgjmZD@$@`69AQM#u(VUQ zPbz08sz^g~JLq$RTstD-L{09i1+YU|BxK7JAn~V1NSj?gOT5Lj5D{`$kNjOhHNh|i z2pfd&$_Z3uSCzX^{*>Y&$5D)BFZ`+!=W4&d6TZ;t_H2M+rCy>m6FFco_*E=&?}!TG zNRNb3kxK4KKF)IJQIxv;kD}9$=}_-p(vH}t(CK-XqoJ?xEj2k%vG0A?&-}HVM&$Ds z9$#)VeJzKk7Nr#z!XN<`-|0US;Cbj2ZP9y0|rHiE>Tfo^L*hK@MMU(V?SVMtPY8rW&B!>A7 z4ay7Zpm)eo+3xHfQ4DCUG)G}olnvb1w?Y~&3xtz&{tTK)VylxW2y-J~>4M<Uj zzNaM21Kjh#b7>Jp8h-L|3G&JCb+TU^3Vv#G$f|teW^NqzuR}^cj0V_mdFQfcZo`*Reu~5d-a4V_ONz`cTOT<#hCoop{=g2 z1YOdEx-l?l?zBGLd-Rnom9}y__Vf6o;1?Ly`kpE@w69N)*?ykaSWIqu( z$12xB?w{{+(w-;NDnEWGuYRA$oQ$b=5um@D`lUb!4Al(qit@33za8oxcHSuxY)80C z9G!ByJVevnRV;Lx)jL;|L~(#OOtLHKBBe>}%JZjjq1m<68+UL(Q=4AF<#4TQ(y7OXFd@R4knDeIWG!5TXa9|A^ zuBYp4k(LUIOsJ7cFFN|e@B{A6D%vVvdlbHYo@6wk{u{4{2?42vz(3!u81oet*6ya( zewIiH)j#9%#AQn=1|* z4PU&Jve(?v2}ueI9>JX4hC6psYoaEALx}v47#Zs8`NJb`ofMCNiL6Y- z574BEq2;J22Kj?$r>BnRr!&4x!z!2ea-9w{g^kti6))@UyBDFtoq;A4=jdOyABRAH z0CKCU5y7t-1fv43QJ6mWRrUJLvd+{FSSgRCG4*KIJ7yeXeSj1ilJMZ5K4aD-&cAdxe;6>_Br)xuA^rzBJ8U5u_m{-`Ya$8S(bqqRGlbh=| z{1jI>F&Pf4J0FS-Jpc@tU6~S)9wF)U{PhW6M<~kle81A|PJ15VMTV9N>d8|Vwr7mMa*;-~(Ac?~E`JT!1U86Y`LU7v4Z{FOE z9|Z`(!Ch>1%~&K%N;<`L<0VPeFZMGF?D15sD?XlLtGuFT7sB@+qKn zr$q*Y$%J%q2s@L(ba_|%J`LgF7HpO{R0Qpgm+jW7>pS*(eb<(ZZOAG8< zd;@%P9_&@KSTC96as;4|^3N%yeWTba?i<778&30UO82EFywB8y^U;c0-~zHaKX)l^`Twron;jz=g~k5fpmy0 zJBZ>=#`6b8L6;=CGe&UG!a!$MLER4Ric71ep&GZSO-k9`KP*W?@pC>3_6*^DRZbHv{AIr>z<9mZJL)5L^M6$TeYYiRr})QqPSpQM@%I=1o%-+GoP6*2xc)cw-#IyX z|Nr{$|2KU8xAorVg;ZjMfjBV;;&g-nWE`3N~)0a(R&nOkVK zoOgrwFGOoI_AB=He^=a;0=?C*o<2~=%hTdSNdM1&ag4=NYya2pj2CHSYNY?mcfECT zk){#<^*gILydj+b`rQ;cV*=fO{jN~t6RiU6fB8<)`=@-$e-R=+?OHyb<$opE@&Axu zJnfgi*pr`bo)$BE0uj*;CdTk zgjd?gjvDNGN^)B8b{5aj$v+eqJ7_5cv1qUFz1NT98>B^#J`d-Zh*2e6*!Y^_X|~@Z z1XB)|#c?ttYIxl)4-j>L!AYk6HtTl_%qhtj*CEB7VOwz6_RK_IBVsCDjP46=IoZz3Z} z8C9su*r@hsiT-GtWASbE0+p;^o;m65g5h$jdAs+sZd+sCAugD$49A(sDy%M56-w8< zg-U-S__E^Hg;&;`_CT!TaX_Q{vt_tQ@%{K^Sa+8(&eNkws4f{ zW?YxNZ5n9|4MCP%aJfQk&sJ%N;y-5La-VGAN9$v@%dtL}DY{a7z++ zxYtJ~hz*>)Ol|wKuS?|zc5u+Q1x~eEh{jn{j0*}VP3vDk)~L@6mNR#JBTN==<(5FN z>*~V{Y=1_KTkrJ;v=)tuciad*_ZV;N0ZLALha&msy>Q0Q!o<$rYKhPc1R7Cm9W0D( zZqyGxVK5dw!IwhviP?Jo3U%goj3ge=}sGh z_tkbCll3kJDobavR;xY5H_yszrh52%yHaS6ZrIbo9a4H4GJbr?bEaK%mKtk+VZq`d zb>R&i)3253081VE+#%?djcD0s)25WA? zT=Z~PsHb^FEtjW~YVkci;f2A)J-BV|*)pQ>VAExZ6SxC3fKaTTEz)Ak%aG2!f0uFE zK9M~6+7aCvCxf@waqK+swz1z2dmEwY;Gty+v>!_8W7|#P$D#b8uLnprS_DVX zau+T;+OW1g$S|_o@gF)!RQ9BorwlYFhta<8%1%Gc9X z-9Ay@?~be)erO+bvndMb+EumVlfE1Co_+0TTX5Hw-BB8`ra$Io>x~KX0W|-anae1c z4{(7FCM5f3ABUsO#jSE6_Nl=VSi)v;@I#_cjWYG@wI9}rABuM8mAlXY*miCO&GEHu zZ#8sQE~!md#%))7c6?(G_XZaIOtOIQ1zX5~!T-%zMoyix+vy+lZd3T%GbQR|Ub0ztZvLo;q3p%bFuaR?N;jWwnS(D@5lpG6#+%K-iyo|@Z ziGjQB{lF9L3kYv-Tijvv{f$59#$=2aH{2;R{1D{E8qk>X&pEt-P0$`Kf&{H##Ha7s z$_bNhWt@VjT1g}K65oHmg^Rq(N2-{wTCDbjKAjl*YUbMH}F} zd7rtH;jJ%+>*#~q-UBXZqpv8b9e?)6mic2UAsry;+vdW!t*FIVb=gFA@g$+FcP}0F zl?(}iGnY|aA+j5w?v86`tWHmS~4I1!~?AxPn zWIXH0a&n)&2l@Q{DrPQ$v4R$5tTlD4)&20>jf?fNsjva}rk%HXwKpwySIW`?klPhr zLy{XyTFccAyY`j~fNP5^h_N8%5J4rvX~SD+Z$2Ykc&66k_dy+`|=hK|&BLzzBfZaVlP14tHr1Ex}Ngk=9L!*yiOkhbRz z2OYZEuJ|z{+(iqbobNx`-c;Ax<(2ykL?_WQnKXL;gLCZMkk7Z(r;d*p{(W+Njs`u1 z17MnfP4Bx_ULfk3{@F@^M~7y5K%?I*rkvG9J=7QT@rzcp9rM-wIOglSDlKRL;{kC& zeP?5!C@}sN>9)972OtqmqAuI-#0qzOzi9QJ`mJH=$1Z?4nCN|nVD=%)`@(tVJm2&uW4tKr(3C{S5 zHd7kqe7ioTxGp|%$J?MKUS%6;KYSBRCA5O_B?%Xy9Cf#MSE4-wrDmjA-yW-}u-;cQ z&(mkgU2-|dZtq%`>cn1m0kS;M*lst+iz7|){uvk7q5PopamvJun#c^l*=XerHbjr& z%NP~6M70>Ef^zpa_RlUt$wwv9z&U`2w6ZFr#$(X~_GvcRM)kty5j}-)| zJ;a)m^}D;Sa&5biqd^>^Zda?nISKlkJOgX%my8KY)Z9awnQ4KYb=bWg9f=MIR>rnl z01C$e9>xw_RXh6l*9fSGW-EiLdhQqAnZYfd_8aauOqhWz4UiOZ0Pxj`>aIJoAjm|l zqiyUyD!W`bYo&#&`4xf z9{1r2V(aDMR?Jwe+~V?AF4>2SgQwl}ySxQQBD@YB9(O=7&T?Pd4jOQ2L`0vbw^}mN zG!cb{%FvdGaeXiKbA!H`&ur9|L~T};^4|q%(y7Uu*RWE$ep0~cOKv)Q<3a;PmsYN2nk&zU|K8YDrsmWZwy@5UX4(p? zgMo8HBwlC1;_U5zLhVS42xX}gu1M0X!EFHy%zoYv{SBZvlYzhgv+J@*m);BWL2Qoy zUh+-(M=_AW@_R!eRTv~Z;7{w5qw-Yqj1u6S40zm1*$7FP`xlLHXz+h_7xCCKf!}oi z)VSZEs*tEa(YZ1?cY?JoxJ{{IL1V6K?jMy?l%GhJkLJpt)_x#+qQDqKaq56i{zuI= zqas)mVvsXB=71jWcR`@gH4e3_)n^m_O7;JK&iVff_Ww}9CIdPikL|ZpfKTnq9*4Hu zbAV+XKi>=1MBs1WS>~`^^Krv@kr+_>@od5$<8e`%{_)QLN%PTVH+!b-Uf&gnbfSMK zl5I14%L-Wb^KRN4??`$o^|OXGkM#Y&>E=bikwwR&lEBU~+OR}Xjsb@7*_Ko18NHI1 zuG0pi*~0sx6e$&<0=C8IEO+eN#s>!j_!vH2G^g&cB@tF#+S@B+fnQqT*iFHSV{!n}-~P zVz#j;aqP|937;*%M`mGjuwaBvtgY~2JyroU%g!@(?Z@he z1Wz}IJ1D$%7R1up|C&hR_YQ zs>k{)?`?InT$9+!B9SAXUJlntkDnbXKBW~G;RPe(_>+srrv)SFsfOBi5C{d5|H@^c zO=s@v>4?)BD*c?A$a3PfH*Y|B^GWvad($N{CoP`uf<+G-g+PqQZfHOHUz!&`*Y6_* zPIBz#Xzs9!R@qcTC*>|+WcZ=&n$_8TzGQUOyk&96rUkN9eeVTeb#7Q{A6+u3tTB3` ztC#1k^wRgcPrssmWK1ZJ&NX<7a+*)KNIhoCHJlUsVinhhe6l+`({|K4kl1V9a((Rn zdx`6Z&6k;WcY%X>r*1^TWD@%}*V8%rXV?z)2&k|3pP-?@MBuiLYnWgJgAt8@ovbRd zO7V?QUi0ek_pP2p9$(q|z` z8!K%si2n#3a_WWOZ9&%W1bIcZhhxxFv3sP@&2NfiuFA%mEXM`>?K%av%uBa>v((hu z%GTd{_fw@KV;x|9vaK{Wlz1D7aMR?m72CL)h1NT>L?zyGo5Y%Z^UP!=zHF9;{cmGg z+B-*$&Q~od=%#YN3goYngMZ@E8ZUjLNLo{4D<8kSASL==pa|z zb=Jfneq(O=`Nl<2?%`3zJt-SQsMW^v&$*5fPP(h14roc5$F`C>rNTQ3I&7tz<)SQ~ zGrFm-FVdkN!RYrDPsfA0z{vyJi0DAJ*0tbCaLruxK&nWrsN0{|%wS%JV{eTP6VSm8 zi|Avo)8CNPX=`pJ!n#P)mJT{#vLe6gUCHMLYYP2Ls zntU=fzaOpRZNkV7y&H!@N$P;R?~O?8Pa!q?Wecv}%Fq6Ik>gl~a|#73Xvj{@RWKN6 z4ylHyh}IkM{UFG^*4NuPu69ocfDIBmuURgxmy6zN7V_G-p8hZ^>WO7Y)ptH#W6v_U zh2%bdb`w21_4F7W;VMDPF7=Ys(XM?G%-q1b7Xgd z9?xRMQa2|$s%+G*j&(K6<3Z(^+NupY?fK)RIc2<;Lcf8g0U%pU!Mbs_+B}HMi<3!_ zM4Q9_#hStK4D=l@<|UgQ^Yr(#^cusoXz^vxf4Sw-2Vf8LW(oo9CjLb!p~8Ck(4!TD z*Ngt17h~IVe85kB>PusZgGd#3sT~m8CPNCnL{U=?x}3fJ6EbC-1iSE7k0+HZ{jsr`U?i66hdgV)qb}DQZ+psDH+dQkU1W ztbHe-LrT8dq3y-YQKn-5!f0q$ z9sbax#%s%CMfa_R-4uule-n$y_GQi1mfA=Fy%M!^8-1?ElkY9DMJjV8So`k6@R9Qt ztq4g+re@`)EPQqJM+rRc0`IC(kj|gXmWv9Wp%3v#DrR#%B-9HA;FR=CcA~UbHIuUV z5%wK%xczlaU-LM;Gi^)Z`fFgIz$zMR2t(j_loN2SR1a9FZdm!Erlvx@4lfIC>@R$7CprigsEKdWthy9FmRH{6<%CVSANH6M#j`stf(GC>6>qMF&)y_68?%pPT9SEDoG5q@XWBOc#y+T<2 z>|@8(kFYt(zcONvLu-{;Z=mv}-}9o%N1`*fp!|~O{iZHc0~szG=9uyJQT(UNc!R>-GV!&>QeNNb>8_@!y6b}hD_G%WBL-ZiRAlh@y{!Q*e5 zbwxRKr7ne&mWb`;29(Jp5xe}9zh=LL{u6#*5vF|fe0^HoPdg`7Q=RuALEX~UhMW>g zhKdN(NW{`b^0RCSA#2>uJEK$=PYvFSl`&?X37#@;I4no)Mju zbFHPTU(cSh$7C_mG*#bMX#v!mXdNH@$5f~5h_#^%=?HD4EF|h}YdQvp_elBSp{(1H zv^vy=@AhG;laIIgM=3beq2|5hSQOB8Y>GGZ`_PO_jrNc&;S7F8Bt!k|dsA;{XpHQ% z!?;blH<=j+kRyXLo6llA>xa|M=k1Bl%4W{LuhXd)PWR{%W+c^I*)^LcW`MoL4TAe- zsv1eSyp><=SM7x?_z&G|ug(c(hn1dfu-W)N(i95Uu0_6lq@`&+GUvFB6t^+`VuxT! zompSO%aE!5bKqr5xN^8@>Q8yzA5aTPe#Wb5Olb+!+A{;tRqY;cv(tL#n(g=G4P*x1 z_VW#=wqO1_?_>9?_St4OEP3j1bbXR#N@xTEAFlx;njQBuKhE19w%Jo%=kx(KRb5C| z95mR&q+kfhzoQJW>Ls=9Ti@Jn?|YGX<&N!DH-$IkRnQ`@v9fs}YF9TYdnKZwc~b4& z_IQ7o`np_3sQca+2sv>NI~ZXGFV3}V%$b=6)Mo>&RC5|Gt}6X~ixq7zGu26MC9WRJ zev|zRYb($}sL@K*(ueGgXi4h z!fMAkyBA}R&C1Q5K|NAD^}@6aU%X8U%VVT}8Q`ROTOZ`5>Dh&5@G<8iYd49oZBJ%f z$=*xtZWhq4ZgDhy1$6Syl)W_qf>&>by`g`e|4nVL69#!slqxk<`dyWdScria&VwT5 z7;4L-mDO_4^Hu!L6SrX_&`&w^KDIVc6Md|XOO7dR)~|BzlY=e?f;P?}bIqGOA>f_z zUFFk#W%KH?iR(4A$9jTalGAT0$Zqv~v1dg!W>lu1E^?n9nuX0uM=Y5kNxS_1{wL14 z%$43NhX+nMkRyv!&DIV4?E(sj<=rZvLw|==PYYl{;`EQglu|?IUAkr{KD+np*)M9P zDP7v7pVaWoMTs;dJ@MhnQVfDcg11ldBaS|`r2e@2*74|!E+{6GrqmtB2}m)7|ePgQK!k}G}8R*>?^id+1jZv5FRJ;$sMSZe)7 zrYcY>7suhrPruza>*ZeG1z`H**?dgq@t@3pcBT2qPy!ThBUz9s&s%zbEH>}ZQ?okP zVIX={qLTas0X~%*Dyd+(9&743lAcrHLvV9%rOB!(sfy{w>I!WtZ z?P~E1(4eUArVw8y*&^RimD7GIa`kbgBhLR}(^VuqFKW6O&@%%UWunM_ds!qV@;SCc zDPYh2jbhR!=^WN}+AEWcK+YW-fG=bj=Cl+IFX<9qUo(CgYd8Nn%Ti=zJ8*41=5+8_ z-MoW0)Er^jlA0bwz2M#sIX-Uyw3QPKp%240iU##-Xl>FpO|=#? zq-Xw*yZ*ycH=9A}UmcX!LtQ;LbO5!?`2bZK5r~zF zw~j5f#Vn$PXc$eBsGML@fFl3XzKXvWgvp6sooszCER9+KL2!x&i!AsO>be~7bY$es zHBC+Z)KwT0T(O4;*nSh@Kg!A+te&R;l8S`48C^xv+Ql7Q{13ZyN7^u>x&rn}_A&CI z#IDUvf1E4lELyNe0eyyTaoj$mS(-QA(01gik-!XV$b2Fv5oY{*YzaJWfI2NN^k8i< z(O;P%mHTz;_XBnWK`wp{#bpO=&r<+zoiLUyRAkdSDGOVjTAtGd=#$$i zlILYn^DN-TVbFyV;gC!v`?U`5F@!uQO#pOXjPShYxxE3;9;29!}|GYn3zv-^nmaV z2Q+Rx7^edqR3lA;ED47QQtt4-=suAEi$nU%MJQvDu-n4lcJDdQ%4#h*L#;+o$f1#u zc`=%o3P;5#s)PyUE!;%KN9Wx!vMjrF7#hl+RHwBzO-OHNh*B5B4_aFHQDcvC>dzP6 zS`612=G^{^CqSJsN;`0~L6d^C#(qZqAmuqs*{Ln002!}IIUa8@f2&Oajmcxb z4>WvHMp5&5YOm{1YjFcpU1rtNntRDmH5*k=7UtbX^U(vl!p_%x8FZwn19X00+vP zPYX0Sq@kx;TXk=fXB<}s?Y`sC?#9^rZ2noqldlNznIlwvn{b>!ORj5; zx{gFLE%_OpKdmdMSoj?1_LL5%UnX=NALnCAH_3ezq2gmq7DLzsnqf=oQY_~lMA@*; z%eR52iNDoLgyIPo+@YQ0I)!xYD;g4?C-62`?xRaKBK4l+5tbrHatlGe*QEe2K+wO8 z(x%Dnn|$=ALel)OeLtig&anGz<#Ey?;i*0t)@D{zO>P=s*sW_ZNyqE6IV;sH1V%Avo}QXefGtIolKg2dp-@KHE5ekExi$d)#KN|@n7#0|7Fa># z3TJ48D=>o?eTMV!uSi_v;Fq z^+}7iD@0xQ!#_X;^*tEziqomM5=K8+YKgu91b!LxYZE7NZF?MVziZJ}`uf{it0X#x zFXOsJcUY7A~B42OWNp(Gf;I#+!~ZpugW@(1QjP;fE4^rRruqA#G?G)L2P=JUwY zZQN7wgbZ7O=xbvibIOwT=Hy?b1C)spUddk$BH@1TRfoi>!OY5*n)vLC-wg23qTTT7 zsh3`@L1~1`a$6I{jML96;z?-}e5D}G;u~Lvwe6|i!1Mj+H<4d?d30eD?>4sOEvv+f zZB+EKixj~0#%k6WValENi9WBP)5l0tGHT)+c?TzU)V$v4Q-Ooqjwf(On1>XfVNa12 z{A_+C3uonRv>C~C>5W#|`(KK)8sxa7v_A*U(Zm>p-lrQr{!Jb39-bS|;;9{dA791} zwK2uo<+88vIeb?N#dfo)qaqS&fo9=9Y_ITbJ3nE>`CS$qI-kX8wjHSR#P#`8w~S`E z&Nj#78R>eqD}X7By((yMV^9}2YAeik3Nw?&{w=B;`S>y^+NCll@+^Yxp-K4=K<#%p zk4g!zB1dUb)1>v}h|^0c;~t+P8~V8dQrYi!0ZuF^9f#yo8nm^s$)DZf!zkgUnM}pA zT}j?i5=-dWtdkpuXaD@3ImkqlgKbM%S~l*Kb`y_t7?17#-E+P)s{gNL8+YU)?Lj`XhR+bstJ<+L2#cS6;f6k5?hXLI)415 zdDWLOLEmqCXXZ0E&je&qnls(>!hP}AHCk^HpzW%h*(@DP@<@2F@^EhP{zu_{>7}+$ zMu5HZ4-fN?tQXRq^!MEjPTffs-(#Xswzw-}FnwwnPt*-HqfEVzlBu;zma2&OBvz*>@vw$Og9fs8dUsxVOY^;VR+k3cwptG zTKG-BP0GBF3f22zE{n|lLwp&g3*pdju%V++m&in>_hUCWG+W4 zKTV$@JE~{nSG9(ngYE=lMO5w}kqxs-=3flclwsNELsg{7@%chKF?FFu8|CLT{UjPR zG>4o1Es9r-r;^r?jx)h=lu_i*;|=`FolC<-K&FW#l|eK>AGoAK?1)}1LlA8pFBv1g zz~eX`I97U?(@vf4DzR)aSs&iZ89d|CWUz&h?oi=M9!@2V|FgR;R4W(VO4VIn2H+G} z^_vDhx-pbqBZweyr|f{}Dv5gG#o{b&rZ%>ywQqzIZV+}q7RgL$_*eEX3S{qsq|>p+ z>Aq`M0r5hxL@Y+rR1+5r0y8IspB5#g9Z++Sh${l*%_UBr5h9dEjAIC?>wVE!XgyF- zG^}g?Vp`9O{HLc}x9^r?V33wNG~{-Y8G5Wh zq7wdN?Jj$x9p%Z z3F(+(Lp6HVCvgw!O`73eD+DLS3z`NQ2lcG9e&zbpEMKresh$yL0E5^MM5Ca zm-A)qr<|$&my2@$DL+e=ZAALM&(`X@O3o#lv0~t5ZbB=HSIGcy!Vvjo=GjM#FD}a^eVkL;JOO= z!wV`0pZJ>gTA%kTHN2 zslHHvVabB4{?{1qGmA#2Nf;{&d8+iiD&5Af^x6Ih{HcOF7=PU5KOHoi($1jR5#-%^ z(*`2bv0!>g)O_0YRy?c=vakI1(pi7_0Y+IZND(I{f$MJ$HRf78)%#ie&^n6m5AcRG z@P|yr!d_5+pBf$Hy24036`=Y#BrzT1?DLjrNe}$@v(CexGtL3Y&d(FGNz{V^aXg2g z(-AbYLV;*(IJPk=oAj(!YxA(2MF+L^Y0BFEiAekbSMHsneronrU+XTHgaPrznWD82 zf4SFJHgFzWJ)D^!z!`nreooRS6_sL_QO!+sUCCd~Irm`kIZ8yVKKsc`E^qO)1QCL9 zjDYIonnCEqr@(J?N;^sWW&^o{+_$U-wd<3*e2~M!-t`6ML>JVB_Q{giecaLbX(?Fw z{;k=vuk$skhi# zQ7pL2f~apV$S)vcCAEt|WiNurY}sJB7C7i{6AJ}Dfi!$^{r`;4Z@8m>GxH4=`+6;- zMB|4gS0+TT@ZkafOw=bQpo#^zJM+##bpy?&Jn{XIj%DKdTgrF-evzgk(ww3r z_eltH+JXl?zNXTct`+3BF*}f(9KnyWYJUklQrQW0Ulm1FqdpAkIcuW^Q@-KELAv9-;>7z30t)!&<( zzAv)-?vKEug->LPmCJB4ZlXjow1CNiu!4KIKS=lZe$E~9j>@7Wp7lk63t_;uHWc8K zj}pW?cC{m!RFy*@#cm(eqAsIqr21`RUV5zmi8jc9TH6!}Cv;_kGLy3t>raD)3R&X> z5;BxYUL0(ucOjkqUE>V?I1y*1QYc%8YBx-Xoq|tv1$u*Gz3Lv@=k-kOzCj`HvJP$O zeMHye@Lx27e)~v5q=8-tQ6n!n{~hQ;voK-A#m>AhBX%z9Qy*y1V@B>^X>s^6$4}9} zzq0<7d$N7m-FsJk#)K<^p=FCJdT0H2eQl;5Qn#;fYP1Ot!iMfSS9r!%i)!LY6^Qzn zeaO3uDOKu-&3F%ITrKGrVeiohD~Z)?s&lwejR2z7X4Bi?SAR+?Spmy671oDXNGfz5o+tI$g0*eGZ`Pz9 zXW3X@7qExtl{-eWd^T%V9oYBKlZ1w}3qOH{TaIpcd&8a9ai1j5?AiXoo;7==zLBtJXz;6aL0SPym2kdO+09oDYPwX`uVS(^DD3xJ^qxXcU zn0rK0P()YyZ?OVAZhm@m<&vtpIV^0y^olf97n8W9S6;*QQM{Dub+?Z8>R7s$Tt$mD z%4ifP6Yaj`gR3(K_G_jaoOnP?i-1v_S7tRISg5dxr;x56G}?mfU2`b)B26I?ru;7| zsC4OH3h`6q?25YIXB1Ci)saq2m#n>^AbJ^bj~*aRrrj+?Rw8A_Fu}tx#dDTe%~s^B zSf9kP*SP3jD9=lMNif93_D-uP=gWfE7*B8b=PqWUIr7gItGLnj6`GdU5jWGnCe8?n zMWOwdRR850VgXrE6K5D`4%k?Qea8(jFS@K-}GxF-B9 z-P1yQtOZ5idds|xzQ7`t4zES8p`p`tc~2Y*VxcF^QDl%7%x}x8WJtKN5ON=1wqj3c zQW-TW5LgKq43RG`%^>AHVGU%w7{ptoOr&m*#|Vu4-2YiydcaZC*`PKjUk`0tcEwBG zBDRuig16yX$~*xv6nALZWJ80C>kspfzqNnM6bet;2(aQ^V`ARJm7(iWfGQ)7N_l@S9IRQG>zuw0-)&m#B@23VEzH@ z_uP7`vC`D)ryMdH-VN*gp?8rH54*zvArtPiO!3@_0-2@gkai10&ve_Z88(X#qSR;) zSreLa4~E*dHL2mX^Fl$CruSv(ciZ;6XO3em7NpX=I2hf8Ll5!9L|3JXwXaOe1>PR; z`B17Vk%h_^C`xAEge?YnmA4DQ)?1}~C- z`xYzqHFMx!Jvjsk8Dmq*JK-#~sSV%wtni1yKn{611LH}3WxP8_mVth3-Vsy_S)0ts z`75M&9kZmR6S<*0~#h9S_Ud5J5H>Kg`E2j_VD z(l0C=ha_TeE}#9?MZ4&S7xH3wzBvB0OWIeePFtzn(q^o4c!Zpjf?-L1 zjKl%j z*i8;qs?tl6s9%vN_iSbngEVx#O~o`Xqpa{moo(T*jv1eq*z~W4IPw0qxQ|xi7M*L( zSGcZuqKX#p)EN%Gr5y|Kn8~b^(!hVpwIV!V;9dVHH|p+17cEDdhTRxe^Rk|*w^8sJ zi%crePUT|J<#$johrO`JB7x%$S~H) z9qpmA>FrYKv8aYaC>&H3WB(IXe;Lqb(?tuQSdrq;BE^FjclRJ|ks`$%g1fsHf)m`K z(Bc~0rMQ;jZpGalZg{_Q&$;)1o+QuA-fOQlGkZ<>*rI8|yFrB7c};XlW#ptt z6b@w%!>Bp8KixVzv|{Dg6rX@(#T^6UQSufW=v2MjV?_p)V|yd~8(e2&43krlC=U{Tz;;e0p{qNiPo5f8kt#=t5kb^4ScZ`-G-Fkpk-A^N7!wW0YB0X(;Co znWDrT7H@?;RR7-;;SA#BI0%C==<%^oileTge8{mlqXq!RQru|pp}zq(S`8lyPVX?% z;;W~kjzbt1y@AbgS?)0mMyAkdYrRp$*WlZr5@IXR#gmHr^6#f-EbbeGC>uaOM=;hE zJ`M7Z_fP17c;R&`U~dZ36yl$h1yr5v)}ciw-y;d8`+v&SbH2`xYOOzzJ)2tD6Y0;x zKK}eg!+jM)dDo9k;8OYKhJcz__O~=MH!;lkVrE=}ol^VC{S^T~%cu=74NjE8Yo$)$ zMG2Nysn@%*G&Oy*BVB%SIRskd_w}jd#s0+mCLbe3W&3b{NC%7vj2N$RrZ&tOM`|DL z3#?MqTR8Z4Xpbne8c z((hmXrg%QZ=>XG`IeZa?i7SEqNU=ybCTC^|{FF0+)%R%;qi)?h>pTmP&3!laT|OA1 zVn0QgDjOWv@lu|CxLQloz*f%b;yRn&#=7mp9KCmn(zucqrv53jx-Q&5<0_z;eQih} zbDorZ{?l@^A1GWv+tcFzLAbC?Fk29hFCAAD0N>%g=6E zGx^1LqJ4YeqD~&8fo+Fepm`4K$$cKK!Drg|v@yzf>$AnieohGRASjp9Ke8LYkF+1v z5Sc^*Kq{4MBlE8o(Ufnd;5;h^zxW$p496}+x~Kw|0QBpB6NUQqjF~FK(Ox7N86KJ5 z(SABmP}LuDW$p#fF$ybkQTHlr5CJ2Hq7|@lwn&c945h4y5MAEGLd4F*)$Q1S8akH( zB9E+eNdf%~U;>{>Rl61V$#iV-_dkdk{LM_Jw=laA5*82WWWrStBi8!#n7kI(9y{%4 zQ6+XMl9kqw9Qa2}rsE);EC-x`9C!DQQxj(L^56}ji0#!+62&};NeYB&*I39|8xT60f6XcBX zbzoCDq{824X;>39A~VtAx&jpr{89N%ts@DPUHZ81a~!{B9bn4^Z_oLxFh^1+eSU(b zwAom&yd}0JEq4MISfBlB4u#3cn16sbJ)dqc?g$;Ph@o9eVn|$Wk}k|pT!{OY0J4^6 zFO$A9#cv$djV~B9q`|qAf>e3;qE{#0r1@pAr)Ah6WsF|U{soM(W|Z)MFE-~R?_Hw2 zB*`(cK&q5KImJbC7QSy9W0L2kKuHU;h!Sy@NH;y^LDlP_Zd6QFTFKU5Uh5OmJ?`Ko z$vWR{`Zk=l3~EOn_S=`=w}dD2v;r}+_GlGoQ@v+V?9`O+=1qMv+7m4BK^t`U3bTed z6i**j=~(k}EKSV_(erdMJ4he16^6M2vKXr~xRXOXsYsMW(qYSLU5 z)mg;Wo!m|}q%3>IrP)?ulE;V3vJh|;4oci;JzKIuZ2U?}ozGmL|IliO7(AQ)KY11V zDzBj1;#sOvh8e22aqqEWHs2QhP7BAQ5&%G{{`PpmWfEDlE)7Gd1ZUVCDmWA0D=MqM zLm8`(6q$T~AV#8q`&Kt(+%Wi0UPagfOdv4*pn#0DsiJ_5Op!}ae*O)R&?{l84%G+db1k z{P%Igg76D21lD`vegXX#Gi~x}CTQ?2b9dXJMgM+-eA5&?Z(%~laah;@>)#IP)n7{g zsNXyre@<>^FYvr;-6ojka9!1UdX+~&PS-9Z+bL<&iz56R9lhp`+YFvBj&GL6o_0E> zEEDlTCFr5f10^wQOh(^xsN)!vbSOuV8vZdQ5x2^;kXS_qi*mreg&hyVypLX(vP_PU zy2HVX{uUzd%Y#^_Y#^#?zRz$Q>0C$PqfpOr;_LY zCe#(qAU`3ZCF4bA%mAgiOqryI)dt6|3#s+j*jC`@+TwS}I}$O1g{M@iAq07!6F0qa zO^LteNuRaNU`TW(Zl*?uvoXeFF7vqtGDkqeiuT$EFP&DW;1K}$jCno-;ewpfGv*RB zt%Ca7`dnoCbP0iB_bRLV4034QrJ^9XduHJHYd&=V((c)FYf$Z`e#x`n2!r!?LQYB3 zvY}kzKabn)(c|~*5#Oc-QVEu71i#N=>~{~J3hj)D8v5hVKF&vMWB%V#nz#W#3*__m zbAijDn28m^({yu_d2Rz^PWy)MQc>fCt zm4|D6U~|RC=XHC)2S*-+1`nmfjq)Sh#f*d950St>Gp^EU%>Q?8TyY2a3yE||iu%_+ zG_9BM*Ek643veDF<0u3T;Czdt$l*YG?|DYNc?yicH7O{g)Fz0DElvj4T4p1kO96SM zq2J`*LMZ`@y7nW6UEbB;7O>}GIye_k#uUByfPo&YxU&EP9D}iNqXtzXEpjbuSH_c{@iE29cGS`nc{YT=H~ATy z(@luvlAZ=Ec-%wxEo^5)UggwuNF=ftR#Y*&Oo;gev4Nw;9ZYR@t^}R*)cO`+g}?Vn zrc5sb0A!{ZvG82ynPZEwb%Tkz#d8L0OTdZV+ip%E-UbofraR;YT z;4*h$xiWhrT*4MOV^)x6&hBPxP~46@>bxhMS1A8?K;^Oo^LEK`;hQPR#%F|3TuSww zQO^G@@2x`sTG$X~RHn21rT~vJqxWOsh*IgOI=EyTKYJ zu_Y33KYN<896QPo+N>h$f0N)O33fS2{|A)$qpoB7ZC1nih5|C18Z%E*v_JSFl>aP; zt;{7C##}cbEU6erxl?+;z$6V#nuwL_t98Dac!w~FoQEYJczIZCjfkbnAT{Sise?*@@! zSTpi6≫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 ^wLu9v1*W)TyezK6}rB_ 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

    _bYOd;n!V`Z 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≦H@ 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

    lc7tTl|!csE~I82=diwT?hW7y%SA9P%BJZKZ)d zvF_QsZa)`yoO{jRlAR8N%UVu$3Yg-qkD~+cRYg{C%3V8VC*$AWByu?b)h{LAulj^h1M88)=T~RtDIZyG28gD zEY0cu;mLWkgePM6T0gvnW!3EzLD`_5?kSRP+iOj87NvFkSnp z#sNT`EOb=@6DPWtuy&LJK|G9BkV^|XApVcV;%hj4*Ou{}VE&qDWUzf|m6z1^E+aCF zPR0_P{xnI7!4au^gbWCzO`_XMo`__@1?zSvxZxVWs)6^@X`FPr*KGG=U13ic(aJ`I z?&v3a-et|e*XbRv?ts^boUL@;jW@jW8sqxtBZ6syA?73#WpDaD3*n}26>Upr6TqwX zV>iMiq`q=OTX~tLL)u?4^(-%cHB2vohj;r|ER$?js{{LHx>^+Rp}0G%2BS7!(`H2L z1*iu9^2uaBa5}I6WlJTsd5wmu0 zzcMOPvwd-PTx+(Df80AXXOxTMX*aqZfK)z8Mp=@h@cqwZn#$c!DxX=|+9pd3oA#Z3 zpl(WjI$y6eR1ORtyG%AyVJy~Gps{8?fodzG`vcCJIN)}f_du-4&?qDDtP!4|B-pEY z3nt?;0>-3j6{*xqzMj`Qq4Ik>&U9b5em-ixh>+Q$HsmXtLb3E$ zAd&U)78rqC6U^8%Dwn{u&J6NK^3|_h`QE(AQhyISS|B=3=+KzFzeRj&m0(;oR!67Q zJ_QwA-L!>gzbrt6?v25x^~%;D^rkHf@!>F*gzCdmMF^nrQ)Eb`raB*ty9pX#&pt$3 zYujsoZ7_Km6V`O5SF;gHUzq8IZi{;SR2;2Dm$Mwi_AH0#i>|17w7lqyX-}2&$RVTV zC}!VxFo@`de|k3R0q7Ak4pZ`SE)93Q>jDh(zIa3VP%J5Sq80tI(|$T(f7#Bc3D#UP z)^!F!cIn&|3P8Q|2LN$c8`M29GVDg9L|<&j0&c0=jryIz5a*LIP{BykiC~=68}HkV z&nIs>)x~f+q03;h0@!aKV)zs9uFsJ??)Oy4VHKv;ZsnkPSk}twswuvkx0fz8<-NPOmG zRieZ>iLSzSO+G3I%~uz1Ue{Q3rgQeQ5!IHSWHsJbgLTHqp0B6fCzHApml8j5{QBZ} zzuh`Hj$;Lwz7oZ5N@^^&glTgJWb;j)=@Xcs$O@p*GpWDLQv_GFoSvMwevVmgKENg8 z($}5Lc%esoX6z%t#5^#|YotJ!SY7wTmz>Z#Ij~`fnJ{ENexZ2AM=j3z4wK+`P*VPj z-HXAY8xHWvI36b-Lb`!vxdL{~wRTrvO7u6qdr&ikFv6a&{Ro#KrUyi)kCFegW?Y zWSJP{)6PvYrHB?3_mK?WX$o*JC7VHeyS9|&flCUbv@!;g%5m3iEEK%|HsxugCa`uYBgiuek!3|<~vj{7DIm-t_tzC2lu~^u8CG2p( z!zj}C+&M6$;i(F5^4=@yEFNaue|{xfWp#jcnfXfOW#)zz^Mi8sg-*ZK&$0-%IPQx* zKs;wcg7>K$ID2kdZEL%TGHBq3D-CWOy#|@X`Q( zK!Cq?6wyId#dhstI?^Rjq^pDpy`f-M=y`?fK*EN*9$oM=`eBhJfH(w{CZVX)nxS7J zAByj+eO7#G+Q437f{~{Y>Nhpw<3x`e@~-ZOfo*O;QR#`{X!wPr3!e}eG|mCY8+dhz zCVUZh{aCZ^FioYtn(K`Q_gP>K8qNl${ir2^BMMwoP__2_;-`6o(U5G(#JYc<(e78= z$pCsnX4=Wq(V)Az9Z$)k!Y(eP1siUImpE!yfi!2jwZS0YUFI9Oz{0zRM!c&MIm%2> zADLtrIxHm9z|fdu$YbFdVm#S-Q87+0Ry#q0oO&zpXo^%zG41HWT<>XpYF;T-SL#v zb#7Ex;mX|Az36o8czk9&@(iaL@!)uw{D93)Vq71d#6HxFRZg3Ky9ND{@1xm|xN|J) zN0qbt(ONM3G0(F;yDA+6OqfB2pyPrV1hUq;J;Apal&F zs)gXRX(EHugNtc{K-leYF=11isAU*4nDI}sVE}bO_G%<>mN>`hGx2+|bP_VMG(#x5 z=S4B-CW>v8u~bb+^4nTS;UCvx3l3{#Du5V zf=6Chdo8Po>2WUN+b)n5lq^-vcdyV6C18f4S)uqY)eZS5M1Q|WYZbtzLSrvs=wqlf zT+DUh;>xz?_6Qdy12*SK)~`R9wT#{*K6KsbKgu*08f~!2#zc*3*uK5B;?VV8E89_u zKHR3OntXGMO2%z13owh>YD-O#hc;6J7;6K(Qg;7@8hbkk&Vvs#X2%5(X>d_?95SSl zf{;3DU&Z<|U6VWgw;b4j=&)?ov!=u3L}pQe1)ovVCq)AGn=YS|brsE4Aai$GMDl9b(}VL8|^WAQT*l`0kdH`Y73zuF4e1__aDV_6`mjI^1;2 zr5lsYYevHdN)|PQWO~YafUnimDoiQ0NNLi|jq{3RIL}7A#0;2qU)^U!^ z?ip>QMk|DRW3*ItuEFWl=?}mm`H3!2*$l;D9O}euaTDl0aNQf`BiUQ)jP$M&XVJJ7 zblI@3as%sHsE4=(_e3xZ?LtGS)>zhbYBCzYo`;Bwo<1G8>zA!OIhw({HFpux)+bi` zV_M2@_0|1u4Xt_2-J{6*O0TPa8B9rhd^e2Z8{P;53q|%hM1|)aOGwVV*u47Jx_u|+ zj%2ECEHtGFe)x@}_!+MHtBFsYQGN8@XgNn0uIDaQH24S@rI6UKf6$1ZY{WF_C3Jtq zycTEy`wjXOEz|C8pH7s*Ty4reCANIaT#@3;WA~w1wI~6)pitf7w;R=J38reVA<_`p ziwLP;pizx}N80Dx9v09y#xmPhj-*QFk_I&gZ6+(MOiP&$Jjv3!u~EP_$-Z0b)GaK> zZWb)Ede&A*Xh^snI|DK`hi_ftLtvH*p)su7Oxb-=b4-1@l_{o@WH?Txks`NI-0?QB zsPUx%K#>8afsF+$`tk<+_ft4DzvO&76 zm53T%TbdFt$@$D!%FR`*Tca`meQz5R#W{VdLG32YfTmm>s$Fm3zaGg?@GgmM{lMpw zvH1BfWGCQ(K|5tIjqJE4dvl^F{*g>K0yZ0AlZ_IK4R&I58g1xTp&F7LFg~fthW89? z+h>?VVN$dQIu8f3j55C1Wc;VvWRS|ek5<=dG$a>UZbt@dR*!nzI))9i9Yr-#xSbsw zpPU^D=bN*GS9`|?;#ccfbIQ?Nb?QcYCl_sMkhS;Incl)rXL{=x^*hu`^Jg8Z)3a9H zko9mkW2ddH;FiZ_J6KOl2;aoC-R=jFZpx~tD% zs2_AY`XLf1zs(`Y+3Kfg6E&a-}MzZ#-LElI- znySJapGylmaeF)BL|fjIg&nsmgTB3eF|sZ1N=L0tg8JDNbCpV={H8P9f-^U#HU1=8 z;a_xO5%0nwJWQ!oi!2V+VAH$-O6*1}(b0K~!R^ms6VYGJ@a=k3yAZF}Wl1O40beKT zWL>@zj0Gc6B{ikS$la3)UxZ8$29z`GpSS*}i5jGTZG2P*6lU$h1VFLf3T(%t%y&NF z_s<*haPl%z9aM7@=Mnq{V;BT*6wHLm1W<9eZwYY4ryG6FQ3%oQ{cHh6PVBdaV56qg zb`zLy2)wy@Vn5-(AdWBxCYp!8WAF_z7VYx%vBpmx>udh8T1$loBd&r4DUeOLBtOM~ zHB$4QnK)VSQxji~s-!vqa*4o}MFdHTgIN&>yk~Yc(9iIy5si8|Wa8q;+M~QxN;>zc z6SQc2fKp~aAu$Yx`W5&i7Na-hj2epZX2)LxEBI@;6KHpYOhB~E8dAE&l7 z=3*-ZzGu8Ci#}>A-hJw$4Tl>)uK7CQAxB>wp6vfn4|c)}|GKM{)=VT|Vcd=`YbI;b zv&01TH6f$d3VIwLkjBYce@A*9T?tBdDcT%b^3hca-BL;u@x-})zy*L)=qigzRVGOY zb*$Z+SUbV{6TpOOETAL9l7`|+t)dD_WSU(S58Mn=qVQg=l@eVvnE>dq^UD+~A-q+h zfqUs#iY8uY@huW&Ca@YlB3ecT1WZeEH~PQ!GK1*{SYAjNEH%$#rRI@Mi?ye*KzuC3 z5Dn?L6a3bR>%M#*L$!*#GEi)sd;oc3lwCQg5XlqYxM9wQNitz^GD+VR zZ3->CCT2w6`XR6-L%dBf8&tB;j9%2N{#GKc0Xx#eMu9AH#6yVE>S5VE$qEt!)Nof9 z@-T`RDP*=uqw7IfBPVJnH=!&;@IOj%qTE*}X% z32!fV%Mlz@CGDM_Ml5$9NYP0){wilDkgxc;9EjnoXoQKwu960ebPo9ICec4;a2~rI z0N)!&Un7!%uVrhd_Q@R>hn>%-pEAv9b@Z_r8X&@%n09pn(4bU@j76khkr@$~5z4ZL zgowvz(`bpc&dqk{K{~=PGi)VLrYurnaw;k7-P?~j5>f=QXu87Unt4BrFc%{)st4NT zZEAR^m$ZIkHqUh*1CZOh(F*)wV}dVT6`FLeUNVrhYa+3#vK(jQxSaLnIED#Fr4c!K z?!FMiz9GT$>)sSm#|iiTUFGQl19QC<^p62DHr(kU(D*O2NQB0qN&F4p${<%cXV|N1 zIzmR_T-T=)y`fzj_oTv3VMHrI)WwSI>I7#OxiLCokF1Vh>X@q1m}RR_o|+KTBQ1Xj z*U)@9>is)^s-FM4`Eaqr-=E6Pf7=^dUw`eK|2Cg(eL4SqhR>Jt-@kJ*J|E3f-#2P4N^Ko8Ye{bhrgt- z9!Wk)FgLs|ww^(xO|C5THW`C@p(igTgO`+N(ZOU$_Mp9RqU{Grj^0IB{a88T1ZNsd&(UIu5u zC-y%OLgt#tY|)9#KJ!F&Lo+%1kDW>KZHC#x$u#(;o+sAHF%mvTuGr^DXq#nxUSWTB zqh(L%tjjy-MrN3;1Hhu*j&Am)(-j6LVn1URtVKaf<^m1xPGU}UCF8kA;n^VjpPfJf zWYkaq5fUo0rHTN~OoJR8Ty{5RQ&S^c&}7zaC6YdUazFVun?5nF|A6U3Zs?yqGPp#} zB69x_YiV%(5d6I942{WzN59j#1js(`RAK?bUBO&p8IIIYsb_4)8LmTxp36cHKo!}d zRH5q*UE25^l1BE2Cyj0;+L+y&HZby^MHUZ32bI%%>D~oipW?X!k!uLBY2I{ZZ{R@r zAmsqXp!iUH*s@vcy?N>H1W{L?08yp{=#d#%V;XAk!S50`N`2rWhmAsjUO+VeCb&>K zib}W$ob))b^PTcorH47s1P*Fd1Kf&p8l1xTwLA}*71D83J2+`KxaJ03?LPN6*?yt0 zvHQ{x9(?Cz2q@WoRd}M{<||OKz?Nx}Fw4kVK*3C|f-e1I+L>=%t1ukoV@^8HcyyV5 zFf4pcU*fr_!C1{MO^60NJ~TC=v(x<;M|alT-@}kzXjU>CW4;>U*f8#)sRr4U490`( z+REQ(2aENre}-`*U-knjCzIYMR8MBtv%Htyj_*w?Sm-*v^_JTFx2LE%iA7=^k2Zj{ z0-~{_C6d9-!>YLv2p`SRAKmYaL(PJ62*3lIg~|zSALf2n$1wu)lbpovc_0=P53P;S#}-mGAMGD&m2&vqb;>nEVo<-QHOOFo@Ku>wN!i!QKU8jC}~ zIEk%mVvY8D8Kd`xZ(U4TUKTMOqO9=k#IykeOaPO{&^Q@A!MJ#(aG{;T#`1hv&`K^m z&V$v{A|T+czdG6TdMeU$!8mwgc;PPD{^hh;Gb>2xpYnCfg8Qc`U9=DIybG|6lYGzz z3j7d&-z>CK-e71nWH;HlgQI?v+)9Q1ohX!_lPl^YH(DYK9lFHXL5?H%%Yzp{tLn8>a> zAb!XFLNRt8y^krqg?4(8BHR$|V)*K8;~6;; ziGVdm)a$v#4W$U>0vmAQPTcQ|2E#igHt{IhCRbA&O?ME7Wf6TBVUmaV;LX|IQS^fS zIB%ad_m22FQux!g&_W^0l(8EcqGW}tx@4+gYLR8HfHX6ek9grG^)XQ?$`vBir3AIT zdgwv4=?wNEXhR<|rxP{WMJdKFHK7Q9rJabpO<_H^ z?SLr)2w2yRXjALpV>w@7XJh0f8mpC~3aZ-ONsx7d3!Kx%J*^0R9+AI?HO@x&`?e+Y zmwLu~(vE}oxC#Zi3PZ=ur`r{^=2Gv@tKGF$sKrCH;5$JTj{x)EZ-Zh3`y=d2N>(bM zPB99Pge1J_S8ee{lOVM?1-u1yFStuV&ri=z-k|fC!Sd%mONmbKxe?lr#8H0&3KkmO z-XM&`hl)je^QWz^fOHE7MqvHqEr_Bi(y#c24tsbvFDQ^}ae1r-3Z!tEh`-tLJ zv^q^YJvw-+YstP5ki(a!ah_XhC*FUhUDTXp@d*YmBN0N^Dkxq*y;@^1nH2Qvu6-kG z8%CLFo{G;8`WZy#m-poSTgZyb&8270opC4Xxdr_XnMY-^;Y_7&Oz=CIPgvXC>vYgf zBGMz!!lgr>Z=Gg?@fEs$itELKP0Y4QT+}4dIQu-jO(MHi_Dqz=8WB)Mn87Us@2Y|< z562B(J2@q4^>amZroNmFhU6uUTWJYnd^nt&azeDyolV)-ouX3gkDhW^CZtpc_0Opx zltz@j$W#cWQ;uo; znx?Y}pG^M4+c3Qn0eyVI__bo9YmD7&hvyftyT#2MVnhK{7WkPQw9UpfZK_8JL{$_X zK7^-5?=_@wHAdhFD8}4bbLc8h75h=&40g0(#N%<+4^Gf%Fy<#ldT5DA71G6N@31Yt zCfRaU(_FAr7szQy`ik;k%$}%X7|n+mEOjGdB3r@4K1C2_Iqzn3g~6EJIhKQ;FF3Qe z^Wq@QHf@=>*UkxZ1oYLC<2g&vlVI2AQqh)5t!A_kWMiVHVfIOs!?H6~w-ptYY~VGz zSIa{o(9Fpq3X82jnO>zmSe_V$!@s42NPu^dRDy5ngLK@0vro5!aZ`|-S)kyFVq+c}=y)jw~=|p^56_)*Nu>+^3 zA70F_ob?o1Z{}4Rjc=nKJT!5ewSr@lX743V$CioL@8wh^><~R-uClaac;LhSP0mE+ z2*sVVm-M6A7&x({jF|m&6mgPr=vikc^gbSpk&_m^--h?w;utTV=O)8^sFRp#U(=47 z`eSbJ!4sO}6G1@#k*ByKS41SGn!`)#%ZwE)2d>p^JB-{Uk(X`Fn1JC-yS_xP!T}Rm<2gik5vdeH$fo`6Heh!}D)VzYfZ8aFmRa zAqbYi@#-}{J}RGkF%ozFccXzlq@aP15E$UVH-d2{QwEHtef7dUZ+phw1*1MZIfe#^ zdr3$Jl6LntEhx(t)52UJ$|Km!G1E4WP?PJ?4mhzF(mCTbmux49c~ovW(ZDtC&We_c z>~88cC%8h&eYkCmo2GGc3_jO*-8|r-rN3Hc$$kY8Jf9ncaFFJZENX+JL~R!;<^A)? zwev=X@v26X%gah55X>INHA;+8dp1_De%up9z{_roHuOu4Py-$;>)sn)*^|z5!SUs@ z33S>Y41u2kMkHwA8r3jjo;5O?aTTM&5v|?&9!wZU4xfeODzdZc!j;3_P;GU;bCs9v zDPtF#?^Oy0qB-rB@C|;M?2p=0a!(s*(&H4ZhhoRXh{O{s#bPJ;^n8cAYJfYcnC8-~ z7ZZ>5lBo>tZj{t6YpEPgreOhI z{;6zqGD|cpS1c}UqEn(KLli%tWFis05IXL!pt9$;TqG)-=ATY34iA{>_EW2Z=LTAz zm zcPp}bD{^r$ueah=7c+Z1c6l+kw?l}3NksBVK2`I74AOM} zeaZjv89ra~f2sXTaV=^7wtmoZHj9)_Ual0R7SN`OVC8<0@ znL#-F^1VW7%zQzS#-^Aye9lxL;@_O5{8(R!GC(bkEE-H;)1G#&YIP#s!DO5NgcC&n zG8*wjiyinj%m))#IzXp?MYXcXKG`~rU!U#0iH~2u(#622Rucklv;BR1)V_#TqtjOx zujAHfJz9_cT9++c9Gu2SKwF;y{=Nx?+=^D^+#I&&r!h^pC2E@=dJ%~#z%WU zQ|*lpui*ogTC9#yUDe($t-T$tZda`_-JetoqE-;j0Iky>w`;;A43)e!ZUXk5AAlF$ zQMujz_eJxf2>?l`Yu@IbN))d~n}~e=(`^v=!RbXiKE62OQ?R+Mp&D-&e5Foazdk(K zJBZsq$L;eIoNJo5bEl#WZ{>>m)DT?W7FVb|4a{j_@AMQ-o-t0OY5`I5@+IIzl|O6l z{}?xaZe!v7z5VY+w|^}t!5XbSHvrI%CIbw7lJRqr$UIo%_m{KYgeA(Wdt$S&)0iGd zy4T4&p=5-n&6(#DP&(wPeq_p1r8l5Hacml}7??5ytI&-528j$3{f>gev~xRROhbP< z$v`j2!7HJ%d)=89qB1ai>|l}MV?7*x0bFGe6=$0CgvaPl(~)r!#s}emiWsLvM2@Td+ zed$SZ#oBGLTd!whZ}L0DT?HKIN+%IoHbceFY~1yZLOKh>6d>@7bkTC#BxcPt)H_+QZRt}5 z5@I?Y-bKI^B1+H-eL{I$`1rNKWXIcdHta<>8nS?6${s2@PHqu3aKia}wx%1f)7s$E z!m_{`Gi6Xg7+R24ENEeW@c~-gwY9`dO}4*h)Lz#OPV8XbVI&%f>XSQ3lJ~@Mi)d7_ zCo$79BXK-=pJ#8q;tIDGQk7@06Nuo42ryc>kSB1D%*>wx)Fy>k1-^}Hez}N*C-+*` z&|-^J@zYtNm&A58X4y-qzxZ-C&GH(KU5v5em&vS~2Wk$@(Tv%#yd5i(6n>aJm$KvX z8Ewga#C#0iK?RppY47X6?t`XHidvIVJelROTE~~O;d_f~sCF9&ogRY5ox{~#8iAi* z(k%dsWDQ4MjKUHmN^A48TY<#MriQmqZtm!G~C3U+ssvB z&4YD4#t6V9$b@1Laa?_hSVAD zv%TYUw6$xny7UjdIXyW!)Fz%a7QHkr=eRP4*7-CUr8h}@4RT{Lt=0A2YXXGdxf`Y( zGy<#%_*UxL^QSVk5nBzidPUZa@@Vc$J1QVV?G!q_-sVs7gKhssx41g;2hbq z5Qq4%RDBvw-g%!Oniz)F(SuJif$9(su_HBgjP058Cz0=|+2#R2;hCUR(2UA{`<_{HaL54>o@9*x3<9(>V&dur2`Nbex!4 z$DoSb)Dl#pSxb{V$5nt&?YaU(>vp==%;;J>_=%J0vhGDI^f5w)hvRH|`S%^S*@^K? zSFG|iL+W0T!)5m*+>(rMd9<;^mjR|Gj8Eor*z@+N(%0$1jo>Aj-PM}MCr8aAH`>XD zsT|QLPm`3H4H}i;T4kU$V;93916OfVRwe_ zVsWd@$~mZC=2~qyEi|N=4^aCpP!WYCEImSQETK*L-aZ4J1Ei@6ydWnGfKVy|&+&TY|b7_mp?;BV^+n zWepmu91r<cdSfLOhiI098hh+;R0nN9W5*ql9s>U2WnUNQ~_-%Dqu-W3r+;BBY z!;gJv@M7GQ^t{3#Eha|>wgprbnAO0wM+PB0d$)YayEooh1D#t6kofSqB(uxuPOcVu zpldbXiW3;3zMRHYDe;?Y{n=W?_j)q)!^~JFbt0x}^0wyuO?-56)~q|^y`VrtGxdpu z8vHCE*obOg;l?|4YO9!K*J`iO*6GIuq#|wQ>B5o8#I-PP+(g6@k{-yiX<_Ndki39I z4el@QjXC!(kWe@dXd^vnzPfnxx`xPXw$Is5n9ijq8DVty2^Z(-3l3`c$ui3-d-ixcNh$0e?O@qrhjzhN^Q{ zmf_Vo%y>dUDs$ecNYiMTj<13TF5nN?%Y0CJ7TLEvrA_nr zfG&vl4i8U$;!B)5s9VdjOib2c6!E0@4qin6TAR@OHLh0PeKPy#-*WL|Zo7=k3!(se z+ZgCjpaxn0B~Q)T1F7<^*R2!6LkqN}<|@lI3$}WJtc!DFiMhlU^UwiOuCu4Rmi?>V zqxYesN%DV7SVb+K0sw!HEHrJwTG92(jJ{|ngr)8A(2K~E;qj^oQv9-p`7sqKY z5qbuyh{tTSW+bAe;HUTo4Kwum>I5wq0-o9e^K0C0wb7f5*-v5)U}o_VeI*=BzKR~} ztpf*S$3YgJD#5&G@?%dHaC>5XlV9!NR*3$csr*UkGr#(W`R#P?z<`dA^ zC(O9wn5xwL48c}FSYy|>XD=P%&NRY$qrue_mk2+QL2*aPU`8AueC`T-M&IefdjUJC zYrrjehVYrFkm{>?To)0cDj1r;n{39sUNQG+Zyl9NllFU^#ruvQ{+I^~C(FL~Jp~I4kCD{gM&@vj(>rOPxG%@v<-xI@|l_@m9CZL;nfJa^#c-9^d8n>->#VsEna zSF}aN^3rNP1r`kXq4ZaTy@2{k^O)-1FiugZBK7KjKZy>EqnINX3zsO*Rbdr!$0r?K z!TQ9d5ImfPT#OhFxR23X`h>InA3gdX8<2@Y4@5-tIND1<#B>zl%0OLeo=l;XD*rbZh7jEU9rv{oGh!yG>O^Jvr z++K?R+_6i4Ix{Ilz&35A7GM5zTP`im8Wpx8TxcC%7^SZjGUl-?8rI((7L{5+l0DpBgAlUlg(BveJ58W$ToR}z< zSAPI3RvKMhCVdR0CM|}d$B*U3gP+@)+@cBx_e`)xTC7)(rrvMOL;*T{`gy-IDJh&- z(4H$eOoL#_3|VWE=cYHwlyo|X%Aiw_d`u3~fr!C4FF8FwLmE&fS zj=Kq4^>lzk{b=+I*v6HLr9mVufQg=%em!W1VT{W$2~a@r2mHqRW61`{vFG33?zgk) z*9_WBS=ubRH%upY+U2`{o!N`q%USi-)H0el+iEp4?1_(#wV~jhxQ7%S*fnPEjg?H+ zqpAV>tY!_$JhC{QS+{wPu{Tx&Ve^fG0r3pSNH1?=k6UT z?7=JzP2j~V$|l85n%b<^#H+enIN($9#cI)G59okG=q9hB1}NsJ*)~M9MRV^!s_e9)9Y?w zW#85&QAcM!8+Rhml?|ffi4)qQZLHbRPi@m1vzef-qGYbjZQY(Jfq2O+%wBC)=_gSa zlRjE=H^4Bt_{&PJAQiE{p{XwZ>oLLQY{7W+!nVcLrB9q!oKb$WEk)3x;9N}3(zG%B zTv!yFQXa=b(W$gcEaTSJGzs!K9x3I~nVuIJ4V$NR zZZ0fO>l|(RVO>|BRj@MF&g3rKx`-y*{nl5|;?0Ie4W*laR)#!Gu~2|byVc%t_U2m# zBikZTf?_pM;Mgb%iK{r5Uuo8;6}5;O#k<*zd|R7;Js}?bt2Q*CupzbvK(#Z0ZD1`% zyZdBTPO4s`9ZBrjpc(eHMQpGWQvrZXDO32QHM}tXq|K~ z*WjHokY%S2jTU8VlW8*POv~ERnzAk(>8v@C`)~&n4{0$Y`Go|Y(@A&TD7wgKIBFwm zJru^^9}U>ss-K<%2jYLgcLg68&<))w7wC-o-;z#lc^RsEramOu{eyU3!xxRqGN3nF z@W_rw&7=L(Uwq+x8qq&wFhEnPvlwKt+~x361EOyuHk2S2HDeh5qYx0nm}x&w^y)LL zq8ZcU1O0<<^I9yV|*U>3?=53GN_eVN90zNAMxC8N}?}^JY-6O z|Ehuv@Q^SWHgFUn=kFVFzIt5wPi_PmvUPOg!E1u5WCHVO*Z#mdwcp;5%8L42co-H5 z2sM*AM)Q8jW*%EnPqSXrQN8U?WsF`26A(Wiq7P1DI0{|62ZHTkqCp!@AGf1ihxR+2v@EtCUKP=O@X(nmZ9HCNq>Y z(9!|mHM>m z#||#UlLXJvB=Izd&#LUYs^4nG15b5%9h-7f#-PA!MFyc!3U?MEVBrqOk*}@#4OQ7F zJ)87!Pjf3UlH7UZM~Oy;)qGJENmO-4H5W(N2E(SUoku#%m3&IYeA&Zw{YnkTQWq_H zL`yGgkgNdN(oe?+lu}0^yTECfV@g){xttm+lpIh0f(MyC-Y*2WAzmm1yi=VuTs=V? z%uf*q*5>a1POS>vv=+YQcM-a2p1r)xB`lC_QE9*}wjo90_A{dD|zoXacJW3YTOI#xIj`_E+{VwT2;>Aa&-ZYBftncE0l6XAzR8>c#|MXa0MPA z;E3^7W5HM!inRLb4k3dh`0W_hU-uTRK8FL?NH|p)cEKe=P=Am`ot#Xwjf94DAhue5 zsa?Y3P`jN;r#r~+=+YMW@ngwiG0^cX=aue)bFY&>!4wgHDvIHwkIXR$nfzmEZRL+XyoAJxQzJneG+ zKcvrqbJHw^JHw%)q4{@^*oLCtCB^Y(b5`|k)o%}Om=qVACj014d<^>1P27B!m{z+s z7~X3RB^0oQ4XCJO!mN|@uNs*1L`V#ZL{+b$$}hE)XC^>%@WcR27A9qO(V z;9i{@kWxCAFyR@9k%=zpn=uJNveX`+WAS}$m_6%&;78gy4r)AbKXh90&yuTexpEXqOSO$fJegc;V=Ybm`=HEL0anC)z7KV?1 z%;vw-$BWJU4zDXaM)O>Hy&M1wXG$!u97K?~P5I&|iyWC^@nVJ~BdWfhG*cGZKUJ}E zF#xS&2Y_2991Zout+-7Xq;Qs9v+c^5SBW_d)-9#QN4Q!t+91<9#5r**WzG`1Zsr?3 z-XZdStvk!pL*!dtsls5}54_Oq8}T4%8kX&dg?}Jgo@+EFaRmq%M=7uw@;eakckNjz zA>v-r@63kz3ul6KrLk7tjQqg2D~}zl+HesMV!!o8^$Z>U7T7%r#bN;BD8?6>h%rbD z2!*>E3n@o1=+ojHFPvRV4|}2E#A6h(cQV%Ki;DiNND7J+xk`%PsZwK!r zSMRztNNUKL^am&Z^Z}a zXM>-OQLzMWl27TWvC2*d3n#`}=y;I-p5*;?a@c-BIU{eQe&LJbLHN{Ad?G?yAV^Eu;>d6ffz zRH-a3@mD~vmXObX$nhnK{6k^dvmx6EsEle4ySGgl3YdLf!s>OI)HERZM3SiqJ%5PQ zkn4vybzi|XyF$;eUJrg}td|W;CP7uwwYKF4rE9Eg^JaYxwW};WR#x!n5&JAProVtAt~P3rXPah#c|g5G!i3zaMJ(xq0~<* zRHz-el3<}NpXfXJ>qUvcL5l6d8z&)O@NT?{6e%rkSh|s5zl@429BKXC^CNMf^NpgO z5%S7+Y;z6XryMGj^yWO$&w&a9loE7wdN+P~lilvEz#j$#eCdvz2ub#3pP`kHBIBaK zRmyLeFYpS0RU#b%Fog4VyuWweu9+}3@JrpPi)|9iL_p2AzI%(JI}7u^BGPoWE-j$M zj@V9V zi9%)BiP?61Rit2TRFO}Eb=+>m(_j^$DD^nH@J-G(8VU~0PL@|;Xii+j3PZDvA}b8d zag-AKH;}DPubs(&(d#751|R5W9<9J1NxK$Z3tcA^VFsv_q^dt=OWNA4cFdx**v64l zRFWx`WV?$fs7kWuRzY8rrlB(L9ge@EMWgplPiv7|YmMz<+C<60_?zqASOEHpu{kuM zyYX~O&u#E-T+FcNrXjdwH)KIfQ&((9L`LI60LAzXRFUNu$FG*bsd(&^7e>iedGYvu zOvY=;cz<04JNCE+*9>iZqz%`r3=O4AjJ?HRC5CP~!$GgMEN!1$D12Ny0!LrgPs-8!#5Zhk(0KEE5Ey|(n&pFXU4-7l=P%8U4Ji2ks;<|_7h zNSB6L#tiUdOplIXdM4>40cc3+px%U{Ui#xsRvDs~Nbcd4_t}OhzXA)OER-TjN;Jrr zCVZA9y(mYovgvzDERQ89EJg$nbx1jm3U5knnNH!&FzIBNyh-)Hg1Yhug8?wVwCtJ^ z$x|lGPCrkk(d0dmW^9CjHT>2phA5EO3x+8`WcuF%@2eU+Yp70f*d}*a<)I`M386_jV56_y{!n!t(epml<~QyNRa4oO01%4K&mFvKb^R)R0Xe1g7R5ed_$%-! zc96qk*ceFAwr8g3q>k(t845t8UJ1#43;2igHMkh9?hJ4Nj&wP0)i@8bPHlpBocGh zEAxZ+)9?6m)%j;K944!qYa46N*0X7ModsH3hl3ga8qdans@__6(LOfdv%USC{=&!l zyZLP6o9BPp{Cea0*0Zm_-q_rP=UW@!eDmy28xJ|q&}W8@ywK$|P4l91W$*35{XstK zE00#9{d96S9b8@KQ4P5L_p{DzGKktq_j;TT)2l&}L5VeBQ9uOI7EI16{Ij_h?SX_u z)iPMMSu(vzdTY=cCn*%ihJ$W0Mrmv|?t#dJve?mV*cnHs=ZDeF7MA`cox#y+j6xf{ zhdNo>&u=?Z5VN}7bc!bml;yB0NL{0hBsW-iy#dN`Ao2Bs&5k;EQF@tUg!T^lG~Hog zyf32s7Lm*YI~QI^8>KxArd%_ppc4i!Vd<6`i-Nmsfa0 z3x8jqHdz6@ZGyjhug+M>|GsFoKkmptdf&JHH;NDN;&|^c-aolGZi75J_-B&#YgYG| z2iE`Q?Z!JeCtC?o;8lki5M9O7r<8kYJnnUdTA&rw6mYcSmd z6osRTfHCRGf?AX&{}|xwyS1z%deF{BQVywHk%vRB7mT1nipo%kKRxW>sFQcE%^9?Z zEHe&s8!~)mn`d}P2VOjV>I97*T;buyrkTOJxpfiF;NZaW({(bA(n&JyFg~8my4O)B zgR@(b;aNP|&!@wu`{=Rz!vHoK+!2xwNq3fGG?822P3icnoN_z zf{z4MM)~bPi(Eub-A>cSVcOGg!BN_CG726d8MgU75pN4(qrLw7*FNs z=(3}dya?lqLt8yq-b!*u%Z~Mh$kw%A_(~~RoJufX$rQH?tOr{JAr$rv4!PaX&`{SX zxBk7!gx0uV$SCuH;0PFnhDq%y9RAT=gFTiKDx*g3-w~~V=!uMl76F$<*{&vMAC88U zJvhr}gxx8d|AEr`xr?0d^19l{*|==XmhW6b6?ncE6YF|?Vsqu<`tnhY77be|VvT5A z+!tq}($-j0t6uTNkENGnsGbb!rBHV~9gI5DJAJUdWSC&`cJ>B}=hqgU2q~`Li@U=# zOKK+B;{=Ktq`c4{2)R;!#*84|!?uLOm<)Qgx>!v?wiT3WI72FBa5PW0K@>KkY67jg zMjAemz!CM>AI0xrM}>_TwJT9~+R3gP(cdvw8Z?B*0-(6l)@d`k#XX!!{3r(!ZhJca z<3b8APjYMwVn>~Crx+@xP;VMsQ5WZDo7SFUzu&6+_9-?{q*HCjQV)eoHO@}G28-+X zQ)PH4a4N`o_6vkgbA1E-!~Kf47pzPL0dPerRQ6@B!_jyOMf2fHYHZMamL`t=PD z<#1lWX_95=G9BI|sjP?&+&35_h<&#$gk+g%ny21-((YY_V+b-A-H@Vsr zS8dkYBD4Wpek|E1aP;@aj?3P{zkI?cbQhp?hBdGs4jvFf_j)j77t$hJ3<@Gf#Mwd5 z$*bf$xS5+{aj7l6lmZVZFMbcgc`{T%LX2}Q4ej@Rukqzm?NjCc=XTneEPne_a{sdl z|J&Gf?th+dZGE}_`3#>g_dj3mf9AjcNxCzT70qj$K_4|N)|JpW$p`S?`e5vTo_8na zi+*>U53TzlyewEB^y3e`Nx{XEadkA;-4h4mbKNO{n2qUUz3+S%T>MosNryx48yr?Q z55F6v!B;5Tj_%CY((00~wf-{b!`cNo_2e-A`QTJuK=I$v)?c5Y0F$B1Ob1U9eHN)Z zx*X){IuIopX1Oc%Bf4S!740$fbjasuw)zeZ3_e4u$ZvTOmvq{|GDIA0*Gplz9y z)kzb@Y?6Lxo*g%RW_+4t%)p}~LL*{;h~5q4GfOGW%&)4glpa2Tf%W~~xib83n6T== z_N_Ap1NFHN)&@%;2RjH09%Y)LLPI`hTyfRa3mlZ4V{>K!yJlnCw(WH6q+{E*?R0G0 z?AW$#C!OSpZ96%6&rHo!&3u{p2fJ#2+WTJXTIFT_?6c?&=qFWEk#GWVu*cIaQ8+F= z_Z8i5e3J=7#qGzi$hsmN2M3Uaky-&HdV}VSG`!d|nU_(G#;h6%e_6hpRPc$=`N~EK zgFAeQmk3fTXk9*Vm0PFMgq8x`TlbT5zURdT*$Xft?RBO96k;KueTwLh+Gk#_YFU8d zm@{VxX{umhMP@eM%PNh=06GL zr|KDpIha79gYX^R{P{~v0F!oY?C?A(?2gHgFx;5Z)b@1n;}1=$X?a89j@LI#{R?M= z+6LY6KnAw)@1K^5*6e;5BtP=sS18E&=d%jNA5?6HNs^*jwlYWTuecA45}k6=3IG_D zO*TE3EaJCh^ljJ41cWaCOGBZwrdQPCWqH{$of^-hXVTZQ0Dv`WE7;fVE!)*+cMw-(`7AEE%Ad;;bkzcU!&?#`5cxOj64h7#(vj_P_p(6*F6{@Bx2{jlGU-7IHo{U>eSYi!i*F4cYN#7{Mrmm z{1jer-k}l%u-!v{lUGS;YSlB48nvxq8?!Y6L@zqpqV^GHGj1(7z+8%sOWdNCxntuP z5H{!|qgZAZ&kez2hcG}snVn%&DHZtbbQ5bi9MVAoBVZRU6d;9R?Fw%Jw~R}yHm222 zu|jZPmovAIe+wMb1OZg+FZ=iS^8MKFtm(Y^`vFrSyv7-67n94xTWayKiHhz{nC9$= zV;k1d%B^z#o3Z6@hWBlX6NIfX^EUUpb-ilFBNLb^lTHqO2E&d%&gWUp@GsjG5TZ$0 z6bm)J`)}!4CB>R@Tg<(za-qv*@r;6D2*-N$E*0AzUEp@}TR@*+u z@n{P49n5oct|qA^pqI0o%RC(5{sH_)!rJH~Iw!<^m_fXVNcWAAFaR@r2&~DjvAE zv;6A~s)d%ewpb?ICsFic^1~2FHPO@Mwi%p7V|;?@R~;6=$W%my*mxGnkimo>kdt#| zg;|-as%v1v0SqG#Zd?_u(hl9-SPiXFb(gxs_w?(KqHQhuU|Mjmbn_hjfgCb>mfVv` za}@LYQ?mbPU=6d^00H(WN6JTkjCika2Og5u4|fS@Y+!gQa9VU#9J3EJL@Ps4>BSX$ zs=Ps(`izoZ!a)Xb{WMra6q7|Uxrm&S0{@Po!pxEZ-P&@OM626O?AD!VIIe)rq@v@5 z_gL{gzkYOz66a7k8Zk&^C>Jx0fxA+Oq;;(AgWL^-fw3+=uK|aAC2tTp!@h#8-EoGYB|3*{ERZo;w9u$&qK(wnf?O+Fw-o;ix=~@) zWru!jfQTE0ZN~f}lN`h6&7$>#88lPhcCP-t^sxsnqB0EKfNa-`d+&l|8pg)Aw*3lF zOxo1LGT!HP$c$EUX-KU2J#jm2To#`KMS!(k$fe~IP2czDBPW`h_8i2h#yNnz_;J2i z_6Jv29YH-IxgOP=zEYf!c#86RfgeeCmy?h##NzbwT+p^UiMO8MddR+p*H4 zu2ds`Jk&xn{%PFBl{g%Zl^ci#Z(&qfZbxUVDje$Wngf5P#>;&gG5#c2C8flmlhbBt0nt=e>{!Qkjxs`B%H(!j?!M8EfBcA(ng=jG;f5##D) zB>u_GQ~vt~-ZaDid?{u|>4N?1dJ0|iE_hvJJi$yv2QI?%w-?I|^-K^pjtp9aSi&}) z=-LN{*zz^PoN#&wN6)Ql4$hT5CeiT$Emg&%Flb6r&d?yUsx$u(m7#J*Y zONB)!2*ZjDU{5##*|vFue2?=aCYiKUutW=f6VjIj+5r!)IBxn&!q<&&()+Z!%^JgH zeeOBK%VlfapcH3E%p+5OL(6x+uad|2wk3pq?)4e-^5tTuwDEl_90%95zMD1)=^;kR zXZVm!rj|cUl@?POixA~Ab8>Pm%oRgNffMbOsV+<CrgxgGwcnei1yp!E5u6Ms zno@u|Sb7@&8aGtT_#tZab-Ng7{%GdT0`W{k;ys4}x|&|^`z?I{0P9u*n5S7n1Qgsz zVkk0^=4LIy2sT(1Dab%2i2OWd=}C z0))x^CGyo9@kw`mIW!z0=uZht4`0-|LdYAiegK!ykt>k6m!m?wmA(C_qV6_VBwL@g z&9xI2_SBlRn-O?UJM^leXbgoHp$ABl-ms$)26|^WsEdtEZ?EYWKF9EMc9R+}en0gb zJeasEM4ztxEDM56JW!ue(9s-W+LLt&sk_svmY<%74zidTtYUGl|4fOr zSSoq2qEMLxv?T-gt!Q@};@7T2==_4x1W9%nUHR4WMiJ1~)V9*DC@WeeWzme_{lx%k z-5WVZxP(~ykKI?<9NG=Oge#MND$F~^z2EuI2|TN` zW0^%=JpO&JKdZ63$gAEN;_sQ^O1UYlp?OPcYh)Zorte(#ou9@EHWutl5i&$UCmAfHY1n3tZ0Yzf zLclr=7h;wPE9B^FQK0%OmP z*35vI{5ucdw^bR>OQQo9xQ+LL=;pi|s#(^PT?!JXp48Y4^&*=p&i;+MJ)M#~j}uNG zvMTo#=hvIh=12u1rw1Hsp|lh~LfSxc4jl)v@l*vrK$o&K7s0P0LmVGH=C1|;H*YD|M;h>*><}#yhk>h8hl-WC2f7_^K zdNEyvRQ7t-t9rB9bt!!%DOqR4SfKc3JH!nqsL5<%PZ|G?3z!8_L#!DOA1Ps;gq=jL zpobQ~fDB%Z(QemiM#_#h{CO@M<=78e;f7YofsR`Rk=?wwUpG%2boHVg+u8P(<7?9S z`&~yzjHF85xKj(#xC<=|$~sV*KG&+5L~Q@( zi}*N8b|zD6M%t7UNZzLe4YU=`?!+}&;&&XGIT}z<_xn3TMtKV=-VV2}-F`myy3@jy z)oWL2P29kFPU?ux7ll=3!2Yxt89KC|6Gkl=E>kUicNN5&cGs7A&-70uRyY*Fm#M+a zl`t=u%90?n9~Ex2umTeCg%TN#EB}cAGnNSVd)Jz9__75!8;$`;nN?d>5!W?Ea10cy z`v=0gYst2VHR22A{_ieKDil~caX9$kUu@T{+$b=WZ;(2+L!oriLOc{61G5ry zfj+b-a@99Fich|bN@+K#3Wz`2P+agrc*{x(Ckb+(zEl+1L+IT3 zvUDleN0I@r5B!1AoFpmr3IW*&x4oX$J6}sc24OWMr$c&$q0$5%xD@F~x*66-4*6xs z(QmOo+Wq2kZF3z?)_qk*X_p%A{=DlkLht{+@AbfWR-Y#Ry{CUm+K2?dc&mzLjJAdE zQzNzMGKPZzC^#;B!y;$W@YWk70TbV{3i=na3{Nh!vU7;E(4=4F?pkKZ7H(xpr}pd~ zQNA78n$szRh|$nclhW7C5DVO!#o~|@9}X>FrQNMghNuXNFG@XZ&|J-2$7~g2oizP6 z=lyjOnQ|Cl2aDv`G3F&%?K5HdHw^rPZ5#AZhxV?^2A9t4>R zO@WSk&Gj0WQhVmD&hhMs?1q<~_gE%QhqkL(Y=v#mpZZu6hl!e>ZaexoeNDD&mmx)Q zP~4)rTwFd|$$Pnewlsk5V=9hd5fQ-~S21H4|2$XRB6SF!bN^nRpF9L9tV|ukcPiC` z;!yWSS<<#dQ^(G+VlmC&4dUKng{#8*Bv$8NyH_jKilxMN(ne)DZi!4ATOwS4QPF^4ZTw%{gP$P$Di)(a{W zjW137%XFP2ZyR4$B$e2J$8{HWdCb30vnOP2ZC%J}jXLowEpX2WcAy1E?%|&;+|s$* z8+B(B4_@(>w`=&>K01KB+0;c+{(^y!D7+(67m%+0Xyx{jkKAMnl#3axtroy5BPg)U z*?i1Co7SkYzTE6oS~x!7N6Ujy?&gU;nI^8{O*MDN#MxgWPxK#yM^5Cn|+DV^uBqq6C~zx>u|pEl(w=FYcjS&ju96^cWdVRH6F z`Oi-aixX7%s%q*ImaOHFJY^V7UqN$IUGn=6D`BXJScLx_Tdrsau?RLBaI z`z4h8c4aBew370&jSvym{-S0-@M4FBqV&C@t#7T9k z9{XE~aogm<$R4#0u&=abHh9IS)%}&-8*wFe{q9_0;L)3>h-&Qqxz5fa-rEa03>S8M ze{SwE+MALY>i)g+4+n5%U)H3E^r6;)iyF9H4HFjh8a8(Tr6JHN9QOQ9{lKlYm?zXt z>izza2_|XYn<6ZP`+mGcYq9_JaRzQXmDfkT&#A;=f%QqI2j81>CiELL%7O??jX)f^ zU;91!4QhV>T8*9<>BD8P<iYh3WEy@K^s%uQc%J<}T6r2--B|gsx8>aqen#Y+ zx;Yl``C3&cs1|)cJ+R|$>zFChY9;U$INziQD$8-H9X)00#v#K_*02^0^R%b`7dWmN z;{OBc^F0_2T4CduQY_-Sm}*D-k}S~NcbFRno9?#YxJuxWN5P*C&2e<`^26G)F+9~@ z&|JDy;KlTa>v6Oc=pAO`$YGc>h%+K9QDK+=TNFL@&OCVo)OrJliXN7U?|N1Ez%r^K zieJXkJ~-gjUzXGx(D2eeb3Y#S=!$To#W~$E*z5x1BA{1FqhJg>(b8+5BXLYwyCHCy z!%q6*=jC>1e4g)#l!GVXJvzSt;NsPd)Vs`Soxz=#uYP)_#Jq%(%DcpG)t7HWmlvfh(Ly_$Ux$3(t4d^Kp8%@Xm;e;{B(f!vs`FyJ;02hH_ zwMO4+wkDA`=irEyiu3ohL~(wz)RyVFjH&@YCBFUv3oEV#*{e_u{aXW zuQ-XIO)F;(0-!Rrq^9FB>mu#(u!0(Xm1Bey>(CvGZ zCVn|@=+AqT7C_FF0%>RQpLb)Qrq(!5xutQpd))ocQ$J}lO4IAsgLiexQOH}xN>>*r zIDZe^tglsXfyULJJknRZ9^;2iezsasW%@ktcQq{r=00AbPq_%2o0VFAsT1 z3v85O&AX&mmdtoWOC1$u`Z!&vsapn`d)!q^ay?p_iKXPPSE5J5eNDq%?7(b!p8WwO z4+r{Dq|%Z-mO8sR#geuqRZ4j~9`{4t9zsMTjHwn6B@KIHG%{=rdO2JHxO04Mh z-xQnlG^3Nrs3lZTXxV6_G7l-)*S#CVVD>S1Z*l{xENqepX6R9yU#v(-l!kBJd`F8}HJUsRz z-sbjJW5+niU%0H6@P0Ra^US&uz`C)+tuv5c@T9VD_%InP@%Gl5iO1TfF zY%x3#Do4@_?VcLJ59npb{~}OUG#sjQ22z@ zIRX%^5WQlcS{7)zp?bt1TPeHUt$}M>GGlMWhs^YaR_Fe}kT|B8{z->TaVkugsQ4QA z8G>+^3)h1i=9J`=FJ&T?p`NrvWj&bZ<3#+|Z(iN9P#YC;=QxUdRE1F@nx>Di-2>{O zf%zSoTHFMJ6%t22AWDc^nBUGWY`Gm_7C7vRy(TkTMq6dSZQDNVK3RkJ=O?bW8jE89n<>XEDpCYO%Qiq(| zR_OHQ25tZnH{K3lPt_Qy39Z0g>s1EI1(qOZgAHS8m4#O#Ge*JJ%U(5TYr*u4F_w(G zZFSF7O$>Nj%ESdYEtU*=S>lgjrYab>wW}K_cyVd9_*P(Op|uJn`5M%VQ3|HP%X77Z zr@>XgJDwD1D`2}COg{@sFY=%JsimCiX6o3=)$3_53)IwLdK&V5_L52ZS7{_>s{)no z*e54O--@Yk)iG9bPsvMws$eSSRyjZy4pcNZJyA1w6~|K{lvU#BJL2!Eh0yQH5t685 zX~L(Dwcxd>QdBQ6pZZEHtl+iz)6g~4cpeL?6bT>c(cO2@H#NMm3TY=3EeRT77c>7A zmIt)SnIdY01Fu(@g4jp2x+&2R!+maAt#aW0B52h=eU0Ph0Ccqt4zCbY%51Au zh+ia0@YbjB(|!S&BeW9+at)kvgT#qk8xs7~4d2?{F}5qM9d;a-|1KECXOX#G5C zM{y_IviRVMSxHF^pG6}}?%tP0Z|eJ`pn=+G-D45r3*GY$ zPn}(#sD!eL7{uW_>CO?81UTpstyxSE+IDM2h`A51!JBV3eJWwt7gAj@FBflH`fI}K zt&{Z@f1utaUMqwOB~S$RLF**aNcdp&NdAEumxPG07tSFHT#poNW7?(Ro8h|WXU>KN zIJL}fqUzrRz2C%_RcV}}?aKwy-B)PsFGP=zz3J&>6qT1?G~xw1?Q*E~+ro3M}xz}R8dz!m>Fpjf+)<4ie7Fn;@^Qx*v3J$P^# z`R9pexpErp_`YPjmgDX@+t^MHJeyh}4g|X3r%eZh}F(BI(pzh=4(QYuhCLh{V|=-7qC+3_Jv(Te&X+=w9L2?+=a% z=W()Bd@$^7mo2@{prFbrysi2RZIxrx5Js3cI%jP=%!P_Y7SZLF;dp{=40KarVRk~Z zCNl4ai_m{ZY|qU$03`+L(}{F*$+WXUP9_#_pC;I&i+>kMH&ORUgHe-T)?d?wqOudR z=~Y(Fi!EDs+}c4-5+3U!(RF)UaLD8uV$S;8!}*$Y2a}nGOg!hxu;zJNFrLK^1*I6r zq;HA@V!k!C1}m4(_w1Z33rOhjGm}V*NTsF%UH+`BYIaDOCiUW_O z`E5rxh^Q)qNW9XaBeEwdRgX@Lv5-6qLk2jpS`D~RGchAY1p^#@;;-A~JLwbkR(S`n zy`n!*Cx7M@A{ETs_D^WSUpsP6)_IPQ%pw?7@;5SmqIy5 z*r|d_;pCkJLgo4qs-C7ON}>`Td~+tmZlgPKE#12D_({@d4NV7xJ}tj`i;~Z*Q1nwC z)xKdgfFI9(7fPXPKXs-u;LA>gN&3Zck;!FSr60hW-!sx`C37Yz4cJdw8J!aB9St9UZf)dv3k?!q=U36Nj&lU;nLBF9#YlVwx0! zaP;^4FVwYvMzvfd2IdHVl#Hb_?q{lb5rTo<79_M6uAABZ6+4vkl&_$PPVaEE-o6Qt zv;_{dHGzia;_r<2e4a!dg-jqb)V~#maXtCP@tiL{R4=EvZ}>x&c_Y$2R2HjY0%tgn zQQX^Vsm1u{DeLF?t*A7i@d~jOeE|dL7`tiV+rUsYx-Mk*B}J^!-;VN z7X_{#Z(uK=USXo)@0jyRxoMzIyvy#qfquZJG{>Oy`Cr>opCWIDtv&J+Jd8w`r1G4YNO^-vsOnN~?PFy{JKJmWxRtv;eF)Dg0`eN0OPba$ZzLUAv!^@Tz9YaGE{F8$qLSbdH*} z10#AJwOJkWZ0uh8;!JB}`szlWCE@E(R!~ghyFHo*h6hv4b)L)kg6$^-DxtGc3N{Ou zHiJDCZ6x}Y%%l-zzqc+~qICSQ`ob8-B4xK&m@Zz%lGFHVz~iLmHhn%J%cu-IvN`(% zn^-~R0{>@US6LTL1r$zAo&%{;VcyJ-e2~kpdqw4CKJ9?#k)o6;EQPnGASF-fvLw7C zztSjqMgu;{bRH+m%Z z5BoCtRqVhk`b^4VaaYp$pU64eEVGLgZa`q^8;2wigbF!EC46~jIlROqz2(uV-TDpy z0dR^Vrs)h`ycJV@EG!4hH|jX%&RFyh91blV+D_}dEB`~-WfbC*WgyU>JQxi=cjb>i z&_(gch`vf}Ek1DZHJCZqU{ROhi*Y));_SHSNpt7?q;3${Os2hpg#csTu0j&0eNaxf zG6FH&K#menls2q%(MT{@md6|06bm&!r6c^2$yl9^$5Db*<#SNP$jr<1^nyvBlI9cS z*dNX4FiOpw;#*8)nu$cb$t7LIRk9TJYH;GUM23I5cKroOiT_xRN-wWRS2S^Jy?(o9 zMK=oZw+ZRPoER<{Iui3iJQlAb$dl-i=VZ4S7eSW4xB-^fbE!=T^3<|PwL0B~;=Bo; z=PhEaUK^k*J!!4w{Lr0Yg;OOK%Srp%Ad#2Xo_4Mlf5*C9i$a1}vHB1yNyRyDhN>is zuB=*eGmjx%h1F^cG#;I@40Vkd?lgGgR>rn`tzSlT*Av-}$8^4B#^b)@O;UB4Ge8%d zO3G^&5x{(Mc-S`Lu$;c6%|nswS~f-Sa<$pfKHqc-6OXHaR|dgt{W^U&Al()Br;D$i&VHCeb2(FEu(~XngZ*6pNgkosdV<)mV4sWi&aJ;ej z62S2aq3*^&)CR9N*%K8n-w`=50{&$rvV|P(IXkQ$Q+rXzUSs`U=gst@aADS05$5Z= zdpPAO`9r(c;v{-a*Q_+hs@i#hbVx3{2B#om@v0YE*#s4H-zmh0mUlmDC@ z${X~+j=g+WY%sF_1Z9_4p-X!Uhcmq@Kc>E*Fyj1^ko7L86eN(@??W6RxCj5-tg`0~ zj0k;)%HoM969J#ECl%Mm=<1;oP}``GVOQaxkxn_ye1qPSIDa7m2yj{N`KFh@&uydO z0 z|0)Xx{ChobOvvY!#(5~kXD0NTD;6se8f@W?j(GT3DSeO{r%BSBQrh2fZR3Tz$kQA8 zUgYH|r*9nnr$;KwYnr_U-@ZGsVlar#t}79K)7`k`(x21l4NC$sLLvM0mI~nvu=&s2 ze|c^vYs9eDv4TQNF}#uIdOFqUjjBq)Zm5iUwK$UrY;Brk9Oim_5gR__vh;ufQ@)f@ zEuU4<-rZE2K}3@y3XL-Ro(D#qe~?LewOAI1=@G+|-sX(L7Vk8V*P)A-I%?WTKP=OC zNR~T1A`AsR8+?sRB?EcM#p*QAeb1mmKs4Y+kO zU)<%7B&l2$|KNxLU)S>bgXsBQ6YlQb**Rl{P~Fw&xT(s}Q36lv1m(~o(`uXONJ8)T zTe(9J%y{`cnuJXjTj!Dvn!PU)KJfJ7qN<8$W=8dSr5Ysn7Ux$&WJTj^kbrY`nJ!m+fGUDurt7ZqpMFhoV`fF+Hprr7 zlI6-mp!c6kOOV=_74_$J^s8&`sD33m3Ugx7hRsoRy`jia)p1DV zoaQuu8fKPD;ZR4JyF3&_)M)x-!>!v=nBC&6b%lXOwtAYtW2I9KB;c7tcrjGqWbFRGV~ZP52;dnte@F4!J5`VOG|wNw*wo z^b(~5QVj4%pe$;G9PT9YA+koI$y_XY$zQj-3d(lwL9OEYM3M&_t93W#?JpAk18=T_ zp+g1KYGPZDR2u`h^3Liilm6s~Qu2O}81=}hWmdoX)|r69v%-!9_NezPDc*ycwk+Hf zZ&_UD83}h7zZ`?0a)9K&xpnxjSrN3(9*6L!Pg{Kvdt_RHE&S0KeJ=W0e_XHITRg&! zNgScPtb-L-r59WKC{miwBn!5`v;MnnUQ{DZUoaL5xJ2{44=UHP(12FpCE^RftdpW@ zx)AqP`&55qQ)GAJ)PzD<@4qq&!jp#>jEtq^x7-F=^{fnTB{Alv_n)dc^wK)W88XAl z5(ZZ>S}!_W6+aNpr%a}HjT^yFLu-<}fU9S7|4eE==lAS{`hI6qx+^lCF|bxd{Y+!p z3~?DU`!f24((qKez!P@JOyp5tR-6d)W_vNZ z73B$PkY>_433-Lf)&-x0&y>z95L#1W+X>)?0?+7s~8UV5cWcd)Ue*%x&qy7HQ(k0pF94@tw0JP%$+ zE95swNfrYSSIgCvm!@&|ORr1Cl;U)h;Q=dVB_3uzjf3JvG35#d&kpmm95;hc>i}k5 zq@56g`n~<`qQ668JKeFlNV8u)#s*o-{pWciK~QK+;zVo+)c$4L zO0a9N12mhIz?2RxEbK_$5~uOSew*JTTwNGhuLeu23h>s8wP4C#i@DUC0lbWTaZnC~u%eH;9puvj^SKuWe3CftI{2(SbMVS7F*qL?Gv zS9((Sm-ET)J-I>*Vm06?#a-QLx;=em>~=-r5T~=l!zx=g0&SpFjWaOa)kaL47E*V1 zqP04+9;nVA?8Mp#jWudGs=b1W6Ej$kywOos8owBPSc{tH9U5S_rEPHv1xPg=iROpJ zHA$t?Ue9Zy0u98s;%1di=G>`D4Nh!5$Xsv zi-|U4fa^|EcEE#ZR|hXo=v@>^KhF+c@?AeD_yaFl02}tLel{bu0ac80`e`s@}q-1$iVEZ06UIc&KAi8s|S@|=6*5d z8o^iv`KE&f%-MG#<%bfC(0DEaiBx)$T%iJ^D?zWdJkv7Q zCBlnc#n%=?;SB7O8xw5$!zvAFn;HXL{z?PxDw*E4wv834;AUDZ97Be{__(duIckkY zAL@SwpVgxIVci}1m0GM)+Z#0-YB&e1UgLziO@8%(ZZ6EAj5dvdZp1wHMPKh%9f1UC zlIQ!8YK0PZ&2Ct$RIHkS#(myhdT;znF58T}(u&|5uY(86oMMeBuP%II=YL_s>ZeZ8 z#1ggCXAD$qehG;iEbW@hpo?r;W6+Dl&Y)oLs30N@X`3*(3Z|atE;(Sj2CYXv>cFkc zlostj)C-#qL5U+l65u}*A-S8!^>f%#NLBPj#{^Ycu7YK^Dw;Xq57q60w);2iPjBZa zM8Qg!{siv&2UZ)^(iTb@?-Cj4#b@8&c4HDm*757T&~rX|UOv%Q;fd8b&giw#=}ymN z#LZFwKm#_Kb~=Op4ZIgloiPTjkS0cQ2DR$tmzA2XHx=~!0eq9&=`kzY^>aD?J~toq z{_-B>>6AZ$kWQIp(t71`2{5a!YufEAhQ$*nJv_$0@4@Rhl-t1AJBr4t1$GoTEI91S zEjZn^>B=mv+;Raswucic_dM&oUON;T<`u@lNp|l{1sy^hw>|b{$!b%$IgS#}mkllg zf#oU9s>Z4u6hf$=fzu#Vfd3PHXtsu}&IEzTO1lnpta8Um!aZibjkzIbZWP-ob)9BsmV2QB!!OZrPlPfLtY=hdOF z4E|59Qyj83KAJ6&^G5Ogz;05}! zi~Y+6o7mzqRe>U=+>s2ZA24G@Y?1J6FR|Q2QL;?sB(!aR&5Psb5!w5S@xz{~0O4ra z_jIy~(j%J10lyT{vz%*c<`qNRnW(kJA5z3@Zp4Evo_~i;x{*?`0^z&7G219*y8Pv< z>I97eA*oHbDM!9}Tn(^GMYm1ord|;iBqkRZ3c;C=OAp3Lx8L;YZmp#=nHv3bBSUf6 zpqB@srJx0SdkZmnOA=5n3SzuM@jJ}iQxm9=uX;m>av;>-t7B7q$;-FP9V~1%l;7+z z9i#?Ko&`AJpY-k=y*#YUTiK)>Mm;QF-)|xj2k6JJCkx+zU3jgVev-ynqzaCuIB%QL zLT!TgiQY9^(kh3YhBJiPV)e3IBcRi*aJx{%vz{zh4|k341sO;_IWwQpP<0 zMnpu&`i}ON`X?K{EVot7-yyDWLxa7f?1zgkSn@l+vZ`EtzC`qK;EMid>J>91?cTw^a75dR?dNcXuaceq5(;_&|MZraSsS5hRjiPuetzdjN zFaZOrQtr*I0NK}SL^PI#C264KtsH!jdg^G*M6WJaj$`Tw?> z?}2pPeyrv>HDWJtS-iZaqQMo#N_gL9`JLlitMivf>@GV3_W7KTGS8N8K9`2)3fDEO zZ;%+VTJ6gd_K&T>eaFsbf5)~kzHGhhoZM_qWcg#sy`8wH?*Eg@U@i%Y?wP)7cwG0m zd@Ff`BL_RDM!n8SeBB}&zbNF3WoHw8M-RwR` zz{dIq>r$>c+lkuvi*MM!<_lYX!RCheN(N$=qzvq~>+(Ou#mR7p{*+%DSnVZfN9yKr zTUZw3|DZ3#1oJGN(Bm2^2UyVjIt6guyLHF>ov*D8zyZfP?)*6~+Bq_dyq5!4LIT}l zQ=i~cf(d?%roPe95BcWB9!Sk1pPGd`V{s&)Q%@QNQTTi^;`JgebAbCKG6j(782?6(tp zwd$XrSR!OCBFXG%fKc+tj{meVOEXA<7VT%VvWxTn$>zot#Z{OqXNK|S`9V&4L*^cr z2)8A|E~5=0ngbSo5b|_7A0mMAu5j??RCF9br(X2$q-8XYG&gjIp4vo1!VdM#GBm2+ zjkZNt0;%DFp&YtZ;U!l6;f6wMcLeQ85_%GegUmlc^6_o|AK?6DukFz}XwSqbcrIt-|EF zit~3Tq}!{q+P~7l<1SQs7mYf?417B#sc^+RWA@{&{zD?}Cpz-jIs76Lim|`^@tQmO zeBOB8xAYljhHU(Lb1iy|OJCS(ekd~TmyA&%c9}S@tL2cTd-Y~7#al%K7*2({#Q--5 zE@(TWStBRb0)UEJIz>1)^bK~B=v?@PScj5+i+Vd&@o0Vp5mqOwxcx8FEHIk+YDFb8 zfsqI~^Y+{?#efQ^qk7vxYW{|?vkK_((ZCg-!BqtV#Iqv%fkwkb87rrlsa7x{JTgYC zBfQ-Fd+d=A85WHcq5z3S|2jq%eU^#%LNJwBwK^~#Xh6qS*61CAnm&qPCkk2P>n>6M ziSjSBC7b$R5DH$JY7*m^+pvu?9=&f)Bnv|dGlTe!mh;#YIhNN9IG_=FfI|=4Kc$Os z@)XQC+=<~>KnJ16#Xm5Z|=W$`#!-o24@3`%|*0-k+X zbR8dFki^$85w_7BR4{Vx9w_tgEs9ywU$583`9_Oe0WkoXP#xYPt#y2PWjBW2y^-hz z48|oSw>clzTk&W3f#qi~EPjRzO4hX;$_I%e4rCgMi+$H&z5^@g>cC|sF!*kttgj%X(l zG&+95N@HPZ&L5Qt^-p<%=OX}}j_G))`z*fkI)OvQUqp~cUaMUGSk1g9f4dsLZ0 zc-WqlAKxWkdfPx$22Pnp$mcHed5k-31UZ<~AC16k>0y*7ic-$9%r0Tv<=jXHRaa#z ze}6ZmBBixas!~EDmdWtnSbuIOBzj^f-KCFr7uYaWbeg9L(VaXQm#5`<)-Y*!b|03- z4&hmKIA#+KJBT~EUsmQy(^4iV=9C7;X-@%I4e zP?In8;siwD*Asvulev}7kNk*of$Vd0Z&qyTlnH6WnX^vrs_0Jhnv>)MU%TxT5X#*WqSS zhP+ca8}KHwd*835VFyvcU(WEK)$3q)-HY4dM^iR#GTMc>-aF%ABnUaprEeM?oh|bT z9a%J$$s#^_H6+p9ds^Q>cR8Yirbw>X>LFd5E|kLB7pr?+>0076d`cnpgFxK@?ey`) z7(JeFZa+%Hbj9ITGJvEqLQh@6S49Vy=YfPqL%@_U1K-c)+ zN^K*j^=)Jl6*gD+MlUz|Q!+$;T`cquiTp$hwU1YYMr?aE8osDYS;wrQ+g!7U8x8Xr z9t7$95>L$TiGfrNcYZ;V-(zuXvBL}mkl4J(XAep}WX+p*;!6hdEp;@(V!o)bx8lS< z3S~#f%pCj%ceQvEUC6?48tw(WIA^Xd9ffo7uNn?np9IZ@9wfB16q9Zn$pTnm`$rf1 z7i=uJ26k>O5JB_f(t7nqO(66wAqk@zM}1v9s%vVl|1M1l(B2dFpt5?CuS7kC$EI5L z3dr!d{6#Ms`Ch`6Z|2pYU#*aI;pbS%L}ge&rm&fyDvX73Hf$AujPNiEo{p5fNx??i z2(o7O%Rpc-?*rb)`N)pBMInvd-MqK&%YOQI*`ASf9GM?X|9O?J$VKVp@wHz#J?U97 zR(M#Eb(?Pa5sVcx?lkuXRYcj6r5KCgGIat0>Xc*^Z<*F+$7HCFBb@bD4o>)FaH789 z7j9CAoy{qX*sg#6x&XM$JLG4*8n~`R&ushQ9~a~?Mqr`+2E2(i`c7MkS?$`<05ve< zMngegvlg)Xl7ay_`Mz+k{Y_WEXl?PAOMunxfGnIfP?u&kXHKA#)Q~ zVNPI(4xMYbZML!6XmN!>hqU4S2esLSIcZy1C?N}r+R$8r-^YaFeQ4zU5_mY(8F9kr zYRZqjVtIaeTKDPT{etAoob)!Wv6&VnA4>gb)lP!8od}g;sGDLftP2NFxJrh)ob91O zdw=Wr`wwJYmJsppT|dMAp-VE$@8V-@Q5^7}+N$-&-qsm#KY$ed48hfSVh`TzBn?Dn zpr2|_!mN}VyPSD>yU2Nkd+cxhGm#KUG-)>izKQp01HwVRY8J&OG1PSKmF3ji7rQ+< zg)ji3DqDseHZ}~0`UHwE!ShW6=Yi|(S!?s8p9eWBzl-9!!`n6IVk8}&)c$CcaH1`UKFXNz^MRb zE6k-9v1W~qZ^&bo{uwz#GKA}rQ5A6#ggp&+K#`caxX;;`OC?f4;{at=D-vQOq4-oA zJX;||tkmvhR^u}lZhl9HykA9uCIuD|uS%@Vd(A-L)YP z(g^EEUhrc=@F;r^N8&-wDCN%#3G81nk$|TpPeg2fx?FYU^6@kor8kKb!A{RwM|;3H zq35%9jJMd;;uo^M)IBdPvVul;6s(#n2+-AG;FCr}_fN z=tZMRO}-P^I+xrqJIGtHT&7qg>jdwQ0cE(kY9nL3M6YC&ZvS!$e>r~rEd*zS4HE}M zH`=gZScXyR;IVhXSi!&jBOi?W=^_Ki`|Ep-+-f51qUDYqp}zOfd&%YOYLT&%J?}jS zZ?{okF6<7UAg?}tZDF}<=(;oR4HNDoH0sp`e$!7wzkxC`Kj8S3CUc~K)oN)ypxb`` z1F;D-gDEyU<3~rz2%F1rxMHKlTaZ{GH$H6s*gTBSn{9o@sXF$yCh0?(C8UkGiJ zzWUq7R|e8?7xFP9Ps{V&pO$h0{7dbYXaj{PG%w12ice2|YM#YM2d@pe7IW}o#7Y+P z87YR@vl_;OI>qXnBye1@&0W{@*{EhzW3J)gYNdJOE6`f8WiE%og-q7UC3v+> zjF)wD?2-;VNn&LeRa>YsGqdsgae5owPSY{Kc8gb>-2p5Rz|SbjuLomFke)|#UjO1* zRxOv8)^eewIKUvP-j3Wb_)uBLqj+*~Bub3_3OGFeTP5s=e;oF*H);Zx)Ki_!QS;*1 z;;Jdr^In_q)+as!vzKmU(*ikj;;eZd2ANF!?5T2Q#-DmtF|F?V(6BAeP<=aO!RR}A zR;tqa7+gaxpS6_LB@r5{UKa7Z@tcJ#Q>$p@k{=hCK6@0I)EQx=ilqr!*9yHG8r1UB zW71=HLEO%lCA_0Yji|$vW9XKEx4PrxmX+lT?*Z-O$RxyL5n>p?u^&Fm5YupkUsccz z3O*y-hT5QE+fpcP4aYHBsG}-Gw~pXS-0(e@aYMH-mHV%xB9rDH2V5H|MU4f8hY-{n z(ZhKD0kOXINwL25sj+U=o5z$mR=RAOGsXTg2iiEzXYRYY|gk`>aF|)lQym<{JH1fL~j7e!jdN9MnTM$X)2~XyWGFXCFAITd89~>`& zI4@)In^R~o@Z{WlKvA+a`6j`tS_r%9abA!q;TP`wg*$N`cc#W(GBKSAE)-5=2+}aq?yyAT_9VbKkpfY1o?exg8*5RVif}WkioShUwQ(Nh>91mrl zTGcaaAfVWYttBt*nS2Oj!$JaBX8ShYfKp7!P=W6+P90Z)^%di1w1RzfCKKij3@6w3 zEZ{lJMo&ALTqn~3G>nnE`*zf=6=tkM!6G_i44sgS|Nrd$d3zhju_z9of3H5pn7LvA z2;3<;R}^&~n1n3+%q=A7C5qm8Kwv;3!ZOATC^E-7pZ)Es-m163fTUz6Are!-OfS{d z)z#J2wPdqt!lT=y1ly1vSNcOMh(f2KY!Yb!qL&P#al$Gw(eW}t03qPJS;dU5 zSXSCOXdc!z0ZIX?&Xq*Fp(eFFV%J=RnsBw+4FCsKOVg#0u`Q)`m<*lfbU}0Ay+e>{ zFnBpI32!vz?KlWU+0po2b+8?$RCS@LkO8i#xy`E|7-8BIwDo!{))#k+!N-U&5RwP z$R(5>-pIyi9A_8V7M*kO+zp+NIjAN!w#7g2-c}qS*c0d+tX$ zsd09UM&epXpJXcFHl!nv${mR4ct?~z&u9E3V)b2;KRJt1O;0FJvwt3}xqy#-!KOL8 zx6^>G?on|S)NDR3iso#1g+noj)~nrNBx-4Q*b|R6%~NWx|IkmV{9l-RX5qA7>QkKm z>)WlDn=kGBU+XWwefgCC>nnVo@_*Hk5kBSrS|tBh_nJ+0iR@iEOP79_a!K9I^EH^T zqgA=|U*jZS8}xn8m|SCJ?qVBWr)-`ujGyL7AC_PDk{kCqH%)P$U(T}9Imm93DFnUb zFZyU#{bTd&yv4}rHT@MIUmR67x0ocl!4s-it%g31c|J0P8Tp7j|llJg?DEb>{W>~cqc73&|n3oirGGg||@ zRySfjMm2T>?hf#)%z!SIicY6?ejdMToWF~IX#N5jC}3FI>#{vS-Cua#G9H^Yo@QD6 zF}Zt>Q9cm~>$f{h0AIg-*}=a%@VAHGH(%nDOZdBUDVlzq1^6#tIKU+E8AP} zw}XHG(ucp7>#|O79oyh-W2;^K+rhTK#qV2K=5kxs`Sx2~ZnH<)Ue~4jn+Rc7*4e=x zw(;pD*5AVVm)K9Ii=`3%ey5JJY?&T*`k+k7?D*uM>W@R3yeZ0chPo>1_NwsQ84@`4sNdt{~F}6b9|dD4AX*!VnNs zaAenT7{LdYmeXK7-Zd2ldy%-dWchi;w9s8CVH(bEE66XNDyn6E*gS`eeeT3`cR#gP*H+x*3* zG%=4fsspDi7(y$L!S0$o2Q4sSoAhs2V?FWFE-xEZYrY8jB`Mbth z^B|Tn+Lk=jyf{8pr}u!CuQ3lBTcV2yA~o?k9=>3=w!k`)b=Zagbrz0wtIR70!(lvP zEkU3XTq|abGjdu*Ox337;Hl2*SQYMWLNcZ*c?pqAt!L9@)WMjevKi;h4lkk__-w#% z-`h**!>)02F50s$Ke1;J{eEhl#z(DVQB05vFtv)^Zq@aMVbhC_)d=e4Z1|CeU=#4w zd0#wXokyN1NU{@TmE6q?@c{Zyj{ojtHqKu~&u4Uh5Pg?CMp(m>dMPB_ERB;f5^RO{ zCu}xqRcoYPnTfx#h6(6PXB2(QYF1gb528V~r@HXZLy>?L^zjyYG+q`&3DVKZ9;I5( znG3OE2PK$u@ZznMjQ?SsvhEf9<6hy+?9QYx8@Zhtefs4Up9?5g$;LvZSdnV1+NjgD z@ut*{7IQ%97{eb&GFz)@5;UHo2Cs+S98v`cy&{3cof|eNb(lqWJkb?*#*;r@lZMn& z(-}`T&fq|EZpJBOTi}N)ptF|CH;@r_lvYNduaadjKW_~Ae={fbti7nLoOPe=x%D{Q zjM)^hu3kM~-@LxQE%6T?M=YgXwz!V3 z6p4HCPIU*cIm?AY=pWv2{{s0Rxa#($BiSNAc_$gXpNVa z2%mzsNu`SHt4^EZoX2jfs-y5yU6ELX=#>ocUEcAQjrNuW==VHF;XDYg^@`Cj&JUlQ z3^ZPhy0?+U`JdJ2w+?yBfv&viO}N0IpIpu|`V%1U(Fbs|1FFbJAOdnD0jm9q?@9zS zeAeyD4nQ*Z7M0(O^K+K5T^`(owYCW8W@j6;h)Eys5w1bVg{ftnD29uO_Wmgd*5t{> zf&HX)>c5_0?ePm5`DKsHq;r3vC&Rt~(Qh=E{FzGEA$nL9V_4pcBnsHvKo}f|n~7CL z>XwX^*1Fx>+wC3LZ z)%5qe!%pj-yU#i{T+@A89)r%Jlwa%{BfFp_OQ@w>O1kp~^nk9p8~Hr#lI=sKj(we5 zF>HFSlAx`^>*=jRjPX2|&&dEtbFVcQD|U=tP6Iln7CsP-`2oFpWjAa*aoge zaPMS?$0X@xWU(K%j(>>HPn*qyxN*@wIc|O*sGb+Fi}ug)F{>J=Ifv2cnrk(%=<1=c zpLbJ4zc^wGRXJ^2StCSx|5(L`JZY_DkPbX-olFILy8X2XsX~V^&XehMmgWwr#OODi z%|?}FyAzWaXdPyF0wEm>c=58%=-R3oJl~Qw=5&i|#=cmn`9uq!7D|a505k3QHl7TP zBebX%4rD{~x)rva->2=|Y@6o3fUz=O!OC@IZg0(Z_#=0-@ZMvT+bBFj6;fovNbYWD z8}2sPFR?M}+W`fGdW|&9b}gC$w&d31>^43hPw+(0JZydi6EOdZThnr8v)zclKRdZN zMGcBk072b!``Y2Bp+W{CQEf1{cRBM1KSP(eCGkUK~xJkVS^ znT(T|49bu`m(`2+gD}!R=)Kfvj5AJFGl+ONWWsA}V>1FH>Cu{ae(*?*(S^q#`2PCs zTkGTAxY=Tx0%4Z+z$r*AA=P}{Gllm&=?Wz%?+Vxv_7ZhC8)AYH6Ph#kaH~LqyRv+W z;f^aSAO)JTG{#HPWa`?Qph>0-`OY|D#o&M_6lcTEO%fZ=Py^>E`efjEB_3H?!rPxQK0!{#i+4aGt1b+>S+^y^r_0b@W_mp~VsBPG13io+fm>S8JI-8YUL$H9 zOQ%Ai+-}a)h8I~i72*mA0BvxfXW0oynGWK`04#J^^626kmK1X?xr&;0tT+JOEs5Ia$ZW`$31RBUcxi&WB4+)xFyFoa>!mL2kd*E zfURE3<}9_(!bX@rqB($^Pln;JQ`pErOv|p)!;Gnz3g;qr8_4H2;5mOPT;AK3N?)!B zB~`^YfpjhdDC7r?h3v7ymL>=cP#S7I++DH6PFT!?EKE>N06ts`8kYHatkK|Hf-M27 z)B+0Dv%DNFes08W)al2a>yVWgxNG+@|B#Ppev!j^1rn9l1A37>qVHRk|Y=x~Li0CzjcI(n+ zn`fFrqiuEwV3_GnMhOIrx#Q-F(Tf5q_i=Pc?(SCdIk%nT`P##9JX9?A`p@(hUq+>#mx1}P#r z-lM6;;djnuughq05%5{l%WwXYsYe@+D*rLL+aRDvl>FxTo?BtgfNXJP!M7cQen3dI zsGJdKku9r0G&|~#X2X2Y?PR%NmlZ8VyE-lF_SWFuL`_uo#$nLAEwruTa^h^%kyZ;- zRJ&iM5VX7E#%xh-ddq|jG}^)6mK_utya9+*`o!E7N(6 z9$kJNrm7y$&DUku`Vej?R)xzNTPFs(AEpsNP$LO>^!$3JWF7>yP~HjJ5E7*1_e4rw z4k^M(?=g^&KQaX`;Q%t9)~U=pC@=N~DOk@|@F?;yGZaaMD7W*Wy;8YI0_0{NG`;dNZ&64sk2K+e z2J!NW&jp0x0Vl1DKV;v?42vhL`Y<^UiJr>REE*KT)@v0Rd;l>A+GjDi`o+y3F{;3_ zY{7f;&)4Rn9=pa`#&BW6w)5k7;0pr$7^xQwl(Bx|^kYu9TeQF;kAzixWeLi{Q$|QX z9Jk`*@8YBHF5dE?)Fb#FA2iwxRJRK@$HVvzdKG#FF$aJJY|mS$XZ;)gU0 zAjd|Tafeq{iXCglD&DW|$8U+Q3Oka1^Tf_aUr>l;Bh8G(0lMVnM5I}qp=y_F zam<$0B|qP;GlJob`BW79t3-0|2K=;M{&GWngljLoRYnB~ z{tL>1E}A6aWjEjH(CL>SkCV|QH}VD|UX-Jgf!K4$r=7K{kIwczOci1=uoFa4Ga9}* z?I3Nc{VgaR6&`N!sEw_w8x0vnCfC@%7~j ziwk+xKltwH5wIdvJ|T5D30K3&zlXWudqO?xDih{Y#~f@3O(Ap`sqP|i=ks_-aW1>m zCFMdJE@?pm2dqVLDaS{?%$XE1emfd~Y58!_wdnA>#$n@lzZw60)N044Cx@;5U*f~Y zFU_;9?FWbsnhK%gh<989-=)Wcc6Fl(L)3)(XVEduQ7;Y#BV~sEu)$&S1`Wl%2Z;LB zk_!t$lFs8ymacTM?P;w>wneI9pNxlhTJ=ttixq7F1i3^Ogl!87W&W59a#Be@k_&kD z3|jwzH}tq=cM;7G#?8deD$0?V3`?O93CHh$@q5uFm5y4DQ1SL?KIc$WQd;nB1ac;_MBYtvqK!2oWd@x!CUg z0jw@4{fZNzxiTI3_o0eX>L1}z!_J{^I!^GWFl>{c4wuOGj2BF@Gahe zD{bI792~TX{<3DzWm~6>vw?$;uQK=SO$U%`h&wr==HQwUY` zlqDhT)VLwlZ2`@?0ji4e7+CS)!_C5HJbg1+=T*zMwFJHdju?zo)f*I@p_B~F;8 zVbWpj0G(ODCS+8SyeP~(uqo#Tg3YRPr;nKCon#FG5TiNr=Ej1v@%R^4|BSgH64kP4 zHy)(yz@;DcvK$|&n|LUL-kkaolz~T&e0hLvLEc!@6r%u0ET@9TiNQ!WI(Q{HrUfr_ zrrI+KxE4F61&eB{)7RFmf2il#7)VP+0*=uDEyBONoC+X=zO_b>&DLq$I*)(cj(=<% zR>YJU$3tvp^=5k&-l6xr(1j-;u0hDpt<4IrxAJDj1;RnPy=rYbsu`HxP&1r7N;Q)q zC)-m5kHhk>U z#kTh-Q8NG$L)p=|f5BuSALeTA6zr_38W!sabfRV^+=(+m{!TvIld&^@zIGmUzINu% zmoJj?VBAY?qdnf?a(IoZqm=iOy_ZIzKeL^% zeXe3^Wyue#kAP(0h4)80FM?A&JG47{fn)wBS>O&4h#zzy8 z^!vA%WR6LI{oBI$5d3;M^V}=5nk#QGqn;+bRdI{FD%{x3t46SQBu7(17xUX%lxmC~ zi;!zzwh#{2yDz9{Sa5{*b@dDN|2X62S1{Y`I~2`hT3^avc|vI2hRC zcDAU&!2Av}u3c5%C4A00e&7;bJbDYV6Zu0MYj}smcLT|myhQ>bLdtLr*{*vFQ$C)| zqD#my?kG!7^74(Up`bn=7W%2^pWOP1T0ekKF4i{=zVp;=0$D=gMhB@+@tnFq=mSZQ z34W(1XYF$$ROl-pLFl#~>CIkA(-d>rcx+2DbHe0)Vgu(Gs}wZM+gPAo$9RP{?n_r) zju&Y-<_V9!vlw4QLD9{-Qb-{=IPgChzkcQK*T?R%8vVv1Sp7VYfBOZ1N{~ zPL&>Z@A0ZA?L6&kUWQqe;oE)J?*(#%L|C~kPn9;Dpd~nd-{(LJQ*R4i_iH%_5m-o@ ziA(Ea;V=bu^*&Sa1#bEcJqp-ypPrl?#%Im*=Gl);*hr!mk$TLd^W#H2jrH{-cq|i5M&M*Cd{Ao<&$9-%>R=djJ-bTM&J~2A;LTwqvdg;&lFi9F zYbK!BJ&cCI$NI8{;X&?0Y)s_vyPaWoHiTPcK!lhyZVv$>7xz(<4uT?Tnw~v33KC3Q zRZy*VN?;E_)@U5IzCW&*mAE}WliU~#g=r`XD1&%0#xS6Ga`_K@SCO#V3YN0N*W^{# z^A5g>j1DTDG!-evGB!YAeor2N`TAHqsLsb8^p#za(Rzq`v5}S?C8OHR9iOxz68i%P zijYEGC7SUrES1sWijyhAcF=s=xHxRb=gs4Tqwh|B76G|TmSlVin`!LtH&5HTAu&+@ z3el_TMTA3!OM%g4MfF_?5>_qD_N!INEfq&3!|_gDEjl~hhxF=*Nt2CxP+1G%-`X}j zqu%}3%B5W{|1)F{{Zjd#Hz3=ylmB^Vee)^*^H=yh<$tar6L`x1yg>fves}E4)SM4S zR`TTJHtC{v$j!gpz3UE>%%Af&lyWze3)q|MSEY45xHvjx%=_r5aeNTBTSrYcA@R{U zqvZ8pk`D| z^2RQS5p?sR6lJpO$){)|TFFE_!Ga>U^NZZfFVdP{B#kZ(PRkT)@0Tjp+CM5+u2iXJ z`(5K~ZpryAb(d(iV!XA4S(CI0rd76wX=_Z(gX&m560@9%Y?A}l*;QvqRj7gJaY2;; zu|R^bJ>aq`mAT5h6*T6sTbH?>3kQNffB}d$xh+}R$udZQ2ycKTLr>EY+NQm7V)hx= zzQYM{aK;*Ln5fhn^qDNDaw~|(Q7swk99Zh%WpXtbTjzWEl5IG%p-|ai5Bxz4ao_|f z@Ow3f2nP^uoAtoX-2B%{giXueyH^zS({YRspgId3DZT z@mjw{ClK-cyTgn$5V8`x~ExrkD zv8697_5}_^M=ElRJGJmhyTeJA=s65bJDGYh8c?BjxDTs~cx!NdRyeEhHKHO;^Pg2l z0BP0dK5q@u;;Mh2{(XIG>-`V1DA&|9 z58^4CHb$AFmw)C%wuWCmbv(sH^y0;!OrjgHBa6zf1T*CMXlU2y=|hJlF>LJ} zZY4_ki+aiUU=tkL@Nx?GD(TH2D3_l2W+!a7nK0A^rI!x9&vPg8x1H&R68iK@x16j7ZP32-po#&dK}gznH%4-|bUM{|Bx#UrhhE zx%u+jZCC%dvHhg~`wE{Y{oj-RZ(;o(gdQGWSqi|sH<&n&hJ#Dz8APKqpCzMCdd>QC zRf>a2*QaTOQ=I#h5#eMu?b>gW?rfTL&4&;W(|nTht3vbPY&>89TUC>MZP52UW1D>H zJRjh@u}1@%qN2up4mZ?m$Zm~x@G<R25JPTJ$C)waO?xX|1($!I}&QZp) zHJDE)!#HJxlXy#TKT_{2xZCr-P=9l;rWfx7`FC%1Ibmg$#7+aIw@si(0tPGIcb}%6 z)cXP)I=wHHH!$j~Gm`KMPcbr*uP@f=y>bZHlAll}eA7q0i@f$cJ!>5`&VGrRV0YGz zPaExbQkPTaup+!rN1cz5b#ux&jEe0dPGUU1NM{JE?#?=p@w4lOk{sP|&l&fO(x{0+ zC*$BJ9BjV`K~^d?sZKKv8~C#X(mv5Je^4nX;d>K=Lr@?CbDfUB9E?{Sue`@uD^m_f zO~2?YZ=u+vKN$c&oNzseDm=EOo%|YeAp>6EKK+BC2gpz-(~q-?EU1(&@B6M04JP}!7#@-uG!9R0?>9e-DhLYn}? zXf;T4trndnqsa|5qKV{w&%{g!2PP9o&8E|2oJ&5l`V8#D_$#*SUotV26@-Ckb2Hgc z1~O}M+f9-lAnmr7#xn@RPC|cRduvoT51eR<5U||`|4n*6%S2u#0{`XzIb(tx%v0-_ z32ODo`1zUW)LGlSTICEyzxb$m1ZalzJfY-(^CPCpoe*?k2Bffifq=l@xPf!kbHf(b zX{IPOl9_%NMIhL;$Abr_Z?W4Gv~On~xOZqv6}y&g|FFGPOoM&gq+(zz)4}D8!4g+0 zy@b#GWXf=0pq>eZpC;1)?v$V=Rm_++Mm^;*|34%ig_upn3P7v1s9!cQMcKuR4KbL7%A9w!d2{S*b@oF;IzTk4?7Dc z)76IrC-p=M_B&n3F=Ggk?r^}^Nu}QzW{KabU2fPvx7w8r2>s+%4-g|+xo~$TuqT3U zEa%!owZe6qm0DGNt5#(%yaO>m&aF?0C@>0cvwt&iE#EXq#3Oeb5gUem89@WqbcXTb zOI^Wdv~f@H9*S*Lb4>p@*d~FBMSE<|K-ZCRTEQXhpB%T(P7dStyR&BFAU3VbA8vyQYgpJ`HPXB?2pHZ*Q}G$yq*Zu6u~^e zMLi>r{qxpa2xJHs+Z?R&QFGzY#YiU_qASN7@LO!2@p^0{-+2{5c268JIBgjTGt7IX z9XB6_w?ptF;!em$Ksw@!To#S*etIY+u+E|Hz3120x35Bf6oL)DZvwymp>93d_)t`S z(<#4ISbp0n|MJ6P>*o8`+qZ{}@6Ydpt}B5q;KPYTN0_*T84crYtWP+%AA_>{w+Mb+ zoK{OOlY7IP&4-tCjYn7BHEvHb4}vB2qhVID*ze0y(E_37^yK{KR@69c2|JZ!IJuH* ziK-v3coR!}BuhS22}vu&Z@tqofdtg9TD>e3DVM7G+t7lYQL*_A$;Zjzn`T$qgPm40+SmQoolOhEDSk|=T zWm>Og2sRgEb2*u4i9w?pQ)d@9_(AA!R-(F{a#!UG0t*Tz5?(O^9QTHhuX8r;0-ixh z#THyfGX|l;!KKB$_!drkAM4WwA?kbY6E1TUB&6>fM&Xrsl0xNlVE;F$ffj%{6xoK3o3rF`SL)phX_ z!ij?qZ-XJa@~YUiqkmYX<&*DC!4B$U7}8M+4$yxXv&WM5f6_+bUPgd(?EkjD-Cnot z|2Do|-*~eB`wE{Y`@b48jwk!SMeP6XvbEXRHNfM_aQAtVPKF*UKFoUC?*+~EEPFY{ zg)AF45h)2x&0J$TpYdCH)49&Hd%ebBjp2)BH#g5D&9Xb2q<)h&`5uB*jk1!C&vR_^ zOrtXCr;NFMG2|Si_Qfa|{?A|FCfJvvI8qnCJp5G(4uwYZ5X!EgW&CWKRa(bCHV#_{ zST$5-=jF?-m)N%*#OuA$?T1~E``2G#T2_&>g2^whB9YX9aha*g%t>MZVT&>#w%w#~ z2i6D~PP$C+p%}rm29+9!MfkWHRdkR;J|(C#v>KWwqY2>A!Yxk+4Y;){h?IB#V`A{| zSkOVN#K5k`6+1$G z>I`z_OXH=0XMRb$UHErx4i+rwTFJ z7YVNAj9ba&PsX@dE#Xw|WyoS+$O%-}txFvzGjNcJS`vRQ`ak zyL!jwW-kuy^6NASX`NS%_uGe%2(XSrS>~IXUf7Fx=0YxIHjw8%kmETu^Pkj^74oI?CO<)JFp1!-zk2?cGaGo7L+@RPFaxFh8Jm zMJ)5988TjJd&pB3r3{X|3PY=ww{Hjz#>ndj$vo@)^aEc*{I_8I^PEo#nH`nMAA{W) z0)Nf;wHGbRi84Xc7WTuE}W7jnO)3Tv6OYs4MDG95>o0N3H$1vH#bL z)>+fIdn7CU({#Y479YP^)eCBwz@qGE6{J;lKUEeRy+O7xI`Fa?;(XYbVECfM7-R$f z0XU!w1&~QYB_I~GQ7B_8SgF=ccq?JkpE@6tSz3}om2)MX%W}RV!wK_+;K~t5E|kl> z3z(ECBv8WON-x%dPJ*e=u4ce>TU%Ho-^oT#m5BEgkaZJE00Ig0n-Y?-n=3-fVFDHY zw(AjnPQ+eonu;7w;8PH0Pb6_yVxLGNOwv;;A)-)%eb@j5j*P4zoS@8aWeKc2|3eC^ zN1|UYh=6#_f7{m#)>HG`aDRd%wfS+u(hI$J?`)*sv`Tn}bzpZgXi1+c@j=~l`vYlO zcD+kt>?RE3XDSZV;KOQ?qLxY{3_d!qh;wF%-n>z#FI_>R(OY8~Peq5#<4y2^sL0xN zd5K|!I`b?rNeb%7LQX5j@>XE)d5L-bL+H4RmjIaRL|vx5ctH-czPNm5U2-iIXk$M0 z^V^EJJ4`x7$0l1v#jCB-n;_0&3-)VXr_ACaY6VY6FJ4H#tFNx+B&;q4I;o5PnuSv2 zC3>@a1Oc7)gNLJ>r@YPltJLNU3tvNE3u`rbR~C&E%%aO(Wb;YX;eNW4QJSFjVmh5L zdLKnhNVpcqQK4NH7jjCxFaO&X-4*<-H8@Y`-Q}ErwXGckf}t+rRe! zC!atQa}AdA9QrvHq=e2aG0p?3ARZUi&-OWI;JG87%iJEosT5-nyF`d5gw`hK#~M<- zOmrDzuQR8Z>Y*}~l+S|!p>xWo{E7~8au?vB?9ohTjW#n2S%w21OauaUjFJ&|w?#;K zem#Q}>hpRkV`Ey%{!^sVxo-%_Li^8+jg9Rs*Zy;B{o5z|&#&-#vj42%Qhc)iT*Uq} zXrqaDq^^0UPWG~ZeWk^G9%L6;GJIe#EMbYTfI9S`GR`|{9?7s9ZFYpkkZ@FrSXu+$ zgth0rwY-ykgnxl^FZt?&2x(W3wl;;EQy%e_z^ayeEv%)3UOejDV!Rx;xwnTG=kMb4 z*7vlz3j2N5K589DFQSc&svnHw#`n!LQU8eB8*Y$1I=-@J&1Nhu6F27$ z!N0~^4F|mDkGv*i@ z)uAVP6UeCp5?BBlc2Z(|XUa~rQ&y;(&bY}n+j+XziMSo8MW3$O`A4R;KiofI0uqzw z^2sC`cBWSeH1g*Rk98{m+HAx?6?NBal#pQnFrf2eAfaM7q@lFA09&h|SnXAuIWqYN z@tvD5+S$0CyCtJUI(isU3gBoeO zJdc93M>MCwk_gLQq`)l=45OB0Az-vB)}ALu!JzZv8!H^Jomhy&!N+8HSMl(8m40V= z*$aW*mJG+y!jc+TSw5hN4k?*!jNt;|If7LO!L{r*R4IHg{FaPaq?y61Dc#;qLcLI^6c8a2n zqF|Bw78E>D>t3dsS}(H>G$;~+uR`gv+hY3WBYCkGVr7KTtURGpsg`PnyR*;}o)s$)}&^qsTw5hyxit&-}q-jJ~}ial?oj`)_!k6-PIS zc!%eIce4#4*Esv*4aBnVP`Ij;0y3V;fX9Kv<95Yd7-P%=>u-lDD5@S2O_tL-1$n_^ zKsped!q1Su*U?O6R|v$8S&0jv8$Yy6Zus!FI)*6qc%*Mu0xmHfG#NIpqb0Nnk`K zg&~(X2Mq|(@UrS%-VV=qTQI}>EH12DA{b{V$N@$`RS8FD_~lRn8{=gUT1 z%fi^9FFT38L8x)*r8Z7(%^Q@kbYR_+fB}r5Sh}~MrRENrT=5G^`c{VRsYR*)dak&a zC}mC`ow<2{?eXmCT5x2NQJg^jA>@4=nHD&Q;5K>Ewq-@ zoXpX|*lbOH=ICNpR=g|j{_=z=z;lUESh9NdCns2wRF8=x#S~K+EnWRn+~F=^+}7Ym zr}7sqdTI!q7eI)>>u*tKmL*vP5<9;{N2z@&ui|nomD{G^!MI2~x(33ee)ngtePr)Iy;i`eEAx{~7imGV6 z;HfspW(SLcNd>~i&wdXYmnUEvW70KT8nr5`ZjOZYJj$-XGz2a@StI;4`>DN^L3~m= z)X#;(QQ*iSQLH-HG5JNsvJH`-RiUVcW*!JW{84Dod?)~kg*ERWG&K;4Hf)n@YA&99 zR37|Jvk$$n?pYV`m(0Ihf@qC29o#_p4vdHa21M{MpUCGG_$@F3j~+%h3L6U$jt!8< z#s~-b2!v#Sw*V#ihZQ6xZBgf?CFiP6vPns>@O@7(%~ezc>Cc|QZny$I5qM zso=q1CM5Vs0fP5xj1XhdpeeR-WQ^;^sL5dMF{)x&U2Q!e+dvY(iC>=3e*G+NSXksxV!^UDxCQ2aTvKz1y3b*#d9`d(UV+F z4_i#+Cf{k8H$v)-=ZXr{5Dy!ZYxBNK)7(NSn5tzDn0Ox%{WtsXRW!cO2AY1n;-Z?^0*zBSXXk&A9Y==tr_D)%?UPMal}59`{+vhBI{C) z^6}TD93$EcP(bGnHMm-Bp-f3UAfSy>QzR47`y%c;KqyKGSQ35Yy?jJOFsp=oR46NI zuweWJaG6}ih07*E7cP7HI9!&mj(ZfKTO<|v>6Fe!9qO9_ybjjjdsO#`6$Pv5y!E%{ zhp?W3?_b94%HuH{%og;60bW<`fx+FU}4{RJX zupz1NMllA^UL9W?m9rbt4LqMklUXjkW-&vX9QL#`zDkgD>hi@(DE!B^HQ`Lphj9kU z^DKUTJzIiHbUCN)6*(r+`2@%nVu^zu zo2tT?vYtJUT74={U}*!vL06AUP*p&p3~8Jmz#O7S<__)}KReyWkm_Q|{+lmsIUVM@ zHfUSzdxgL{tnyj9+7nbwjy`Iz>ptZn?UKnvsCl zsXEou2whd{yDnjjQev7Jpp9-id;C?l2!}D+re=cFyQK8g1TQ!D#7K8dY8EK6R8AtU zE5C-dXVz;yj%5Z{Q;;z}bs!{5XNso{t0VC5V-nI@^q09hJZaWWP-57)Ga7R`d_FVJ z_~xamo_=!-bwBuC3cI&Q=OPpaCau<#tNRUpxO@*1+;>~7HHj2M%Xwvl%4W}cB#cLc_F+s%eM+i|McEw_E=dzoZaxgBnZ#YMnxtvqAKZncsS}t5xg$=u? zhrcT8!EBtHr%Bh%u@LnEA!d|U?=uAo^THrGjCkzZ+ic)uId^(A^32XD@{C@k=o{*; zaLzov*)t_O)9nOLvaTzcchc&SPd7lhqha!+MiWd@0nK-^yKy%jf$1!z$x@my_$;gu zN>S5GrX2m}DccSahF;iILu4>R&d?h_7mt}E8aeP$>-)0?0~TT?!cKt9-D8}ouHn!= z6AHhL&rjp#@n56g)bD+^BmUL$Rt*fs@31;AkDEihgk^A?lp8nI62Hrv|AdnIcf`SWmKu^N@ zD6A4TD+cH@7S|l|R%$Hfg<{jX5nGF~tEoH7KPr@|ZG3DJv0LVKqzV5g#(d7s+f5Wh z-Eb|cA*n#&;iUZ<3#T?dSgS?jNtDg{{XusCUNro!THkwF+CVBg8M8Qlikq)Y=zayr^^yHU`APwPbb!Co6uO_|F*L?ge;?vM{`a?1DYb-di0qaAbT; zCs)dBnGfPW3vGeB;!)HUjHAWy*IHh!M#Ib~M9aCdgz+mQY<^I*Dn252>YWxaRqQl!8 z^;7FK-@J)7LSdZvgo`TOPTJ`X@;gSDq)iV^Q;H@fKNyWZL{Vmw5gp(>}bNANgB97Mia@B3#@%Y+fPl>aouA*Zgbo>dz$JIJRq~|I&`-MR%gcA zUO|iPnZ+n?2s5$|hTjQ!0luBKP~n>bMhhk9K#_kfD#E<6 zBouuI(5_|5Y<5Z17WPT3%=CCxhHB8B9}1*earE-QS8&fMNarZDFzE!5=jQxqLpW;Q z#b=05PtdxnCclXxmY+w#N=3aQySlmsAm4Fq{g2Ag?$Zbv&tZT<`ymBkzXHyqc*C3- zGbeSuKcBBDfiRv0_jJOsIN`<%I#4a<1md_{c~fM^t9zb}MIaNb4m!Vb@#vuA=UJpo z=%i7CFq%cQ+4o`afr=|{lo4uJ_Ct}+Jxi_I_&CoeX*5HBYfcjw@fQO8G70cbcztH8 zCYF41Wb`6(&Vx~Hp7U)0lW!=Q`T2#d=yW)Sj{tOaj494d{}R9>g>guvq2#(DJ}h+MH3WOXj^}b z#iZaVyQmyF*pib7izDQrX~w#aHVl7%2fkm%YJ47}x1OO@d1wcKp%(4{aO^DD0(9eL z_5pi|vfgC|8oCE)LM}FHw|GfdbdjUiWsxj|tS^ePHLgcv^Ptydc#u6jA@XxBB=CnU zC^YUF;XwSv7Z7#s#er1w59UCsCB=b)Qx@VqY-p;L541)1w8M_Q9x{~?C75EvBK*4zBWo$odvX%bg}x@pW0vPxfumjjaNw%#VRJt0+26695uvoCk?&kX0u`a z)769#=Va!I^Ogq;?@ZHEwf&eEsLSZ>y%A#EPD}-i#%ziba+mW-=F1v_dSv!&-5>ju zS-y_|xK5>@-7vfuz27tlC|sw;D!E&iRV4=E=84Bh zk5qpI>k(F(bMjP#?Fm32NyFng{&m*l7o3vf6*Awr;Gt_HD7Tbf6($HJDBRBMqI~{w zd?piioxHd@);;0=%dl&A1&-bI=RNN&z|?IU@*=JtI1Y{<&f1AhmBHJIO_g8;wJM$0 z@xAFesHC=UCX06j4R}4WjjJtVw6dFmf1vl=BRt`i@DfB39JvhvX+L`LVo=(a%wT3? z6ah8N@1M^;po|FDA&Sj;kr3j2Y|sOv$-#$uWZbeC@2dKqB^YAqk#{y@6T{Pz$NCt! zrea&*UrcX!HNz4oGe6rZ+WrhHeq;Y5=vn{p^>@N@yz5@HI{vq(REfaAhF`)8wPKw3 zABk@k$N>xR!V;jB;cm9XsD*Fl;)N3NDc$)=&zf1#V<5gAxbG%#MD4rd$9zptWHyo*|2wsYWyFc zEevcEY-T+!MfgZ%l)vTi4)_Fh216R@)him>B+dBpa`eCJw_8>C{bDcLrf{cpy79?g z5$)`HD?&=z4@DKRK)CYeyvmyemAB?q-uhtds0_T#Yh3> z-e=RqIN4-&bxp(CGH$Y~+u!`c?QeX!_I+w^YS{+d*=N`mTG?RSkP4XKNkzs>PQ^wt zP5NCt-pD%QNsLjzspX_yV~-s{3+;VIl&`U|^Gt`J+hxbuq+iD<##j_|tQ*7tVqSP3 zK4>y5Kn=D2w$NfQ7M(sN6ibzi7=tJ~k)q^_JzAq2?gMdJ1K5w=m`E;mN#Pry+6jTZ zLSqa0pRn5X5G~A?wgR;BjYTWc z5!W8m>c9k*HP1)qHs(Da%a7j-(LSA8mg8L9w*YsJ%Kk1crJ3EF6R@ubb8uf=p)p^X zQICGDhW4h?OM;%+jYNH9CDJoviQ82up==Z8ty{&UUPtTT#G!t_+4JNv)B{<>SE1x7 za+xD_<6r9l84B>^oEfTqIi*YuaQFZ$&80ONCruYd!Vq9`x@geW6O74s>= zM-9$Yr`9Bs`86lf3czLZ5(SH&sa#ul$xGp>(CJo0Cz|vUcBt<+MQtj`%AH(<-vM1^=m5D5P)@QW~a9v&6X9*mlly(mQo4nWJP zX_esM!g2?{hyNyVr$&yQRC(e!qe&qgiECQ|?Aw%W;g+Av5Kwo27F935<>V4e0^Sm4rUe7egi(My3bDUtH9n(IfqyIHKWUfTiWn1H6`Qk1VRik{u zZ=0k`kh0E%w>X7KPjpfd)QBVp!()Wk<#Dq`Y}3=mFNY_M0~tcKc!+6t)V@KFJG>2Y_R8>8{0cu|F!+xhbxf&!HE3sOS4)fk> zw7I^yzQX=&tVWF?lPRHErUEvvLUV$sAUFMR&`rh}JDAMIJ(1z@Xg2JOqto-l=w=g( z|1z0HUG`|kBo*Yv*`%L;>M(ZQ=`u3xfxnS3L!5iMog7Dv<7laI&Ymts-!;x#=k@5PR{Pz_MLS}p**4N{HP54y zx2)VR(GRWTgL>3t@0({)^JlhooU?al&`0a&^sv=rZ(GOvhZhH}+@BrJA^74{uNo5l7qwNA7@bd*|@RH|{kaE!;pe|4AGCoKLy^f0}@dde7~D&i=o# zxv}xm+5b0pUOw&rU*W^{|Hs|_7u)^6(B{9$-oMD!{}p!rFTe4VeZTa!&vt#fzk~h1 zv*!;7m*%tCc)%W;&-?;I(w$9{uG1nYE#V<~I{Y+9*Wl09KiO814Q}I3Ixs8JA`r?g z@OF~snc27$QW(vHeBuf(f(=sHMK~I>>BD1a^Z3X3{FigSVJ#gV$QMg?h4T}Pl@}SG zC5A%Y*J?I#s>nW|UVPX*#ww?c_B)VuiU49Hy3gDHzVWx_;bAlWju9U|hPHwoL0u*f z9hh~6gv4vAs?DE)R`KmYyno!L!`gTz{gQd=AxuGb6(_fdUUAX)-fjVrTw&71 zbcL5%($X9RKj*MS37BzkYCx6Lm7FSQyO(xyun%Dr&*Z}f-e3!LhB>d1x)($lQ#Qek z`Gf@=fS!zR;GV3DnS}y#Bd*?2>ke8=fCI`~&B(_E&FBI9f!1RkjQbNQ@oN2|IhgKs z0@r$jaSw-J)M5N${IRmM20gB2$*{kc z+$KwP4MANIceDZ~RIm5EQ9G=Nf1J9o5sYaGQ8K5~?)9`n8vgUzpNZu8jVe9Ad43r@ z9d}1*<;4qCv2M-7DkTy}w^!5eV``g;1soIxc~`Zh9AI6%W27r1cQTt8?%$*;@1DhdFwF-3Z2k5I=eD zfhA$@1KsUCXHvvRG;b&XiXVz>PQ&On>E^i2i0udnOsY#^o56Qc4gUHqGUX(8MeTm-D@GTIcE zXU-7-@#wTXvz>hf>c=gH+E_9h(8(-uF$tgA_rKN=mt_=(BMDN!>0O$Dg-`D?K za;D&BF)&a1l_}tOP#WGEecS&d5>Ba+c}69ou2Z-<3v;AiOAzvjQl^j_>BI%0g(=SgJ2Bpt=EDi6#RULeG4!;GSFZEUXF z`v1+Hot-EB|5x}t>HnYf|K;@mC2svY`D8S()%ZT$KBO`ADfW5hmCU2DN0o*9IPa$J z(_+29eQ`ka{N2fDG#Rf60*)^`8MhHLZv#Xr%-qhudv6Ouw+P+7|2eeheUaqXz2wH< z)?}Pd!E=aBUg9nBsRMZPyikAruWtrZw!XZt(Bg19OZ^qCy~0;SL>%S!C``P91VTSH z&(2$H3B9Jjz+)g}c#6uO*P+ul~W6I?+`C_j8ghvXEj z9SJ?BSUa?($#{Z8HqU6}jc|>~-phUq5X%QIk95>ekz&-neGN2*4N2cZqE~@jAaH!` zq-g}(=WIOacF+o2Xu+T&FCtpfS~1unxm11JgN70? zIGJ8>kg1H2xX))&&iY{2d1b8*t8KHq9o0guV-MWW;|G^37`!Q5(X?a5nUXf9bLOgm z6U(MWutIe;uz$*gvWxR(+&TpVW>j6H54c1P=f!2&RpA~bX4}J^AUPM?fA7h=e3v*S zDYGp3Elzr#u~`&Ymii>Ukr}odhk4ZjfVz*0A+Bg_TJe`f>3B%x|m&h5z=SCm_kKKldm#YSqclv!e{@=kh zW{ytugMTKIzHD^RWBXS(ow1VDdbI3$slu<%RX1j;F%jR*T z7^ZTbHda8v6HgV4So&v*(Q3vN5IAk&%i3$v5QSm+Jzb-Gd=Q9<-V+zJHR{~*mL$2X zm!SqGoN)MImIH=PyDrC8AS)47a%n9uyJZ-~nNS)&x;FfwR`jfR)*)F6YOd6QM>hx8~VNW!WHEczoV$S9qh4r$W9ZD+LHo zFBS!n)zky1-@ge%8r^8n?L;393Jj(e~d|-~6 zMNdslSP$5<$V#aFU`8H-VEmrV)j5fHCTE*(DF`PcF93vnxACP#izm>IHu6tsPE$9|x&mo2-y+VFZ1)&IO?(G9gljoCJG6 z2c_p=JR`2oBr%4JtyXdCe8dkWz5*i%ObpMm6?bY{wp+s;Nj2CWk|E z4$pLXCQ1!NNOkz-H2{J12Q@GPOz)N=THz6jL8GXZk+}3?ac*z0K}frtl0DNZ<)Gj^ z(YN+-k^5>&*7$lM&d9SfVLQCL%JW&33Iu}ca?kERCr!EK>_}y`dQ|o2K|nmc#fR1CMW8?~3fSgdsD9u|{s@9`)T8Up4L3Pu6FHrv(?KUs zqEV7xPkJCoLH0W_B9b%^Ad|>HJ&MnMj!%DRpF@CO9nWGo`4p#`~TD#+~V4lIhsI8>>-kj5m9|Bu{vhgEV1f z*k&`}SEg(UUM5qx6P+gAWN-tSLppf>hF7;qmT|2JUcF*6*2$2V7GvmI_KJhYAYgC} z2mj(8 zyNn4>pDg22Mb~5KofEWxC&MUj(_2gMfr7pU0isGpyj?N7hoHU$LkG=vbD!T${Pvpy zm{&#^R_tX~1@#|k0T3LwjzvpV+i3o*#sUzqe3wUI^*E%d4AkrOZ{xzcM6qY;@Qo3CkmDCaF>D5m zlF+2qf~ff^&^?=~71j~0C7z0vVDH&d@sHXzt0ta4%|SSVo9+|8frcuc^iefvG;LjL zTD4yXy{iIx9@3AOwR)HUX9R>DAbR;`pRrvw>EQ{Fn7NeWT5c1IF?)w4A#Xt&pDYAOb;Yu<2)?$pFQOjrsW+k1%_EAcMnOBk3#-gl()x!#W>Z7@@o`QuemD~h z2R_NEm_;h4G{QJ|6?M_!7Os+wMOG{6jWJ3_+?#>dQ*walzKZ)Pxn(Kt+!PVTNUO5x zC1Fg-UGvyR#lLW~Ena5<@-iATH^BSvdPSR?6lay&kZ%%0muy`=i5nWhd^r*1iK6br z1yR5$L+Da{YYUTSHjfXSQ-Nn!$L$*iLpJF7qW8-Q-8ngF)8nRravJfc-{59&4HJmc| zL@2m>@2)(qU1Y$%ab1C~PAnZ#60H7b!`z6P%8Qp?(5f{-%3>Wyfkhppg@Bq9X>B-2 zFpbX@x=!(ZZNW(vDiVHfK0j#>jvN(CPs|$+NBf><>vgT7u$pyl$ z&?k!G`boi2rO48PS_@(y!f;n>d^caA5g!w_;j$~6jgl;0Swsa?q6Y4cb4({koG;I!w4upY<7aXVWP|!tjoX>4^yS zF-zfS9LeQPb{ew84gDr-u+M2#Qa3*Gq;GTJGjir~KGI_|GlrxNv=4YXx1W1)zk4Bv z@kWUlR{w|N7NcM`HyI-*@T0p*#>tdPjd!p#R^aj|YOS4Q{3Zv3qk{);lHqo5)W-X~ zfxal|u)SiCUq?#aaXeXF2i;{hgG&(DXANP1uyHUfwv{FD%w0+SzIjv0-F)Kf&KPcU z1#Fy~OEIIiO5RcO1mktjkZpX>y#5<7eT9oP zp)*QGDHtI6wxw14Yuxt~*DkK9cqQkNqOKYyEv$H$ahI*|?AZaRe?3J%zr!(=6w2>4 zrU%Ee2meKMqiQlsX&uA!D_ZkNfyClZQi6LL);f2TKus0=;^$hY18H9-2echn5t^me{$WKe&4JO4wP!eGz;W`wsj>>auj>P}F@WDphSGe?AOh z=Our57sgzb9J|$H8NE*JY_^?i2z-4*36sYnY9X`3lSGbWIyuuHC;NnQU zHHx{OJA@J>x@)1Pq8GF+b8wiRv-It?`~+Dy_v>L|;N&Kmx>pZm5z^}i3v;4WL{qk6 zR!rP%^yRnfLLf)vyI!3OyQedyiefm1ZD)p^iZq#eH$n}S(-C~6wYIYE_3T)45o3Py zsjqz;%yQLy#7k8BMo*_s#sY?u6uC0=xJcDimIa6@)jU6E|F(W?w3}3Z5b3JyR?Mwc zoSYUgKo}XK#XT+%Jcuv^4eBXDvY3uKWK+3(3>d!~&OUg#yDMW3xUOb*6WI zExBiFEDZk`@+aqHhLDSP?tM{7!f|rJpAdi5S{Hm~z=oJe<6&b^RC*4kSssJUU#7*z z%=K@@ecarcgG)}y+iF5Y#7UzwJJX~uGBByICn-%!6|-qfAaZ?cH51*a8sLTxBa7Wb z>WU?AB8~fW*wx4ocC8Y0^D~NB8a;YOk+r>n@a72Q5mJw26%a!xO~uens>S1v>Zue1 zDbx#>lcL?}^&Ns3lh(8C12nLs@Rj3PH9{J$OBc$ZNuHKm`9=}sL0UvCL6YxXQ3aja zU~WI_j+NviJdT5%8zK^sZnaN~8iSK2SHXmtYRj(_d$nNwKx|UDBs#fhdzj%ISS=Tv zlJcf>>>%<4wcuUr~IgK?!PcNXlH9Ef`0%==X$@vsDola+|M1Hj*q6jY7iv=oS|%(X@X#!u^Ua+7&90^5)G~G{RxZ>DPHO7HhX;@?Qi)jZ zS&DH3i-<1oOyJ2Kf*k)Q<>CRx!=^+Nq%FTb10=p$aK+iHCJ@or;ByfA*PSdF!Yc}r z2)6%>cq2jtocZ!}nVUXWBW7(9cIXd?3EcOGM&9B`^7!DhMIoP_HP4%8KQ<4Pd%o*! z?+Z{LiOVMpbA$qWWne9gZ@l5uL6y$~q)XiqjMTZWvgQfXf8q8<1gnuo;R;A)gnx(uhYj{?A^t zJl~<8Xwr?HmO?4+huODSY-gf&oh!ZT?qI2bN_JIB^22{vVYn>;(f7B#=ihl51J6HByW5*`F9Y zf%{J2v>cQ_<1ufRfkWar>qAVS39kD(Xso-}A^`<2j2El0Ibu8r=wj96*7usc;<;l} zCr=M$ap{{I`HdmLl~d42gzWd4_sST1-flH#{JrDZK7AJZl#2hX{^s{e0a+aXd24%f zW5lp5i~(kkLKGe_kN|voEouKZoO8wl*8P&-mfO6QKFN$s7xUI?oBa z{GjN{PK@Vyv7xO9(_k6HL|Sj#LU+W(q5H;J4n~wF{CvUK&%togG^R5TXf+t2hGm4| zYbP=0DpQVxm$QCUgTLAP4|U>FJ{w7y+^!FWE2z%IYIW ?vo~{`wr~m*EdAU5hia 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 literal 0 HcmV?d00001 diff --git a/gazelle.spec b/gazelle.spec index b31e477..649d843 100644 --- a/gazelle.spec +++ b/gazelle.spec @@ -1,15 +1,15 @@ %define conf_path %{_sysconfdir}/%{name} Name: gazelle -Version: 1.0.2 -Release: 85 +Version: 1.0.3 +Release: 1 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.2.0-63 +BuildRequires: lwip >= 2.2.0-73 BuildRequires: dpdk-devel >= 21.11-5 BuildRequires: numactl-devel libpcap-devel libconfig-devel libboundscheck uthash-devel %ifarch ppc64le @@ -19,365 +19,6 @@ BuildRequires: libarchive libarchive-devel Requires: dpdk >= 21.11-5 Requires: numactl libpcap libconfig libboundscheck iproute -Patch9001: 0001-remove-unused-dpdk-dynamic-libraries.patch -Patch9002: 0002-gazelle_stat_pkts-gazelle_stat_low_power_info.patch -Patch9003: 0003-set-localhost-ip-when-bind-ip-is-same-as-ip-in-lstac.patch -Patch9004: 0004-refactoring-preload-module.patch -Patch9005: 0005-fix-previous-commit-refactoring-preload-module.patch -Patch9006: 0006-add-lstack_preload.c-to-makefile.patch -Patch9007: 0007-cosmetic-changes.patch -Patch9008: 0008-add-loongarch64-and-sw64-arch-support.patch -Patch9009: 0009-CFG-fixed-the-dpdk-primary-default-parameter.patch -Patch9010: 0010-suport-clang-build.patch -Patch9011: 0011-ethdev-fix-pbuf-chain-tot_len-incorrect.patch -Patch9012: 0012-kernelevent-kernel-event-thread-report-kernel-events.patch -Patch9013: 0013-fix-bond-port-reta_size-init.patch -Patch9014: 0014-init-remove-sync-sem-between-lstack-thread-and-main-.patch -Patch9015: 0015-lstack_lwip-external-api-start-with-do_lwip_-prefix.patch -Patch9016: 0016-cfg-nic-rx-tx-queue-size-configure.patch -Patch9017: 0017-epoll-distinguish-add-del_sock_event-and-add-del_soc.patch -Patch9018: 0018-preload-support-thread-hijacking-mode.patch -Patch9019: 0019-cfg-add-run-to-completion-mode-configure.patch -Patch9020: 0020-statck-the-for-loop-in-lstack-thread-is-defined-as-s.patch -Patch9021: 0021-delete_rule-bug.patch -Patch9022: 0022-tools-gazelle_setup-adapt-non-ltran-mode.patch -Patch9023: 0023-wrap-add-run-to-completion-wakeup-mode-api.patch -Patch9024: 0024-fix-arping-gazelle-return-value-is-1.patch -Patch9025: 0025-init-stack-setup-in-app-thread-when-app-call-socket-.patch -Patch9026: 0026-epoll-adapt-epoll-interface-for-rtc-mode.patch -Patch9027: 0027-clean-useless-code.patch -Patch9028: 0028-ethdev-fix-arp-unicast-packets-cannot-be-transmitted.patch -Patch9029: 0029-stack-add-semaphore-to-ensure-all-stack-threads-setu.patch -Patch9030: 0030-ethdev-register-offload-to-netif.patch -Patch9031: 0031-epoll-fix-epollet-mode-error.patch -Patch9032: 0032-bond6.patch -Patch9033: 0033-cfg-fix-bond_mode-null.patch -Patch9034: 0034-dfx-add-four-snmp-udp-datas.patch -Patch9035: 0035-cfg-nic-queue-size-only-support-power-of-2.patch -Patch9036: 0036-stack-fix-possible-coredump-when-arp-packet-broadcas.patch -Patch9037: 0037-Fix-coredump-issue-and-skip-rte_pdump_init-for-secon.patch -Patch9038: 0038-solve-problem-that-rte_pktmbuf_poll_creat-in-same-nu.patch -Patch9040: 0040-when-timeout-occurs-process-exits.patch -Patch9041: 0041-wrap-support-select.patch -Patch9042: 0042-add-vlan-support.patch -Patch9043: 0043-slave-mac-addr.patch -Patch9044: 0044-PRE_LOG-modify-prelog-info-transfer-to-terminal-at-t.patch -Patch9045: 0045-ethdev-mbuf-data-start-pointer-pbuf-payload.patch -Patch9047: 0047-cfg-fix-lstack-mempool-lookup-failed-in-ltran-mode.patch -Patch9048: 0048-add-tx-package-timeout.patch -Patch9049: 0049-modif-mem.patch -Patch9050: 0050-enable-ipv6.patch -Patch9051: 0051-wrap-dont-hijack-select-temporarily.patch -Patch9052: 0052-ipv6.patch -Patch9053: 0053-add-gazelle-log.patch -Patch9054: 0054-PRE_LOG-modify-log-info-while-there-are-repeated-ite.patch -Patch9055: 0055-add-gazelle-log.patch -Patch9056: 0056-wrap-fix-connect-wrong-port-after-addr-bind-two-port.patch -Patch9057: 0057-cfg-rm-ipv6_enable.patch -Patch9058: 0058-ltran-support-vlan.patch -Patch9059: 0059-update-src-ltran-ltran_param.c.patch -Patch9060: 0060-dfx-support-bond-get-dpdk-xstats.patch -Patch9061: 0061-add-tcp-faste-timer-cnt.patch -Patch9062: 0062-stack-fix-coredump-caused-by-gazelleclt-in-rtc-mode.patch -Patch9063: 0063-dfx-add-tcp-exception-and-kernel-event-statistics.patch -Patch9064: 0064-add-vlan_id-in-netif.patch -Patch9065: 0065-support-vlan-offload.patch -Patch9066: 0066-gazellectl-fix-gazellectl-lstack-show-1-r-error.patch -Patch9067: 0067-fix-coredump-because-sock-closed-before-send-data-fu.patch -Patch9068: 0068-fix-compilation-error.patch -Patch9069: 0069-fix-coredump-because-of-addr-null-in-lwip_fill_sendr.patch -Patch9070: 0070-add-struct-gz_addr_t.patch -Patch9071: 0071-wrap-support-shutdown.patch -Patch9072: 0072-1.solve-the-problem-of-1w-connection-not-being-able-.patch -Patch9073: 0073-dfx-gazellectl-c-support-ipv6.patch -Patch9074: 0074-The-call-stack-is-not-printed-in-the-proactive-exit-.patch -Patch9075: 0075-dfx-fix-gazellectl-lstack-show-ip-failed.patch -Patch9076: 0076-gazellectl-add-connect-para.patch -Patch9077: 0077-log-optimize-lstack-log.patch -Patch9078: 0078-support-show-nic-offload-and-features.patch -Patch9079: 0079-Fixed-an-issue-where-no-packet-is-sent-or-received-w.patch -Patch9080: 0080-fix-example-print-error.patch -Patch9081: 0081-dfx-fix-kernel_events-stat.patch -Patch9082: 0082-add-keep-alive-info.patch -Patch9083: 0083-fix-close-can-t-exit.patch -Patch9084: 0084-mod-unix-time-stamp-to-local-time.patch -Patch9085: 0085-optimize-gazelle-exit-process.patch -Patch9086: 0086-fix-EPOLLIN-event-error.patch -Patch9087: 0087-mod-time-err.patch -Patch9088: 0088-fix-gazellectl-lstack-show-ip-r-with-ltran-error-log.patch -Patch9089: 0089-fix-udp-multicast-bind-error.patch -Patch9090: 0090-support-netperf.patch -Patch9091: 0091-fix-alloc-not-free.patch -Patch9092: 0092-sigaction-fix-deprecated-signal-flags.patch -Patch9093: 0093-fix-gazellectl-c-msg-error.patch -Patch9094: 0094-CFG-fix-check-func-strdup-return-value-is-NULL.patch -Patch9095: 0095-fix-func-separate_str_to_array-overflow-problem.patch -Patch9096: 0096-use-default-nonblock-mode.patch -Patch9097: 0097-fix-rte_ring_create-free-time-consuming.patch -Patch9098: 0098-optimize-shutdown-exit-process.patch -Patch9099: 0099-fix-func-separate_str_to_array-overflow-problem.patch -Patch9100: 0100-fix-func-separate_str_to_array-overflow-problem.patch -Patch9101: 0101-fix-func-separate_str_to_array-overflow-problem.patch -Patch9102: 0102-fix-func-separate_str_to_array-overflow-problem.patch -Patch9103: 0103-fix-func-stack_setup_thread-array-doesn-t-init.patch -Patch9104: 0104-fix-stack_setup_thread-array-range.patch -Patch9105: 0105-fix-func-separate_str_to_array-overflow-problem.patch -Patch9106: 0106-fix-dpdk_alloc_pktmbuf-time-consuming.patch -Patch9107: 0107-ltran-optimize-config-file-error-message.patch -Patch9108: 0108-replace-with-gz_addr_t.patch -Patch9109: 0109-match_host_addr-func-support-ipv6.patch -Patch9110: 0110-add-example-keep-alive-interval-para.patch -Patch9111: 0111-update-src-common-dpdk_common.c.patch -Patch9112: 0112-listen_shadow-support-ipv6.patch -Patch9113: 0113-lstack_dpdk-limit-mbuf-max-num.patch -Patch9114: 0114-gazellectl-add-tcp_input-empty-ack-cnt.patch -Patch9115: 0115-add-socket-accept-fail-cnt.patch -Patch9116: 0116-diff-lstack-and-ltran-dfx-sock.patch -Patch9117: 0117-fix-host_addr6-can-be-assigned-a-multicast-address.patch -Patch9118: 0118-udp-do-not-merge-data-into-last-pbuf.patch -Patch9119: 0119-adpat-dpdk-23.11.patch -Patch9120: 0120-modify-conf-vlan-default-vlaue.patch -Patch9121: 0121-remove-unused-variables-in-pbuf-and-reduce-mbuf-size.patch -Patch9122: 0122-optimize-recv-exit-process-for-FIN-and-unsupport-SO_.patch -Patch9123: 0123-remove-expand_send_ring.patch -Patch9124: 0124-set-ltran.patch -Patch9125: 0125-add-bond-doc.patch -Patch9126: 0126-cfg-host_addr-is-not-mandatory.patch -Patch9127: 0127-add-bond1-support.patch -Patch9128: 0128-fix-t_params-double-free.patch -Patch9129: 0129-fix-receive-fin-packet-process-error.patch -Patch9130: 0130-support-netperf-UDP_STREAM-and-UDP_RR.patch -Patch9131: 0131-adapt-lwip-2.2.0.patch -Patch9132: 0132-add-observable-method-of-data-aggregation.patch -Patch9133: 0133-try-to-ensure-arp-packet-can-be-sent.patch -Patch9134: 0134-gazellectl-support-send-latency-show.patch -Patch9135: 0135-rpc-function-does-not-depend-on-protocol-stack.patch -Patch9136: 0136-readv-return-1-errno-is-EAGAIN-when-recvring-no-data.patch -Patch9137: 0137-split-the-flow-fules-related-functions-into-separate.patch -Patch9138: 0138-fix-coreddump-when-stack-setup-failed-in-rtc-mode.patch -Patch9139: 0139-diff-udp-and-tcp-read-from-stack.patch -Patch9140: 0140-FAULT-INJECT-gazelle-add-packet-delay-and-packet-dro.patch -Patch9141: 0141-recv-support-MSG_DONTWAIT.patch -Patch9142: 0142-do_setsockopt-function-no-longer-checks-the-results-.patch -Patch9143: 0143-FAUT-INJECT-add-fault-inject-unset-method.patch -Patch9144: 0144-support-udp-pkglen-mtu.patch -Patch9145: 0145-add-limit-with-level-for-sockopt.patch -Patch9146: 0146-udp-add-restriction-message-too-long.patch -Patch9147: 0147-dfx-improve-log-readability-when-connect-ltran-lstac.patch -Patch9148: 0148-fix-rpc_pool-create-failed-coredump.patch -Patch9149: 0149-ensure-the-bond-interface-flow_type_rss_offloads-mat.patch -Patch9150: 0150-FAULT-INJECT-add-duplicate-and-reorder-methods.patch -Patch9151: 0151-select-timeout-arguments-check.patch -Patch9152: 0152-recvfrom-support-timeout.patch -Patch9153: 0153-fix-netperf-setsockopt-fail.patch -Patch9154: 0154-fix-LATENCY_WRITE-increase-in-recv-process.patch -Patch9155: 0155-dpdk-add-vlan-filter.patch -Patch9156: 0156-Correcting-spelling-errors.patch -Patch9157: 0157-perftool-add-lhist-statstic-tool.patch -Patch9158: 0158-add-udp-poll.patch -Patch9159: 0159-DFX-adapt-testcase-for-gazellectl-connect-failed.patch -Patch9160: 0160-warp-add-configuration-check-with-host_addr-and-serv.patch -Patch9161: 0161-add-latency-nodes-READ_APP_CALL-WRITE_RPC_MSG.patch -Patch9162: 0162-fix-vlan-filter-can-be-added-when-vlan_mode-1.patch -Patch9163: 0163-Add-support-for-arch-ppc64le.patch -Patch9164: 0164-dfx-support-get-nic-bond-status.patch -Patch9165: 0165-remove-dpdk_skip_nic_init-for-dpdk-23.11.patch -Patch9166: 0166-gazellectl-add-lwip-stats_proto-print.patch -Patch9167: 0167-fix-port-not-support-vlan-filter.patch -Patch9168: 0168-fix-tcp-recv-does-not-return-pkg-when-ring-buffer-is.patch -Patch9169: 0169-add-tuple_fileter-error-info.patch -Patch9170: 0170-adapt-dpdk-23.11-remove-kni.patch -Patch9171: 0171-fix-ioctl-set-failed.patch -Patch9172: 0172-ltran-memset-quintuple.patch -Patch9173: 0173-gazellectl-add-lwip-stats_proto-print.patch -Patch9174: 0174-CFG-set-multicast-IP-assert.patch -Patch9175: 0175-cfg-devices-must-be-in-bond_slave_mac-for-BONDING_MO.patch -Patch9176: 0176-CFG-fix-multicast-IP-assert-error.patch -Patch9177: 0177-fix-mbuf-leak-in-dpdk-23.11-due-to-kni-removed.patch -Patch9178: 0178-add-riscv64-support.patch -Patch9179: 0179-dfx-fix-gazellectl-x-for-bond.patch -Patch9180: 0180-change-gazelle_stat_lstack_proto-from-u16-to-u64.patch -Patch9181: 0181-memary-error-fix-some-memary-error.patch -Patch9182: 0182-bond-remove-bond-initialization-code-in-dpdk_ethdev_.patch -Patch9183: 0183-make-rpc_msg_max-recv_ring_size-configurable.patch -Patch9184: 0184-EPOLL-fix-coredump-while-event-count-exceed-maxevent.patch -Patch9185: 0185-fix-fin-pack-free-coredump.patch -Patch9186: 0186-fix-MySQL-shutdown-cmd.patch -Patch9187: 0187-cfg-remove-map-perfect-flag-in-lstack.conf.patch -Patch9188: 0188-redis-perf-add-tx-driver-cache.patch -Patch9189: 0189-optimized-latency-distribution-dotting.patch -Patch9190: 0190-rtc-adapt-rtc_close.patch -Patch9191: 0191-virtio-flow_bifurcation-switch.patch -Patch9192: 0192-remove-legacy-mem.patch -Patch9193: 0193-cfg-bond_slave_mac-support-pci-addr.patch -Patch9194: 0194-refactor-tx-cache-module.patch -Patch9195: 0195-virtio-create-and-init-virtio_port.patch -Patch9196: 0196-refactor-udp-send.patch -Patch9197: 0197-solve-compile-err-in-20.03.patch -Patch9198: 0198-fix-function-call-error.patch -Patch9199: 0199-perftool-add-latency-tool.patch -Patch9200: 0200-cfg-del-unnecessary-logs.patch -Patch9201: 0201-fix-dpdk_bond_primary_set-bug.patch -Patch9202: 0202-fix-build-failed-in-2003sp4.patch -Patch9203: 0203-virtio-cfg-ipv4-and-ipv6-addr.patch -Patch9204: 0204-parse-packages-type-in-rx_poll.patch -Patch9205: 0205-virtio-distribute-pkg-by-dst_port.patch -Patch9206: 0206-fix-coredump-when-get-empty-from-udp-sendring.patch -Patch9207: 0207-fix-poll-init-not-clear-old-fd.patch -Patch9208: 0208-virtio-mode-actual_queue_num.patch -Patch9209: 0209-virtio-update-g_rule_port-by-reg_ring_type-enum.patch -Patch9210: 0210-virtio-dfx-data-of-virtio.patch -Patch9211: 0211-add-flow_bifurcation-switch-in-lstack_cfg-file.patch -Patch9212: 0212-example-sync-example-update.patch -Patch9213: 0213-cleancode-improving-makefile-readability.patch -Patch9214: 0214-add-.gitignore.patch -Patch9215: 0215-cleancode-rename-gazelle-files-in-lwip.patch -Patch9216: 0216-cleancode-refactor-lwipsock.h.patch -Patch9217: 0217-cleancode-refactor-posix-type-and-get_socket.patch -Patch9218: 0218-fix-some-error-of-NULL-pointer.patch -Patch9219: 0219-cleancode-refactor-posix_api.patch -Patch9220: 0220-cleancode-refactor-lwipgz_list.h.patch -Patch9221: 0221-fix-EPOLLIN-event-dropd.patch -Patch9222: 0222-cleancode-refactor-lwipgz_hlist.h.patch -Patch9223: 0223-add-sem-post-when-update-event.patch -Patch9224: 0224-cleancode-refactor-sys_now-and-lwip_ioctl.patch -Patch9225: 0225-POSIX-fix-select-timeout-disable-and-build-failed-in.patch -Patch9226: 0226-support-kernel-connect.patch -Patch9227: 0227-Check-the-return-of-lwip_init.patch -Patch9228: 0228-vitio_user-modify-mbuf-index-for-bond4.patch -Patch9229: 0229-fix-redis-coredump-when-hugetlbs-pagesize-is-1024M.patch -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 -Patch9238: 0238-virtio_user-The-program-establishes-a-network-connec.patch -Patch9239: 0239-WRAP-fix-ltran-mode-did-not-bind-kernel-while-open-k.patch -Patch9240: 0240-WRAP-fix-bind-log-error.patch -Patch9241: 0241-virtio-mod-virtio_user_name-when-multi-process-is-on.patch -Patch9242: 0242-fix-redis-coredump-ctrl-c-during-the-pressure-test.patch -Patch9243: 0243-virtio_user-check-netif-status.patch -Patch9244: 0244-virtio-solve-compilation-error-in-2003sp3.patch -Patch9245: 0245-CMAKE-fix-ltran-build-error-in-2403.patch -Patch9246: 0246-fix-mbuf_total-calculation-error.patch -Patch9247: 0247-cfg-modify-maximum-tcp_conn_count-to-2w.patch -Patch9248: 0248-tools-fix-sync-patch-script-date-wrong-and-update-th.patch -Patch9249: 0249-epoll-fix-wild-pointer-detected-by-cooddy.patch -Patch9250: 0250-tools-fix-script-generate-patchname-wrong.patch -Patch9251: 0251-fix-when-errno-is-ENOTCONN-ignore-it.patch -Patch9252: 0252-rtc-do_lwip_init_sock-no-need-to-create-ring-in-rtc-.patch -Patch9253: 0253-example-solve-double-free.patch -Patch9254: 0254-WRAP-support-setsockopt-SO_SNDTIMEO-SO_SNBUF.patch -Patch9255: 0255-DFX-adapt-log-optimization.patch -Patch9256: 0256-LOG-add-log-when-udp-send_ring-is-exhausted.patch -Patch9257: 0257-cleancode-refactor-rtc_api-rtw_api-and-dummy_api.patch -Patch9258: 0258-cleancode-move-some-API-from-stack-to-rpc-and-rtw.patch -Patch9259: 0259-cleancode-add-rpc_async_call-remove-rpc_msg_arg.sock.patch -Patch9260: 0260-cleancode-declare-different-cfg_params-types.patch -Patch9261: 0261-Fill-in-a-portion-of-mbuf-to-send_ring-when-mbuf-is-.patch -Patch9262: 0262-add-pingpong-dfx-support.patch -Patch9263: 0263-add-interrupt-mode-support.patch -Patch9264: 0264-af_xdp-set-rlimit-unlimit-when-gazelle-init.patch -Patch9265: 0265-fix-stack-null-when-register-interrupt.patch -Patch9266: 0266-rtw-fix-send-length-exceeding-send_ring_size.patch -Patch9267: 0267-rpc-fix-rpc_sync_call-spinlock-block-when-msg-be-rec.patch -Patch9268: 0268-bugfix-fix-gazelle-init-failed-while-setup-by-non-ro.patch -Patch9269: 0269-xdp-skip-checksum-temporarily-due-to-kernel-cannot-t.patch -Patch9270: 0270-fix-dpdk_nic_is_xdp-coredump-in-ltran-mode.patch -Patch9271: 0271-fix-the-coredump-when-gazellectl-l.patch -Patch9272: 0272-control-call-epoll_ctl-delete-fd-when-fd-close.patch -Patch9273: 0273-epoll-remove-unnecessary-judgment-code.patch -Patch9274: 0274-slove-compile-err-when-GAZELLE_TCP_REUSE_IPPORT-is-o.patch -Patch9275: 0275-bugfix-start-fail-when-executing-the-popen-command-f.patch -Patch9276: 0276-Fix-annotation-errors.patch -Patch9277: 0277-remove-the-unused-return-variable.patch -Patch9278: 0278-add-SO_NUMA_ID-optname-for-adapting-opneGauss.patch -Patch9279: 0279-xdp-support-XDP_STATISTICS-by-posix_api-getsockopt_f.patch -Patch9280: 0280-interrupt-fix-timeout-events-cannot-be-counted.patch -Patch9281: 0281-remove-code-about-nobolck-mode-for-mysql.patch -Patch9282: 0282-LOG-Optimize-some-log-displays.patch -Patch9283: 0283-xdp-support-bind-no-cpu-mode.patch -Patch9284: 0284-support-auto-set-xdp-addr.patch -Patch9285: 0285-suport-kernel-accept-for-openGauss.patch -Patch9286: 0286-openGauss-support-kernel-accept4.patch -Patch9287: 0287-socket-init-wakeup-in-blocking-socket.patch -Patch9288: 0288-fix-socket-of-control-thread-is-overwirtten-due-to-a.patch -Patch9289: 0289-LWIP-adjust-position-of-shutdown-in-callback-of-conn.patch -Patch9290: 0290-Fix-the-wrong-spelling-description-in-the-notes-and-.patch -Patch9291: 0291-update-test-unitest-ltran-ltran_param_test.c.patch -Patch9292: 0292-fix-free-null-pointer-when-no-matching-device-is-fou.patch -Patch9293: 0293-cfg-show-dpdk-args-after-dpdk_adjust_args.patch -Patch9294: 0294-fix-build-error-in-2003SP4.patch -Patch9295: 0295-CFG-fix-xdp-iface-check-error.patch -Patch9296: 0296-xdp-support-stack-bind-numa.patch -Patch9297: 0297-openGauss-support-kernel-connnect.patch -Patch9298: 0298-DUMP-gazelle-supports-dump-lstack.patch -Patch9299: 0299-openGauss-fix-gs_ctl-switchover-failed.patch -Patch9300: 0300-openGauss-fix-connection-attempt-failed.patch -Patch9301: 0301-remove-app_bind_numa-check-from-exclude_cpus.patch -Patch9302: 0302-fix-rpc-pool-leak-when-thread-exits.patch -Patch9303: 0303-fix-epoll-and-recv-threads-blocked-on-the-same-semap.patch -Patch9304: 0304-fix-errno-ETIMEFOUT.patch -Patch9305: 0305-cfg-notify-that-it-s-unsupported-when-stack_num-1.patch -Patch9306: 0306-fix-a-contention-issue-when-rpc-pools-are-added-to-r.patch -Patch9307: 0307-openGauss-unsupport_tcp_optname.patch -Patch9308: 0308-kernerl-bind-add-ipv6-add-check.patch -Patch9309: 0309-Connect-execute-lwip-connect-if-dst_ip-and-host_ip-a.patch -Patch9310: 0310-DUMP-fix-build-error-of-oe2003-because-of-micro-is-n.patch -Patch9311: 0311-SIGNAL-Adjust-sigaction-function-to-keep-lstack-sign.patch -Patch9312: 0312-SIGNAL-Adjust-hijack-sigal-table-to-hijack-SIGABRT-S.patch -Patch9313: 0313-DUMP-fix-abnomal-printing-in-the-dump-process.patch -Patch9314: 0314-fix-the-memory-leak-when-using-strdup.patch -Patch9315: 0315-Stack-unset-stack_stop-while-stacks-exit-by-rpc-mess.patch -Patch9316: 0316-SIGNAL-block-SIGSEGV-during-exit-process.patch -Patch9317: 0317-add-xdp-tx-checksum-tso-offload.patch -Patch9318: 0318-RTC-mode-fix-gazellectl-can-t-print-connenct-info.patch -Patch9319: 0319-Connect-fix-benchmark_dws-connect-failed.patch -Patch9320: 0320-Protocal-fixing-deathlock-between-protocol-threads-a.patch -Patch9321: 0321-update-gazelle-max-numa-nodes-8.patch -Patch9322: 0322-RTC-fixing-program-stuck-while-gazelle-exit-in-multi.patch -Patch9323: 0323-cleancode-add-GAZELLE_SAME_NODE.patch -Patch9324: 0324-cleancode-remove-gazelle_light_ring.patch -Patch9325: 0325-cleancode-remove-get_stack_tid-DPDK_PKT_BURST_SIZE-P.patch -Patch9326: 0326-socket-refactor-sock_event.patch -Patch9327: 0327-socket-adapt-to-sock_event.patch -Patch9328: 0328-socket-refactor-tcp-and-udp.patch -Patch9329: 0329-socket-adapt-to-tcp-and-udp.patch -Patch9330: 0330-cfg-add-mem_cache_max-and-change-default-rpc_msg_max.patch -Patch9331: 0331-cfg-add-mem_async_mode.patch -Patch9332: 0332-mempool-add-mem_thread_cache_flush.patch -Patch9333: 0333-dfx-support-sk_wait-stat.patch -Patch9334: 0334-mempool-fix-copy_mbuf_private.patch -Patch9335: 0335-socket-fix-connect-blocking.patch -Patch9336: 0336-socket-fix-stack_tcp_read-do-not-recv_finish_burst.patch -Patch9337: 0337-tcp-add-GAZELLE_TCP_ASYNC_RECVD.patch -Patch9338: 0338-socket-fix-tcp-closed.patch -Patch9339: 0339-socket-fix-sk_wait-cannot-be-interrupted-by-signals.patch -Patch9340: 0340-mempool-modify-mbuf-num-and-rpc_msg-num.patch -Patch9341: 0341-mempool-fix-mbox_ring-free-not-call-recv_finish_burs.patch -Patch9342: 0342-mempool-mem_get_rpc-add-reserve-limit.patch -Patch9343: 0343-mempool-fix-pthread_tryjoin_np-coredump-when-mysqld-.patch -Patch9344: 0344-mempool-stop-using-cache-when-too-many-threads.patch -Patch9345: 0345-sk_wait-fix-lwip_tcp_allow_send-coredump.patch -Patch9346: 0346-mbox-fix-mbox_ring_common_free-coredump-when-rte_rin.patch -Patch9347: 0347-sk_wait-fix-sock_wait_common_free.patch -Patch9348: 0348-socket-fix-stack_udp_readmsg-return-len.patch -Patch9349: 0349-sk_wait-fix-lwip_wait_foreach_notify-coredump-at-sta.patch -Patch9350: 0350-epoll-fix-do_lwip_connected_callback.patch -Patch9351: 0351-sockio-fix-rtw_stack_tcp_write-wrong-copied_total-af.patch -Patch9352: 0352-sk_event-fix-rtw-epoll-wrong-event-notify-and-remove.patch -Patch9353: 0353-poll-fix-do_lwip_connected_callback-not-delete-poll-.patch -Patch9354: 0354-sockctl-fix-rtw-broadcast-close-and-shutdown.patch -Patch9355: 0355-mempool-increase-MEM_THREAD_MANAGER_FREE_S-to-avoid-.patch -Patch9356: 0356-sockio-fix-callback_tcp_send-output-too-many-at-once.patch -Patch9357: 0357-sockio-fix-sendmbox-full-return-EWOULDBLOCK.patch -Patch9358: 0358-sk_wait-igonre-mem_thread-flush-signal.patch -Patch9359: 0359-fix-20.03-LTS-build-failed.patch -Patch9360: 0360-sockio-fix-tcp_write-not-remove-EPOLLOUT.patch -Patch9361: 0361-sockio-fix-rpc_send-coredump-after-RPC_MSG_EXIT.patch %description %{name} is a high performance user-mode stack. @@ -419,6 +60,9 @@ install -Dpm 0640 %{_builddir}/%{name}-%{version}/src/ltran/ltran.conf %{b %config(noreplace) %{conf_path}/ltran.conf %changelog +* Fri Aug 1 2025 yinbin - 1.0.3-1 +- update version to 1.0.3 + * Wed Jul 09 2025 yinbin6 - 1.0.2-85 - sockio: fix rpc_send coredump after RPC_MSG_EXIT - sockio: fix tcp_write not remove EPOLLOUT -- Gitee

  • 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%0DgWuJt~?OFK<>96zt!o5-Q%ieSmhmww8YC@duf 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≺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