From 2a42ad20b9730706ad371ae3787d4597c4e42276 Mon Sep 17 00:00:00 2001 From: sharath reddy Date: Tue, 4 Jun 2019 11:53:49 +0530 Subject: Feature: 19.04 part-2 Change-Id: I0b52a6bb67c25c7955d58e29eb81a3cc9efea9e9 Signed-off-by: sharath reddy --- CMakeLists.txt | 5 +- app_example/CMakeLists.txt | 18 + app_example/func-test/CMakeLists.txt | 18 + app_example/func-test/file_transfer/CMakeLists.txt | 32 + .../func-test/file_transfer/client_filetrans.c | 276 ++ .../func-test/file_transfer/server_filetrans.c | 336 ++ app_example/func-test/fork/CMakeLists.txt | 32 + app_example/func-test/fork/tcpclient.c | 169 + app_example/func-test/fork/tcpserver.c | 156 + app_example/perf-test/CMakeLists.txt | 47 + app_example/perf-test/multi_tcp_common_Ser.c | 538 ++++ app_example/perf-test/multi_tcp_common_app_Cli.c | 392 +++ app_example/perf-test/multi_tcp_epoll_app_Ser.c | 627 ++++ app_example/perf-test/multi_tcp_select_app_Ser.c | 431 +++ demo/nginx_proxy/README.md | 24 + demo/nginx_proxy/demo-1/Vagrantfile | 98 + demo/nginx_proxy/demo-1/adjust_hugepage.sh | 14 + demo/nginx_proxy/demo-1/apply_patch.sh | 9 + demo/nginx_proxy/demo-1/demo_2stack.patch | 15 + demo/nginx_proxy/demo-1/module_config.json | 26 + demo/nginx_proxy/demo-1/proxy_nginx.conf | 81 + demo/nginx_proxy/demo-1/rd_config.json | 42 + demo/nginx_proxy/demo-1/setup_proxy.sh | 54 + demo/nginx_proxy/demo-1/setup_upstream.sh | 45 + demo/nginx_proxy/demo-1/startup.conf | 20 + demo/nginx_proxy/demo-1/upstream_nginx.conf | 80 + demo/nginx_proxy/demo-1/vpp_config | 6 + demo/nginx_proxy/demo-2/README.md | 69 + demo/nginx_proxy/demo-2/Vagrantfile | 116 + demo/nginx_proxy/demo-2/adjust_hugepage.sh | 14 + demo/nginx_proxy/demo-2/apply_patch.sh | 9 + demo/nginx_proxy/demo-2/dem-2-topo.png | Bin 0 -> 32437 bytes demo/nginx_proxy/demo-2/demo-2.png | Bin 0 -> 125156 bytes demo/nginx_proxy/demo-2/demo_2stack.patch | 15 + demo/nginx_proxy/demo-2/module_config.json | 26 + demo/nginx_proxy/demo-2/proxy_nginx.conf | 33 + demo/nginx_proxy/demo-2/rd_config.json | 43 + demo/nginx_proxy/demo-2/setup_client.sh | 25 + demo/nginx_proxy/demo-2/setup_proxy.sh | 54 + demo/nginx_proxy/demo-2/setup_udpserver.sh | 25 + demo/nginx_proxy/demo-2/setup_upstream.sh | 44 + demo/nginx_proxy/demo-2/startup.conf | 20 + demo/nginx_proxy/demo-2/udpclient.c | 49 + demo/nginx_proxy/demo-2/udpserver.c | 54 + demo/nginx_proxy/demo-2/upstream_nginx.conf | 80 + demo/nginx_proxy/demo-2/vpp_config | 6 + demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md | 26 + demo/nginx_proxy/demo-3/proxy_nginx.conf | 81 + demo/nginx_proxy/demo-3/rd_config.json | 23 + demo/nginx_proxy/demo-3/rsocket.png | Bin 0 -> 10614 bytes demo/nginx_proxy/demo-3/server/index.html | 31 + demo/nginx_proxy/demo-3/server/test.c | 315 ++ pkg/deb/control | 13 + pkg/rpm/dmm.spec | 50 + release/configure/module_config.json | 25 + release/configure/rd_config.json | 18 + scripts/build.sh | 4 +- scripts/build_dmm_dep.sh | 4 +- scripts/build_vpp.sh | 4 +- scripts/prep_app_test.sh | 37 +- src/include/nstack_callback_ops.h | 1 + src/nSocket/nstack/nstack_fd_mng.c | 23 + src/nSocket/nstack/nstack_fd_mng.h | 1 + src/nSocket/nstack/nstack_socket.c | 1 + stacks/lwip_stack/CMakeLists.txt | 111 + stacks/lwip_stack/build/.gitkeep | 0 stacks/lwip_stack/configure/module_config.json | 26 + stacks/lwip_stack/configure/nStackConfig.json | 32 + stacks/lwip_stack/configure/rd_config.json | 24 + stacks/lwip_stack/doc/README.md | 125 + stacks/lwip_stack/doc/dmm_lwip.png | Bin 0 -> 52940 bytes stacks/lwip_stack/lwip_src/CMakeLists.txt | 106 + stacks/lwip_stack/lwip_src/api/nsfw_msg.c | 23 + stacks/lwip_stack/lwip_src/api/spl_api.c | 50 + stacks/lwip_stack/lwip_src/api/spl_api_msg.c | 3320 ++++++++++++++++++++ stacks/lwip_stack/lwip_src/api/spl_netbuf.c | 57 + stacks/lwip_stack/lwip_src/api/spl_netifapi.c | 279 ++ stacks/lwip_stack/lwip_src/api/spl_sbr.c | 477 +++ stacks/lwip_stack/lwip_src/api/spl_tcpip.c | 1531 +++++++++ stacks/lwip_stack/lwip_src/common/rb_tree.c | 389 +++ stacks/lwip_stack/lwip_src/common/rb_tree.h | 110 + stacks/lwip_stack/lwip_src/common/spl_def.h | 138 + stacks/lwip_stack/lwip_src/common/spl_opt.h | 329 ++ stacks/lwip_stack/lwip_src/common/spl_rti.c | 91 + stacks/lwip_stack/lwip_src/common/stackx_app_res.c | 951 ++++++ stacks/lwip_stack/lwip_src/common/stackx_app_res.h | 103 + stacks/lwip_stack/lwip_src/common/stackx_common.c | 351 +++ stacks/lwip_stack/lwip_src/common/stackx_common.h | 44 + .../lwip_stack/lwip_src/common/stackx_common_opt.h | 147 + stacks/lwip_stack/lwip_src/common/stackx_debug.h | 70 + stacks/lwip_stack/lwip_src/common/stackx_err.h | 68 + stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c | 276 ++ stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h | 82 + stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h | 145 + stacks/lwip_stack/lwip_src/common/stackx_netbuf.h | 43 + stacks/lwip_stack/lwip_src/common/stackx_pbuf.c | 220 ++ stacks/lwip_stack/lwip_src/common/stackx_pbuf.h | 80 + .../lwip_stack/lwip_src/common/stackx_pbuf_comm.h | 109 + stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h | 241 ++ .../lwip_stack/lwip_src/common/stackx_spl_share.c | 192 ++ .../lwip_stack/lwip_src/common/stackx_spl_share.h | 444 +++ stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h | 42 + stacks/lwip_stack/lwip_src/common/stackx_tx_box.c | 62 + stacks/lwip_stack/lwip_src/common/stackx_tx_box.h | 39 + stacks/lwip_stack/lwip_src/common/stackx_types.h | 68 + stacks/lwip_stack/lwip_src/common/stackxopts.h | 53 + stacks/lwip_stack/lwip_src/core/global_tick.c | 48 + stacks/lwip_stack/lwip_src/core/spl_pbuf.c | 605 ++++ stacks/lwip_stack/lwip_src/core/spl_timers.c | 599 ++++ stacks/lwip_stack/lwip_src/core/unmatch_version.c | 59 + .../lwip_src/include/ip_module/config_common.h | 64 + .../include/ip_module/configuration_reader.h | 26 + .../lwip_src/include/ip_module/container_ip.h | 39 + .../lwip_src/include/ip_module/ip_module_api.h | 223 ++ .../lwip_src/include/ip_module/network.h | 36 + .../lwip_src/include/ip_module/trp_rb_tree.h | 77 + .../lwip_src/include/ipv4/stackx/spl_ip_addr.h | 162 + stacks/lwip_stack/lwip_src/include/netif/common.h | 227 ++ .../lwip_stack/lwip_src/include/netif/kni_proc.h | 103 + stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h | 79 + .../lwip_src/include/netif/sharedmemory.h | 149 + stacks/lwip_stack/lwip_src/include/netif/spl_hal.h | 112 + .../lwip_src/include/stackx/internal_msg.h | 90 + .../lwip_stack/lwip_src/include/stackx/spl_api.h | 276 ++ .../lwip_src/include/stackx/spl_api_msg.h | 128 + .../lwip_stack/lwip_src/include/stackx/spl_err.h | 40 + .../lwip_src/include/stackx/spl_instance.h | 30 + .../lwip_src/include/stackx/spl_netbuf.h | 52 + .../lwip_stack/lwip_src/include/stackx/spl_pbuf.h | 174 + .../lwip_stack/lwip_src/include/stackx/spl_sbr.h | 33 + .../lwip_src/include/stackx/spl_sockets.h | 252 ++ .../lwip_stack/lwip_src/include/stackx/spl_tcpip.h | 80 + .../lwip_src/include/stackx/spl_timers.h | 108 + .../lwip_src/include/stackx/stackx_instance.h | 91 + stacks/lwip_stack/lwip_src/instance/spl_instance.c | 47 + .../lwip_src/ip_module/configuration_reader.c | 1039 ++++++ .../lwip_stack/lwip_src/ip_module/container_ip.c | 1117 +++++++ .../lwip_stack/lwip_src/ip_module/ip_module_api.c | 356 +++ stacks/lwip_stack/lwip_src/ip_module/network.c | 1093 +++++++ stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c | 563 ++++ .../lwip_stack/lwip_src/maintain/spl_mt_config.c | 778 +++++ stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c | 392 +++ stacks/lwip_stack/lwip_src/netif/ethernetif.c | 164 + stacks/lwip_stack/lwip_src/netif/sc_dpdk.c | 563 ++++ stacks/lwip_stack/lwip_src/netif/spl_hal.c | 1755 +++++++++++ .../lwip_stack/lwip_src/recycle/stackx_recycle.c | 666 ++++ stacks/lwip_stack/lwip_src/socket/CMakeLists.txt | 75 + stacks/lwip_stack/lwip_src/socket/stackx_cfg.h | 54 + .../lwip_src/socket/stackx_container_cfg.c | 329 ++ .../lwip_stack/lwip_src/socket/stackx_epoll_api.c | 143 + .../lwip_stack/lwip_src/socket/stackx_epoll_api.h | 46 + stacks/lwip_stack/lwip_src/socket/stackx_event.c | 175 ++ stacks/lwip_stack/lwip_src/socket/stackx_event.h | 46 + stacks/lwip_stack/lwip_src/socket/stackx_macro.h | 24 + .../lwip_src/socket/stackx_msg_handler.c | 766 +++++ .../lwip_src/socket/stackx_msg_handler.h | 78 + .../lwip_stack/lwip_src/socket/stackx_prot_com.c | 670 ++++ .../lwip_stack/lwip_src/socket/stackx_prot_com.h | 159 + .../lwip_src/socket/stackx_protocol_api.c | 109 + stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c | 271 ++ stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h | 67 + stacks/lwip_stack/lwip_src/socket/stackx_socket.h | 138 + stacks/lwip_stack/lwip_src/socket/stackx_tcp.c | 1682 ++++++++++ stacks/lwip_stack/lwip_src/socket/stackx_udp.c | 1149 +++++++ stacks/lwip_stack/patch/.gitkeep | 0 stacks/lwip_stack/release/configure/ip_data.json | 8 + .../lwip_stack/release/configure/nStackConfig.json | 32 + .../release/configure/network_data_tonStack.json | 16 + .../lwip_stack/release/include/nstack_custom_api.h | 42 + stacks/lwip_stack/release/lib64/.gitkeep | 0 .../release/lwip_helper_files/arch/queue.c | 120 + .../release/lwip_helper_files/arch/sys_arch.c | 303 ++ .../release/lwip_helper_files/core/memp.c | 495 +++ .../release/lwip_helper_files/core/timeouts.c | 527 ++++ .../release/lwip_helper_files/download_lwip.sh | 36 + .../release/lwip_helper_files/include/lwipopts.h | 39 + .../release/lwip_helper_files/include/opt.h | 2875 +++++++++++++++++ .../release/lwip_helper_files/include/sys.h | 455 +++ .../release/lwip_helper_files/include/timeouts.h | 134 + .../lwip_helper_files/lwip/arch/atomic_32.h | 53 + .../release/lwip_helper_files/lwip/arch/cc.h | 82 + .../release/lwip_helper_files/lwip/arch/queue.h | 30 + .../release/lwip_helper_files/lwip/arch/sys_arch.h | 29 + .../lwip_helper_files/lwip/arch/win_minmax.h | 120 + stacks/lwip_stack/release/script/nstack_fun.sh | 591 ++++ stacks/lwip_stack/release/script/nstack_var.sh | 65 + .../lwip_stack/release/script/run_nstack_main.sh | 27 + .../lwip_stack/release/script/run_nstack_master.sh | 29 + stacks/lwip_stack/release/send_alarm.sh | 17 + stacks/lwip_stack/release/start_nstack.sh | 149 + stacks/lwip_stack/release/stop_nstack.sh | 51 + stacks/lwip_stack/release/uninstall.sh | 34 + stacks/lwip_stack/release_tar.sh | 86 + stacks/lwip_stack/run_stackx.txt | 49 + stacks/lwip_stack/src/CMakeLists.txt | 61 + stacks/lwip_stack/src/alarm/CMakeLists.txt | 38 + stacks/lwip_stack/src/alarm/alarm.c | 857 +++++ stacks/lwip_stack/src/alarm/alarm.h | 80 + stacks/lwip_stack/src/alarm/alarm_api.h | 107 + stacks/lwip_stack/src/include/common_func.h | 140 + stacks/lwip_stack/src/include/common_mem_api.h | 134 + .../lwip_stack/src/include/common_mem_base_type.h | 85 + stacks/lwip_stack/src/include/common_mem_buf.h | 78 + stacks/lwip_stack/src/include/common_mem_common.h | 25 + stacks/lwip_stack/src/include/common_mem_mbuf.h | 40 + stacks/lwip_stack/src/include/common_mem_mempool.h | 25 + .../src/include/common_mem_pal_memconfig.h | 26 + stacks/lwip_stack/src/include/common_mem_rwlock.h | 25 + .../lwip_stack/src/include/common_mem_spinlock.h | 38 + stacks/lwip_stack/src/include/nsfw_msg.h | 201 ++ stacks/lwip_stack/src/include/nsfw_msg_api.h | 305 ++ stacks/lwip_stack/src/include/nsfw_mt_config.h | 63 + stacks/lwip_stack/src/include/nsfw_rti.h | 49 + stacks/lwip_stack/src/include/nstack_dmm_adpt.h | 64 + stacks/lwip_stack/src/io_adpt/CMakeLists.txt | 41 + stacks/lwip_stack/src/io_adpt/dpdk.c | 2499 +++++++++++++++ stacks/lwip_stack/src/mem/CMakeLists.txt | 36 + .../src/mem/include/common_mem_memzone.h | 25 + .../src/mem/include/common_pal_bitwide_adjust.h | 204 ++ .../lwip_stack/src/mem/include/common_sys_config.h | 46 + .../lwip_stack/src/mem/lib_common_mem/common_api.c | 163 + .../lwip_stack/src/mem/lib_common_mem/common_buf.c | 299 ++ .../src/mem/lib_common_mem/common_func.c | 211 ++ stacks/lwip_stack/src/mem/lwip_mem_api.c | 86 + stacks/lwip_stack/src/mem/lwip_mem_desc.c | 80 + .../src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c | 44 + .../src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h | 22 + .../src/mem/nsfw_nshmem/nsfw_nshmem_mng.c | 529 ++++ .../src/mem/nsfw_nshmem/nsfw_nshmem_mng.h | 70 + .../src/mem/nsfw_nshmem/nsfw_nshmem_ring.c | 434 +++ .../src/mem/nsfw_nshmem/nsfw_nshmem_ring.h | 38 + .../src/mem/nsfw_shmem/nsfw_rshmem_mng.c | 989 ++++++ .../src/mem/nsfw_shmem/nsfw_rshmem_mng.h | 51 + .../src/mem/nsfw_shmem/nsfw_shmem_mdesc.c | 48 + .../src/mem/nsfw_shmem/nsfw_shmem_mdesc.h | 22 + .../lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c | 800 +++++ .../lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h | 135 + .../src/mem/nsfw_shmem/nsfw_shmem_ring.c | 843 +++++ .../src/mem/nsfw_shmem/nsfw_shmem_ring.h | 60 + stacks/lwip_stack/src/nStackMain/CMakeLists.txt | 66 + stacks/lwip_stack/src/nStackMain/main.c | 457 +++ stacks/lwip_stack/src/sbr/CMakeLists.txt | 37 + stacks/lwip_stack/src/sbr/sbr_err.h | 190 ++ stacks/lwip_stack/src/sbr/sbr_index_ring.c | 212 ++ stacks/lwip_stack/src/sbr/sbr_index_ring.h | 61 + stacks/lwip_stack/src/sbr/sbr_protocol_api.h | 102 + stacks/lwip_stack/src/sbr/sbr_res_mgr.c | 87 + stacks/lwip_stack/src/sbr/sbr_res_mgr.h | 155 + stacks/lwip_stack/src/sbr/sbr_socket.c | 1324 ++++++++ stacks/lwip_stack/src/tools/CMakeLists.txt | 26 + stacks/lwip_stack/src/tools/dump_tool.c | 611 ++++ stacks/lwip_stack/src/tools/dump_tool.h | 81 + stacks/lwip_stack/tools/CMakeLists.txt | 95 + stacks/lwip_stack/tools/nping.c | 615 ++++ stacks/lwip_stack/tools/ntcpdump.c | 1334 ++++++++ stacks/lwip_stack/tools/tool_common.h | 243 ++ stacks/lwip_stack/vagrant/Vagrantfile | 65 + stacks/lwip_stack/vagrant/build.sh | 59 + stacks/lwip_stack/vagrant/env.sh | 7 + stacks/lwip_stack/vagrant/start_nstackMain.sh | 105 + stacks/vpp/adapt/dmm_vcl.h | 45 + stacks/vpp/adapt/dmm_vcl_adpt.c | 205 ++ stacks/vpp/configure/module_config.json | 20 + stacks/vpp/configure/rd_config.json | 26 + stacks/vpp/configure/startup.conf | 21 + stacks/vpp/configure/vpp_config | 6 + stacks/vpp/doc/README.md | 115 + stacks/vpp/patch/vpp.patch | 104 + stacks/vpp/vagrant/Vagrantfile | 63 + stacks/vpp/vagrant/build.sh | 224 ++ stacks/vpp/vagrant/env.sh | 7 + stacks/vpp/vagrant/install_prereq.sh | 39 + testcode/app_example/CMakeLists.txt | 31 - testcode/app_example/build/.gitkeep | 0 testcode/app_example/func-test/CMakeLists.txt | 18 - .../func-test/file_transfer/CMakeLists.txt | 30 - .../func-test/file_transfer/client_filetrans.c | 276 -- .../func-test/file_transfer/server_filetrans.c | 336 -- testcode/app_example/func-test/fork/CMakeLists.txt | 30 - testcode/app_example/func-test/fork/tcpclient.c | 170 - testcode/app_example/func-test/fork/tcpserver.c | 156 - testcode/app_example/module_config.json | 15 - testcode/app_example/perf-test/CMakeLists.txt | 43 - .../app_example/perf-test/multi_tcp_common_Ser.c | 538 ---- .../perf-test/multi_tcp_common_app_Cli.c | 392 --- .../perf-test/multi_tcp_epoll_app_Ser.c | 627 ---- .../perf-test/multi_tcp_select_app_Ser.c | 431 --- testcode/app_example/rd_config.json | 14 - 288 files changed, 57947 insertions(+), 3131 deletions(-) create mode 100644 app_example/CMakeLists.txt create mode 100644 app_example/func-test/CMakeLists.txt create mode 100644 app_example/func-test/file_transfer/CMakeLists.txt create mode 100644 app_example/func-test/file_transfer/client_filetrans.c create mode 100644 app_example/func-test/file_transfer/server_filetrans.c create mode 100644 app_example/func-test/fork/CMakeLists.txt create mode 100644 app_example/func-test/fork/tcpclient.c create mode 100644 app_example/func-test/fork/tcpserver.c create mode 100644 app_example/perf-test/CMakeLists.txt create mode 100644 app_example/perf-test/multi_tcp_common_Ser.c create mode 100644 app_example/perf-test/multi_tcp_common_app_Cli.c create mode 100644 app_example/perf-test/multi_tcp_epoll_app_Ser.c create mode 100644 app_example/perf-test/multi_tcp_select_app_Ser.c create mode 100644 demo/nginx_proxy/README.md create mode 100644 demo/nginx_proxy/demo-1/Vagrantfile create mode 100644 demo/nginx_proxy/demo-1/adjust_hugepage.sh create mode 100755 demo/nginx_proxy/demo-1/apply_patch.sh create mode 100644 demo/nginx_proxy/demo-1/demo_2stack.patch create mode 100644 demo/nginx_proxy/demo-1/module_config.json create mode 100644 demo/nginx_proxy/demo-1/proxy_nginx.conf create mode 100644 demo/nginx_proxy/demo-1/rd_config.json create mode 100644 demo/nginx_proxy/demo-1/setup_proxy.sh create mode 100644 demo/nginx_proxy/demo-1/setup_upstream.sh create mode 100644 demo/nginx_proxy/demo-1/startup.conf create mode 100644 demo/nginx_proxy/demo-1/upstream_nginx.conf create mode 100644 demo/nginx_proxy/demo-1/vpp_config create mode 100644 demo/nginx_proxy/demo-2/README.md create mode 100644 demo/nginx_proxy/demo-2/Vagrantfile create mode 100644 demo/nginx_proxy/demo-2/adjust_hugepage.sh create mode 100755 demo/nginx_proxy/demo-2/apply_patch.sh create mode 100644 demo/nginx_proxy/demo-2/dem-2-topo.png create mode 100644 demo/nginx_proxy/demo-2/demo-2.png create mode 100644 demo/nginx_proxy/demo-2/demo_2stack.patch create mode 100644 demo/nginx_proxy/demo-2/module_config.json create mode 100644 demo/nginx_proxy/demo-2/proxy_nginx.conf create mode 100644 demo/nginx_proxy/demo-2/rd_config.json create mode 100644 demo/nginx_proxy/demo-2/setup_client.sh create mode 100644 demo/nginx_proxy/demo-2/setup_proxy.sh create mode 100644 demo/nginx_proxy/demo-2/setup_udpserver.sh create mode 100644 demo/nginx_proxy/demo-2/setup_upstream.sh create mode 100644 demo/nginx_proxy/demo-2/startup.conf create mode 100644 demo/nginx_proxy/demo-2/udpclient.c create mode 100644 demo/nginx_proxy/demo-2/udpserver.c create mode 100644 demo/nginx_proxy/demo-2/upstream_nginx.conf create mode 100644 demo/nginx_proxy/demo-2/vpp_config create mode 100644 demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md create mode 100644 demo/nginx_proxy/demo-3/proxy_nginx.conf create mode 100644 demo/nginx_proxy/demo-3/rd_config.json create mode 100644 demo/nginx_proxy/demo-3/rsocket.png create mode 100644 demo/nginx_proxy/demo-3/server/index.html create mode 100644 demo/nginx_proxy/demo-3/server/test.c create mode 100644 pkg/deb/control create mode 100644 pkg/rpm/dmm.spec create mode 100644 release/configure/module_config.json create mode 100644 release/configure/rd_config.json create mode 100644 stacks/lwip_stack/CMakeLists.txt create mode 100644 stacks/lwip_stack/build/.gitkeep create mode 100644 stacks/lwip_stack/configure/module_config.json create mode 100644 stacks/lwip_stack/configure/nStackConfig.json create mode 100644 stacks/lwip_stack/configure/rd_config.json create mode 100644 stacks/lwip_stack/doc/README.md create mode 100644 stacks/lwip_stack/doc/dmm_lwip.png create mode 100644 stacks/lwip_stack/lwip_src/CMakeLists.txt create mode 100644 stacks/lwip_stack/lwip_src/api/nsfw_msg.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_api.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_api_msg.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_netbuf.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_netifapi.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_sbr.c create mode 100644 stacks/lwip_stack/lwip_src/api/spl_tcpip.c create mode 100644 stacks/lwip_stack/lwip_src/common/rb_tree.c create mode 100644 stacks/lwip_stack/lwip_src/common/rb_tree.h create mode 100644 stacks/lwip_stack/lwip_src/common/spl_def.h create mode 100644 stacks/lwip_stack/lwip_src/common/spl_opt.h create mode 100644 stacks/lwip_stack/lwip_src/common/spl_rti.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_app_res.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_app_res.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_common.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_common.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_common_opt.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_debug.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_err.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_netbuf.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_pbuf.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_pbuf.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_spl_share.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_spl_share.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_tx_box.c create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_tx_box.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackx_types.h create mode 100644 stacks/lwip_stack/lwip_src/common/stackxopts.h create mode 100644 stacks/lwip_stack/lwip_src/core/global_tick.c create mode 100644 stacks/lwip_stack/lwip_src/core/spl_pbuf.c create mode 100644 stacks/lwip_stack/lwip_src/core/spl_timers.c create mode 100644 stacks/lwip_stack/lwip_src/core/unmatch_version.c create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/config_common.h create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/network.h create mode 100644 stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h create mode 100644 stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h create mode 100644 stacks/lwip_stack/lwip_src/include/netif/common.h create mode 100644 stacks/lwip_stack/lwip_src/include/netif/kni_proc.h create mode 100644 stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h create mode 100644 stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h create mode 100644 stacks/lwip_stack/lwip_src/include/netif/spl_hal.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_api.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_err.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h create mode 100644 stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h create mode 100644 stacks/lwip_stack/lwip_src/instance/spl_instance.c create mode 100644 stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c create mode 100644 stacks/lwip_stack/lwip_src/ip_module/container_ip.c create mode 100644 stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c create mode 100644 stacks/lwip_stack/lwip_src/ip_module/network.c create mode 100644 stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c create mode 100644 stacks/lwip_stack/lwip_src/maintain/spl_mt_config.c create mode 100644 stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c create mode 100644 stacks/lwip_stack/lwip_src/netif/ethernetif.c create mode 100644 stacks/lwip_stack/lwip_src/netif/sc_dpdk.c create mode 100644 stacks/lwip_stack/lwip_src/netif/spl_hal.c create mode 100644 stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c create mode 100644 stacks/lwip_stack/lwip_src/socket/CMakeLists.txt create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_cfg.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_event.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_event.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_macro.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_socket.h create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_tcp.c create mode 100644 stacks/lwip_stack/lwip_src/socket/stackx_udp.c create mode 100644 stacks/lwip_stack/patch/.gitkeep create mode 100644 stacks/lwip_stack/release/configure/ip_data.json create mode 100644 stacks/lwip_stack/release/configure/nStackConfig.json create mode 100644 stacks/lwip_stack/release/configure/network_data_tonStack.json create mode 100644 stacks/lwip_stack/release/include/nstack_custom_api.h create mode 100644 stacks/lwip_stack/release/lib64/.gitkeep create mode 100644 stacks/lwip_stack/release/lwip_helper_files/arch/queue.c create mode 100644 stacks/lwip_stack/release/lwip_helper_files/arch/sys_arch.c create mode 100644 stacks/lwip_stack/release/lwip_helper_files/core/memp.c create mode 100644 stacks/lwip_stack/release/lwip_helper_files/core/timeouts.c create mode 100644 stacks/lwip_stack/release/lwip_helper_files/download_lwip.sh create mode 100644 stacks/lwip_stack/release/lwip_helper_files/include/lwipopts.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/include/opt.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/include/sys.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/include/timeouts.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/lwip/arch/atomic_32.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/lwip/arch/cc.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/lwip/arch/queue.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/lwip/arch/sys_arch.h create mode 100644 stacks/lwip_stack/release/lwip_helper_files/lwip/arch/win_minmax.h create mode 100755 stacks/lwip_stack/release/script/nstack_fun.sh create mode 100755 stacks/lwip_stack/release/script/nstack_var.sh create mode 100755 stacks/lwip_stack/release/script/run_nstack_main.sh create mode 100755 stacks/lwip_stack/release/script/run_nstack_master.sh create mode 100755 stacks/lwip_stack/release/send_alarm.sh create mode 100755 stacks/lwip_stack/release/start_nstack.sh create mode 100755 stacks/lwip_stack/release/stop_nstack.sh create mode 100755 stacks/lwip_stack/release/uninstall.sh create mode 100644 stacks/lwip_stack/release_tar.sh create mode 100644 stacks/lwip_stack/run_stackx.txt create mode 100644 stacks/lwip_stack/src/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/alarm/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/alarm/alarm.c create mode 100644 stacks/lwip_stack/src/alarm/alarm.h create mode 100644 stacks/lwip_stack/src/alarm/alarm_api.h create mode 100644 stacks/lwip_stack/src/include/common_func.h create mode 100644 stacks/lwip_stack/src/include/common_mem_api.h create mode 100644 stacks/lwip_stack/src/include/common_mem_base_type.h create mode 100644 stacks/lwip_stack/src/include/common_mem_buf.h create mode 100644 stacks/lwip_stack/src/include/common_mem_common.h create mode 100644 stacks/lwip_stack/src/include/common_mem_mbuf.h create mode 100644 stacks/lwip_stack/src/include/common_mem_mempool.h create mode 100644 stacks/lwip_stack/src/include/common_mem_pal_memconfig.h create mode 100644 stacks/lwip_stack/src/include/common_mem_rwlock.h create mode 100644 stacks/lwip_stack/src/include/common_mem_spinlock.h create mode 100644 stacks/lwip_stack/src/include/nsfw_msg.h create mode 100644 stacks/lwip_stack/src/include/nsfw_msg_api.h create mode 100644 stacks/lwip_stack/src/include/nsfw_mt_config.h create mode 100644 stacks/lwip_stack/src/include/nsfw_rti.h create mode 100644 stacks/lwip_stack/src/include/nstack_dmm_adpt.h create mode 100644 stacks/lwip_stack/src/io_adpt/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/io_adpt/dpdk.c create mode 100644 stacks/lwip_stack/src/mem/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/mem/include/common_mem_memzone.h create mode 100644 stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h create mode 100644 stacks/lwip_stack/src/mem/include/common_sys_config.h create mode 100644 stacks/lwip_stack/src/mem/lib_common_mem/common_api.c create mode 100644 stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c create mode 100644 stacks/lwip_stack/src/mem/lib_common_mem/common_func.c create mode 100644 stacks/lwip_stack/src/mem/lwip_mem_api.c create mode 100644 stacks/lwip_stack/src/mem/lwip_mem_desc.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c create mode 100644 stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h create mode 100644 stacks/lwip_stack/src/nStackMain/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/nStackMain/main.c create mode 100644 stacks/lwip_stack/src/sbr/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/sbr/sbr_err.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_index_ring.c create mode 100644 stacks/lwip_stack/src/sbr/sbr_index_ring.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_protocol_api.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_res_mgr.c create mode 100644 stacks/lwip_stack/src/sbr/sbr_res_mgr.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_socket.c create mode 100644 stacks/lwip_stack/src/tools/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/tools/dump_tool.c create mode 100644 stacks/lwip_stack/src/tools/dump_tool.h create mode 100644 stacks/lwip_stack/tools/CMakeLists.txt create mode 100644 stacks/lwip_stack/tools/nping.c create mode 100644 stacks/lwip_stack/tools/ntcpdump.c create mode 100644 stacks/lwip_stack/tools/tool_common.h create mode 100644 stacks/lwip_stack/vagrant/Vagrantfile create mode 100644 stacks/lwip_stack/vagrant/build.sh create mode 100644 stacks/lwip_stack/vagrant/env.sh create mode 100644 stacks/lwip_stack/vagrant/start_nstackMain.sh create mode 100644 stacks/vpp/adapt/dmm_vcl.h create mode 100644 stacks/vpp/adapt/dmm_vcl_adpt.c create mode 100644 stacks/vpp/configure/module_config.json create mode 100644 stacks/vpp/configure/rd_config.json create mode 100644 stacks/vpp/configure/startup.conf create mode 100644 stacks/vpp/configure/vpp_config create mode 100644 stacks/vpp/doc/README.md create mode 100644 stacks/vpp/patch/vpp.patch create mode 100644 stacks/vpp/vagrant/Vagrantfile create mode 100644 stacks/vpp/vagrant/build.sh create mode 100644 stacks/vpp/vagrant/env.sh create mode 100644 stacks/vpp/vagrant/install_prereq.sh delete mode 100644 testcode/app_example/CMakeLists.txt delete mode 100644 testcode/app_example/build/.gitkeep delete mode 100644 testcode/app_example/func-test/CMakeLists.txt delete mode 100644 testcode/app_example/func-test/file_transfer/CMakeLists.txt delete mode 100644 testcode/app_example/func-test/file_transfer/client_filetrans.c delete mode 100644 testcode/app_example/func-test/file_transfer/server_filetrans.c delete mode 100644 testcode/app_example/func-test/fork/CMakeLists.txt delete mode 100644 testcode/app_example/func-test/fork/tcpclient.c delete mode 100644 testcode/app_example/func-test/fork/tcpserver.c delete mode 100644 testcode/app_example/module_config.json delete mode 100644 testcode/app_example/perf-test/CMakeLists.txt delete mode 100644 testcode/app_example/perf-test/multi_tcp_common_Ser.c delete mode 100644 testcode/app_example/perf-test/multi_tcp_common_app_Cli.c delete mode 100644 testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c delete mode 100644 testcode/app_example/perf-test/multi_tcp_select_app_Ser.c delete mode 100644 testcode/app_example/rd_config.json diff --git a/CMakeLists.txt b/CMakeLists.txt index e199873..892baf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,8 +94,9 @@ FILE(APPEND ${post_compile} rm -rf ${OLD_DPDK_PATH}; +mkdir -p ${CMAKE_CURRENT_LIST_DIR}/release/include/glog/ cp -f ${CMAKE_CURRENT_LIST_DIR}/src/include/*.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ -mkdir ${CMAKE_CURRENT_LIST_DIR}/release/include/glog/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/include/declare_syscalls.h.tmpl ${CMAKE_CURRENT_LIST_DIR}/release/include/ cp -f ${CMAKE_CURRENT_LIST_DIR}/thirdparty/glog/glog-0.3.5/src/glog/nstack_glog.ph ${CMAKE_CURRENT_LIST_DIR}/release/include/glog/ cp -f ${CMAKE_CURRENT_LIST_DIR}/thirdparty/glog/glog-0.3.5/src/glog/nstack_glog_in.h ${CMAKE_CURRENT_LIST_DIR}/release/include/glog/ echo post compile process success. @@ -118,7 +119,6 @@ ADD_CUSTOM_TARGET(pkg-rpm COMMAND sh ../scripts/generate_dmm_rpm.sh) ADD_CUSTOM_TARGET(pkg-deb COMMAND sh ../scripts/generate_dmm_deb.sh) ADD_CUSTOM_TARGET(vpp-stack -COMMAND cp -f ${CMAKE_CURRENT_LIST_DIR}/src/include/declare_syscalls.h.tmpl ${CMAKE_CURRENT_LIST_DIR}/release/include/ COMMAND sh ../scripts/build_vpp.sh) ADD_DEPENDENCIES(vpp-stack DPDK) ADD_CUSTOM_TARGET(checkstyle @@ -175,5 +175,6 @@ ExternalProject_Add( ) ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(app_example) ADD_SUBDIRECTORY(thirdparty/apps) ADD_SUBDIRECTORY(stacks/rsocket) diff --git a/app_example/CMakeLists.txt b/app_example/CMakeLists.txt new file mode 100644 index 0000000..a82c752 --- /dev/null +++ b/app_example/CMakeLists.txt @@ -0,0 +1,18 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +ADD_SUBDIRECTORY(perf-test) +ADD_SUBDIRECTORY(func-test) diff --git a/app_example/func-test/CMakeLists.txt b/app_example/func-test/CMakeLists.txt new file mode 100644 index 0000000..865eba5 --- /dev/null +++ b/app_example/func-test/CMakeLists.txt @@ -0,0 +1,18 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +ADD_SUBDIRECTORY(fork) +ADD_SUBDIRECTORY(file_transfer) diff --git a/app_example/func-test/file_transfer/CMakeLists.txt b/app_example/func-test/file_transfer/CMakeLists.txt new file mode 100644 index 0000000..408fc7a --- /dev/null +++ b/app_example/func-test/file_transfer/CMakeLists.txt @@ -0,0 +1,32 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") + +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) + +ADD_EXECUTABLE(vc_serv_file server_filetrans.c) +ADD_DEPENDENCIES(vc_serv_file nStackAPI) +TARGET_LINK_LIBRARIES(vc_serv_file libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(vc_cli_file client_filetrans.c) +ADD_DEPENDENCIES(vc_cli_file nStackAPI) +TARGET_LINK_LIBRARIES(vc_cli_file libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(kc_serv_file server_filetrans.c) +TARGET_LINK_LIBRARIES(kc_serv_file pthread) + +ADD_EXECUTABLE(kc_cli_file client_filetrans.c) +TARGET_LINK_LIBRARIES(kc_cli_file pthread) \ No newline at end of file diff --git a/app_example/func-test/file_transfer/client_filetrans.c b/app_example/func-test/file_transfer/client_filetrans.c new file mode 100644 index 0000000..f0e2a80 --- /dev/null +++ b/app_example/func-test/file_transfer/client_filetrans.c @@ -0,0 +1,276 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +char *END_FLAG = "=================END"; +#define HEXCONVERT_COLS 8 +#define HEX_CONVERT 1 +//#define DEBUG 1 +#define out(fmt, arg...) (void)printf(fmt, ##arg) + +#ifdef DEBUG +#define DBG(fmt, arg...) do { \ + out("[Debug] " fmt, ##arg); \ + } while (0) +#else +#define DBG(fmt, arg...) ((void)0) +#endif + +void error(const char *msg) +{ + perror(msg); + out("./client_tcp [server_ip_address] [port number] [filename] [client_ip_address]\n"); + exit(1); +} + +#if defined(HEX_CONVERT) && defined(DEBUG) +void hexconvert(void *mem, unsigned int len) +{ + unsigned int i; + + for (i = 0; + i < + len + + ((len % HEXCONVERT_COLS) ? (HEXCONVERT_COLS - + len % HEXCONVERT_COLS) : 0); i++) + { + /* print offset */ + if (i % HEXCONVERT_COLS == 0) + { + DBG("\n0x%06x: ", i); + } + + /*print hex data */ + if (i < len) + { + DBG("%02x ", 0xFF & ((char *) mem)[i]); + } + else /* end of block, just aligning for ASCII dump */ + { + DBG("\n"); + } + } +} +#endif + +void tcp(char **pArgv) +{ + + int sockfd, portno; + char buff[1024]; + + struct sockaddr_in serv_addr, cli_addr; + struct hostent *server; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + error("error in socket creation\n"); + } + out("socket create successful\n"); + + portno = atoi(pArgv[2]); + server = gethostbyname(pArgv[1]); + + if (server == NULL) + { + fprintf(stderr, "error no such host\n"); + } + + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + bzero((char *) &cli_addr, sizeof(serv_addr)); + + cli_addr.sin_family = AF_INET; + cli_addr.sin_addr.s_addr = inet_addr(pArgv[4]); + cli_addr.sin_port = htons(portno); + if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) + { + error("bind fail"); + } + out("Bind successful\n"); + + if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < + 0) + { + error("connection fail"); + } + out("connection done\n"); + + FILE *file; + int filebyte = 0; + int lsize, totalsize = 0; + + file = fopen(pArgv[3], "r"); + fseek(file, 0, SEEK_END); + lsize = ftell(file); + rewind(file); + out("Name of file: %s, Size of file : %d\n", pArgv[3], lsize); + if (write(sockfd, &lsize, sizeof(int)) == -1) + { + out("error executing write\n"); + } + if (write(sockfd, pArgv[3], 255) == -1) + { + out("error executing write\n"); + } + while (lsize > totalsize) + { + bzero(buff, 1024); + fseek(file, totalsize, SEEK_SET); + filebyte = fread(buff, 1, sizeof(buff), file); + if (filebyte == 0) + { + printf("file End of file\n"); + break; + } + + if (filebyte < 0) + error("error in reading file. \n"); +#if defined(HEX_CONVERT) && defined(DEBUG) + DBG("=========================================\n"); + hexconvert(buff, filebyte); + DBG("=========================================\n"); +#endif + + void *p = buff; + totalsize += filebyte; + + while (filebyte > 0) + { +#ifdef DEBUG + DBG("=========================================\n"); + puts((const char *) p); + DBG("=========================================\n"); +#endif + int bytes_written = write(sockfd, p, filebyte); + if (bytes_written <= 0) + { + error("error in Socket write.\n"); + } + + filebyte -= bytes_written; + p += bytes_written; +//#if DEBUG + DBG("Total size of file = %d, Total Bytes sent to socket = %d, bytes_written in each step = %d\n", lsize, totalsize, bytes_written); +//#endif + } + } + out("file has been sent successfully\n"); + out("Final Total size of file = %d, Total Bytes sent to socket = %d\n", + lsize, totalsize); + + fclose(file); + sleep(60); + close(sockfd); + return; +} + +void udp(char **pArgv) +{ + int sockfd, n, fd, sz, portno, MAXLINE; + FILE *fp; + struct sockaddr_in servaddr, cliaddr; + char *buf; + char *target, *path; + portno = atoi(pArgv[2]); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(portno); + servaddr.sin_addr.s_addr = inet_addr(pArgv[1]); + bzero(&cliaddr, sizeof(servaddr)); + cliaddr.sin_family = AF_INET; + cliaddr.sin_port = htons(portno); + cliaddr.sin_addr.s_addr = inet_addr(pArgv[3]); + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + out("error in socket creation\n"); + } + out("socket create successful\n"); + + if (bind(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0) + { + out("bind fail"); + } + out("Bind successful\n"); + + path = pArgv[4]; + target = pArgv[5]; + MAXLINE = atoi(pArgv[6]); + buf = malloc(MAXLINE * sizeof(int)); + fp = fopen(path, "r"); + fseek(fp, 0L, SEEK_END); + sz = ftell(fp); + out("The size of the path file is %d", sz); + sendto(sockfd, target, strlen(target), 0, + (struct sockaddr *) &servaddr, sizeof(servaddr)); + n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, NULL); + if (!strncmp(buf, "ok", 2)) + { + out("Filename sent.\n"); + } + + fd = open(path, O_RDONLY); + while ((n = read(fd, buf, MAXLINE)) > 0) + { + sendto(sockfd, buf, n, 0, (struct sockaddr *) &servaddr, + sizeof(servaddr)); + } + sendto(sockfd, END_FLAG, strlen(END_FLAG), 0, + (struct sockaddr *) &servaddr, sizeof(servaddr)); + fclose(fp); + sleep(60); + close(sockfd); + return; +} + +int main(int argc, char *argv[]) +{ + int i; + char **pArgv, str[10]; + pArgv = (char **) malloc(sizeof(char *) * 10); + for (i = 0; i < 10; i++) + { + pArgv[i] = (char *) malloc(sizeof(char) * 20); + } + printf("%s", argv[1]); + + if (strcmp("tcp", argv[1]) == 0) + { + strcpy(pArgv[0], "tcp"); + printf("pArgv[0]=%s", pArgv[0]); + /* The arguments of tcp are [server_ip_address] [port number] [filename] [client_ip_address] */ + for (i = 1; i < 5; i++) + { + strcpy(pArgv[i], argv[i + 1]); + } + tcp(pArgv); + } + + else + { + strcpy(str, argv[1]); + if (strcmp("udp", str) == 0) + { + strcpy(pArgv[0], "udp"); + printf("pArgv[0]=%s", pArgv[0]); + /* The arguments of udp are [server_ip_address] [port number] [client_ip_address] [filename] [target_filename] [MAX_BUFFER_LENGTH] */ + for (i = 1; i < 7; i++) + { + strcpy(pArgv[i], argv[i + 1]); + } + udp(pArgv); + } + } + return 0; +} diff --git a/app_example/func-test/file_transfer/server_filetrans.c b/app_example/func-test/file_transfer/server_filetrans.c new file mode 100644 index 0000000..8b7e25f --- /dev/null +++ b/app_example/func-test/file_transfer/server_filetrans.c @@ -0,0 +1,336 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +char *END_FLAG = "=================END"; +#define HEXCONVERT_COLS 8 +#define HEX_CONVERT 1 +//#define DEBUG 1 +#define out(fmt, arg...) (void)printf(fmt, ##arg) + +#ifdef DEBUG +#define DBG(fmt, arg...) do { \ + out("[Debug] " fmt, ##arg); \ + } while (0) +#else +#define DBG(fmt, arg...) ((void)0) +#endif + +void error(const char *msg) +{ + perror(msg); + out("./server_tcp [server_ip_address] [port number]\n"); + exit(1); +} + +#if defined(HEX_CONVERT) && defined(DEBUG) +void hexconvert(void *mem, unsigned int len) +{ + unsigned int i; + + for (i = 0; + i < + len + + ((len % HEXCONVERT_COLS) ? (HEXCONVERT_COLS - + len % HEXCONVERT_COLS) : 0); i++) + { + /* print offset */ + if (i % HEXCONVERT_COLS == 0) + { + DBG("\n0x%06x: ", i); + } + + /*print hex data */ + if (i < len) + { + DBG("%02x ", 0xFF & ((char *) mem)[i]); + } + else /* end of block, just aligning for ASCII dump */ + { + DBG("\n"); + } + } +} +#endif +int compareFiles(FILE * fp1, FILE * fp2) +{ + + char ch1 = getc(fp1); + char ch2 = getc(fp2); + int error = 0, pos = 0, line = 1; + + while (ch1 != EOF && ch2 != EOF) + { + pos++; + if (ch1 == '\n' && ch2 == '\n') + { + line++; + pos = 0; + } + + if (ch1 != ch2) + { + error++; + DBG("Line Number : %d \tError" " Position :%d \n", line, pos); + } + + ch1 = getc(fp1); + ch2 = getc(fp2); + } + + //printf("Total Errors : %d\t", error); + return error; +} + +void tcp(char **pArgv) +{ + + int sockfd, newsockfd, portno; + char buff[1024], filename[255]; + + struct sockaddr_in serv_addr, cli_addr; + socklen_t clilen; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + error("error in socket creation"); + } + out("socket create successful\n"); + + bzero((char *) &serv_addr, sizeof(serv_addr)); + portno = atoi(pArgv[2]); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(pArgv[1]); + serv_addr.sin_port = htons(portno); + + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + error("bind fail"); + } + out("Bind successful\n"); + listen(sockfd, 5); + clilen = sizeof(cli_addr); + + newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); + if (newsockfd < 0) + { + error("error in accept"); + } + out("socket accept succesful\n"); + bzero(buff, 1024); + + FILE *fp; + int lSize = 0, totallSize = 0; + + bzero(filename, 255); + + fclose(fopen("receive_file.txt", "w")); + if (system("chmod +x *") == -1) + { + out(" incorrect use of system\n"); + } + fp = fopen("receive_file.txt", "a"); + + if (read(newsockfd, &lSize, sizeof(int)) == -1) + { + out("error executing read\n"); + } + if (read(newsockfd, filename, sizeof(filename)) == -1) + { + out("error executing read\n"); + } + + while (lSize > totallSize) + { + int bytes_read = 0; + bzero(buff, 1024); + + bytes_read = read(newsockfd, buff, 1024); + + if (bytes_read == 0) + { + break; + } + + if (bytes_read < 0) + { + error("error in Socket read.\n"); + } + +#if defined(HEX_CONVERT) && defined(DEBUG) + DBG("=========================================\n"); + hexconvert(buff, bytes_read); + DBG("=========================================\n"); +#endif +#ifdef DEBUG + DBG("=========================================\n"); + puts((const char *) buff); + DBG("=========================================\n"); +#endif + totallSize += bytes_read; + + if (fwrite(buff, 1, bytes_read, fp) == -1) + { + error("error in file write\n"); + } +//#if DEBUG + DBG("Total size of file = %d, Total Bytes sent to socket = %d, bytes_read in each step = %d\n", lSize, totallSize, bytes_read); +//#endif + } + out("file name = %s\n", filename); + out("Final total size of file = %d, total read from socket = %d\n", lSize, + totallSize); + out("copy complete\n"); + fclose(fp); + + FILE *fp1 = fopen("receive_file.txt", "r"); + FILE *fp2 = fopen(filename, "r"); + + fseek(fp2, 0L, SEEK_END); + int lfile_size = ftell(fp2); + rewind(fp2); + if (lfile_size != lSize) + { + out("Size unmatch...\n"); + } + else + { + out("Size match...\n"); + } + + if (compareFiles(fp1, fp2) > 0) + { + out("file unmatch...\n"); + } + else + { + out("file match...\n"); + } + + close(newsockfd); + close(sockfd); + return; +} + +void +run(int sockfd, struct sockaddr *cliaddr, socklen_t clilen, char *res_buf, + int MAXLINE) +{ + int n, fd; + socklen_t len; + char *buf, *buf2; + FILE *fp1, *fp2; + buf = malloc(MAXLINE + 1); + len = clilen; + n = recvfrom(sockfd, buf, MAXLINE, 0, cliaddr, &len); + buf[n] = 0; + out("Received from client:[%s] \n", buf); + buf2 = malloc(MAXLINE); + strcpy(buf2, buf); + sendto(sockfd, "ok", strlen("ok"), 0, cliaddr, len); + fd = open(buf, O_RDWR | O_CREAT, 0666); + while ((n = recvfrom(sockfd, buf, MAXLINE, 0, cliaddr, &len))) + { + buf[n] = 0; + //out("%s", buf); + if (!(strcmp(buf, END_FLAG))) + { + break; + } + if (write(fd, buf, n) == -1) + { + out("error in executing write\n"); + } + } + fp1 = fopen(buf2, "r"); + fp2 = fopen(res_buf, "r"); + + if (compareFiles(fp1, fp2) == 0) + { + out("\nPass:The contents of the files are same"); + } + else + { + out("\nFail:The contents of the files are different"); + } + close(fd); +} + +void udp(char **pArgv) +{ + int sockfd, portno, MAXLINE; + struct sockaddr_in servaddr, cliaddr; + char *res_buf; + res_buf = pArgv[3]; + + portno = atoi(pArgv[2]); + MAXLINE = atoi(pArgv[4]); + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + { + out("error in socket creation\n"); + } + out("socket create successful\n"); + + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = inet_addr(pArgv[1]); + servaddr.sin_port = htons(portno); + + if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) + { + out("bind fail"); + } + out("Binded successfully\n"); + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(sockfd, &read_fds); + int fdmax = sockfd; + if (FD_ISSET(sockfd, &read_fds)) + { + run(fdmax, (struct sockaddr *) &cliaddr, sizeof(cliaddr), res_buf, + MAXLINE); + } + return; +} + +int main(int argc, char *argv[]) +{ + int i, j; + char **pArgv; + pArgv = (char **) malloc(sizeof(char *) * 10); + for (i = 0; i < 10; i++) + { + pArgv[i] = (char *) malloc(sizeof(char) * 20); + } + if (strcmp("tcp", argv[1]) == 0) + { + strcpy(pArgv[0], "tcp"); + /* The arguments of tcp are [server_ip_address] [port number] */ + for (i = 1; i < 3; i++) + { + strcpy(pArgv[i], argv[i + 1]); + } + tcp(pArgv); + } + else if (strcmp("udp", argv[1]) == 0) + { + strcpy(pArgv[0], "udp"); + /* The arguments of udp are [server_ip_address] [port number] [filename] [MAX_BUFFER_LENGTH] */ + for (i = 1; i < 5; i++) + { + strcpy(pArgv[i], argv[i + 1]); + } + udp(pArgv); + } + + return 0; +} diff --git a/app_example/func-test/fork/CMakeLists.txt b/app_example/func-test/fork/CMakeLists.txt new file mode 100644 index 0000000..f37dae7 --- /dev/null +++ b/app_example/func-test/fork/CMakeLists.txt @@ -0,0 +1,32 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") + +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) + +ADD_EXECUTABLE(vtcp_fork_server tcpserver.c) +ADD_DEPENDENCIES(vtcp_fork_server nStackAPI) +TARGET_LINK_LIBRARIES(vtcp_fork_server libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(vtcp_client tcpclient.c) +ADD_DEPENDENCIES(vtcp_client nStackAPI) +TARGET_LINK_LIBRARIES(vtcp_client libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(ktcp_fork_server tcpserver.c) +TARGET_LINK_LIBRARIES(ktcp_fork_server pthread) + +ADD_EXECUTABLE(ktcp_client tcpclient.c) +TARGET_LINK_LIBRARIES(ktcp_client pthread) \ No newline at end of file diff --git a/app_example/func-test/fork/tcpclient.c b/app_example/func-test/fork/tcpclient.c new file mode 100644 index 0000000..1a48e86 --- /dev/null +++ b/app_example/func-test/fork/tcpclient.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define DBG(fmt, arg...) do { \ + printf(fmt, ##arg); \ +} while(0) +#else +#define DBG(fmt, arg...) ((void)0) +#endif + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +int srcPort = 0; +int destPort = 0; +int times = 0; + +void random_str(char *str, const int len) +{ + static const char alphaNum[] = + "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i = 0; + + for (i = 0; i < len; i++) + { + str[i] = alphaNum[rand() % (sizeof(alphaNum) - 1)]; + } + + str[len] = 0; +} + +static void setArgsDefault() +{ + + memset(&g_dest, 0, sizeof(g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + g_dest.sin_port = htons(12345); + bzero(&(g_dest.sin_zero), 8); + + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + times = 1; +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:t:"; + + if (argc < 5) + { + DBG("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -t times; \n"); + return -1; + } + setArgsDefault(); + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + g_dest.sin_port = htons(atoi(optarg)); + break; + case 'd': + g_dest.sin_addr.s_addr = inet_addr(optarg); + break; + case 's': + g_src.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + g_src.sin_port = htons(atoi(optarg)); + break; + case 't': + times = atoi(optarg); + break; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + + int clientSocket, ret, i; + char sndbuffer[1024]; + char rcvbuffer[1024]; + int result = 0; + + /* + * check command line arguments + */ + if (0 != process_arg(argc, argv)) + { + DBG("Error in argument.%d\n", argc); + exit(1); + } + + clientSocket = socket(AF_INET, SOCK_STREAM, 0); + if (clientSocket < 0) + { + DBG("Error in connection.\n"); + exit(1); + } + DBG("[INFO]Client Socket is created.\n"); + + ret = bind(clientSocket, (struct sockaddr *) &g_src, sizeof(g_src)); + if (ret < 0) + { + DBG("Error in binding.\n"); + exit(1); + } + + DBG("[INFO]Bind to client aaddress port 0\n"); + + ret = connect(clientSocket, (struct sockaddr *) &g_dest, sizeof(g_dest)); + if (ret < 0) + { + DBG("Error in connection.\n"); + exit(1); + } + DBG("[INFO]Connected to Server.\n"); + + memset(sndbuffer, '\0', 1024 * sizeof(char)); + memset(rcvbuffer, '\0', 1024 * sizeof(char)); + + for (i = 1; i <= times; i++) + { + DBG("Client: \t"); + random_str(sndbuffer, 50); + send(clientSocket, sndbuffer, strlen(sndbuffer), 0); + + if (recv(clientSocket, rcvbuffer, 1024, 0) < 0) + { + DBG("Error in receiving data.\n"); + } + else + { + DBG("Server: \t%s\n", rcvbuffer); + } + if (0 != strcmp(sndbuffer, rcvbuffer)) + { + result = -1; + break; + } + } + + /* Send exit message to server */ + strcpy(sndbuffer, "#exit"); + send(clientSocket, sndbuffer, strlen(sndbuffer), 0); + + DBG("Result = %s\n", (result == 0) ? "Success" : "Fail"); + close(clientSocket); + DBG("Disconnecting from server.\n"); + return 0; +} diff --git a/app_example/func-test/fork/tcpserver.c b/app_example/func-test/fork/tcpserver.c new file mode 100644 index 0000000..73c053a --- /dev/null +++ b/app_example/func-test/fork/tcpserver.c @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct sockaddr_in g_src; +int srcPort = 0; +int destPort = 0; +int times = 0; + +#ifdef DEBUG +#define DBG(fmt, arg...) do { \ + DBG(fmt, ##arg); \ +} while(0) +#else +#define DBG(fmt, arg...) ((void)0) +#endif + +static void setArgsDefault() +{ + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + times = 1; +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "s:a:t:"; + + if (argc < 5) + { + DBG("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -t times; \n"); + return -1; + } + setArgsDefault(); + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 's': + g_src.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + g_src.sin_port = htons(atoi(optarg)); + break; + case 't': + times = atoi(optarg); + break; + } + } + return 0; +} + +int main(int argc, char *argv[]) +{ + + int sockfd, ret; + int newSocket; + socklen_t addr_size; + static struct sockaddr_in accept_addr; + char buffer[1024]; + pid_t childpid; + + /* + * check command line arguments + */ + if (0 != process_arg(argc, argv)) + { + DBG("Error in argument.%d\n", argc); + exit(1); + } + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + DBG("Error in connection.\n"); + exit(1); + } + DBG("Server Socket is created. %d\n", sockfd); + + ret = bind(sockfd, (struct sockaddr *) &g_src, sizeof(g_src)); + if (ret < 0) + { + DBG("Error in binding.\n"); + exit(1); + } + + DBG("Bind sucess port %d\n", g_src.sin_port); + + if (listen(sockfd, 10) == 0) + { + DBG("Listening on %s....\n", inet_ntoa(g_src.sin_addr)); + } + else + { + DBG("Error in binding.\n"); + } + + while (1) + { + newSocket = + accept(sockfd, (struct sockaddr *) &accept_addr, &addr_size); + if (newSocket < 0) + { + DBG("Error: Exiting here pid %d", getpid()); + exit(1); + } + + DBG("Connection accepted from %s:%d fd %d\n", + inet_ntoa(accept_addr.sin_addr), + ntohs(accept_addr.sin_port), newSocket); + if ((childpid = fork()) == 0) + { + DBG("[ PID %d] Child process Created. Pid %d \r\n", getpid(), + getpid()); + DBG("[ PID %d] Closing fd %d\n", getpid(), sockfd); + close(sockfd); + + while (1) + { + memset(buffer, '\0', 1024 * sizeof(char)); + recv(newSocket, buffer, 1024, 0); + if (strcmp(buffer, "#exit") == 0) + { + DBG("Disconnected from %s:%d\n", + inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port)); + break; + } + else + { + DBG("[PID %d]Client: %s\n", getpid(), buffer); + send(newSocket, buffer, strlen(buffer), 0); + bzero(buffer, sizeof(buffer)); + } + } + + DBG("[PID %d]Closing socket %d\r\n", getpid(), newSocket); + close(newSocket); + } + + } + + DBG("[PID %d]Process exiting... %d\r\n", getpid(), getpid()); + return 0; +} diff --git a/app_example/perf-test/CMakeLists.txt b/app_example/perf-test/CMakeLists.txt new file mode 100644 index 0000000..7f05b84 --- /dev/null +++ b/app_example/perf-test/CMakeLists.txt @@ -0,0 +1,47 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") + +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) + +ADD_EXECUTABLE(vc_common multi_tcp_common_app_Cli.c) +ADD_DEPENDENCIES(vc_common nStackAPI) +TARGET_LINK_LIBRARIES(vc_common libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(vs_epoll multi_tcp_epoll_app_Ser.c) +ADD_DEPENDENCIES(vs_epoll nStackAPI) +TARGET_LINK_LIBRARIES(vs_epoll libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(vs_select multi_tcp_select_app_Ser.c) +ADD_DEPENDENCIES(vs_select nStackAPI) +TARGET_LINK_LIBRARIES(vs_select libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(kc_common multi_tcp_common_app_Cli.c) +TARGET_LINK_LIBRARIES(kc_common pthread) + +ADD_EXECUTABLE(ks_epoll multi_tcp_epoll_app_Ser.c) +TARGET_LINK_LIBRARIES(ks_epoll pthread) + +ADD_EXECUTABLE(ks_select multi_tcp_select_app_Ser.c) +TARGET_LINK_LIBRARIES(ks_select pthread) + +ADD_EXECUTABLE(vs_common multi_tcp_common_Ser.c) +ADD_DEPENDENCIES(vs_common nStackAPI) +TARGET_LINK_LIBRARIES(vs_common libnStackAPI.so -lpthread -lrt) + +ADD_EXECUTABLE(ks_common multi_tcp_common_Ser.c) +TARGET_LINK_LIBRARIES(ks_common pthread) + diff --git a/app_example/perf-test/multi_tcp_common_Ser.c b/app_example/perf-test/multi_tcp_common_Ser.c new file mode 100644 index 0000000..27d44ae --- /dev/null +++ b/app_example/perf-test/multi_tcp_common_Ser.c @@ -0,0 +1,538 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define __USE_GNU +#include +#include +#include +#include +#include + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void setArgsDefault() +{ + + memset(&g_dest, 0, sizeof(g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + g_dest.sin_port = htons(12345); + bzero(&(g_dest.sin_zero), 8); + + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + memset(&g_recv, 0, sizeof(g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_recv.sin_port = htons(7895); + bzero(&(g_recv.sin_zero), 8); + +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi(optarg); + g_dest.sin_port = htons(atoi(optarg)); + break; + case 'd': + stpcpy(destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr(optarg); + break; + case 's': + stpcpy(sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr(optarg); + g_recv.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi(optarg); + break; + case 'l': + msg_length = atoi(optarg); + break; + case 't': + times = atoi(optarg); + break; + case 'e': + sleepCnt = atoi(optarg); + break; + case 'i': + sleepTime = atoi(optarg); + break; + case 'f': + fdNumber = atoi(optarg); + break; + case 'r': + recvPort = atoi(optarg); + g_recv.sin_port = htons(atoi(optarg)); + break; + case 'n': + connectNum = atoi(optarg); + break; + case 'w': + waitTime = atoi(optarg); + break; + case 'u': + unitPrint = atoi(optarg); + break; + case 'x': + flagPrint = atoi(optarg); + break; + + } + } + return 1; +} + +void process_client(void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + + memset(&countStart, 0, sizeof(countStart)); + memset(&countEnd, 0, sizeof(countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf("client %d failed,err %d\n", i, errno); + } + else + { + printf("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, + (void *) &optval, sizeof(optval)); + if (ret == -1) + { + printf("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons(srcPort + i); + errbind[i] = + _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); + if (errbind[i] < 0) + { + printf("client %d bind Failed %d\n", i, errno); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d bind Success port:%d IP:%s\n", i, + ntohs(g_src.sin_port), + inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof(g_dest)); + if (errconn[i] < 0) + { + printf("client %d Connect Failed %d\n", i, errno); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d Connect Success port:%d, IP:%s\n", i, + ntohs(g_dest.sin_port), + inet_ntoa(* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep(1); + + clock_gettime(CLOCK_MONOTONIC, &startTime); + clock_gettime(CLOCK_MONOTONIC, &countStart); + + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep(sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0) + { + clock_gettime(CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf(" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime(CLOCK_MONOTONIC, &countStart); + } + } + + clock_gettime(CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE(c_socketfd[i]); + } + + pthread_exit(NULL); +} + +/* + using this thread to do recv msg; +*/ +void *process_server_msg_thread(void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + struct timespec recvStart; + struct timespec recvEnd; + memset(&recvStart, 0, sizeof(recvStart)); + memset(&recvEnd, 0, sizeof(recvEnd)); + + pthread_detach(pthread_self()); + + int msgFd = *(int *) pArgv; + clock_gettime(CLOCK_MONOTONIC, &recvStart); + while (recv_count < times) + { + recvLen = 0; + recvLen2 = 0; + while (1) + { + recvLen2 = + recv(msgFd, recv_buf + recvLen, msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + if (msg_length != send(msgFd, send_buf, msg_length, 0)) + { + printf("send failed!====, need exit\n"); + } + + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime(CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint; + printf("receive count:%d, receive time: %ld ns\n", recv_count, + recv_ppstime); + printf("receive pps = %d\n", recv_pps); + clock_gettime(CLOCK_MONOTONIC, &recvStart); + } + } + } + close(msgFd); +} + +/* + using this thread to do accept connect +*/ +void *process_server_accept_thread(void *pArgv) +{ + int listenFd = 0; + int x, optval, ret, m = 0; + int acpt_socketfd[1000] = { 0 }; + + listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf("ERROR:socket failed,errno [%d]\n", errno); + return; + } + else + { + printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) + { + printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close(listenFd); + } + + optval = 1; + ret = + setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof(optval)); + if (ret == -1) + { + printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close(listenFd); + return; + } + + if (0 != + bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) + { + printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close(listenFd); + exit(-1); + } + else + { + printf("Info Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen(listenFd, 100)) + { + printf("server socket listen failed. err %d\n", errno); + close(listenFd); + return; + } + printf("Listen Success\n"); + + int timeout = -1; + int accpedNum = 0; + while (accpedNum < connectNum) + { + while (1) + { + acpt_socketfd[accpedNum] = + accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + break; + } + + fcntl(acpt_socketfd[accpedNum], F_SETFL, 0); + + /*add new accptFd to MsgEpFD */ + pthread_t ser_rcv_thread_id; + if (pthread_create + (&ser_rcv_thread_id, NULL, process_server_msg_thread, + (void *) &acpt_socketfd[accpedNum]) == -1) + { + printf("create process_server_msg_thread fail\n"); + break; + } + + printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + close(listenFd); + while (1) + { + sleep(10); + } + + pthread_exit(NULL); +} + +void main(int argc, char *argv[]) +{ + socklen_t addrlen = sizeof(struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault(); + ret = process_arg(argc, argv); + if (ret != 1) + { + printf("The param error\n"); + return; + } + + pthread_t server_thread_id; + + if (pthread_create + (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) + { + printf("create process_server_accept_thread fail\n"); + return; + } + + printf("create process_server_accept_thread success\n"); + + if (server_thread_id != 0) + { + printf("Server Thread join\n"); + pthread_join(server_thread_id, NULL); + } + + while (1) + { + sleep(10); + } + + return; +} diff --git a/app_example/perf-test/multi_tcp_common_app_Cli.c b/app_example/perf-test/multi_tcp_common_app_Cli.c new file mode 100644 index 0000000..02991bd --- /dev/null +++ b/app_example/perf-test/multi_tcp_common_app_Cli.c @@ -0,0 +1,392 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void setArgsDefault() +{ + + memset(&g_dest, 0, sizeof(g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + g_dest.sin_port = htons(12345); + bzero(&(g_dest.sin_zero), 8); + + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + memset(&g_recv, 0, sizeof(g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_recv.sin_port = htons(7895); + bzero(&(g_recv.sin_zero), 8); + +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi(optarg); + g_dest.sin_port = htons(atoi(optarg)); + break; + case 'd': + stpcpy(destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr(optarg); + break; + case 's': + stpcpy(sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr(optarg); + g_recv.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi(optarg); + break; + case 'l': + msg_length = atoi(optarg); + break; + case 't': + times = atoi(optarg); + break; + case 'e': + sleepCnt = atoi(optarg); + break; + case 'i': + sleepTime = atoi(optarg); + break; + case 'f': + fdNumber = atoi(optarg); + break; + case 'r': + recvPort = atoi(optarg); + g_recv.sin_port = htons(atoi(optarg)); + break; + case 'n': + connectNum = atoi(optarg); + break; + case 'w': + waitTime = atoi(optarg); + break; + case 'u': + unitPrint = atoi(optarg); + break; + case 'x': + flagPrint = atoi(optarg); + break; + + } + } + return 1; +} + +void process_client(void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + char recv_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + memset(&countStart, 0, sizeof(countStart)); + memset(&countEnd, 0, sizeof(countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf("client %d failed,err %d\n", i, errno); + } + else + { + printf("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, + (void *) &optval, sizeof(optval)); + if (ret == -1) + { + printf("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons(srcPort + i); + errbind[i] = + _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); + if (errbind[i] < 0) + { + printf("client %d bind Failed %d\n", i, errno); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d bind Success port:%d IP:%s\n", i, + ntohs(g_src.sin_port), + inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof(g_dest)); + if (errconn[i] < 0) + { + printf("client %d Connect Failed %s\n", i, strerror(errno)); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d Connect Success port:%d, IP:%s\n", i, + ntohs(g_dest.sin_port), + inet_ntoa(* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep(1); + + clock_gettime(CLOCK_MONOTONIC, &startTime); + clock_gettime(CLOCK_MONOTONIC, &countStart); + + int recvLen2, recvLen; + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + recvLen = 0; + do + { + recvLen2 = + recv(c_socketfd[i], recv_buf + recvLen, + msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + continue; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + break; + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + } + while (1); + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep(sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0 && send_count[0] > 0) + { + clock_gettime(CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf(" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime(CLOCK_MONOTONIC, &countStart); + } + } + + clock_gettime(CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE(c_socketfd[i]); + } + + pthread_exit(NULL); +} + +void main(int argc, char *argv[]) +{ + socklen_t addrlen = sizeof(struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault(); + ret = process_arg(argc, argv); + if (ret != 1) + { + printf("The param error\n"); + return; + } + + pthread_t client_thread_id; + + if (pthread_create + (&client_thread_id, NULL, (void *) (&process_client), NULL) == -1) + { + printf("create client thread fail\n"); + return; + } + + printf("create client thread success\n"); + + if (client_thread_id != 0) + { + printf("Client Thread join\n"); + pthread_join(client_thread_id, NULL); + } + + return; +} diff --git a/app_example/perf-test/multi_tcp_epoll_app_Ser.c b/app_example/perf-test/multi_tcp_epoll_app_Ser.c new file mode 100644 index 0000000..b37a9c3 --- /dev/null +++ b/app_example/perf-test/multi_tcp_epoll_app_Ser.c @@ -0,0 +1,627 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void setArgsDefault() +{ + + memset(&g_dest, 0, sizeof(g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + g_dest.sin_port = htons(12345); + bzero(&(g_dest.sin_zero), 8); + + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + memset(&g_recv, 0, sizeof(g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_recv.sin_port = htons(7895); + bzero(&(g_recv.sin_zero), 8); + +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi(optarg); + g_dest.sin_port = htons(atoi(optarg)); + break; + case 'd': + stpcpy(destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr(optarg); + break; + case 's': + stpcpy(sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr(optarg); + g_recv.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi(optarg); + break; + case 'l': + msg_length = atoi(optarg); + break; + case 't': + times = atoi(optarg); + break; + case 'e': + sleepCnt = atoi(optarg); + break; + case 'i': + sleepTime = atoi(optarg); + break; + case 'f': + fdNumber = atoi(optarg); + break; + case 'r': + recvPort = atoi(optarg); + g_recv.sin_port = htons(atoi(optarg)); + break; + case 'n': + connectNum = atoi(optarg); + break; + case 'w': + waitTime = atoi(optarg); + break; + case 'u': + unitPrint = atoi(optarg); + break; + case 'x': + flagPrint = atoi(optarg); + break; + + } + } + return 1; +} + +void process_client(void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + memset(&countStart, 0, sizeof(countStart)); + memset(&countEnd, 0, sizeof(countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf("client %d failed,err %d\n", i, errno); + } + else + { + printf("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, + (void *) &optval, sizeof(optval)); + if (ret == -1) + { + printf("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons(srcPort + i); + errbind[i] = + _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); + if (errbind[i] < 0) + { + printf("client %d bind Failed %d\n", i, errno); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d bind Success port:%d IP:%s\n", i, + ntohs(g_src.sin_port), + inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof(g_dest)); + if (errconn[i] < 0) + { + printf("client %d Connect Failed %d\n", i, errno); + _CLOSE(c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf("client %d Connect Success port:%d, IP:%s\n", i, + ntohs(g_dest.sin_port), + inet_ntoa(* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep(1); + + clock_gettime(CLOCK_MONOTONIC, &startTime); + clock_gettime(CLOCK_MONOTONIC, &countStart); + + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep(sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0) + { + clock_gettime(CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf(" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime(CLOCK_MONOTONIC, &countStart); + } + + } + + clock_gettime(CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE(c_socketfd[i]); + } + + pthread_exit(NULL); +} + +/* + using this thread to do recv msg; +*/ +void *process_server_msg_thread(void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + struct epoll_event event; + + struct epoll_event eventList[MAX_EVENTS]; + + struct timespec recvStart; + struct timespec recvEnd; + memset(&recvStart, 0, sizeof(recvStart)); + memset(&recvEnd, 0, sizeof(recvEnd)); + + pthread_detach(pthread_self()); + + int msgEpFd = epoll_create(100); + int msgFd = *(int *) pArgv; + + event.events = EPOLLIN | EPOLLET; + event.data.fd = msgFd; + if (epoll_ctl(msgEpFd, EPOLL_CTL_ADD, msgFd, &event) < 0) + { + printf("epoll add fd[%d] to msgEpfd:[%d] failed\n", msgFd, msgEpFd); + close(msgEpFd); + close(msgFd); + return NULL; + } + + clock_gettime(CLOCK_MONOTONIC, &recvStart); + while (1) + { + int timeout = -1; + int m; + int sock; + ret = epoll_wait(msgEpFd, eventList, MAX_EVENTS, timeout); + if (ret == 0) + continue; + + for (m = 0; m < ret; m++) + { + if ((eventList[m].events & EPOLLERR) + || (eventList[m].events & EPOLLHUP) + || !(eventList[m].events & EPOLLIN)) + { + printf("fd %d epoll error event:%d\n", eventList[m].data.fd, + eventList[m].events); + close(eventList[m].data.fd); + continue; + } + else + { + recvLen = 0; + recvLen2 = 0; + sock = eventList[m].data.fd; + + do + { + recvLen2 = + recv(sock, recv_buf + recvLen, msg_length - recvLen, + 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + if (msg_length != send(sock, send_buf, msg_length, 0)) + { + printf("send failed!====, need exit\n"); + } + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime(CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = + ((float) 1000000000 / recv_ppstime) * unitPrint; + printf("receive count:%d, receive time: %ld ns\n", + recv_count, recv_ppstime); + printf("receive pps = %d\n", recv_pps); + clock_gettime(CLOCK_MONOTONIC, &recvStart); + } + } + while (1); + } + + } + + if (recv_count == times) + { + break; + } + } + close(msgFd); + close(msgEpFd); +} + +/* + using this thread to do accept connect +*/ +void *process_server_accept_thread(void *pArgv) +{ + int listenFd = 0; + int x, optval, ret = 0; + int acpt_socketfd[1000] = { 0 }; + + listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf("ERROR:socket failed,errno [%d]\n", errno); + return NULL; + } + else + { + printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) + { + printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close(listenFd); + } + + optval = 1; + ret = + setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof(optval)); + if (ret == -1) + { + printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close(listenFd); + return NULL; + } + + if (0 != + bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) + { + printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close(listenFd); + //return NULL; + exit(-1); + } + else + { + printf("INFO:Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen(listenFd, 100)) + { + printf("server socket listen failed. err %d\n", errno); + close(listenFd); + return NULL; + } + printf("Listen Success\n"); + + int accEpFd; + struct epoll_event eventList[100]; + accEpFd = epoll_create(100); + struct epoll_event event; + event.events = EPOLLIN | EPOLLET; + event.data.fd = listenFd; + + if (epoll_ctl(accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0) + { + printf("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd); + exit(-1); + } + + int timeout = -1; + int accpedNum = 0; + while (accpedNum < connectNum) + { + ret = epoll_wait(accEpFd, eventList, connectNum, timeout); + + if (ret < 0) + { + printf("accept_thread epoll_wait error, epfd[%d], errno[%d]\n", + accEpFd, errno); + continue; + } + else if (ret == 0) + continue; + + /*loop done ever Event */ + for (x = 0; x < ret; x++) + { + printf("event:%d; ret:%d\n", eventList[x].events, ret); + if ((eventList[x].events & EPOLLERR) + || !(eventList[x].events & EPOLLIN)) + { + printf("epoll fd %d error\n", eventList[x].data.fd); + close(eventList[x].data.fd); + continue; + } + + while (1) + { + acpt_socketfd[accpedNum] = + accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + printf("no more connect\n"); + break; + } + /*add new accptFd to MsgEpFD */ + pthread_t ser_rcv_thread_id; + if (pthread_create + (&ser_rcv_thread_id, NULL, process_server_msg_thread, + (void *) &acpt_socketfd[accpedNum]) == -1) + { + printf("create process_server_msg_thread fail\n"); + break; + } + + printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + } + + close(listenFd); + close(accEpFd); + + while (1) + { + sleep(10); + } + + pthread_exit(NULL); +} + +void main(int argc, char *argv[]) +{ + socklen_t addrlen = sizeof(struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault(); + ret = process_arg(argc, argv); + if (ret != 1) + { + printf("The param error\n"); + return; + } + + pthread_t server_thread_id; + + if (pthread_create + (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) + { + printf("create process_server_accept_thread fail\n"); + return; + } + + printf("create process_server_accept_thread success\n"); + + if (server_thread_id != 0) + { + printf("Server Thread join\n"); + pthread_join(server_thread_id, NULL); + } + + while (1) + { + sleep(10); + } + + return; +} diff --git a/app_example/perf-test/multi_tcp_select_app_Ser.c b/app_example/perf-test/multi_tcp_select_app_Ser.c new file mode 100644 index 0000000..56b9c5d --- /dev/null +++ b/app_example/perf-test/multi_tcp_select_app_Ser.c @@ -0,0 +1,431 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void setArgsDefault() +{ + + memset(&g_dest, 0, sizeof(g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); + g_dest.sin_port = htons(12345); + bzero(&(g_dest.sin_zero), 8); + + memset(&g_src, 0, sizeof(g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_src.sin_port = htons(7895); + bzero(&(g_src.sin_zero), 8); + + memset(&g_recv, 0, sizeof(g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); + g_recv.sin_port = htons(7895); + bzero(&(g_recv.sin_zero), 8); + +} + +static int process_arg(int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt(argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi(optarg); + g_dest.sin_port = htons(atoi(optarg)); + break; + case 'd': + stpcpy(destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr(optarg); + break; + case 's': + stpcpy(sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr(optarg); + g_recv.sin_addr.s_addr = inet_addr(optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi(optarg); + break; + case 'l': + msg_length = atoi(optarg); + break; + case 't': + times = atoi(optarg); + break; + case 'e': + sleepCnt = atoi(optarg); + break; + case 'i': + sleepTime = atoi(optarg); + break; + case 'f': + fdNumber = atoi(optarg); + break; + case 'r': + recvPort = atoi(optarg); + g_recv.sin_port = htons(atoi(optarg)); + break; + case 'n': + connectNum = atoi(optarg); + break; + case 'w': + waitTime = atoi(optarg); + break; + case 'u': + unitPrint = atoi(optarg); + break; + case 'x': + flagPrint = atoi(optarg); + break; + + } + } + return 1; +} + +/* + using this thread to do recv msg; +*/ +void *process_server_msg_thread(void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + struct timeval timeout; + fd_set rfds; + int maxfd; + + struct timespec recvStart; + struct timespec recvEnd; + memset(&recvStart, 0, sizeof(recvStart)); + memset(&recvEnd, 0, sizeof(recvEnd)); + + pthread_detach(pthread_self()); + + int msgFd = *(int *) pArgv; + + clock_gettime(CLOCK_MONOTONIC, &recvStart); + while (1) + { + FD_ZERO(&rfds); + FD_SET(msgFd, &rfds); + maxfd = msgFd + 1; + timeout.tv_sec = 10; + timeout.tv_usec = 0; + ret = select(maxfd, &rfds, NULL, NULL, &timeout); + + if (ret <= 0) + { + continue; + } + + if (FD_ISSET(msgFd, &rfds) == 0) + { + continue; + } + + recvLen = 0; + recvLen2 = 0; + + do + { + recvLen2 = + recv(msgFd, recv_buf + recvLen, msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + if (msg_length != send(msgFd, send_buf, msg_length, 0)) + { + printf("send failed!====, need exit\n"); + } + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime(CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint; + printf("receive count:%d, receive time: %ld ns\n", + recv_count, recv_ppstime); + printf("receive pps = %d\n", recv_pps); + clock_gettime(CLOCK_MONOTONIC, &recvStart); + } + } + while (1); + + if (recv_count == times) + { + break; + } + } + close(msgFd); +} + +/* + using this thread to do accept connect +*/ +void *process_server_accept_thread(void *pArgv) +{ + int listenFd = 0; + int x, optval, ret, m = 0; + int acpt_socketfd[1000] = { 0 }; + struct timeval timeout; + fd_set rfds; + int maxfd; + + listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf("ERROR:socket failed,errno [%d]\n", errno); + return NULL; + } + else + { + printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) + { + printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close(listenFd); + } + + optval = 1; + ret = + setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof(optval)); + if (ret == -1) + { + printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close(listenFd); + return NULL; + } + + if (0 != + bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) + { + printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close(listenFd); + //return NULL; + exit(-1); + } + else + { + printf("INFO:Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), + inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen(listenFd, 100)) + { + printf("server socket listen failed. err %d\n", errno); + close(listenFd); + return NULL; + } + printf("Listen Success\n"); + + int accpedNum = 0; + while (accpedNum < connectNum) + { + FD_ZERO(&rfds); + FD_SET(listenFd, &rfds); + maxfd = listenFd + 1; + timeout.tv_sec = 10; + timeout.tv_usec = 0; + ret = select(maxfd, &rfds, NULL, NULL, &timeout); + + if (ret <= 0) + { + continue; + } + + if (FD_ISSET(listenFd, &rfds) == 0) + { + continue; + } + + while (1) + { + acpt_socketfd[accpedNum] = + accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + printf("no more connect\n"); + break; + } + /*add new accptFd to MsgEpFD */ + pthread_t ser_rcv_thread_id; + if (pthread_create + (&ser_rcv_thread_id, NULL, process_server_msg_thread, + (void *) &acpt_socketfd[accpedNum]) == -1) + { + printf("create process_server_msg_thread fail\n"); + break; + } + + printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + + close(listenFd); + + while (1) + { + sleep(10); + } + + pthread_exit(NULL); +} + +void main(int argc, char *argv[]) +{ + socklen_t addrlen = sizeof(struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault(); + ret = process_arg(argc, argv); + if (ret != 1) + { + printf("The param error\n"); + return; + } + + pthread_t server_thread_id; + + if (pthread_create + (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) + { + printf("create process_server_accept_thread fail\n"); + return; + } + + printf("create process_server_accept_thread success\n"); + + if (server_thread_id != 0) + { + printf("Server Thread join\n"); + pthread_join(server_thread_id, NULL); + } + + while (1) + { + sleep(10); + } + + return; +} diff --git a/demo/nginx_proxy/README.md b/demo/nginx_proxy/README.md new file mode 100644 index 0000000..4085cc9 --- /dev/null +++ b/demo/nginx_proxy/README.md @@ -0,0 +1,24 @@ +# Introduction +DMM (Dual Mode, Multi-protocol, Multi-instance) is to implement a transport agnostic framework for network +applications that can +1. Work with both user space and kernel space network stacks +2. Use different network protocol stacks based on their functional and performance requirements (QOS) +3. Work with multiple instances of a transport protocol stack. + +Following demo directory demonstrates some of these features of DMM. +Procedures and details of how to run this demo is inside each demo directory. + +##demo-1 + +This demo use NGINX as a reverse proxy server. The server uses lwip as client facing stack and kernel tcp/ip +stack as upstream server facing stack. + +##demo-2 + +This demo NGINX as a reverse proxy server. The server uses lwip as client facing stack and kernel tcp/ip stack +as upstream server facing stack for UDP, vpp-hoststack for another updtream server facing stack for TCP. + +##demo-3 + +This demo NGINX as a reverse proxy server. The server uses kernel tcp/ip as client facing stack and rsocket +stack as upstream server facing stack. diff --git a/demo/nginx_proxy/demo-1/Vagrantfile b/demo/nginx_proxy/demo-1/Vagrantfile new file mode 100644 index 0000000..d3db5e5 --- /dev/null +++ b/demo/nginx_proxy/demo-1/Vagrantfile @@ -0,0 +1,98 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +boxes = [ + { + :name => "rproxy-client", + :hostname => "rproxy-client", + :mem => "1024", + :cpu => "1" + }, + { + :name => "rproxy-server", + :hostname => "rproxy-server", + :mem => "1024", + :cpu => "1" + }, + { + :name => "rproxy-proxy", + :hostname => "rproxy-proxy", + :mem => "10144", + :cpu => "4" + } +] + +Vagrant.configure(2) do |config| + + # Pick the right distro and bootstrap, default is ubuntu1604 + distro = ( ENV['DMM_VAGRANT_DISTRO'] || "ubuntu") + if distro == 'centos7' + config.vm.box = "puppetlabs/centos-7.2-64-nocm" + else + config.vm.box = "puppetlabs/ubuntu-16.04-64-nocm" + end + + config.vm.box_check_update = false + #ddconfig.ssh.password = vagrant + if Vagrant.has_plugin?("vagrant-cachier") + config.cache.scope = :box + end + + # Define some physical ports for your VMs to be used by DPDK + #nics = (ENV['DMM_VAGRANT_NICS'] || "2").to_i(10) + #for i in 1..nics + # config.vm.network "private_network", type: "dhcp" + #end + + if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf") + config.proxy.http = ENV['http_proxy'] + config.proxy.https = ENV['https_proxy'] + config.proxy.no_proxy = "localhost,127.0.0.1" + end + + config.ssh.forward_agent = true + config.ssh.forward_x11 = true + + boxes.each do |opts| + config.vm.define opts[:name] do |srv| + srv.vm.hostname = opts[:hostname] + srv.vm.provider "virtualbox" do |vb| + vb.customize ["modifyvm", :id, "--ioapic", "on"] + vb.customize ["modifyvm", :id, "--memory", opts[:mem]] + vb.customize ["modifyvm", :id, "--cpus", opts[:cpu]] + end + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../scripts/install_prereq.sh") + puts ' '..srv.vm.hostname + + if opts[:name] == "rproxy-proxy" + puts 'NGINX Proxy Server, Run nginx in below way ' + puts 'export LD_LIBRARY_PATH=/DMM/stacks/lwip_stack/release/lib64' + puts './DMM/thirdparty/apps/nginx/release/nginx' + srv.vm.synced_folder "../../../", "/DMM", type: "rsync" + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"adjust_hugepage.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"apply_patch.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../stacks/lwip_stack/vagrant/build.sh"), :args => "/DMM vagrant" + srv.vm.network "private_network", ip: "192.168.50.20" + srv.vm.network "private_network", ip: "172.167.50.20" + srv.vm.network "private_network", type: "dhcp" + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../stacks/lwip_stack/vagrant/start_nstackMain.sh"), :args => "/DMM vagrant" + #possibly overwrite by previous script so adjust again + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"adjust_hugepage.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"setup_proxy.sh"), run: 'always' + end + if opts[:name] == "rproxy-client" + puts 'Client use command: curl http://192.168.50.20' + srv.vm.network "private_network", type: "dhcp" + srv.vm.network "private_network", ip: "192.168.50.10" + end + if opts[:name] == "rproxy-server" + puts 'Upstream server ' + + srv.vm.synced_folder "./", "/NGINX", type: "rsync" + srv.vm.network "private_network", type: "dhcp" + srv.vm.provision "up", type: "shell", :path => File.join(File.dirname(__FILE__),"setup_upstream.sh"), run: 'always' + srv.vm.network "private_network", ip: "172.167.50.30" + end + end + end +end diff --git a/demo/nginx_proxy/demo-1/adjust_hugepage.sh b/demo/nginx_proxy/demo-1/adjust_hugepage.sh new file mode 100644 index 0000000..282e3bd --- /dev/null +++ b/demo/nginx_proxy/demo-1/adjust_hugepage.sh @@ -0,0 +1,14 @@ +#!/bin/bash -x +hugepagesize=$(cat /proc/meminfo | grep Hugepagesize | awk -F " " {'print$2'}) +if [ "$hugepagesize" == "2048" ]; then + pages=3000 +elif [ "$hugepagesize" == "1048576" ]; then + pages=5 +fi +sudo sysctl -w vm.nr_hugepages=$pages +HUGEPAGES=`sysctl -n vm.nr_hugepages` +echo "Configured hugepages: $HUGEPAGE" +if [ $HUGEPAGES != $pages ]; then + echo "Warning: Unable to get $pages hugepages, only got $HUGEPAGES. Cannot finish." +fi + diff --git a/demo/nginx_proxy/demo-1/apply_patch.sh b/demo/nginx_proxy/demo-1/apply_patch.sh new file mode 100755 index 0000000..84ecc59 --- /dev/null +++ b/demo/nginx_proxy/demo-1/apply_patch.sh @@ -0,0 +1,9 @@ +#!/bin/bash -x +sudo apt-get install patch -y +cd /DMM/src/ +sudo patch -p2 -i /DMM/demo/nginx_proxy/demo-1/demo_2stack.patch +if [ $? -ne 0 ]; then + echo "Patch Apply failed. Downlaod correct commit. Check README for details." + exit -1 +fi +cd - diff --git a/demo/nginx_proxy/demo-1/demo_2stack.patch b/demo/nginx_proxy/demo-1/demo_2stack.patch new file mode 100644 index 0000000..100f825 --- /dev/null +++ b/demo/nginx_proxy/demo-1/demo_2stack.patch @@ -0,0 +1,15 @@ +diff --git a/src/nSocket/nstack/nstack_module.c b/src/nSocket/nstack/nstack_module.c +index fdfea06..27e96d6 100644 +--- a/src/nSocket/nstack/nstack_module.c ++++ b/src/nSocket/nstack/nstack_module.c +@@ -61,6 +61,10 @@ int nstack_get_deploy_type() + if (g_nstack_module_desc[icnt].deploytype > type) + { + type = g_nstack_module_desc[icnt].deploytype; ++ if (NSTACK_MODEL_TYPE3 == type) ++ { ++ break; ++ } + } + } + return type; diff --git a/demo/nginx_proxy/demo-1/module_config.json b/demo/nginx_proxy/demo-1/module_config.json new file mode 100644 index 0000000..2ed8f19 --- /dev/null +++ b/demo/nginx_proxy/demo-1/module_config.json @@ -0,0 +1,26 @@ +{ + "default_stack_name": "kernel", + "module_list": [ + { + "stack_name": "kernel", + "function_name": "kernel_stack_register", + "libname": "./", + "deploytype": "1", + "stackid": "0" + }, + { + "stack_name": "lwip", + "function_name": "lwip_stack_register", + "libname": "liblwip_dpdk.so", + "deploytype": "3", + "stackid": "1" + }, + { + "stack_name": "vpp_hoststack", + "function_name": "vpp_hoststack_stack_register", + "libname": "./libdmm_vcl.so", + "deploytype": "4", + "stackid": "2" + } + ] +} diff --git a/demo/nginx_proxy/demo-1/proxy_nginx.conf b/demo/nginx_proxy/demo-1/proxy_nginx.conf new file mode 100644 index 0000000..05d8d2a --- /dev/null +++ b/demo/nginx_proxy/demo-1/proxy_nginx.conf @@ -0,0 +1,81 @@ +user root; +worker_processes 1; +daemon off; +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 192.168.50.20:80 default_server; + server_name 192.168.50.20; + + location / { + proxy_bind 172.167.50.20:2020; + proxy_pass http://172.167.50.30:80; + proxy_set_header X-Real-IP $remote_addr; + sendfile off; + proxy_buffering off; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + + +} diff --git a/demo/nginx_proxy/demo-1/rd_config.json b/demo/nginx_proxy/demo-1/rd_config.json new file mode 100644 index 0000000..0ba79fd --- /dev/null +++ b/demo/nginx_proxy/demo-1/rd_config.json @@ -0,0 +1,42 @@ +{ + "modules": [ + { + "name": "kernel", + "ip_route": [ + "192.168.50.10/32" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "2", + "attr": "0" + } + ] + }, + { + "name": "lwip", + "ip_route": [ + "192.168.50.20/32" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "1", + "attr": "0" + } + ] + }, + { + "name": "vpp_hoststack", + "ip_route": [ + "172.167.50.20/24" + ], + "type_route": [ + ], + "protocol_route": [ + ] + } + ] +} diff --git a/demo/nginx_proxy/demo-1/setup_proxy.sh b/demo/nginx_proxy/demo-1/setup_proxy.sh new file mode 100644 index 0000000..d7bce92 --- /dev/null +++ b/demo/nginx_proxy/demo-1/setup_proxy.sh @@ -0,0 +1,54 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x +sudo su +# Clean up build NGINX +cd /DMM/build/ + +#Download and compile NGINX +make NGINX +#Download and compile vpp-stack +make vpp-stack + +#cp vpp libs +cp -r /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib/vpp_plugins /usr/lib/ +mkdir -p /etc/vpp/ +cp /DMM/demo/nginx_proxy/demo-1/startup.conf /etc/vpp/ +cp /DMM/demo/nginx_proxy/demo-1/vpp_config /etc/vpp/ +cd /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/bin +#run vpp +sudo ifconfig enp0s9 down +./vpp -c /etc/vpp/startup.conf + +#cp nginx libs +cd /DMM/thirdparty/apps/nginx/release + +# Move the conf file. +cp /DMM/demo/nginx_proxy/demo-1/module_config.json /DMM/thirdparty/apps/nginx/release/ +cp /DMM/stacks/lwip_stack/configure/nStackConfig.json /DMM/thirdparty/apps/nginx/release/ +cp /DMM/demo/nginx_proxy/demo-1/proxy_nginx.conf /DMM/thirdparty/apps/nginx/release/ +cp /DMM/demo/nginx_proxy/demo-1/rd_config.json /DMM/thirdparty/apps/nginx/release/ +mv /DMM/thirdparty/apps/nginx/release/proxy_nginx.conf /DMM/thirdparty/apps/nginx/release/nginx.conf + +sleep 5 + +# Run nginx +cp /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib/libdmm_vcl.so /DMM/thirdparty/apps/nginx/release/ +echo "export LD_LIBRARY_PATH=/DMM/stacks/lwip_stack/release/lib64" +echo "./nginx" + +exit 0 diff --git a/demo/nginx_proxy/demo-1/setup_upstream.sh b/demo/nginx_proxy/demo-1/setup_upstream.sh new file mode 100644 index 0000000..0c2c774 --- /dev/null +++ b/demo/nginx_proxy/demo-1/setup_upstream.sh @@ -0,0 +1,45 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +# Download nginx +cd /NGINX +wget http://nginx.org/download/nginx-1.14.0.tar.gz +tar -zxf nginx-1.14.0.tar.gz + +#install supportive softwares +apt-get install -yq libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev + +# Compile nginx +cd nginx-1.14.0 +./configure +make +make install + +# Move the conf file. +cd /usr/local/nginx/sbin +cp -r * /usr/local/sbin +cp /NGINX/upstream_nginx.conf /usr/local/nginx/conf/ +mv /usr/local/nginx/conf/upstream_nginx.conf /usr/local/nginx/conf/nginx.conf + +# Run nginx + +cd /usr/local/sbin +./nginx +echo "hi" +exit 0 + diff --git a/demo/nginx_proxy/demo-1/startup.conf b/demo/nginx_proxy/demo-1/startup.conf new file mode 100644 index 0000000..616cd88 --- /dev/null +++ b/demo/nginx_proxy/demo-1/startup.conf @@ -0,0 +1,20 @@ +unix { + log /var/log/vpp/vpp.log + cli-listen localhost:5002 + exec /etc/vpp/vpp_config +} + +api-trace { + on +} + +cpu { + main-core 2 +} + +dpdk { + socket-mem 1024 + uio-driver igb_uio + dev 0000:00:09.0 +} + diff --git a/demo/nginx_proxy/demo-1/upstream_nginx.conf b/demo/nginx_proxy/demo-1/upstream_nginx.conf new file mode 100644 index 0000000..3904197 --- /dev/null +++ b/demo/nginx_proxy/demo-1/upstream_nginx.conf @@ -0,0 +1,80 @@ +#user nobody; +worker_processes 1; +#daemon off; + +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 80; + #server_name localhost; + + #charset koi8-r; + + #access_log logs/host.access.log main; + + location / { + return 200 "Hello from upstream $hostname $server_addr:$server_port. Connect from $http_x_real_ip - $remote_user via $remote_addr:$remote_port at [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent\n"; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + +} diff --git a/demo/nginx_proxy/demo-1/vpp_config b/demo/nginx_proxy/demo-1/vpp_config new file mode 100644 index 0000000..aaeadfb --- /dev/null +++ b/demo/nginx_proxy/demo-1/vpp_config @@ -0,0 +1,6 @@ +set int state GigabitEthernet0/9/0 up +set int ip addr GigabitEthernet0/9/0 172.167.50.20/24 +show version +show version verbose +show cpu +show int diff --git a/demo/nginx_proxy/demo-2/README.md b/demo/nginx_proxy/demo-2/README.md new file mode 100644 index 0000000..7d6feb1 --- /dev/null +++ b/demo/nginx_proxy/demo-2/README.md @@ -0,0 +1,69 @@ +#demo-2 +## Introduction +This demo NGINX as a reverse proxy server. The server uses "lwip" for client facing socket and "kernel tcp/ip stack " +as upstream server facing socket for UDP, "vpp-hoststack" for another updtream server facing stack for TCP. + +## Topology +![demo-2.png](demo-2.png) +![dem-2-topo.png](dem-2-topo.png) +## Steps +####1. Create VMs using vagrant. +Start demo VMs. Go to dmm/demo/nginx_proxy/demo-2 . +``` +$ vagrant up +``` +This command will create 4 VMs namely rproxy-client, rproxy-server1, rproxy-server2 and rproxy-proxy. The memory +requirement for this demo is 13GB (approx). + +####2. Log in to VMs +Open four terminal and login to VMs. +``` +$ vagrant ssh +``` + +####3. Run Udp server Application at rproxy-server2 +``` +$ vagrant ssh rproxy-server2 +Inside VM +vagrant@rproxy-server2:~$ sudo su +root@rproxy-server2:/home/vagrant# cd /UDPSERVER/ +root@rproxy-server2:/UDPSERVER# ./udpserver +``` + +####4. Run NGINX proxy server at rproxy-proxy +``` +$ vagrant ssh rproxy-proxy +Inside VM +vagrant@rproxy-proxy:~$ sudo su +root@rproxy-proxy:/home/vagrant# cd /DMM/thirdparty/apps/nginx/release +root@rproxy-proxy:/DMM/thirdparty/apps/nginx/release# export LD_LIBRARY_PATH=/DMM/stacks/lwip_stack/release/lib64 +root@rproxy-proxy:/DMM/thirdparty/apps/nginx/release# ./nginx +``` +####5. Test TCP traffic +``` +$ vagrant ssh rproxy-client +vagrant@rproxy-client:~$ cd /CLIENT/ +vagrant@rproxy-client:/CLIENT$ curl http://192.168.50.20 +Hello from upstream rproxy-server1 172.167.50.30:80. Connect from - via 172.167.50.20:15140 at [12/Nov/2018:06:17:25 -0800] GET / HTTP/1.1 200 0 curl/7.47.0 + +``` + +####6. Test UDP traffic +``` +$ vagrant ssh rproxy-client +vagrant@rproxy-client:~$ cd /CLIENT/ +vagrant@rproxy-client:/CLIENT$ ./udpclient +Hello message sent. +Server : Hello from server +``` +#### Notes: +a. If enable debugs i.e. export NSTACK_LOG_ON=DBG before we run nginx in rroxy-proxy we can find below logs which suggest we use diffrent stack for diffrent ip/protoccol. +``` +... +nstack_bindfd addr Select module]fd=18,addr=192.168.50.20,module=lwip +... +nstack_bindfd addr Select module]fd=22,addr=172.167.50.20,module=vpp_hoststack +... +nstack_bindfd addr Select module]fd=22,addr=182.167.50.20,module=kernel +``` +b. This demo depends on commit of dmm. Please check commit version of your code. diff --git a/demo/nginx_proxy/demo-2/Vagrantfile b/demo/nginx_proxy/demo-2/Vagrantfile new file mode 100644 index 0000000..dbd703a --- /dev/null +++ b/demo/nginx_proxy/demo-2/Vagrantfile @@ -0,0 +1,116 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +boxes = [ + { + :name => "rproxy-client", + :hostname => "rproxy-client", + :mem => "1024", + :cpu => "1" + }, + { + :name => "rproxy-server1", + :hostname => "rproxy-server1", + :mem => "1024", + :cpu => "1" + }, + { + :name => "rproxy-server2", + :hostname => "rproxy-server2", + :mem => "1024", + :cpu => "1" + }, + { + :name => "rproxy-proxy", + :hostname => "rproxy-proxy", + :mem => "10144", + :cpu => "4" + } +] + +Vagrant.configure(2) do |config| + + # Pick the right distro and bootstrap, default is ubuntu1604 + distro = ( ENV['DMM_VAGRANT_DISTRO'] || "ubuntu") + if distro == 'centos7' + config.vm.box = "puppetlabs/centos-7.2-64-nocm" + else + config.vm.box = "puppetlabs/ubuntu-16.04-64-nocm" + end + + config.vm.box_check_update = false + #ddconfig.ssh.password = vagrant + if Vagrant.has_plugin?("vagrant-cachier") + config.cache.scope = :box + end + + # Define some physical ports for your VMs to be used by DPDK + #nics = (ENV['DMM_VAGRANT_NICS'] || "2").to_i(10) + #for i in 1..nics + # config.vm.network "private_network", type: "dhcp" + #end + + if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf") + config.proxy.http = ENV['http_proxy'] + config.proxy.https = ENV['https_proxy'] + config.proxy.no_proxy = "localhost,127.0.0.1" + end + + config.ssh.forward_agent = true + config.ssh.forward_x11 = true + + boxes.each do |opts| + config.vm.define opts[:name] do |srv| + srv.vm.hostname = opts[:hostname] + srv.vm.provider "virtualbox" do |vb| + vb.customize ["modifyvm", :id, "--ioapic", "on"] + vb.customize ["modifyvm", :id, "--memory", opts[:mem]] + vb.customize ["modifyvm", :id, "--cpus", opts[:cpu]] + end + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../scripts/install_prereq.sh") + puts ' '..srv.vm.hostname + + if opts[:name] == "rproxy-proxy" + puts 'NGINX Proxy Server, Run nginx in below way ' + puts 'export LD_LIBRARY_PATH=/DMM/stacks/lwip_stack/release/lib64' + puts './DMM/thirdparty/apps/nginx/release/nginx' + srv.vm.synced_folder "../../../", "/DMM", type: "rsync" + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"adjust_hugepage.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"apply_patch.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../stacks/lwip_stack/vagrant/build.sh"), :args => "/DMM vagrant" + srv.vm.network "private_network", ip: "192.168.50.20" + srv.vm.network "private_network", ip: "172.167.50.20" + srv.vm.network "private_network", ip: "182.167.50.20" + srv.vm.network "private_network", type: "dhcp" + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../stacks/lwip_stack/vagrant/start_nstackMain.sh"), :args => "/DMM vagrant" + #possibly overwrite by previous script so adjust again + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"adjust_hugepage.sh"), run: 'always' + srv.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"setup_proxy.sh"), run: 'always' + end + if opts[:name] == "rproxy-client" + puts 'Client use command for TCP: curl http://192.168.50.20' + puts 'Client use command for UDP: ./udpclient' + srv.vm.synced_folder "./", "/CLIENT", type: "rsync" + srv.vm.network "private_network", type: "dhcp" + srv.vm.network "private_network", ip: "192.168.50.10" + srv.vm.provision "up", type: "shell", :path => File.join(File.dirname(__FILE__),"setup_client.sh"), run: 'always' + end + if opts[:name] == "rproxy-server1" + puts 'Upstream server 1' + + srv.vm.synced_folder "./", "/NGINX", type: "rsync" + srv.vm.network "private_network", type: "dhcp" + srv.vm.provision "up", type: "shell", :path => File.join(File.dirname(__FILE__),"setup_upstream.sh"), run: 'always' + srv.vm.network "private_network", ip: "172.167.50.30" + end + if opts[:name] == "rproxy-server2" + puts 'Upstream server 2 ' + + srv.vm.synced_folder "./", "/UDPSERVER", type: "rsync" + srv.vm.network "private_network", type: "dhcp" + srv.vm.provision "up", type: "shell", :path => File.join(File.dirname(__FILE__),"setup_udpserver.sh"), run: 'always' + srv.vm.network "private_network", ip: "182.167.50.30" + end + end + end +end diff --git a/demo/nginx_proxy/demo-2/adjust_hugepage.sh b/demo/nginx_proxy/demo-2/adjust_hugepage.sh new file mode 100644 index 0000000..282e3bd --- /dev/null +++ b/demo/nginx_proxy/demo-2/adjust_hugepage.sh @@ -0,0 +1,14 @@ +#!/bin/bash -x +hugepagesize=$(cat /proc/meminfo | grep Hugepagesize | awk -F " " {'print$2'}) +if [ "$hugepagesize" == "2048" ]; then + pages=3000 +elif [ "$hugepagesize" == "1048576" ]; then + pages=5 +fi +sudo sysctl -w vm.nr_hugepages=$pages +HUGEPAGES=`sysctl -n vm.nr_hugepages` +echo "Configured hugepages: $HUGEPAGE" +if [ $HUGEPAGES != $pages ]; then + echo "Warning: Unable to get $pages hugepages, only got $HUGEPAGES. Cannot finish." +fi + diff --git a/demo/nginx_proxy/demo-2/apply_patch.sh b/demo/nginx_proxy/demo-2/apply_patch.sh new file mode 100755 index 0000000..05e8c66 --- /dev/null +++ b/demo/nginx_proxy/demo-2/apply_patch.sh @@ -0,0 +1,9 @@ +#!/bin/bash -x +sudo apt-get install patch -y +cd /DMM/src/ +sudo patch -p2 -i /DMM/demo/nginx_proxy/demo-2/demo_2stack.patch +if [ $? -ne 0 ]; then + echo "Patch Apply failed. Downlaod correct commit. Check README for details." + exit -1 +fi +cd - diff --git a/demo/nginx_proxy/demo-2/dem-2-topo.png b/demo/nginx_proxy/demo-2/dem-2-topo.png new file mode 100644 index 0000000..ad81372 Binary files /dev/null and b/demo/nginx_proxy/demo-2/dem-2-topo.png differ diff --git a/demo/nginx_proxy/demo-2/demo-2.png b/demo/nginx_proxy/demo-2/demo-2.png new file mode 100644 index 0000000..604c301 Binary files /dev/null and b/demo/nginx_proxy/demo-2/demo-2.png differ diff --git a/demo/nginx_proxy/demo-2/demo_2stack.patch b/demo/nginx_proxy/demo-2/demo_2stack.patch new file mode 100644 index 0000000..100f825 --- /dev/null +++ b/demo/nginx_proxy/demo-2/demo_2stack.patch @@ -0,0 +1,15 @@ +diff --git a/src/nSocket/nstack/nstack_module.c b/src/nSocket/nstack/nstack_module.c +index fdfea06..27e96d6 100644 +--- a/src/nSocket/nstack/nstack_module.c ++++ b/src/nSocket/nstack/nstack_module.c +@@ -61,6 +61,10 @@ int nstack_get_deploy_type() + if (g_nstack_module_desc[icnt].deploytype > type) + { + type = g_nstack_module_desc[icnt].deploytype; ++ if (NSTACK_MODEL_TYPE3 == type) ++ { ++ break; ++ } + } + } + return type; diff --git a/demo/nginx_proxy/demo-2/module_config.json b/demo/nginx_proxy/demo-2/module_config.json new file mode 100644 index 0000000..2ed8f19 --- /dev/null +++ b/demo/nginx_proxy/demo-2/module_config.json @@ -0,0 +1,26 @@ +{ + "default_stack_name": "kernel", + "module_list": [ + { + "stack_name": "kernel", + "function_name": "kernel_stack_register", + "libname": "./", + "deploytype": "1", + "stackid": "0" + }, + { + "stack_name": "lwip", + "function_name": "lwip_stack_register", + "libname": "liblwip_dpdk.so", + "deploytype": "3", + "stackid": "1" + }, + { + "stack_name": "vpp_hoststack", + "function_name": "vpp_hoststack_stack_register", + "libname": "./libdmm_vcl.so", + "deploytype": "4", + "stackid": "2" + } + ] +} diff --git a/demo/nginx_proxy/demo-2/proxy_nginx.conf b/demo/nginx_proxy/demo-2/proxy_nginx.conf new file mode 100644 index 0000000..925e1a9 --- /dev/null +++ b/demo/nginx_proxy/demo-2/proxy_nginx.conf @@ -0,0 +1,33 @@ +user root; +worker_processes 1; +daemon off; +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + +stream { + upstream stream_tcp { + server 172.167.50.30:80; + } + upstream stream_udp { + server 182.167.50.30:53; + } + server { + listen 192.168.50.20:80; + proxy_bind 172.167.50.20:2020; + proxy_pass stream_tcp; + } + server { + listen 192.168.50.20:53 udp; + proxy_bind 182.167.50.20:53; + proxy_pass stream_udp; + } +} + diff --git a/demo/nginx_proxy/demo-2/rd_config.json b/demo/nginx_proxy/demo-2/rd_config.json new file mode 100644 index 0000000..e312af4 --- /dev/null +++ b/demo/nginx_proxy/demo-2/rd_config.json @@ -0,0 +1,43 @@ +{ + "modules": [ + { + "name": "kernel", + "ip_route": [ + "192.168.50.10/32", + "182.167.50.20/32" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "2", + "attr": "0" + } + ] + }, + { + "name": "lwip", + "ip_route": [ + "192.168.50.20/32" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "1", + "attr": "0" + } + ] + }, + { + "name": "vpp_hoststack", + "ip_route": [ + "172.167.50.20/24" + ], + "type_route": [ + ], + "protocol_route": [ + ] + } + ] +} diff --git a/demo/nginx_proxy/demo-2/setup_client.sh b/demo/nginx_proxy/demo-2/setup_client.sh new file mode 100644 index 0000000..a0f4363 --- /dev/null +++ b/demo/nginx_proxy/demo-2/setup_client.sh @@ -0,0 +1,25 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +# Download nginx +cd /CLIENT + +gcc udpclient.c -o udpclient + +exit 0 + diff --git a/demo/nginx_proxy/demo-2/setup_proxy.sh b/demo/nginx_proxy/demo-2/setup_proxy.sh new file mode 100644 index 0000000..b46fe6a --- /dev/null +++ b/demo/nginx_proxy/demo-2/setup_proxy.sh @@ -0,0 +1,54 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x +sudo su +# Clean up build NGINX +cd /DMM/build/ + +#Download and compile NGINX +make NGINX +#Download and compile vpp-stack +make vpp-stack + +#cp vpp libs +cp -r /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib/vpp_plugins /usr/lib/ +mkdir -p /etc/vpp/ +cp /DMM/demo/nginx_proxy/demo-2/startup.conf /etc/vpp/ +cp /DMM/demo/nginx_proxy/demo-2/vpp_config /etc/vpp/ +cd /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/bin +#run vpp +sudo ifconfig enp0s9 down +./vpp -c /etc/vpp/startup.conf + +#cp nginx libs +cd /DMM/thirdparty/apps/nginx/release + +# Move the conf file. +cp /DMM/demo/nginx_proxy/demo-2/module_config.json /DMM/thirdparty/apps/nginx/release/ +cp /DMM/stacks/lwip_stack/configure/nStackConfig.json /DMM/thirdparty/apps/nginx/release/ +cp /DMM/demo/nginx_proxy/demo-2/proxy_nginx.conf /DMM/thirdparty/apps/nginx/release/ +cp /DMM/demo/nginx_proxy/demo-2/rd_config.json /DMM/thirdparty/apps/nginx/release/ +mv /DMM/thirdparty/apps/nginx/release/proxy_nginx.conf /DMM/thirdparty/apps/nginx/release/nginx.conf + +sleep 5 + +# Run nginx +cp /DMM/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib/libdmm_vcl.so /DMM/thirdparty/apps/nginx/release/ +echo "export LD_LIBRARY_PATH=/DMM/stacks/lwip_stack/release/lib64" +echo "./nginx" + +exit 0 diff --git a/demo/nginx_proxy/demo-2/setup_udpserver.sh b/demo/nginx_proxy/demo-2/setup_udpserver.sh new file mode 100644 index 0000000..d684286 --- /dev/null +++ b/demo/nginx_proxy/demo-2/setup_udpserver.sh @@ -0,0 +1,25 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +# Download nginx +cd /UDPSERVER + +gcc udpserver.c -o udpserver + +exit 0 + diff --git a/demo/nginx_proxy/demo-2/setup_upstream.sh b/demo/nginx_proxy/demo-2/setup_upstream.sh new file mode 100644 index 0000000..ee7dbd4 --- /dev/null +++ b/demo/nginx_proxy/demo-2/setup_upstream.sh @@ -0,0 +1,44 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +# Download nginx +cd /NGINX +wget http://nginx.org/download/nginx-1.14.0.tar.gz +tar -zxf nginx-1.14.0.tar.gz + +#install supportive softwares +apt-get install -yq libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev + +# Compile nginx +cd nginx-1.14.0 +./configure +make +make install + +# Move the conf file. +cd /usr/local/nginx/sbin +cp -r * /usr/local/sbin +cp /NGINX/upstream_nginx.conf /usr/local/nginx/conf/ +mv /usr/local/nginx/conf/upstream_nginx.conf /usr/local/nginx/conf/nginx.conf + +# Run nginx + +cd /usr/local/sbin +./nginx +exit 0 + diff --git a/demo/nginx_proxy/demo-2/startup.conf b/demo/nginx_proxy/demo-2/startup.conf new file mode 100644 index 0000000..616cd88 --- /dev/null +++ b/demo/nginx_proxy/demo-2/startup.conf @@ -0,0 +1,20 @@ +unix { + log /var/log/vpp/vpp.log + cli-listen localhost:5002 + exec /etc/vpp/vpp_config +} + +api-trace { + on +} + +cpu { + main-core 2 +} + +dpdk { + socket-mem 1024 + uio-driver igb_uio + dev 0000:00:09.0 +} + diff --git a/demo/nginx_proxy/demo-2/udpclient.c b/demo/nginx_proxy/demo-2/udpclient.c new file mode 100644 index 0000000..3aca2df --- /dev/null +++ b/demo/nginx_proxy/demo-2/udpclient.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PORT 53 +#define MAXLINE 1024 + +// Driver code +int main() +{ + int sockfd; + char buffer[MAXLINE]; + char *hello = "Hello from client"; + struct sockaddr_in servaddr; + + // Creating socket file descriptor + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } + + memset(&servaddr, 0, sizeof(servaddr)); + + // Filling server information + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(PORT); + servaddr.sin_addr.s_addr = inet_addr("192.168.50.20"); + + int n, len; + + sendto(sockfd, (const char *) hello, strlen(hello), + MSG_CONFIRM, (const struct sockaddr *) &servaddr, + sizeof(servaddr)); + printf("Hello message sent.\n"); + + n = recvfrom(sockfd, (char *) buffer, MAXLINE, + MSG_WAITALL, (struct sockaddr *) &servaddr, &len); + buffer[n] = '\0'; + printf("Server : %s\n", buffer); + + close(sockfd); + return 0; +} diff --git a/demo/nginx_proxy/demo-2/udpserver.c b/demo/nginx_proxy/demo-2/udpserver.c new file mode 100644 index 0000000..dfea2f2 --- /dev/null +++ b/demo/nginx_proxy/demo-2/udpserver.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PORT 53 +#define MAXLINE 1024 + +int main() +{ + int sockfd; + char buffer[MAXLINE]; + char *hello = "Hello from server"; + + struct sockaddr_in servaddr, cliaddr; + char name[128] = { 0 }; + + // Creating socket file descriptor + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } + + memset(&servaddr, 0, sizeof(servaddr)); + memset(&cliaddr, 0, sizeof(cliaddr)); + + // Filling server information + servaddr.sin_family = AF_INET; // IPv4 + servaddr.sin_addr.s_addr = inet_addr("182.167.50.30"); + servaddr.sin_port = htons(PORT); + + if (bind(sockfd, (const struct sockaddr *) &servaddr, + sizeof(servaddr)) < 0) + { + perror("bind failed"); + exit(EXIT_FAILURE); + } + + int len, n; + n = recvfrom(sockfd, (char *) buffer, MAXLINE, + MSG_WAITALL, (struct sockaddr *) &cliaddr, &len); + buffer[n] = '\0'; + (void) gethostname(name, 127); + printf("Client : %s \n", buffer); + sendto(sockfd, (const char *) hello, strlen(hello), + MSG_CONFIRM, (const struct sockaddr *) &cliaddr, len); + printf("%s\n", hello); + return 0; +} diff --git a/demo/nginx_proxy/demo-2/upstream_nginx.conf b/demo/nginx_proxy/demo-2/upstream_nginx.conf new file mode 100644 index 0000000..3904197 --- /dev/null +++ b/demo/nginx_proxy/demo-2/upstream_nginx.conf @@ -0,0 +1,80 @@ +#user nobody; +worker_processes 1; +#daemon off; + +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 80; + #server_name localhost; + + #charset koi8-r; + + #access_log logs/host.access.log main; + + location / { + return 200 "Hello from upstream $hostname $server_addr:$server_port. Connect from $http_x_real_ip - $remote_user via $remote_addr:$remote_port at [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent\n"; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + +} diff --git a/demo/nginx_proxy/demo-2/vpp_config b/demo/nginx_proxy/demo-2/vpp_config new file mode 100644 index 0000000..aaeadfb --- /dev/null +++ b/demo/nginx_proxy/demo-2/vpp_config @@ -0,0 +1,6 @@ +set int state GigabitEthernet0/9/0 up +set int ip addr GigabitEthernet0/9/0 172.167.50.20/24 +show version +show version verbose +show cpu +show int diff --git a/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md b/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md new file mode 100644 index 0000000..6deb348 --- /dev/null +++ b/demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md @@ -0,0 +1,26 @@ +# Demo: NGINX working with multi-stack using DMM + +![image](rsocket.png) + + + +In above diagram NGINX box in the middle is working as reverse proxy. +One of the NIC ( client facing) is using kernel tcp/ip stack whereas the +other NIC is connected to upstream server using rsocket tcp/ip stack. + +you can use test.c to compile a server depend on libnStackAPI.so. It bind the +port 8888 by default and you can change it to other port. Then copy the +module_config.json rd_config.json to the folder of server. Then you can start the +server as follow: +./server 162.128.1.16 + +####More Information: +https://wiki.fd.io/view/DMM +https://www.nginx.com/blog/ip-transparency-direct-server-return-nginx-plus-transparent-proxy/ + + + + + + + diff --git a/demo/nginx_proxy/demo-3/proxy_nginx.conf b/demo/nginx_proxy/demo-3/proxy_nginx.conf new file mode 100644 index 0000000..fb085ac --- /dev/null +++ b/demo/nginx_proxy/demo-3/proxy_nginx.conf @@ -0,0 +1,81 @@ +user root; +worker_processes 1; +daemon off; +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 192.168.131.181:80 default_server; + server_name 192.168.131.181; + + location / { + proxy_bind 192.168.21.181; + proxy_pass http://192.168.21.180:8888; + proxy_set_header X-Real-IP $remote_addr; + sendfile off; + proxy_buffering off; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + + +} diff --git a/demo/nginx_proxy/demo-3/rd_config.json b/demo/nginx_proxy/demo-3/rd_config.json new file mode 100644 index 0000000..51fa4a5 --- /dev/null +++ b/demo/nginx_proxy/demo-3/rd_config.json @@ -0,0 +1,23 @@ +{ + "ip_route": [ + { + "subnet": "192.168.131.1/24", + "stack_name": "kernel", + }, + { + "subnet": "192.168.21.1/24", + "stack_name": "rsocket", + }, + ], + "prot_route": [ + { + "proto_type": "1", + "stack_name": "rsocket", + }, + { + "proto_type": "2", + "stack_name": "kernel", + } + ], +} + diff --git a/demo/nginx_proxy/demo-3/rsocket.png b/demo/nginx_proxy/demo-3/rsocket.png new file mode 100644 index 0000000..389ae19 Binary files /dev/null and b/demo/nginx_proxy/demo-3/rsocket.png differ diff --git a/demo/nginx_proxy/demo-3/server/index.html b/demo/nginx_proxy/demo-3/server/index.html new file mode 100644 index 0000000..9ab30e1 --- /dev/null +++ b/demo/nginx_proxy/demo-3/server/index.html @@ -0,0 +1,31 @@ + + + + + + + + Hello, world + + + + + +

Hello, world

+ + +

Click on the button to fetch the message.

+ + + diff --git a/demo/nginx_proxy/demo-3/server/test.c b/demo/nginx_proxy/demo-3/server/test.c new file mode 100644 index 0000000..d0e9ecb --- /dev/null +++ b/demo/nginx_proxy/demo-3/server/test.c @@ -0,0 +1,315 @@ +/* + * httpd.c + * + * Copyright Adin Scannell 2011 + * + * This code is intended for demo purposes only, + * please don't actually use it to do anything. + * + * To compile, use: + * gcc -o httpd httpd.c + * Then, create a file 'index.html' in the directory + * that you are running the server from. Put stuff in + * it. + * Then go to http://localhost:8888 and see the file. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define HTTP_BAD_REQUEST "HTTP/1.0 404 Not Found\r\n" +#define HTTP_GOOD_REQUEST "HTTP/1.0 200\r\n" +#define HTTP_CONTENT_TYPE "Content-Type: text/html\r\n" +#define HTTP_CONTENT_LENGTH "Content-Length: %ld\r\n\r\n" +#define MAX_REQUEST_SIZE 4096 +#define DEFAULT_PATH "index.html" + +#define DEBUG +#ifdef DEBUG +#define log(fmt, args...) fprintf(stderr, fmt "\n", ## args) +#else +#define log(fmt, args...) +#endif + +int send_error(int fd) +{ + write(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST)); + write(fd, HTTP_CONTENT_TYPE, strlen(HTTP_CONTENT_TYPE)); + return 0; +} + +int send_file(int fd, char *path) +{ + int iofd = open(path, O_RDONLY); + + int ret = 0; + if (iofd < 0) + { + write(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST)); + write(fd, HTTP_CONTENT_TYPE, strlen(HTTP_CONTENT_TYPE)); + log("error opening file"); + } + else + { + char length[MAX_REQUEST_SIZE]; + struct stat statinfo; + if (fstat(iofd, &statinfo) < 0) + { + /* Can't get the length. */ + write(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST)); + write(fd, HTTP_CONTENT_TYPE, strlen(HTTP_CONTENT_TYPE)); + log("error fetching size"); + } + else + { + ret = write(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST)); + + log("write HTTP_GOOD_REQUEST %s ret %d", HTTP_GOOD_REQUEST, ret); + ret = write(fd, HTTP_CONTENT_TYPE, strlen(HTTP_CONTENT_TYPE)); + log("write HTTP_CONTENT_TYPE %s ret %d", HTTP_CONTENT_TYPE, ret); + snprintf(length, MAX_REQUEST_SIZE, + HTTP_CONTENT_LENGTH, statinfo.st_size); + + ret = write(fd, length, strlen(length)); + log("write %s ret %d", length, ret); + +#if 1 +#if 1 + //char *source = NULL; + //source = malloc(sizeof(char) * (statinfo.st_size + 1)); + void *file_addr = NULL; + file_addr = + mmap(NULL, statinfo.st_size, PROT_READ, MAP_PRIVATE, iofd, 0); + + if (write(fd, file_addr, statinfo.st_size) < 0) + { + perror("wyl new"); + } + +#else +// if( write(fd, length, strlen(length)) < 0 || + if (sendfile(fd, iofd, NULL, statinfo.st_size) < 0) + { + /* Error sending the file. Nothing can be done. */ + perror("error writing file"); + } +#endif + +#endif + close(fd); + } + + close(iofd); + } + + return 0; +} + +int process(int fd, char *header) +{ + char npath[MAX_REQUEST_SIZE]; + + char *eol = strchr(header, '\r'); + + /* Nuts to thread-safe, this demo uses it's own process :P */ + char *method = strtok(header, " "); + char *path = strtok(NULL, " "); + char *http = strtok(NULL, " "); + + if (eol != NULL) + { + *eol = '\0'; + } + + /* Debug output here, just in case anyone is watching. */ + log(" * method = %s", method); + log(" * path = %s", path); + log(" * http = %s", http); + + /* Ensure that we can process it. */ + if (strcmp(method, "GET") || + (strcmp(http, "HTTP/1.0") && strcmp(http, "HTTP/1.1"))) + { + log("bad request"); + return send_error(fd); + } + else + { + if (path[0] == '/' && path[1] == '\0') + { + path = DEFAULT_PATH; + } + else if (path[0] == '/') + { + snprintf(npath, MAX_REQUEST_SIZE, ".%s", path); + path = npath; + } + log("sending %s to %d", path, fd); + return send_file(fd, path); + } +} + +int service(int fd) +{ + char buffer[MAX_REQUEST_SIZE]; + int readbytes = 0, scanned = 0; + + /* Attempt to read a chunk of bytes, but not process forever. */ + while (readbytes < (MAX_REQUEST_SIZE - 1)) + { + log("read from %d", fd); + int cur = read(fd, &(buffer[readbytes]), + (MAX_REQUEST_SIZE - 1) - readbytes); + if (cur < 0) + { + perror("read failed"); + return -1; + } + else + { + buffer[readbytes + cur + 1] = '\0'; + readbytes += cur; + } + + /* Check for the \n\n found at the end of the header. */ + for (; scanned < readbytes - 3; scanned++) + { + if (buffer[scanned] == '\r' && buffer[scanned + 1] == '\n' && + buffer[scanned + 2] == '\r' && buffer[scanned + 3] == '\n') + { + buffer[scanned] = '\0'; + return process(fd, buffer); + } + } + } + + /* Failed to find the end of the header. */ + log("header too long"); + return -1; +} + +int main(int argc, char *argv[]) +{ + + struct sockaddr_in servaddr; + int serversock = socket(AF_INET, SOCK_STREAM, 0); + int on = 1; + + if (NULL == argv[1]) + { + log("please set the ip argument"); + return 1; + } + + /* Create socket. */ + if (serversock < 0) + { + perror("error creating socket"); + return 1; + } + + /* Tweak it for reuse. Not necessary for fork, just useful * + * when one is killing and running this server a few times. */ + if (setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + { + perror("unable to tweak socket options"); + } + + /* Bind to port 8888. */ + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + //servaddr.sin_addr.s_addr = inet_addr("192.168.21.180"); + servaddr.sin_addr.s_addr = inet_addr(argv[1]); + servaddr.sin_port = htons(8888); + if (bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) + { + perror("couldn't bind to given address"); + return 1; + } + log("bound to %s:8888", argv[1]); + + /* Start listening, queue size 10. */ + if (listen(serversock, 10) < 0) + { + perror("listen failed"); + return 1; + } + log("listening"); + + /* Enter the service loop. */ + while (1) + { + int clientsock, pid, childstatus; + log("waiting for next request"); + + /* Grab the next request. */ + clientsock = accept(serversock, NULL, NULL); + if (clientsock < 0) + { + perror("accept failed"); + break; + } + log("accepted connection %d from %d, forking ", clientsock, + serversock); + + /* Fork off a handler. */ + //pid = fork(); + pid = 0; + if (pid < 0) + { + perror("fork failed"); + close(clientsock); + continue; + } + else if (pid > 0) + { + close(clientsock); + } + else + { + //close(serversock); + log("servicing connection (as child) sfd %d cfd %d", serversock, + clientsock); + service(clientsock); + //return 0; + } + + /* Collect any exit statuses (lazy). */ + +#if 0 + while (1) + { + pid = waitpid(-1, &childstatus, WNOHANG); + if (pid < 0) + { + perror("waitpid error?"); + break; + } + else if (pid == 0) + { + break; + } + else if (WIFEXITED(childstatus)) + { + log("child %d exited with status %d", pid, + WEXITSTATUS(childstatus)); + } + } +#endif + + } + + /* Should never arrive here. */ + return 254; +} diff --git a/pkg/deb/control b/pkg/deb/control new file mode 100644 index 0000000..24302e3 --- /dev/null +++ b/pkg/deb/control @@ -0,0 +1,13 @@ +Package: dmm +Version: 18.10 +Section: tuils +Priority: optional +Depends: libc6, libstdc++6, libgcc1 +Suggests: +Architecture: amd64 +Installed-Size: +Maintainer: jorth +Original-Maintainer: +Provides: +Description: DMM is a framework for protocol stack. +Homepage: https://gerrit.fd.io/r/dmm diff --git a/pkg/rpm/dmm.spec b/pkg/rpm/dmm.spec new file mode 100644 index 0000000..51ebef1 --- /dev/null +++ b/pkg/rpm/dmm.spec @@ -0,0 +1,50 @@ +Name: dmm +Version: 18.10 +Release: 1%{?dist} +Summary: DMM Project + +License: GPL +URL: https://gerrit.fd.io/r/dmm +Source: %{name}-%{version}.tar.gz + +BuildRequires: glibc, libstdc++, libgcc, numactl-libs +BuildRequires: dpdk >= 18.02, dpdk-devel >= 18.02 + +%description +The DMM framework provides posix socket APIs to the application. A protocol +stack could be plugged into the DMM. DMM will choose the most suitable stack +for the application. + +%prep +%setup -q + + +%build +cd build/ +cmake .. +make -j 8 + +%install +cd ../../BUILDROOT +mkdir -p %{name}-%{version}-%{release}.x86_64/usr/bin +mkdir -p %{name}-%{version}-%{release}.x86_64/usr/lib64 + +install -c ../BUILD/%{name}-%{version}/release/bin/kc_common %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/ks_epoll %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/vc_common %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/vs_epoll %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/ks_select %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/vs_select %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/ks_common %{name}-%{version}-%{release}.x86_64/usr/bin +install -c ../BUILD/%{name}-%{version}/release/bin/vs_common %{name}-%{version}-%{release}.x86_64/usr/bin + +install -c ../BUILD/%{name}-%{version}/release/lib64/libdmm_api.so %{name}-%{version}-%{release}.x86_64/usr/lib64 +install -c ../BUILD/%{name}-%{version}/release/lib64/libnStackAPI.so %{name}-%{version}-%{release}.x86_64/usr/lib64 + +%files +/usr/bin/* +/usr/lib64/* +%doc + + +%changelog diff --git a/release/configure/module_config.json b/release/configure/module_config.json new file mode 100644 index 0000000..03f0940 --- /dev/null +++ b/release/configure/module_config.json @@ -0,0 +1,25 @@ +{ + "default_stack_name": "kernel", /*when rd can't be find maybe choose the defualt one*/ + "module_list": [ + { + "stack_name": "kernel", /*stack name*/ + "function_name": "kernel_stack_register", + "libname": "./", /*library name, if loadtype is static, this maybe + null, else must give a library name*/ + "deploytype": "1", /*deploy model type:model type1, model type2, + model type3. Indicating single or multi process + deployment. Used during shared memory initialization.*/ + "stackid": "0", /*stack id, this must be ordered and not be repeated*/ + }, + /************************** + *this is not a real stack, just an example for multiple stack configurations* + { + "stack_name": "stackx", + "function_name": "stack_name_stack_register", + "libname": "libstackx.so", + "deploytype": "3", + "stackid": "1", + }, + ***************************/ + ] +} diff --git a/release/configure/rd_config.json b/release/configure/rd_config.json new file mode 100644 index 0000000..697067e --- /dev/null +++ b/release/configure/rd_config.json @@ -0,0 +1,18 @@ +{ + "modules": [ + { + "name": "kernel", + "ip_route": [ + "192.168.50.1/32" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "2", + "attr": "0" + } + ] + } + ] +} diff --git a/scripts/build.sh b/scripts/build.sh index c04b92c..282817e 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -58,9 +58,11 @@ bash -x $DMM_DIR/scripts/compile_dmm.sh || exit 1 if [ "${BUILD_ALL}" == "YES" ]; then #===========build LWIP================ - #bash -x $DMM_DIR/stacks/lwip_stack/vagrant/build.sh "from-base-build" || exit 1 + bash -x $DMM_DIR/stacks/lwip_stack/vagrant/build.sh "from-base-build" || exit 1 #============build rsocket============================ bash -x $DMM_DIR/scripts/build_rsocket.sh || exit 1 + #============build VPP=============================== + #bash -x $DMM_DIR/scripts/build_vpp.sh || exit 1 #=======other new stacks build can be called from here echo "SUCCESSFULLY built all the stacks" fi diff --git a/scripts/build_dmm_dep.sh b/scripts/build_dmm_dep.sh index ecbb686..9a7837e 100755 --- a/scripts/build_dmm_dep.sh +++ b/scripts/build_dmm_dep.sh @@ -13,10 +13,10 @@ OS_ID=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') if [ "$OS_ID" == "ubuntu" ]; then export DEBIAN_FRONTEND=noninteractive export DEBCONF_NONINTERACTIVE_SEEN=true - + sudo rm /var/lib/apt/lists/* -vf APT_OPTS="--assume-yes --no-install-suggests --no-install-recommends -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\"" sudo apt-get update ${APT_OPTS} - sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev vim pkg-config tcl libnl-route-3-200 flex graphviz tk debhelper dpatch gfortran ethtool libgfortran3 bison dkms quilt chrpath swig python-libxml2 unzip + sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev vim pkg-config tcl libnl-route-3-200 flex graphviz tk debhelper dpatch gfortran ethtool libgfortran3 bison dkms quilt chrpath swig python-libxml2 unzip libibverbs-dev elif [ "$OS_ID" == "debian" ]; then echo "not tested for debian and exit" exit 1 diff --git a/scripts/build_vpp.sh b/scripts/build_vpp.sh index fad02fc..d9dd1c8 100755 --- a/scripts/build_vpp.sh +++ b/scripts/build_vpp.sh @@ -17,7 +17,9 @@ set -x -cd ../stacks/vpp +SCRIPT_DIR=`dirname $(readlink -f $0)` + +cd $SCRIPT_DIR/../stacks/vpp git clone https://gerrit.fd.io/r/vpp cd vpp diff --git a/scripts/prep_app_test.sh b/scripts/prep_app_test.sh index 23bfa8b..9aa86f4 100755 --- a/scripts/prep_app_test.sh +++ b/scripts/prep_app_test.sh @@ -43,26 +43,27 @@ echo '{ }' | tee module_config.json echo '{ - "ip_route": [ + "modules": [ { - "subnet": "'$ifaddress1'/24", - "type": "nstack-kernel", - }, - { - "subnet": "'$ifaddress2'/24", - "type": "nstack-kernel", - }, - ], - "prot_route": [ - { - "proto_type": "1", - "type": "nstack-kernel", - }, - { - "proto_type": "2", - "type": "nstack-kernel", + "name": "kernel", + "ip_route": [ + "'$ifaddress1'/24", + "'$ifaddress2'/24" + ], + "type_route": [ + ], + "protocol_route": [ + { + "value": "1", + "attr": "0" + }, + { + "value": "2", + "attr": "0" + } + ] } - ], + ] }' | tee rd_config.json cp -r ${DMM_DIR}/release/lib64/* . diff --git a/src/include/nstack_callback_ops.h b/src/include/nstack_callback_ops.h index ab90cea..df24cba 100644 --- a/src/include/nstack_callback_ops.h +++ b/src/include/nstack_callback_ops.h @@ -54,6 +54,7 @@ typedef struct __nstack_proc_ops int (*fork_init_child) (pid_t p, pid_t c); void (*fork_fd) (int s, pid_t p, pid_t c); void (*fork_free_fd) (int s); + void (*fork_parent_fd) (int s, pid_t p); /*after fork, stack parent process proc again if needed. */ void (*(*ep_triggle) (int proFD, int triggle_ops, void *epinfo, void *epitem)); int (*ep_getEvt) (int proFD); diff --git a/src/nSocket/nstack/nstack_fd_mng.c b/src/nSocket/nstack/nstack_fd_mng.c index 81d3818..e90a92c 100644 --- a/src/nSocket/nstack/nstack_fd_mng.c +++ b/src/nSocket/nstack/nstack_fd_mng.c @@ -342,6 +342,29 @@ void nstack_fork_fd(pid_t ppid) } } +void nstack_fork_init_parent(pid_t ppid) +{ + int fd; + nstack_fd_Inf *fdInf = NULL; + for (fd = 0; fd < (int) NSTACK_KERNEL_FD_MAX; fd++) + { + fdInf = nstack_get_valid_inf(fd); + if ((NULL != fdInf) && (!((u32_t) (fdInf->type) & SOCK_CLOEXEC))) + { + int i; + nstack_each_mod_inx(i) + { + if ((nstack_fd_deal[i].fork_parent_fd) + && (fdInf->protoFD[i].fd >= 0)) + { + nstack_fd_deal[i].fork_parent_fd(fdInf->protoFD[i].fd, + ppid); + } + } + } + } +} + void nstack_fork_init_child(pid_t ppid) { pid_t cpid = updata_sys_pid(); diff --git a/src/nSocket/nstack/nstack_fd_mng.h b/src/nSocket/nstack/nstack_fd_mng.h index fcf7ed4..6af8c64 100644 --- a/src/nSocket/nstack/nstack_fd_mng.h +++ b/src/nSocket/nstack/nstack_fd_mng.h @@ -225,6 +225,7 @@ extern void nstack_fd_free(nstack_fd_Inf * fdInf); void nstack_fork_init_child(pid_t ppid); void nstack_fork_fd(pid_t ppid); +void nstack_fork_init_parent(pid_t ppid); #ifdef __cplusplus /* *INDENT-OFF* */ diff --git a/src/nSocket/nstack/nstack_socket.c b/src/nSocket/nstack/nstack_socket.c index a69747d..0248226 100644 --- a/src/nSocket/nstack/nstack_socket.c +++ b/src/nSocket/nstack/nstack_socket.c @@ -3095,6 +3095,7 @@ pid_t nstack_fork(void) dmm_write_lock(get_fork_lock()); if (NSTACK_MODULE_SUCCESS == g_nStackInfo.fwInited) { + nstack_fork_init_parent(ppid); fork_parent_start(ppid); pid = nsfw_base_fork(); if (pid == 0) diff --git a/stacks/lwip_stack/CMakeLists.txt b/stacks/lwip_stack/CMakeLists.txt new file mode 100644 index 0000000..c032a65 --- /dev/null +++ b/stacks/lwip_stack/CMakeLists.txt @@ -0,0 +1,111 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11) +PROJECT(nStack) +SET(CMAKE_C_COMPILER "gcc") +SET(OS_RELEASE "" CACHE STRING "User-specified OS release.") +SET(EXECUTABLE_PATH ${CMAKE_CURRENT_LIST_DIR}/release/bin) +SET(LIB_PATH_STATIC ${PROJECT_BINARY_DIR}) +SET(LIB_PATH_SHARED ${CMAKE_CURRENT_LIST_DIR}/release/lib64) +SET(NSTACKTOOLS_PATH ${CMAKE_CURRENT_LIST_DIR}/release/tools) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH_STATIC}) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_PATH}) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB_PATH_SHARED}) + + +MESSAGE(STATUS "Top dir is: " ${CMAKE_CURRENT_LIST_DIR}) +MESSAGE(STATUS "Static library dir: " ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) +MESSAGE(STATUS "Executable binary dir: " ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +MESSAGE(STATUS "Shared library dir: " ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + +option(WITH_SECUREC_LIB "Option description" OFF) +option(WITH_HAL_LIB "Option description" OFF) + +if(NOT WITH_SECUREC_LIB) + add_definitions(-DSYSTEMC_LIB) +endif() + +if(WITH_HAL_LIB) + add_definitions(-DHAL_LIB) +endif() + +SET(post_compile "${PROJECT_BINARY_DIR}/post_compile.sh") +FILE(WRITE ${post_compile} "#!/bin/bash\n") +FILE(APPEND ${post_compile} +" + +ln -sfn ./run_nstack_main.sh ${CMAKE_CURRENT_LIST_DIR}/release/script/run_nstack.sh +echo post compile process success. +" +) + +ADD_CUSTOM_TARGET(DPDK ALL COMMAND sh post_compile.sh) + +execute_process( + #COMMAND cp -rf ${CMAKE_CURRENT_LIST_DIR}/../../release/include ${CMAKE_CURRENT_LIST_DIR}/src/ + COMMAND cp ${CMAKE_CURRENT_LIST_DIR}/../../release/lib64/libnStackAPI.so ${CMAKE_CURRENT_LIST_DIR}/release/lib64/ + COMMAND cp ${CMAKE_CURRENT_LIST_DIR}/../../build/libnStackFw.a ${CMAKE_CURRENT_LIST_DIR}/release/lib64/ + COMMAND echo "stacklwip prepare ok" +) +execute_process( + COMMAND sh ${CMAKE_CURRENT_LIST_DIR}/release/lwip_helper_files/download_lwip.sh +) + +#ADD_DEFINITIONS(-D_GNU_SOURCE -DNSTACK_GETVER_VERSION="18.10") + +SET(JSON_C_SRC ${CMAKE_CURRENT_LIST_DIR}/../../thirdparty/json/json-c-0.12.1) +INCLUDE(ExternalProject) +ExternalProject_Add( + JSON + SOURCE_DIR ${JSON_C_SRC} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND sh autogen.sh COMMAND sh ./configure --enable-static --with-pic + BUILD_COMMAND make -j 8 + INSTALL_COMMAND cp -f .libs/libjson-c.a ${LIB_PATH_STATIC}/ +) + +SET(SECUREC_SRC ${CMAKE_CURRENT_LIST_DIR}/../SecureC/src) +SET(SECUREC_SRC_H ${CMAKE_CURRENT_LIST_DIR}/../SecureC/include) + +if(WITH_SECUREC_LIB) +INCLUDE(ExternalProject) +ExternalProject_Add( + SECUREC + SOURCE_DIR ${SECUREC_SRC} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND COMMAND make -j 8 + INSTALL_COMMAND cp -f ${SECUREC_SRC}/../lib/libsecurec.so ${LIB_PATH_SHARED}/ +) +endif() + +SET(GLOG_SRC ${CMAKE_CURRENT_LIST_DIR}/../../thirdparty/glog/glog-0.3.5) +INCLUDE(ExternalProject) +ExternalProject_Add( + GLOG + SOURCE_DIR ${GLOG_SRC} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND autoreconf COMMAND sh configure CFLAGS=-fPIC CXXFLAGS=-fPIC + BUILD_COMMAND COMMAND make -j 8 + INSTALL_COMMAND cp -f ${GLOG_SRC}/.libs/libglog.a ${LIB_PATH_STATIC}/ +) + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(lwip_src) +ADD_SUBDIRECTORY(lwip_src/socket) +ADD_SUBDIRECTORY(tools) +#ADD_SUBDIRECTORY(thirdparty/rsrdma) diff --git a/stacks/lwip_stack/build/.gitkeep b/stacks/lwip_stack/build/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/lwip_stack/configure/module_config.json b/stacks/lwip_stack/configure/module_config.json new file mode 100644 index 0000000..33767cb --- /dev/null +++ b/stacks/lwip_stack/configure/module_config.json @@ -0,0 +1,26 @@ +{ + "default_stack_name": "kernel", /*when rd can't be find maybe choose the defualt one*/ + "module_list": [ + { + "stack_name": "kernel", /*stack name*/ + "function_name": "kernel_stack_register", + "libname": "./", /*library name, if loadtype is static, this maybe + null, else must give a library name*/ + "deploytype": "1", /*deploy model type:model type1, model type2, + model type3. Indicating single or multi process + deployment. Used during shared memory initialization.*/ + "stackid": "0", /*stack id, this must be ordered and not be repeated*/ + }, + { + "stack_name": "lwip", /*stack name*/ + "function_name": "lwip_stack_register", + "libname": "liblwip_dpdk.so", /*library name, if loadtype is static, this maybe + null, else must give a library name*/ + "deploytype": "3", /*deploy model type:model type1, model type2, + model type3. Indicating single or multi process + deployment. Used during shared memory initialization.*/ + "stackid": "1", /*stack id, this must be ordered and not be repeated*/ + }, + + ] +} diff --git a/stacks/lwip_stack/configure/nStackConfig.json b/stacks/lwip_stack/configure/nStackConfig.json new file mode 100644 index 0000000..3cc54c5 --- /dev/null +++ b/stacks/lwip_stack/configure/nStackConfig.json @@ -0,0 +1,32 @@ +{ +"cfg_seg_socket": [ +{ + "socket_num": 8192, + "arp_stale_time": 300, + "arp_bc_retrans_num": 5 +} +], +"cfg_seg_log": [ +{ + "run_log_size": 50, + "run_log_count": 10, + "mon_log_size": 10, + "mon_log_count": 10 +} +], +"cfg_seg_thread_pri": [ +{ + "comment":"0:SCHED_OTHER, 1:SCHED_FIFO, 2:SCHED_RR", + "sched_policy": 0, + "thread_pri": 0 +} +], +"cfg_seg_path": [ +{ + "stackpool_log_path": "/var/log/nStack", + "master_log_path": "/var/log/nStack", + "nstack_log_path": "/var/log/nStack", + "dpdk_log_path": "/var/log/nstack-dpdk" +} +] +} diff --git a/stacks/lwip_stack/configure/rd_config.json b/stacks/lwip_stack/configure/rd_config.json new file mode 100644 index 0000000..14c26b8 --- /dev/null +++ b/stacks/lwip_stack/configure/rd_config.json @@ -0,0 +1,24 @@ +{ + "modules": [ + { + "name": "kernel", + "ip_route": [ + "127.0.0.1/24" + ], + "type_route": [ + ], + "proto_route": [ + ] + }, + { + "name": "lwip", + "ip_route": [ + "192.168.1.1/24" + ], + "type_route": [ + ], + "proto_route": [ + ] + }, + ] +} diff --git a/stacks/lwip_stack/doc/README.md b/stacks/lwip_stack/doc/README.md new file mode 100644 index 0000000..a76b18a --- /dev/null +++ b/stacks/lwip_stack/doc/README.md @@ -0,0 +1,125 @@ +# 1. What is lwIP +lwIP is a light-weight implementation of the TCP/IP protocol suite. +lwIP is freely available (under a BSD-style license) in C source +code format and can be downloaded from the development homepage. +The focus of the lwIP TCP/IP implementation is to reduce the RAM +usage while still having a full scale TCP. + +# 2. How to use lwIP + +## How to integrate lwIP into DMM +The file CMakeList.txt defined the compiling process, including downloading +the lwip 2.7.0 code and pushing the helper files into it, or modify +lwip files. + +Currently lwip will not be build as separate lib, instead it'll be part +of the excutable namely "nStackMain". +lwip Stack will run in pipeline mode. Application will run in one process +and lwip will run as "nStackMain" process. Below picture depicts +a birds eye view of lwip in DMM pipeline mode. +![Lwip in DMM framework](dmm_lwip.png) + +## Compile +```sh + #cd dmm/build && cmake .. + #make + #cd ../stacks/lwip_stack/build && cmake .. + #make +``` + +## Test +- Steps 1: update some environment variables +```sh + #export LD_LIBRARY_PATH=${dmm}/stacks/lwip_stack/release/lib64/ + #export LD_PRELOAD=${dmm}/release/lib64/libnStackAPI.so + #export NSTACK_MOD_CFG_FILE=${dmm}/stacks/lwip_stack/configure/module_config.json + #export NSTACK_MOD_CFG_RD=${dmm}/stacks/lwip_stack/configure/rd_config.json + #export NSTACK_LOG_ON=DBG (optional enable debug) +``` +- Steps 2: Modify rd_config.json(located at dmm/stacks/lwip_stack/configure/) +```sh + #vim rd_config.json + Eg. set "subnet": "192.168.21.1/24" +``` +Note: + Means dmm chose lwip_stack if subnet matches 192.168.21.* + +- Steps 3: Run nStackMain(lwip stack)) +```sh + #cp ${dmm}/stacks/lwip_stack/release/configure/ip_data.json ${dmm}/stacks/lwip_stack/release/bin/ + #cp ${dmm}/stacks/lwip_stack/release/configure/network_data_tonStack.json ${dmm}/stacks/lwip_stack/release/bin/ + +``` +Modify ip_data.json +``` +Change ref_nic => to interface name which you want to use +Change ip_cidr => ip address you want to use. +``` +Modify network network_data_tonStack.json +``` +Change ref_nic => to interface name which you want to use +Change subnet => Subnet (ip_cidr belongs to this subnet) +Change gateway, range-start, range-end, dst, gw accordingly. This information will be used by DMM to configure network. +``` +Run the process: +``` + #cd ${dmm}/stacks/lwip_stack/release + #./start_nstack.sh +``` + +If you want to run it with vhost-user, you can run the start_nstack.sh with parameters as follow. +``` + #./start_nstack.sh --vdev virtio_user,mac=fa:16:3e:5f:b3:08,path=/tmp/unix/sock1.sock,queues=8,queue_size=1024 --no-pci +``` + +- Steps 4: Communication test between machine A(as server) with machine B + (as client) + +##### Run in machine A +```sh + #./dmm/release/bin/vs_epoll -p 20000 -d 192.168.21.180 -a 10000 -s 192.168.21.181 -l 1000 -t 500000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 50000 -e 10 -x 1 +``` +Note: + Means the current machine would be server, and it's +destination address is 192.168.21.180 (client address), +source address is 192.168.21.181(server address) + +##### Run in machine B +``` + #./dmm/release/bin/vc_common -p 20000 -d 192.168.21.181 -a 10000 -s 192.168.21.180 -l 1000 -t 500000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 50000 -e 10 -x 1 +``` +Note: + Means the current machine would be client, and it's +destination address is 192.168.21.181 (server address), +source address is 192.168.21.180(client address) + +# 3. Document description + +(dmm/stacks/lwip_stack/doc) + +## CMakeLists.txt +Control file for Cmake compiling. + +## config folder +##### module_config.json +- module_config.json is for configuring dmm protocol stack module. + +##### rd_config.json +- rd_config.json is to choose which module is better to go through, if subnet matches, It will go through lwip protocol stack when RD type is nstack-dpdk + +## lwip helper files. +lwip helper files is implmentation and modification of some supportive functions to run lwip with dmm. + +## lwip_stack/src folder + +- Implmetation of nStackMain process which provides the framework to hold lwip stack. + +## lwip_stack/lwip_src +- Downloaded opensource lwip 2.7.0. code. + +# 4. More Information +https://wiki.fd.io/view/DMM +https://savannah.nongnu.org/projects/lwip/ +http://lwip.wikia.com/wiki/LwIP_Wiki +[DMM_DeveloperManual.md](../../doc/DMM_DeveloperManual.md) + diff --git a/stacks/lwip_stack/doc/dmm_lwip.png b/stacks/lwip_stack/doc/dmm_lwip.png new file mode 100644 index 0000000..403eed3 Binary files /dev/null and b/stacks/lwip_stack/doc/dmm_lwip.png differ diff --git a/stacks/lwip_stack/lwip_src/CMakeLists.txt b/stacks/lwip_stack/lwip_src/CMakeLists.txt new file mode 100644 index 0000000..170cc46 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/CMakeLists.txt @@ -0,0 +1,106 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIE -pie -fPIC -m64 -mssse3 -std=gnu89") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium") + +ADD_DEFINITIONS(-D_GNU_SOURCE) +ADD_DEFINITIONS(-DDPDK_MODULE=0) +if(WITH_HAL_LIB) +SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../src/include/rtp_config.h) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") + SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/src/mem/include/common_sys_config.h) + INCLUDE_DIRECTORIES( + ${PAL_H_DIRECTORIES} + ) +endif() +SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/common/compile_config.h) +SET(MGR_COM ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/ipc/mgr_com/mgr_com.h) +SET(COMMON_MEM_API ${CMAKE_CURRENT_LIST_DIR}/../src/include/common_mem_api.h) +ADD_DEFINITIONS(-include ${RTP_CONFIG}) +ADD_DEFINITIONS(-include ${COMPLE_CONFIG}) +ADD_DEFINITIONS(-include ${MGR_COM}) +ADD_DEFINITIONS(-include ${COMMON_MEM_API}) +if(WITH_SECUREC_LIB) +LINK_LIBRARIES(pthread rt securec) +else() +LINK_LIBRARIES(pthread rt) +endif() +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../../../SecureC/include + ${CMAKE_CURRENT_LIST_DIR}/../../../thirdparty/json/json-c-0.12.1/ + ${CMAKE_CURRENT_LIST_DIR}/../../../thirdparty/glog/glog-0.3.5/src/ + ${CMAKE_CURRENT_LIST_DIR}/../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/lwip/include/ + ${CMAKE_CURRENT_LIST_DIR}/lwip/include/lwip/ + ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../src/mem/include/ + ${CMAKE_CURRENT_LIST_DIR}/../src/mem/nsfw_shmem/ +) + +FILE(GLOB API api/*.c) +FILE(GLOB_RECURSE CORE core/*.c) +FILE(GLOB INSTANCE instance/*.c) +FILE(GLOB IPMODULE ip_module/*.c) +FILE(GLOB NETIF netif/*.c) +FILE(GLOB RECYCLE recycle/*.c) +FILE(GLOB_RECURSE MAINTAIN maintain/*.c) +FILE(GLOB COMMON common/*.c) +FILE(GLOB_RECURSE LWIPSRC lwip/arch/*.c lwip/core/*.c lwip/netif/*.c) +FOREACH(item ${LWIPSRC}) + IF(${item} MATCHES "slipif.c") + LIST(REMOVE_ITEM LWIPSRC ${item}) + ENDIF(${item} MATCHES "slipif.c") +ENDFOREACH(item) + +ADD_LIBRARY(stacklwip STATIC ${API} ${ARCH} ${CORE} ${NETIF} ${NETTOOL} ${IPMODULE} ${COMMON} ${INSTANCE} ${RECYCLE} ${MAINTAIN} ${LWIPSRC}) +ADD_DEPENDENCIES(stacklwip JSON GLOG DPDK) +TARGET_INCLUDE_DIRECTORIES( + stacklwip + BEFORE + PRIVATE + common/ + socket/ + include/ + include/util/ + include/log/ + include/ipv4/ + include/ipv4/stackx + include/stackx/ + include/netif/ + include/nstack/ + include/ip_module/ + lwip/include/lwip/ + lwip/include/lwip/arch/ + lwip/include/lwip/apps/ + lwip/include/lwip/priv/ + lwip/include/lwip/prot/ + lwip/include/netif/ + lwip/include/netif/ppp/ + lwip/include/netif/ppp/polarssl/ + ${CMAKE_CURRENT_LIST_DIR}/../src/sbr/ + ${CMAKE_CURRENT_LIST_DIR}/../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../src/alarm/ + ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/ipc/mgr_com/ +) + diff --git a/stacks/lwip_stack/lwip_src/api/nsfw_msg.c b/stacks/lwip_stack/lwip_src/api/nsfw_msg.c new file mode 100644 index 0000000..338f803 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/nsfw_msg.c @@ -0,0 +1,23 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_msg.h" +/* *INDENT-OFF* */ +msg_fun g_msg_module_fun_array[MAX_MODULE_TYPE] = {NULL}; +msg_fun g_msg_module_major_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE] = {{NULL}}; +msg_fun g_msg_module_major_minor_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE][MAX_MINOR_TYPE] = {{{NULL}}}; +msg_fun g_msg_unsupport_fun = NULL; +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_api.c b/stacks/lwip_stack/lwip_src/api/spl_api.c new file mode 100644 index 0000000..5f48d15 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_api.c @@ -0,0 +1,50 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_init_api.h" +//#include "sockets.h" +//#include + +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +//#include "stackx/ip.h" +#include "sharedmemory.h" +#include "spl_hal.h" +#include "nsfw_hal_api.h" +#include "alarm_api.h" +#include "nsfw_mt_config.h" +#include "nsfw_recycle_api.h" +#include "nstack_dmm_adpt.h" + +/* main entry for stackx */ +int spl_main_init(void *args) +{ + (void) args; + if (init_by_main_thread() < 0) + { + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME ("STACKX_MAIN") +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_ALARM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_RECYCLE_MODULE) +NSFW_MODULE_INIT (spl_main_init) +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_api_msg.c b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c new file mode 100644 index 0000000..79ea0b6 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c @@ -0,0 +1,3320 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_msg.h" +#include "spl_opt.h" +#include "spl_ip_addr.h" +//#include "stackx_socket.h" +#include "cpuid.h" +//#include "sockets.h" +#include +#include +#include + +#include "stackx_prot_com.h" +#include "spl_api.h" +//#include "stackx/ip.h" +#include "sc_dpdk.h" +#include "spl_sbr.h" +//#include "maintain/spl_dfx.h" +#include "stackx_tx_box.h" +#include "spl_instance.h" +#include "spl_sockets.h" + +#include "nstack_dmm_adpt.h" + +#include "tcp.h" +#include "udp.h" +#include "pbuf.h" +#include "tcp_priv.h" +#include "init.h" +#include "timeouts.h" + +#include "stackx_pbuf_comm.h" +#include "spl_netbuf.h" +#include "spl_hal.h" +#include "sys_arch.h" +#include "tcpip.h" +#include "debug.h" +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif +#include "nstack_epoll_api.h" + +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ +extern struct tcp_pcb **const tcp_pcb_lists[NUM_TCP_PCB_LISTS]; +extern stackx_instance *p_def_stack_instance; +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +#define TCP_FN_NULL 0 +#define TCP_FN_DEFAULT 1 +#define TCP_FN_STACKX 2 +#define TCP_FN_MAX 3 + +struct callback_fn tcp_fn[TCP_FN_MAX] = { + {NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + {NULL, spl_tcp_recv_null, NULL, NULL, NULL, NULL}, + {spl_sent_tcp, spl_recv_tcp, spl_do_connected, spl_poll_tcp, spl_err_tcp, + NULL, spl_accept_function}, +}; + +// extern int nstack_get_nstack_fd_snapshot_from_proto_fd(int proto_fd); +extern void tcp_drop_conn(spl_netconn_t * conn); +extern void unlink_pcb(struct common_pcb *cpcb); +extern struct queue *get_msgbox(int tos); + +#define SPL_SET_NONBLOCKING_CONNECT(conn, val) \ +do { \ + if (val) \ + { \ + (conn)->flags |= SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ + } \ + else \ + { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \ + } \ + } while (0) + +#define SPL_IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0) + +extern int tcpip_thread_control; + +void +spl_event_callback(struct spl_netconn *conn, enum spl_netconn_evt evt, + int postFlag) +{ + NSPOL_LOGDBG(SOCK_INFO, "Get event]conn=%p,evt=%d,postFlag=%d", conn, evt, + postFlag); + /* Get socket */ + if (!conn) + { + NSPOL_LOGDBG(SOCK_INFO, "conn=NULL"); + return; + } + + switch (evt) + { + case SPL_NETCONN_EVT_RCVPLUS: + __sync_fetch_and_add(&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN, + postFlag); + } + break; + case SPL_NETCONN_EVT_RCVMINUS: // This will never be reached + __sync_fetch_and_sub(&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN, + postFlag); + } + break; + case SPL_NETCONN_EVT_SENDPLUS: + conn->sendevent = 1; + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLOUT, + postFlag); + } + break; + case SPL_NETCONN_EVT_SENDMINUS: + conn->sendevent = 0; + + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLOUT, + postFlag); + } + break; + case SPL_NETCONN_EVT_ERROR: + conn->errevent |= EPOLLERR; + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), + conn->errevent, postFlag); + conn->errevent = 0; + } + break; +#if 1 + case SPL_NETCONN_EVT_ACCEPT: + __sync_fetch_and_add(&conn->rcvevent, 1); + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN, + postFlag); + } + break; + + case SPL_NETCONN_EVT_HUP: + conn->errevent |= EPOLLHUP; + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), + conn->errevent, postFlag); + conn->errevent = 0; + } + break; + case SPL_NETCONN_EVT_RDHUP: + conn->errevent |= EPOLLRDHUP; + if ((conn->epoll_flag) && (postFlag)) + { + NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), + conn->errevent, postFlag); + conn->errevent = 0; + } + break; +#endif + + default: + NSTCP_LOGERR("unknown event]conn=%p,event=%d", conn, evt); + return; + } + return; +} + +u8 get_shut_op(data_com_msg * m) +{ + if (m && m->param.module_type == MSG_MODULE_SBR + && m->param.major_type == SPL_TCPIP_NEW_MSG_API) + { + if (m->param.minor_type == SPL_API_DO_CLOSE) + return ((msg_close *) (m->buffer))->shut; + + if (m->param.minor_type == SPL_API_DO_DELCON) + return ((msg_delete_netconn *) (m->buffer))->shut; + } + + return SPL_NETCONN_SHUT_RDWR; +} + +/* + Never using head/tail to judge whether need to do enque/deque, just do enque&deque, the return val will tell you ring is full/empty or not + rtp_perf_ring never provid ring_full/ring_empty function; + one more thing the rtp_ring_enque/deque result must be checked. +*/ +err_t accept_enqueue(spl_netconn_t * conn, void *p) +{ + if (conn == NULL) + { + NSPOL_LOGERR("accept_enqueue: invalid input]conn=%p", conn); + return ERR_VAL; + } + + NSPOL_LOGDBG(NEW_RING_DEBUG, "accept_enqueue]conn=%p,p=%p", conn, p); + mring_handle ring = conn->recv_ring; + if (NULL == ring) + { + NSPOL_LOGERR("conn=%p accept new conn=%p enqueue ring addr is null", + conn, p); + return ERR_VAL; + } + + err_t retVal = ERR_MEM; + int enQSucCnt = 0; + int nTryCnt = 0; + do + { + enQSucCnt = nsfw_mem_ring_enqueue(ring, (void *) p); + if (1 == enQSucCnt) + { + retVal = ERR_OK; + break; + } + else if (0 == enQSucCnt) + { + sys_sleep_ns(0, 3000); + nTryCnt++; + } + else + { + retVal = ERR_VAL; + break; + } + } + while (nTryCnt < MAX_TRY_GET_MEMORY_TIMES); + + return retVal; +} + +err_t +accept_dequeue(spl_netconn_t * lconn, void **new_buf, + u32_t timeout /*miliseconds */ ) +{ + struct timespec starttm; + struct timespec endtm; + long timediff; + long timediff_sec; + u32_t timeout_sec = timeout / 1000; + +#define FAST_SLEEP_TIME 10000 +#define SLOW_SLEEP_TIME 500000 +#define FAST_RETRY_COUNT 100 + unsigned int retry_count = 0; + + if (NULL == lconn || NULL == new_buf) + { + NSPOL_LOGERR("accept_dequeue invalid input]conn=%p,newbuf=%p", lconn, + new_buf); + return ERR_ARG; + } + + if (timeout != 0) + { + /* Handle system time change side-effects */ + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &starttm))) + { + //NSPOL_LOGERR("Failed to get time]errno=%d", errno); + } + } + + mring_handle ring = lconn->recv_ring; + if (ring == NULL) + { + NSPOL_LOGERR("Get rtp_perf_ring failed]conn=%p", lconn); + return ERR_ARG; + } + + int nDequeRt; + int retVal; + while (1) + { + if ((lconn->shut_status) && (-1 != (int) timeout)) + { + retVal = ERR_VAL; + break; + } + + nDequeRt = nsfw_mem_ring_dequeue(ring, new_buf); + if (nDequeRt == 1) + { + retVal = ERR_OK; + break; + } + else if (nDequeRt == 0) + { + if ((int) timeout == -1) + { + retVal = ERR_WOULDBLOCK; + break; + } + + if (timeout != 0) + { + /* Handle system time change side-effects */ + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &endtm))) + { + //NSPOL_LOGERR("Failed to get time, errno = %d", errno); + } + timediff_sec = endtm.tv_sec - starttm.tv_sec; + if (timediff_sec >= timeout_sec) + { + timediff = endtm.tv_nsec > starttm.tv_nsec ? + (timediff_sec * 1000) + (endtm.tv_nsec - + starttm.tv_nsec) / + USEC_TO_SEC : (timediff_sec * 1000) - + ((starttm.tv_nsec - endtm.tv_nsec) / USEC_TO_SEC); + + /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value + will be negetive if still 0.5 ms is not elapsed. this is intended and we should + not typecast to any unsigned type during this below if check */ + if (timediff > (long) timeout) + { + retVal = ERR_TIMEOUT; + break; + } + } + } + + /* reduce CPU usage in blocking mode */ + if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns(0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns(0, SLOW_SLEEP_TIME); + } + + continue; + } + else + { + retVal = ERR_VAL; + break; + } + } + + return retVal; +} + +err_t sp_enqueue(struct common_pcb * cpcb, void *p) +{ + mring_handle ring = NULL; + spl_netconn_t *conn = NULL; + int enQueRet = 0; + + if (cpcb == NULL || (NULL == (conn = cpcb->conn))) + { + NSTCP_LOGERR("conn NULL!"); + return ERR_VAL; + } + + NSPOL_LOGDBG(NEW_RING_DEBUG, "]conn=%p,buf=%p", cpcb->conn, p); + ring = conn->recv_ring; + if (NULL == ring) + { + NSPOL_LOGERR("Get rtp_perf_ring failed]conn=%p.", conn); + return ERR_CLSD; + } + + /* clear LOOP_SEND_FLAG to indicate that this pbuf has been given to upper layer */ + struct spl_pbuf *tmpbuf = p; + while (tmpbuf) + { + tmpbuf->res_chk.u8Reserve &= ~LOOP_SEND_FLAG; + tmpbuf = tmpbuf->next; + } + + enQueRet = nsfw_mem_ring_enqueue(ring, p); + if (1 != enQueRet) + { + NS_LOG_CTRL(LOG_CTRL_RECV_QUEUE_FULL, LOGTCP, "NSTCP", NSLOG_WAR, + "ringvbox_enqueue buf is full]conn=%p.", conn); + + return ERR_MEM; + } + + return ERR_OK; +} + +/** + * Receive callback function for UDP netconns. + * Posts the packet to conn->recvmbox or deletes it on memory error. + * + * @see udp.h (struct udp_pcb.recv) for parameters + */ + +static void +spl_recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, + const ip_addr_t * ipaddr, u16_t port) +{ + struct spl_netbuf *buf; + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct spl_pbuf *spl_pb = NULL; //?? + + if (NULL == pcb) + { + NSPOL_LOGERR("recv_udp must have a pcb argument"); + pbuf_free(p); + return; + } + + if (NULL == arg) + { + NSPOL_LOGERR("recv_udp must have an argument"); + pbuf_free(p); + return; + } + /* //@TODO: malloc and Copy splbuf */ + struct common_pcb *cpcb = (struct common_pcb *) (conn->comm_pcb_data); + + u16_t proc_id = spl_get_lcore_id(); + + spl_pb = spl_pbuf_alloc_hugepage(SPL_PBUF_TRANSPORT, + p->tot_len + + g_offSetArry[SPL_PBUF_TRANSPORT], + SPL_PBUF_HUGE, proc_id, conn); + + if (!spl_pb) + { + NSPOL_LOGINF(TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return; + } + + pbuf_to_splpbuf_copy(spl_pb, p); + pbuf_free(p); + + buf = (struct spl_netbuf *) ((char *) spl_pb + sizeof(struct spl_pbuf)); + buf->p = spl_pb; + spl_ip_addr_set(&buf->addr, ipaddr); + buf->port = port; + + err_t ret = sp_enqueue(cpcb, (void *) spl_pb); + if (ret != ERR_OK) + { + NSPOL_LOGDBG(UDP_DEBUG, "mbox post failed"); + spl_netbuf_delete(buf); + return; + } + else + { + /* Register event with callback */ + NSPOL_LOGDBG(UDP_DEBUG | LWIP_DBG_TRACE, + "recv a udp packet: and api_event"); + SPL_API_EVENT(cpcb->conn, SPL_NETCONN_EVT_RCVPLUS, 1); + } +} + +/** + * Receive callback function for TCP netconns. + * Posts the packet to conn->recvmbox, but doesn't delete it on errors. + * + * @see tcp.h (struct tcp_pcb.recv) for parameters and return value + */ + +err_t spl_recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct spl_pbuf *spl_pb = NULL; + u32_t len; + + if (NULL == pcb) + { + NSTCP_LOGERR("recv_tcp must have a pcb argument"); + pbuf_free(p); + return ERR_ARG; + } + + if (NULL == arg) + { + NSTCP_LOGERR("must have an argument]pcb=%p", pcb); + pbuf_free(p); + return ERR_ARG; + } + + spl_netconn_t *conn = (spl_netconn_t *) arg; + + /* Unlike for UDP or RAW pcbs, don't check for available space + using recv_avail since that could break the connection + (data is already ACKed) */ + /* don't overwrite fatal errors! */ + (void) err; + if (p == NULL) + { + return ERR_OK; + } + + len = p->tot_len; + + u16_t proc_id = spl_get_lcore_id(); + + spl_pb = spl_pbuf_alloc_hugepage(SPL_PBUF_TRANSPORT, + p->tot_len + + g_offSetArry[SPL_PBUF_TRANSPORT], + SPL_PBUF_HUGE, proc_id, conn); + + if (!spl_pb) + { + NSPOL_LOGINF(TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + } + + pbuf_to_splpbuf_copy(spl_pb, p); + pbuf_free(p); + + if (sp_enqueue((struct common_pcb *) conn->comm_pcb_data, (void *) spl_pb) + != ERR_OK) + { + NSPOL_LOGDBG(TCP_DEBUG, "sp_enqueue!=ERR_OK]conn=%p", conn); + spl_pbuf_free(spl_pb); + return ERR_MEM; + } + + SPL_API_EVENT(conn, SPL_NETCONN_EVT_RCVPLUS, 1); + conn->recv_avail_prod += len; + + return ERR_OK; +} + +/** + * Poll callback function for TCP netconns. + * Wakes up an application thread that waits for a connection to close + * or data to be sent. The application thread then takes the + * appropriate action to go on. + * + * Signals the conn->sem. + * netconn_close waits for conn->sem if closing failed. + * + * @see tcp.h (struct tcp_pcb.poll) for parameters and return value + */ +err_t spl_poll_tcp(void *arg, struct tcp_pcb * pcb) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct tcp_pcb *tpcb = NULL; + + if (NULL == conn) + { + NSPOL_LOGERR("conn==NULL"); + return ERR_VAL; + } + + if (conn->state == SPL_NETCONN_WRITE) + { + (void) do_writemore(conn); + + /* do_close_internal, can release th PCB + and connection CB. so checking NETCONN_FLAG_CHECK_WRITESPACE should not be + done after do_close_internal. anyway this flag is used with data send.(do_writemore) */ + /* Did a nonblocking write fail before? Then check available write-space. */ + if (conn->flags & SPL_NETCONN_FLAG_CHECK_WRITESPACE) + { + tpcb = (struct tcp_pcb *) conn->private_data; + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if ((tpcb != NULL) && (tcp_sndbuf(tpcb) > TCP_SNDLOWAT) && + (tcp_sndqueuelen(tpcb) < TCP_SNDQUEUELOWAT)) + { + conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE; + SPL_API_EVENT(conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + } + } + else if (conn->state == SPL_NETCONN_CLOSE) + { + (void) do_close_internal((struct common_pcb *) conn->comm_pcb_data, + 0); + } + + /* @todo: implement connect timeout here? */ + return ERR_OK; +} + +/** + * Default receive callback that is called if the user didn't register + * a recv callback for the pcb. + */ +err_t +spl_tcp_recv_null(void *arg, struct tcp_pcb * pcb, struct pbuf * p, err_t err) +{ + LWIP_UNUSED_ARG(arg); + + if (p != NULL) + { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + else if (err == ERR_OK) + { + return tcp_close(pcb); + } + + return ERR_OK; +} + +/** + * Sent callback function for TCP netconns. + * Signals the conn->sem and calls API_EVENT. + * netconn_write waits for conn->sem if send buffer is low. + * + * @see tcp.h (struct tcp_pcb.sent) for parameters and return value + */ +err_t spl_sent_tcp(void *arg, struct tcp_pcb * pcb, u16_t len) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + + if (NULL == conn) + { + NSPOL_LOGERR("conn==NULL"); + return ERR_VAL; + } + + if (conn->state == SPL_NETCONN_WRITE) + { + (void) do_writemore(conn); + } + else if (conn->state == SPL_NETCONN_CLOSE) + { + (void) do_close_internal((struct common_pcb *) conn->comm_pcb_data, + 0); + } + + /* conn is already checked for NULL above with ASSERT */ + /* If the queued byte- or pbuf-count drops below the configured low-water limit, + let select mark this pcb as writable again. */ + if (conn->snd_buf > TCP_SNDLOWAT) + { + conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE; + if (((struct common_pcb *) conn->comm_pcb_data)->model == + SOCKET_STACKX) + SPL_API_EVENT(conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + + return ERR_OK; +} + +/** + * Error callback function for TCP netconns. + * Signals conn->sem, posts to all conn mboxes and calls API_EVENT. + * The application thread has then to decide what to do. + * + * @see tcp.h (struct tcp_pcb.err) for parameters + */ +void spl_err_tcp(void *arg, err_t err) +{ + spl_netconn_t *conn; + enum spl_netconn_state old_state; + data_com_msg *forFree = NULL; + + struct common_pcb *cpcb; + + NSTCP_LOGINF("Enter err_tcp."); + + conn = (spl_netconn_t *) arg; + cpcb = (struct common_pcb *) (conn->comm_pcb_data); + + old_state = conn->state; + conn->state = SPL_NETCONN_NONE; + + /* Call unlink pcb no matter what */ + unlink_pcb(cpcb); + if (old_state == SPL_NETCONN_CLOSE) + { + /* RST during close: let close return success & dealloc the netconn */ + err = ERR_OK; + SPL_NETCONN_SET_SAFE_ERR(conn, ERR_OK); + } + else + { + SPL_NETCONN_SET_SAFE_ERR(conn, err); + } + + NSTCP_LOGWAR("inform HUP and ERROR event."); + SPL_API_EVENT(conn, SPL_NETCONN_EVT_RCVPLUS, 0); + SPL_API_EVENT(conn, SPL_NETCONN_EVT_SENDPLUS, 0); + SPL_API_EVENT(conn, SPL_NETCONN_EVT_ERROR, 0); + SPL_API_EVENT(conn, SPL_NETCONN_EVT_HUP, 1); + + if ((old_state == SPL_NETCONN_WRITE) || (old_state == SPL_NETCONN_CLOSE) + || (old_state == SPL_NETCONN_CONNECT)) + { + int was_nonblocking_connect = spl_netconn_is_nonblocking(conn); + SPL_SET_NONBLOCKING_CONNECT(conn, 0); + + if (!was_nonblocking_connect) + { + /* set error return code */ + if (NULL == cpcb->current_msg) + { + NSPOL_LOGERR("conn->current_msg==NULL"); + return; + } + + /* current msg could be connect msg or write_buf_msg */ + SET_MSG_ERR(cpcb->current_msg, err); + /* signal app to exit */ + if (old_state == SPL_NETCONN_CONNECT + && !spl_netconn_is_nonblocking(conn)) + { + SYNC_MSG_ACK(cpcb->current_msg); + } + + /* no matter it's connect msg or write msg, we will no process it any more */ + cpcb->current_msg = NULL; + + /* but, if msg is write_buf_msg, then we should release the pbuf in msg */ + if (cpcb->msg_head != NULL) + { + /* current_msg should be write_buf_msg */ + msg_write_buf *tmp_msg = cpcb->msg_head; + while (tmp_msg != NULL) + { + + forFree = MSG_ENTRY(tmp_msg, data_com_msg, buffer); + spl_pbuf_free(tmp_msg->p); + tmp_msg = tmp_msg->next; + + // free msg + ASYNC_MSG_FREE(forFree); + } + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + } + } + } + else + { + + } +} + +/** + * Setup a tcp_pcb with the correct callback function pointers + * and their arguments. + * + * @param conn the TCP netconn to setup + */ +NSTACK_STATIC void setup_tcp(struct tcp_pcb *pcb, spl_netconn_t * conn) +{ + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + + /* callback have the same value as cpcb->conn */ + cpcb->conn = conn; + tcp_arg(pcb, (void *) conn); + tcp_recv(pcb, tcp_fn[TCP_FN_STACKX].recv_fn); + tcp_sent(pcb, tcp_fn[TCP_FN_STACKX].sent_fn); + tcp_poll(pcb, tcp_fn[TCP_FN_STACKX].poll_fn, 4); + tcp_err(pcb, tcp_fn[TCP_FN_STACKX].err_fn); + +} + +/** + * Accept callback function for TCP netconns. + * Allocates a new netconn and posts that to conn->acceptmbox. + * + * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value + */ +err_t spl_accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) +{ + spl_netconn_t *newconn; + spl_netconn_t *lconn = (spl_netconn_t *) arg; /* listen conneciton */ + struct common_pcb *cpcb = NULL; + + NSPOL_LOGDBG(API_MSG_DEBUG, "]state=%s", + tcp_debug_state_str(newpcb->state)); + + if (lconn == NULL) + { + NSPOL_LOGERR("accept_function: conn is NULL"); + return ERR_VAL; + } + + /* We have to set the callback here even though + * the new socket is unknown. conn->socket is marked as -1. */ + newconn = ss_malloc_conn(lconn->conn_pool, SPL_NETCONN_TCP); + if (newconn == NULL) + { + NSPOL_LOGERR("conn alloc failed"); + return ERR_MEM; + } + + cpcb = alloc_common_pcb(SPL_NETCONN_TCP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + /* used by application to recycle conn */ + newconn->recycle.accept_from = lconn; + newconn->conn_pool = lconn->conn_pool; + + newconn->recv_obj = (i64) & newconn->private_data; + newconn->private_data = (i64) newpcb; + newconn->comm_pcb_data = (i64) cpcb; + + NSFW_LOGINF("alloc accept conn]conn=%p,pcb=%p,lconn=%p", newconn, newpcb, + lconn); + newconn->shut_status = 0xFFFF; + newconn->last_err = ERR_OK; + newconn->CanNotReceive = 0; + newconn->flags = 0; + + newconn->state = SPL_NETCONN_NONE; + newconn->mss = newpcb->mss; + newconn->remote_ip.addr = newpcb->remote_ip.addr; + newconn->remote_port = newpcb->remote_port; + ss_set_local_ip(newconn, newpcb->local_ip.addr); + ss_set_local_port(newconn, newpcb->local_port); + + setup_tcp(newpcb, newconn); + newpcb->state = ESTABLISHED; + update_tcp_state(newconn, ESTABLISHED); + + /*Initialize flow control variables */ + newconn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE; + newconn->tcp_wmem_alloc_cnt = 0; + newconn->tcp_wmem_sbr_free_cnt = 0; + newconn->tcp_wmem_spl_free_cnt = 0; + newconn->snd_buf = 0; + + newconn->bind_thread_index = lconn->bind_thread_index; + ss_set_msg_box(newconn, + ss_get_instance_msg_box(newconn->bind_thread_index, 0)); + + /* no protection: when creating the pcb, the netconn is not yet known + to the application thread */ + newconn->last_err = err; + + NSPOL_LOGDBG(TCP_DEBUG, + "trypost]newconn=%p, tcp=%p state=%d conn state=%d ", + newconn, newpcb, newpcb->state, newconn->state); + if (accept_enqueue(lconn, (void *) newconn) != ERR_OK) + { + /* remove all references to this netconn from the pcb */ + NSPOL_LOGERR("sp_enqueue!=ERR_OK]ring = %p", newconn->recv_ring); + + tcp_arg(newpcb, NULL); + tcp_recv(newpcb, tcp_fn[TCP_FN_NULL].recv_fn); + tcp_sent(newpcb, tcp_fn[TCP_FN_NULL].sent_fn); + tcp_poll(newpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0); + tcp_err(newpcb, tcp_fn[TCP_FN_NULL].err_fn); + /* drop conn */ + tcp_drop_conn(newconn); + return ERR_MEM; + } + + SPL_API_EVENT(lconn, SPL_NETCONN_EVT_ACCEPT, 1); + /* tcp_accepted_with_return_value(newpcb); */ + + return ERR_OK; +} + +int common_pcb_init(struct common_pcb *cpcb) +{ + // u32 threadnum = p_lwip_instance->rss_queue_id + 1;//0 for app + + cpcb->hostpid = get_sys_pid(); + + cpcb->socket = 0; + /* run and close repeatly nstackmain coredum */ + cpcb->close_progress = 0; + cpcb->model = SOCKET_STACKX; + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + cpcb->write_offset = 0; + + cpcb->recv_timeout = cpcb->send_timeout = 0; + + cpcb->sk_rcvlowat = 1; + + cpcb->l4_tick = 0; + cpcb->dataSentFlag = 0; + cpcb->recv_ring_not_empty = 0; + + return 0; +} + +int common_pcb_reset(struct common_pcb *cpcb) +{ + cpcb->conn = NULL; + cpcb->hostpid = 0; + + cpcb->socket = 0; + /* run and close repeatly nstackmain coredum */ + cpcb->close_progress = 0; + cpcb->model = 0; + cpcb->current_msg = NULL; + cpcb->msg_head = cpcb->msg_tail = NULL; + cpcb->write_offset = 0; + + cpcb->recv_timeout = cpcb->send_timeout = 0; + + cpcb->sk_rcvlowat = 0; + + cpcb->l4_tick = 0; + cpcb->dataSentFlag = 0; + cpcb->recv_ring_not_empty = 0; + + return 0; +} + +void unlink_pcb(struct common_pcb *cpcb) +{ + if (cpcb && cpcb->conn) + { + /* whatever the private data will be reset */ + cpcb->conn->private_data = 0; + update_tcp_state(cpcb->conn, CLOSED); + } + else + { + NSPOL_LOGINF(API_MSG_DEBUG, "conn is detached already!"); + } +} + +void unlink_recv_ring(spl_netconn_t * conn) +{ + if (conn) + conn->recv_ring_valid = 0; +} + +void recycle_tmr(void *arg) +{ + if (arg == NULL) + { + NSPOL_LOGERR("recycle_message is NULL!"); + } + else + { + (void) ss_recycle_conn(arg, do_try_delconn); + } +} + +/** + * Create a new pcb of a specific type. + * Called from do_newconn(). + * + * @param msg the api_msg_msg describing the connection type + * @return msg->conn->err, but the return value is currently ignored + */ +int spl_pcb_new(msg_new_netconn * pmsg) +{ + u16_t thread_index = spl_get_lcore_id(); + struct common_pcb *cpcb = NULL; + enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4; + + /* Allocate a PCB for this connection */ + switch (SPL_NETCONNTYPE_GROUP(pmsg->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *u = udp_new_ip_type(iptype); + if (u == NULL) + { + return ERR_MEM; + } + + if (pmsg->type == SPL_NETCONN_UDPNOCHKSUM) + { + udp_setflags(u, UDP_FLAGS_NOCHKSUM); + } + + cpcb = + (struct common_pcb *) alloc_common_pcb(SPL_NETCONN_UDP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + pmsg->conn->comm_pcb_data = (i64) cpcb; + pmsg->conn->private_data = (i64) u; + udp_recv(u, spl_recv_udp, (void *) pmsg->conn); + break; + } + + case SPL_NETCONN_TCP: + { + struct tcp_pcb *t = tcp_new_ip_type(iptype); + if (t == NULL) + { + return ERR_MEM; + } + + cpcb = alloc_common_pcb(SPL_NETCONN_TCP); + if (cpcb == NULL) + { + return ERR_MEM; + } + + pmsg->conn->comm_pcb_data = (i64) cpcb; + pmsg->conn->private_data = (i64) t; + setup_tcp(t, pmsg->conn); + break; + } + + default: + /* Unsupported netconn type, e.g. protocol disabled */ + NSPOL_LOGERR("Unsupported netconn type!"); + return ERR_VAL; + } + + /* type and socket value for all type */ + cpcb->socket = pmsg->socket; + cpcb->conn = pmsg->conn; + cpcb->bind_thread_index = thread_index; + + /* used to find pcb when a msg is received */ + return ERR_OK; +} + +/** + * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in + * these mboxes + * + * @param conn the netconn to free + * @bytes_drained bytes drained from recvmbox + * @accepts_drained pending connections drained from acceptmbox + */ +int netconn_drain(enum spl_netconn_type type, spl_netconn_t * conn) +{ + int i, n; + mring_handle ring = NULL; + void *addr[32] = { 0 }; + int not_empty = 0; + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ + ring = conn->recv_ring; + do + { + /*every times get atmost 32 to release */ + n = nsfw_mem_ring_dequeuev(ring, addr, 32); + for (i = 0; i < n; i++) + { + /* if the con is UDP, buffer type also is struct spl_netbuf,it is same as RAW */ + if ((type == SPL_NETCONN_RAW) || (type == SPL_NETCONN_UDP)) + { + spl_pbuf_free((struct spl_pbuf *) addr[i]); + if (type == SPL_NETCONN_UDP) + { + UDP_STATS_INC(udp.drop); + } + } + else + { + spl_pbuf_free((struct spl_pbuf *) addr[i]); + } + + if (not_empty == 0) + not_empty = 1; + } + } + while (0 != n); + return not_empty; +} + +/* need free mbuf inside recv ring before free conn */ +void free_conn_by_spl(spl_netconn_t * conn) +{ + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + + free_common_pcb(cpcb); + + (void) netconn_drain(conn->type, conn); + ss_free_conn(conn); +} + +int +do_close_finished(struct common_pcb *cpcb, u8_t close_finished, u8_t shut, + err_t err, int OpShutDown) +{ + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + spl_netconn_t *conn = cpcb->conn; + + if (!close_finished) + { + /* Closing succeeded */ + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + if (LISTEN == tpcb->state) + { + NSPOL_LOGERR("Closing a listen pcb may not fail!"); + return ERR_VAL; + } + + tcp_sent(tpcb, tcp_fn[TCP_FN_STACKX].sent_fn); + tcp_poll(tpcb, tcp_fn[TCP_FN_STACKX].poll_fn, 1); + tcp_err(tpcb, tcp_fn[TCP_FN_STACKX].err_fn); + tcp_arg(tpcb, conn); + /* don't restore recv callback: we don't want to receive any more data */ + } + else + { + /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */ + if (cpcb->current_msg) + { + SET_MSG_ERR(cpcb->current_msg, err); + cpcb->current_msg = NULL; + } + + conn->state = SPL_NETCONN_NONE; + NSTCP_LOGINF("release pcb]conn=%p,pcb=%p", conn, tpcb); + unlink_pcb(cpcb); + } + + return ERR_OK; +} + +NSTACK_STATIC void +reset_tcp_callback(struct tcp_pcb *tpcb, struct common_pcb *cpcb, u8 shut) +{ + spl_netconn_t *conn = cpcb->conn; + + /* some callbacks have to be reset if tcp_close is not successful */ + if (shut & SPL_NETCONN_SHUT_RD) + { + conn->CanNotReceive = 1; + tcp_recv(tpcb, tcp_fn[TCP_FN_NULL].recv_fn); + tcp_accept(tpcb, tcp_fn[TCP_FN_NULL].accept_fn); + } + + if (shut & SPL_NETCONN_SHUT_WR) + { + tcp_sent(tpcb, tcp_fn[TCP_FN_NULL].sent_fn); + } + + if (shut == SPL_NETCONN_SHUT_RDWR) + { + tcp_poll(tpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0); + tcp_err(tpcb, tcp_fn[TCP_FN_NULL].err_fn); + } +} + +/** + * Internal helper function to close a TCP netconn: since this sometimes + * doesn't work at the first attempt, this function is called from multiple + * places. + * + * @param conn the TCP netconn to close + */ +err_t do_close_internal(struct common_pcb *cpcb, int OpShutDown) +{ + err_t err; + u8_t shut, ucclose; + u8_t close_finished = 0; + + if (NULL == cpcb) + { + NSTCP_LOGERR("invalid conn"); + return ERR_ARG; + } + + spl_netconn_t *conn = cpcb->conn; + if (SPL_NETCONN_TCP != cpcb->type || SPL_NETCONN_CLOSE != conn->state) + { + NSTCP_LOGERR("conn=%p, err_type=%d, error_state=%d", + conn, cpcb->type, conn->state); + return ERR_VAL; + } + + struct tcp_pcb *tpcb = (struct tcp_pcb *) (conn->private_data); + + if (cpcb->current_msg != NULL) + shut = get_shut_op(cpcb->current_msg); + else + shut = SPL_NETCONN_SHUT_RDWR; + + /* shutting down both ends is the same as closing */ + ucclose = (shut == SPL_NETCONN_SHUT_RDWR); + + /* Set back some callback pointers */ + if (ucclose) + { + conn->CanNotReceive = 1; + tcp_arg(tpcb, conn); + } + + if (tpcb->state == LISTEN) + { + tcp_accept(tpcb, tcp_fn[TCP_FN_NULL].accept_fn); + } + else + { + reset_tcp_callback(tpcb, cpcb, shut); + } + + /* Try to close the connection */ + if (shut == SPL_NETCONN_SHUT_RDWR && !OpShutDown) + { + err = tcp_close(tpcb); + } + else + { + err = + tcp_shutdown(tpcb, shut & SPL_NETCONN_SHUT_RD, + shut & SPL_NETCONN_SHUT_WR); + } + + if (err == ERR_OK) + { + close_finished = 1; + } + else + { + if (err == ERR_MEM) + { + /* Blocking close, check the timeout */ + close_finished = 1; + if (ucclose) + { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; + } + } + else + { + /* Closing failed for a non-memory error: give up */ + close_finished = 1; + } + } + + err_t err1 = do_close_finished(cpcb, close_finished, + shut, err, OpShutDown); + if (err1 != ERR_OK) + { + NSTCP_LOGERR("return err1]pcb=%p,err1=%d", tpcb, err1); + return err1; + } + return err; + + /* If closing didn't succeed, we get called again either + from poll_tcp or from sent_tcp */ +} + +void do_try_delconn(void *close_data, u32 delay_sec) +{ + msg_delete_netconn *dmsg = (msg_delete_netconn *) close_data; + data_com_msg *m = MSG_ENTRY(dmsg, data_com_msg, buffer); + struct common_pcb *cpcb = NULL; + + spl_netconn_t *conn = dmsg->conn; + + /* no receiver in some recycle cases */ + if (0 == m->param.comm_receiver) + { + if (NULL == conn) + { + NSFW_LOGERR("release err conn!]pid=%d", dmsg->pid); + /* need to free pbufs which are attached to msg */ + do_pbuf_free(dmsg->buf); + return; + } + + cpcb = (struct common_pcb *) conn->comm_pcb_data; + } + else + { + cpcb = COMM_PRIVATE_PTR(m); + } + + /* no pcb in some recycle cases */ + if (conn->private_data == 0) + { + /* though pcb is gone, still need to clean the mbox */ + if (conn != NULL) + (void) netconn_drain(conn->type, conn); + + NSFW_LOGWAR("release conn pcb null]pcb=%p", m->param.receiver); + /* need to free pbufs which are attached to msg */ + do_pbuf_free(dmsg->buf); + return; + } + + if (delay_sec) + { + NSFW_LOGWAR("delay to recycle!]pcb=%p, msg=%d", cpcb, dmsg); + sys_timeout(delay_sec * 1000, recycle_tmr, dmsg); + return; + } + + do_delconn(cpcb, dmsg); + + /* after the do_delconn, the PCB maybe released, but the conn is ok */ + sys_sem_s_signal(&dmsg->conn->close_completed); + + return; +} + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_delconn(struct common_pcb *cpcb, msg_delete_netconn * dmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY(dmsg, data_com_msg, buffer); + + /*if already close, just return */ + /* run and close repeatly nstackmain coredum */ + if (1 == cpcb->close_progress) + { + SET_MSG_ERR(pmsg, ERR_OK); + return; + } + cpcb->close_progress = 1; + + /* Pbuf free should be done in network stack */ + do_pbuf_free(dmsg->buf); + + /* @todo TCP: abort running write/connect? */ + if ((conn->state != SPL_NETCONN_NONE) + && (conn->state != SPL_NETCONN_LISTEN) + && (conn->state != SPL_NETCONN_CONNECT)) + { + /* this only happens for TCP netconns */ + if (SPL_NETCONN_TCP != cpcb->type) + { + NSTCP_LOGERR("msg->conn->type error!]conn=%p,msg->conn->type=%d", + conn, cpcb->type); + SET_MSG_ERR(pmsg, ERR_VAL); + return; + } + NSPOL_LOGINF(SOCK_INFO, "conn is not for free state]conn=%p,state=%d", + conn, conn->state); + + //need to release pcb + if (cpcb->current_msg != NULL && cpcb->msg_tail != NULL) + { + NSPOL_LOGINF(SOCK_INFO, + "conn there is data in conn->current_msg when close the conn]conn=%p,state=%d", + conn, conn->state); + (void) do_writemore(cpcb->conn); + } + } + + /* + the accpet connections waiting in listen queue will be clear in + netconn_drain. + */ + if (conn->state == SPL_NETCONN_LISTEN) + { + /* This function does nothing in original code. */ + } + else + { + /* Drain pbuf from non-listen mboxes */ + if (netconn_drain(cpcb->type, conn)) + { + cpcb->recv_ring_not_empty = 1; + + NSPOL_LOGWAR(SOCK_INFO, + "still some data leave in recv ring when close"); + } + } + + /* conn will be released outside */ + + switch (SPL_NETCONNTYPE_GROUP(cpcb->type)) + { + + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = + (struct udp_pcb *) cpcb->conn->private_data; + upcb->recv_arg = NULL; + udp_remove(upcb); + break; + } + + case SPL_NETCONN_TCP: + { + conn->state = SPL_NETCONN_CLOSE; + dmsg->shut = SPL_NETCONN_SHUT_RDWR; + cpcb->current_msg = pmsg; + + if (ERR_INPROGRESS == do_close_internal(cpcb, 0)) + { + return; + } + } + default: + break; + } + + /* tcp netconns don't come here! */ + +} + +/** + * Bind a pcb contained in a netconn + * Called from netconn_bind. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IPaddress and port to bind to + */ +void do_bind(struct common_pcb *cpcb, msg_bind * bmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY(bmsg, data_com_msg, buffer); + ip_addr_t stIpaddr; + + stIpaddr.addr = bmsg->ipaddr.addr; + + if (SPL_ERR_IS_FATAL(conn->last_err) + && ERR_CANTASSIGNADDR != conn->last_err) + { + NSTCP_LOGERR("bind but conn has err]pcb=%p,conn=%p,err=%d", cpcb, + conn, conn->last_err); + SET_MSG_ERR(pmsg, conn->last_err); + } + else + { + if (!ip_addr_isany(&bmsg->ipaddr) + && !ip_addr_ismulticast(&bmsg->ipaddr)) + { + if (!get_netif_by_ip(bmsg->ipaddr.addr) + && !netif_check_broadcast_addr(&bmsg->ipaddr)) + { + NSPOL_LOGERR("ip is not exist]pcb=%p,ip=%u", cpcb, + bmsg->ipaddr.addr); + SET_MSG_ERR(pmsg, ERR_CANTASSIGNADDR); + return; + } + } + + SET_MSG_ERR(pmsg, ERR_VAL); + switch (SPL_NETCONNTYPE_GROUP(cpcb->type)) + { + case SPL_NETCONN_UDP: + SET_MSG_ERR(pmsg, + udp_bind((struct udp_pcb *) (cpcb-> + conn->private_data), + &stIpaddr, bmsg->port)); + + /* Set local Ip, willbe used during connect */ + struct udp_pcb *upcb = + (struct udp_pcb *) cpcb->conn->private_data; + ss_set_local_ip(cpcb->conn, upcb->local_ip.addr); + ss_set_local_port(cpcb->conn, upcb->local_port); + NSTCP_LOGINF("updated Ip to spl_netconn_t] %x", + upcb->local_ip.addr); + + NSUDP_LOGINF + ("udp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d", + (struct udp_pcb *) cpcb->conn->private_data, + &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16(&stIpaddr), + bmsg->port, GET_MSG_ERR(pmsg)); + break; + + case SPL_NETCONN_TCP: + SET_MSG_ERR(pmsg, + tcp_bind((struct tcp_pcb *) cpcb-> + conn->private_data, &stIpaddr, + bmsg->port)); + + /* Set local Ip, willbe used during connect */ + struct tcp_pcb *tpcb = + (struct tcp_pcb *) cpcb->conn->private_data; + NSTCP_LOGINF("updated Ip to spl_netconn_t] %x", + tpcb->local_ip.addr); + ss_set_local_ip(cpcb->conn, tpcb->local_ip.addr); + ss_set_local_port(cpcb->conn, tpcb->local_port); + + NSTCP_LOGINF + ("tcp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d", + (struct tcp_pcb *) cpcb->conn->private_data, + &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16(&stIpaddr), + &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16(&stIpaddr), + bmsg->port, GET_MSG_ERR(pmsg)); + break; + default: + break; + } + } + + conn->last_err = GET_MSG_ERR(pmsg); + NSPOL_LOGDBG(TESTSOCKET_DEBUG | LWIP_DBG_TRACE, "the msg is doing bind"); + NSTCP_LOGINF("the msg is doing bind"); +} + +/** + * TCP callback function if a connection (opened by tcp_connect/do_connect) has + * been established (or reset by the remote host). + * + * @see tcp.h (struct tcp_pcb.connected) for parameters and return values + */ +err_t spl_do_connected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + spl_netconn_t *conn = (spl_netconn_t *) arg; + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + data_com_msg *m = cpcb->current_msg; + int was_blocking; + + if (conn == NULL) + { + NSTCP_LOGERR("conn is NULL!]arg=%p", arg); + return ERR_ARG; + } + + if (SPL_NETCONN_CONNECT != conn->state) + { + NSTCP_LOGERR("conn->state error!]conn=%p,state=%d", conn, + conn->state); + return ERR_VAL; + } + + if ((NULL == m) && (0 == spl_netconn_is_nonblocking(conn))) + { + NSTCP_LOGERR("conn->current_msg!]conn=%p,current_msg=%p", conn, m); + return ERR_VAL; + } + + if (m != NULL) + { + SET_MSG_ERR(m, err); + } + + if ((cpcb->type == SPL_NETCONN_TCP) && (err == ERR_OK)) + { + setup_tcp(pcb, conn); + } + + ss_set_local_ip(conn, pcb->local_ip.addr); + ss_set_local_port(conn, pcb->local_port); + conn->remote_ip.addr = pcb->remote_ip.addr; + conn->remote_port = pcb->remote_port; + + conn->mss = pcb->mss; + cpcb->current_msg = NULL; + + was_blocking = !SPL_IN_NONBLOCKING_CONNECT(conn); + SPL_SET_NONBLOCKING_CONNECT(conn, 0); + conn->state = SPL_NETCONN_NONE; + SPL_NETCONN_SET_SAFE_ERR(conn, ERR_OK); + + update_tcp_state(pcb->callback_arg, ESTABLISHED); + SPL_API_EVENT(conn, SPL_NETCONN_EVT_SENDPLUS, 1); + + if (was_blocking && m != NULL) + { + SYNC_MSG_ACK(m); + } + + return ERR_OK; +} + +int +do_internal_tcp_connect(struct common_pcb *cpcb, struct tcp_pcb *tpcb, + msg_connect * cmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY(cmsg, data_com_msg, buffer); + ip_addr_t ip_addr; + + ip_addr.addr = cmsg->ipaddr.addr; + + /* Prevent connect while doing any other action. */ + if (conn->state != SPL_NETCONN_NONE) + { + if (conn->state == SPL_NETCONN_CONNECT + || conn->state == SPL_NETCONN_WRITE) + { + if (tpcb->state != ESTABLISHED) + { + SET_MSG_ERR(pmsg, ERR_ALREADY); + } + else + { + SET_MSG_ERR(pmsg, ERR_ISCONN); + } + } + else + { + SET_MSG_ERR(pmsg, ERR_ISCONN); + } + + NSTCP_LOGINF + ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d", + tpcb, conn->state, ip4_addr1_16(&ip_addr), + ip4_addr2_16(&ip_addr), ip4_addr3_16(&ip_addr), + ip4_addr4_16(&ip_addr), cmsg->port, + ip4_addr1_16(&tpcb->local_ip), ip4_addr2_16(&tpcb->local_ip), + ip4_addr3_16(&tpcb->local_ip), ip4_addr4_16(&tpcb->local_ip), + tpcb->local_port, GET_MSG_ERR(pmsg)); + } + else + { + setup_tcp(tpcb, conn); + SET_MSG_ERR(pmsg, + tcp_connect(tpcb, &ip_addr, cmsg->port, + tcp_fn[TCP_FN_STACKX].connected_fn)); + conn->mss = tpcb->mss; + SPL_API_EVENT(conn, NETCONN_EVT_SENDMINUS, 1); + SPL_API_EVENT(conn, NETCONN_EVT_RCVMINUS, 1); + + NSTCP_LOGINF + ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d", + tpcb, conn->state, ip4_addr1_16(&ip_addr), + ip4_addr2_16(&ip_addr), ip4_addr3_16(&ip_addr), + ip4_addr4_16(&ip_addr), cmsg->port, + ip4_addr1_16(&tpcb->local_ip), ip4_addr2_16(&tpcb->local_ip), + ip4_addr3_16(&tpcb->local_ip), ip4_addr4_16(&tpcb->local_ip), + tpcb->local_port, GET_MSG_ERR(pmsg)); + if (GET_MSG_ERR(pmsg) == ERR_OK) + { + int nonblock = spl_netconn_is_nonblocking(conn); + SPL_SET_NONBLOCKING_CONNECT(conn, nonblock); + conn->state = SPL_NETCONN_CONNECT; + if (nonblock) + { + SET_MSG_ERR(pmsg, ERR_INPROGRESS); + } + else + { + cpcb->current_msg = pmsg; + /* sys_sem_signal() is called from do_connected (or err_tcp()), + * when the connection is established! */ + return -1; + } + } + } + + return 0; +} + +/** + * Connect a pcb contained inside a netconn + * Called from netconn_connect. + * + * @param msg the api_msg_msg pointing to the connection and containing + * the IPaddress and port to connect to + */ +void do_connect(struct common_pcb *cpcb, msg_connect * cmsg) +{ + data_com_msg *pmsg = MSG_ENTRY(cmsg, data_com_msg, buffer); + ip_addr_t ipaddr; + + SET_MSG_ERR(pmsg, ERR_OK); + + if (cpcb == NULL) + { + /* This may happen when calling netconn_connect() a second time */ + NSTCP_LOGERR("conn connect but conn has err]msg=%p", pmsg); + SET_MSG_ERR(pmsg, ERR_CLSD); + return; + } + + ipaddr.addr = cmsg->ipaddr.addr; + switch (SPL_NETCONNTYPE_GROUP(cpcb->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = + (struct udp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany(&upcb->local_ip)) + { + upcb->local_ip.addr = cmsg->local_ip.addr; + ss_set_local_ip(cpcb->conn, upcb->local_ip.addr); + } + + SET_MSG_ERR(pmsg, udp_connect(upcb, &ipaddr, cmsg->port)); + if (ERR_OK == pmsg->param.err) + { + cpcb->conn->remote_ip.addr = cmsg->ipaddr.addr; + cpcb->conn->remote_port = cmsg->port; + } + break; + } + case SPL_NETCONN_TCP: + { + struct tcp_pcb *tpcb = + (struct tcp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany(&tpcb->local_ip)) + { + tpcb->local_ip.addr = cmsg->local_ip.addr; + ss_set_local_ip(cpcb->conn, tpcb->local_ip.addr); + } + + if (0 != do_internal_tcp_connect(cpcb, tpcb, cmsg)) + { + return; + } + + } + break; + default: + NSPOL_LOGERR("Invalid netconn type]type=%d", cpcb->type); + SET_MSG_ERR(pmsg, ERR_VAL); + break; + } + + /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(), + so use TCPIP_APIMSG_ACK() here. + Do as lwip-2.0.0. set conn->last_error here. */ + SPL_NETCONN_SET_SAFE_ERR(cpcb->conn, GET_MSG_ERR(pmsg)); +} + +/* Pbuf free should be done in network stack */ +void do_pbuf_free(struct spl_pbuf *buf) +{ + if (buf) + { + struct spl_pbuf *pCur = buf; + while (buf) + { + pCur = buf; + buf = buf->freeNext; + spl_pbuf_free(pCur); + } + } +} + +/** + * Set a TCP pcb contained in a netconn into listen mode + * Called from netconn_listen. + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_listen(struct common_pcb *cpcb, msg_listen * lmsg) +{ + err_t err = ERR_OK; + spl_netconn_t *conn = cpcb->conn; + data_com_msg *pmsg = MSG_ENTRY(lmsg, data_com_msg, buffer); + + if (SPL_ERR_IS_FATAL(conn->last_err)) + { + NSTCP_LOGERR("conn listern but conn has err]conn=%p,err=%d", + conn, conn->last_err); + SET_MSG_ERR(pmsg, conn->last_err); + } + else + { + SET_MSG_ERR(pmsg, ERR_CONN); + + if (cpcb->type == SPL_NETCONN_TCP) + { + if (conn->state == SPL_NETCONN_NONE) + { + struct tcp_pcb *lpcb; + if (((struct tcp_pcb *) (cpcb->conn->private_data))->state != + CLOSED) + { + /* connection is not closed, cannot listen */ + SET_MSG_ERR(pmsg, ERR_VAL);; + } + else + { + u8_t backlog = TCP_DEFAULT_LISTEN_BACKLOG; + + lpcb = + tcp_listen_with_backlog_and_err((struct tcp_pcb + *) (cpcb-> + conn->private_data), + backlog, &err); + if (lpcb == NULL) + { + /* in this case, the old pcb is still allocated */ + SET_MSG_ERR(pmsg, err); + } + else + { + SET_MSG_ERR(pmsg, ERR_OK); + /* conn now is put on lpcb */ + conn->state = SPL_NETCONN_LISTEN; + + /* NOTE: pmsg->conn->comm_pcb_data == (i64)cpcb; should be already same. */ + conn->private_data = (i64) lpcb; + + tcp_arg(lpcb, conn); + tcp_accept(lpcb, tcp_fn[TCP_FN_STACKX].accept_fn); + + SPL_API_EVENT(conn, NETCONN_EVT_SENDMINUS, 1); + SPL_API_EVENT(conn, NETCONN_EVT_RCVMINUS, 1); + } + } + } + else if (conn->state == SPL_NETCONN_LISTEN) + { + SET_MSG_ERR(pmsg, ERR_OK); + } + } + NSTCP_LOGINF("listen]conn=%p,pcb=%p,connstate=%d,err=%d", + conn, cpcb, conn->state, GET_MSG_ERR(pmsg)); + + } + +} + +/** + * Send some data on UDP pcb contained in a netconn + * Called from do_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void spl_udp_send(struct common_pcb *cpcb, msg_send_buf * smsg) +{ + struct spl_pbuf *p_from = smsg->p; + spl_netconn_t *conn = cpcb->conn; + struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data); + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + struct pbuf *p_to = NULL; + err_t err = ERR_OK; + + //allocate pbuf and copy spl_pbuf, send , free pbuf and spl_pbuf + do + { + p_to = pbuf_alloc(PBUF_TRANSPORT, p_from->len, PBUF_RAM); + if (NULL == p_to) + { + NSPOL_LOGERR("pbuf is NULL]conn=%p,pcb=%p", conn, upcb); + return; + } + + err = splpbuf_to_pbuf_transport_copy(p_to, p_from); + if (err != ERR_OK) + { + SET_MSG_ERR(m, conn->last_err); + return; + } + + if (ip_addr_isany(&smsg->addr)) + { + SET_MSG_ERR(m, udp_send(upcb, p_to)); + } + else + { + SET_MSG_ERR(m, + udp_sendto(upcb, p_to, (ip_addr_t *) & smsg->addr, + smsg->port)); + } + + p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a); + } + while (p_from != NULL); + +} + +/** + * Send some data on a RAW or UDP pcb contained in a netconn + * Called from netconn_send + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_send(struct common_pcb *cpcb, msg_send_buf * smsg) +{ + struct spl_pbuf *p = smsg->p; + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + spl_netconn_t *conn = cpcb->conn; + + pbuf_set_recycle_flg(p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */ + + if (SPL_ERR_IS_FATAL(conn->last_err)) + { + SET_MSG_ERR(m, conn->last_err); + NSPOL_LOGERR("Invalid param]msg->conn=%p", conn); + goto err_return; + } + + switch (SPL_NETCONNTYPE_GROUP(cpcb->type)) + { + case SPL_NETCONN_UDP: + { + struct udp_pcb *upcb = + (struct udp_pcb *) (cpcb->conn->private_data); + if (ip_addr_isany(&upcb->local_ip)) + { + upcb->local_ip.addr = smsg->local_ip.addr; + ss_set_local_ip(conn, smsg->local_ip.addr); + } + + spl_udp_send(cpcb, smsg); + + break; + } + + default: + SET_MSG_ERR(m, ERR_CONN); + break; + } + + err_return: + pbuf_free_safe(smsg->p); + ASYNC_MSG_FREE(m); + + return; +} + +/** + * Indicate data has been received from a TCP pcb contained in a netconn + * Called from netconn_recv + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_recv(struct common_pcb *cpcb, msg_recv_buf * rmsg) +{ + data_com_msg *m = MSG_ENTRY(rmsg, data_com_msg, buffer); + SET_MSG_ERR(m, ERR_OK); + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (NULL == tpcb) + { + if (rmsg->p) + { + NSPOL_LOGDBG(TCP_DEBUG, + "When pcb was freed: do recv, and free pbuf"); + spl_pbuf_free(rmsg->p); + rmsg->p = NULL; + } + + return; + } + + if (cpcb->conn->type == SPL_NETCONN_TCP) + { + /* Pbuf free should be done in network stack */ + if (rmsg->p) + { + NSPOL_LOGDBG(TCP_DEBUG, "do recv, and free pbuf"); + spl_pbuf_free(rmsg->p); + rmsg->p = NULL; + } + tcp_recved(tpcb, rmsg->len * TCP_MSS); + } +} + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ + +/** + * See if more data needs to be written from a previous call to netconn_write. + * Called initially from do_write. If the first call can't send all data + * (because of low memory or empty send-buffer), this function is called again + * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the + * blocking application thread (waiting in netconn_write) is released. + * + * @param conn netconn (that is currently in state NETCONN_WRITE) to process + * @return ERR_OK + * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished + */ +err_t do_writemore(struct spl_netconn *conn) +{ + err_t err = ERR_OK; + u16_t len = 0, available; + u8_t write_finished = 0; + struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data; + common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + size_t diff; + const void *dataptr; + + if ((NULL == tpcb) || (NULL == conn) || (SPL_NETCONN_WRITE != conn->state) + || (NULL == cpcb->current_msg)) + { + NSPOL_LOGERR("conn=NULL"); + return ERR_ARG; + } + + msg_write_buf *wmsg = (msg_write_buf *) cpcb->current_msg->buffer; + start_write: + + if (NULL == wmsg->p) + { + NSPOL_LOGERR("wmsg->p is NULL]conn=%p,pcb=%p", conn, tpcb); + return ERR_VAL; + } + + u8_t apiflags = wmsg->apiflags; + struct spl_pbuf *current_w_pbuf = wmsg->p; + current_w_pbuf->res_chk.u8Reserve |= NEED_ACK_FLAG; + wmsg->p = current_w_pbuf->next; + current_w_pbuf->next = NULL; + + dataptr = (const u8_t *) current_w_pbuf->payload + cpcb->write_offset; + diff = current_w_pbuf->len - cpcb->write_offset; + + if (diff > 0xffffUL) + { + len = 0xffff; + apiflags |= TCP_WRITE_FLAG_MORE; + } + else + { + len = (u16_t) diff; + } + + available = tcp_sndbuf(tpcb); + if (!available) + { + err = ERR_MEM; + goto err_mem; + } + + if (available < len) + { + /* don't try to write more than sendbuf */ + len = available; + apiflags |= TCP_WRITE_FLAG_MORE; + } + + err = tcp_write(tpcb, dataptr, len, apiflags); + if ((err == ERR_OK) || (err == ERR_MEM)) + { + err_mem: + if ((tcp_sndbuf(tpcb) <= TCP_SNDLOWAT) || + (tcp_sndqueuelen(tpcb) >= TCP_SNDQUEUELOWAT)) + { + SPL_API_EVENT(conn, NETCONN_EVT_SENDMINUS, 1); + } + } + if (err == ERR_OK) + { + cpcb->write_offset += len; + tcp_output(tpcb); + + if (cpcb->write_offset == current_w_pbuf->len) + { + cpcb->write_offset = 0; + spl_pbuf_free(current_w_pbuf); + if (NULL == wmsg->p) + { + /* this message is finished */ + cpcb->write_offset = 0; + SET_MSG_ERR(cpcb->current_msg, err); + + /* go to next msg */ + data_com_msg *forFreemsg = cpcb->current_msg; + msg_write_buf *msg_head_prev = cpcb->msg_head; + cpcb->msg_head = cpcb->msg_head->next; + + /* no msg remain */ + if (cpcb->msg_head == NULL) + { + write_finished = 1; + if (cpcb->msg_tail != NULL + && msg_head_prev != cpcb->msg_tail) + { + NSPOL_LOGWAR(TCP_DEBUG, + "err maybe lost one mesg]conn=%p,pcb=%p", + conn, tpcb); + } + cpcb->msg_tail = NULL; + cpcb->current_msg = NULL; + conn->state = SPL_NETCONN_NONE; + } + else /* go to handle next message */ + { + + cpcb->current_msg = + MSG_ENTRY(cpcb->msg_head, data_com_msg, buffer); + wmsg = cpcb->msg_head; + write_finished = 0; + } + + ASYNC_MSG_FREE(forFreemsg); + } + + } + else + { + if (cpcb->write_offset > current_w_pbuf->len) + { + NSPOL_LOGERR + ("Big trouble write_offset > current_w_pbuf->len"); + } + + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + } + if ((write_finished == 0) && (NULL != wmsg->p)) + { + goto start_write; + } + } + else if (err == ERR_MEM) + { + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + tcp_output(tpcb); + } + else + { + NSPOL_LOGERR("]pcb=%p, error when send %d", tpcb, err); + write_finished = 1; + cpcb->write_offset = 0; + current_w_pbuf->next = wmsg->p; + wmsg->p = current_w_pbuf; + tcp_abort(tpcb); + return err; + } + NSTCP_LOGINF("do_writemore finished with err %d", err); + return ERR_OK; +} + +/** + * Send some data on a TCP pcb contained in a netconn + * Called from netconn_write + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_write(struct common_pcb *cpcb, msg_write_buf * wmsg) +{ + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + spl_netconn_t *conn = cpcb->conn; + data_com_msg *m = MSG_ENTRY(wmsg, data_com_msg, buffer); + + pbuf_set_recycle_flg(wmsg->p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */ + + int tcpState = -1; + + /* if msg->conn is null, then return */ + if (NULL == conn) + { + NSPOL_LOGERR("Invalid param]msg->conn=%p", conn); + SET_MSG_ERR(m, ERR_VAL); + goto err_return; + } + + tcpState = tpcb->state; + + if ((SPL_ERR_IS_FATAL(conn->last_err)) + && !((ERR_CLSD == conn->last_err) && (CLOSE_WAIT == tcpState))) + { + SET_MSG_ERR(m, conn->last_err); + } + else + { + if (cpcb->type == SPL_NETCONN_TCP) + { + if (cpcb->current_msg != NULL) + { + if (NULL == cpcb->msg_head || NULL == cpcb->msg_tail) + { + /* if possible only if connect is not finished and it's + blocking, then the current_msg is connect msg. + */ + NSPOL_LOGERR("netconn do_write msg is null]msg_type=%d", + cpcb->current_msg->param.minor_type); + goto err_return; + } + + /* only msg_write_buf will be in msg_head-msg_tail queue */ + wmsg->next = NULL; + cpcb->msg_tail->next = wmsg; + cpcb->msg_tail = wmsg; + (void) do_writemore(conn); + NSTCP_LOGINF("do_write finished...."); + return; + } + + if (conn->state != SPL_NETCONN_NONE) + { + /* netconn is connecting, closing or in blocking write */ + NSPOL_LOGINF(TCP_DEBUG, + "msg->conn->state != SPL_NETCONN_NONE..netconn is connecting, " + "closing or in blocking write]conn=%p", conn); + SET_MSG_ERR(m, ERR_INPROGRESS); + } + /* this means we should start to process this message */ + else if (tpcb != NULL) + { + conn->state = SPL_NETCONN_WRITE; + + /* set all the variables used by do_writemore */ + if (0 != cpcb->write_offset) + { + NSPOL_LOGERR("already writing or closing]conn=%p", conn); + goto err_return; + } + + if (0 == wmsg->len) + { + NSPOL_LOGERR("msg->msg.w.len=0]conn=%p", conn); + goto err_return; + } + + /* record the msg will be processed */ + cpcb->current_msg = m; + if (cpcb->msg_head != NULL || cpcb->msg_tail != NULL) + { + NSPOL_LOGERR("error maybe lost mesg]conn=%p", conn); + } + cpcb->msg_head = cpcb->msg_tail = wmsg; + wmsg->next = NULL; + cpcb->write_offset = 0; + + (void) do_writemore(conn); + + if ((conn->snd_buf) > TCP_SNDLOWAT) + { + if (cpcb->model == SOCKET_STACKX) + SPL_API_EVENT(conn, SPL_NETCONN_EVT_SENDPLUS, 1); + } + NSTCP_LOGINF("do_write finished %d", conn->snd_buf); + + /* for both cases: if do_writemore was called, don't ACK the APIMSG + since do_writemore ACKs it! */ + return; + } + else + { + SET_MSG_ERR(m, ERR_CONN); + } + } + else + { + SET_MSG_ERR(m, ERR_VAL); + } + } + NSTCP_LOGINF("do_write finished"); + + err_return: + pbuf_free_safe(wmsg->p); + ASYNC_MSG_FREE(m); + + return; +} + +void do_getsockname(struct common_pcb *cpcb, msg_getaddrname * amsg) +{ + spl_netconn_t *conn; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct sockaddr_in *paddr = (struct sockaddr_in *) &amsg->sock_addr; + + data_com_msg *m = MSG_ENTRY(amsg, data_com_msg, buffer); + + if ((NULL == cpcb) || !(conn = cpcb->conn)) + { + NSTCP_LOGERR("failed to get sock"); + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR(m, ERR_CONN); + return; + } + + NS_LOG_CTRL(LOG_CTRL_GETSOCKNAME, LOGTCP, "NSTCP", NSLOG_DBG, + "cpcb=%p,conn=%p,cmd=%u", cpcb, cpcb->conn, amsg->cmd); + + paddr->sin_family = AF_INET; + SET_MSG_ERR(m, ERR_OK); + + if (amsg->cmd == 0) + { + if (cpcb->type == SPL_NETCONN_TCP) + { + tcp = (struct tcp_pcb *) cpcb->conn->private_data; + /* add judgement:(NETCONN_LISTEN == conn->state) in following if words */ + /* If connect is not done in TCP then the remote address will not be there so need to update proper error code + if the application call the getpeername in TCP mode */ + if ((SPL_NETCONN_LISTEN == conn->state) + || (tcp->remote_ip.addr == 0) || (tcp->remote_port == 0)) + { + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR(m, ERR_CONN); + } + else + { + paddr->sin_port = spl_htons(tcp->remote_port); + paddr->sin_addr.s_addr = tcp->remote_ip.addr; + } + } + else if (cpcb->type == SPL_NETCONN_UDP) + { + udp = (struct udp_pcb *) cpcb->conn->private_data; + /* If connect is not done in UDP then the remote address will not be there so need to update proper error code + if the application call the getpeername in UDP mode + */ + if ((udp->remote_ip.addr == 0) || (udp->remote_port == 0)) + { + paddr->sin_family = 0; + paddr->sin_port = 0; + paddr->sin_addr.s_addr = 0; + SET_MSG_ERR(m, ERR_CONN); + } + else + { + paddr->sin_port = spl_htons(udp->remote_port); + paddr->sin_addr.s_addr = udp->remote_ip.addr; + } + } + } + else + { + if (cpcb->type == SPL_NETCONN_TCP) + { + tcp = (struct tcp_pcb *) cpcb->conn->private_data; + paddr->sin_port = spl_htons(tcp->local_port); + paddr->sin_addr.s_addr = tcp->local_ip.addr; + } + else if (cpcb->type == SPL_NETCONN_UDP) + { + udp = (struct udp_pcb *) cpcb->conn->private_data; + paddr->sin_port = spl_htons(udp->local_port); + paddr->sin_addr.s_addr = udp->local_ip.addr; + } + } +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +void do_close(struct common_pcb *cpcb, msg_close * cmsg) +{ + spl_netconn_t *conn = cpcb->conn; + data_com_msg *m = MSG_ENTRY(cmsg, data_com_msg, buffer); + + NSTCP_LOGDBG("msg->conn=%p,state=%d", conn, conn->state); + + /* @todo: abort running write/connect? */ + if ((conn->state != SPL_NETCONN_NONE) + && (conn->state != SPL_NETCONN_LISTEN) + && (conn->state != SPL_NETCONN_CONNECT)) + { + if (SPL_NETCONN_TCP != cpcb->type) + { + NSTCP_LOGERR("msg->conn=%p,type=%d", conn, cpcb->type); + return; + } + NSTCP_LOGWAR("msg->conn=%p,state=%d", conn, conn->state); + SET_MSG_ERR(m, ERR_INPROGRESS); + } + else if (cpcb->type == SPL_NETCONN_TCP) //clear codeDEX warning , CID:24336, cpcb can't be null. + { + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (tpcb == NULL) + { + NSTCP_LOGERR("tpcb null msg->conn=%p,type=%d", conn, cpcb->type); + return; + } + if ((cmsg->shut != SPL_NETCONN_SHUT_RDWR) + && (conn->state == SPL_NETCONN_LISTEN)) + { + /* LISTEN doesn't support half shutdown */ + NSTCP_LOGERR + ("LISTEN doesn't support half shutdown!]conn=%p,pcb=%p,state=%d", + conn, tpcb, conn->state); + SET_MSG_ERR(m, ERR_CONN); + } + else + { + if (cmsg->shut & SPL_NETCONN_SHUT_RD) + { + /* Drain and delete mboxes */ + (void) netconn_drain(cpcb->type, conn); + unlink_recv_ring(conn); + } + + if (((NULL != cpcb->current_msg) + && (conn->state != SPL_NETCONN_CONNECT)) + || (0 != cpcb->write_offset)) + { + NSTCP_LOGERR + ("already writing or closing]conn=%p,pcb=%p,offset=%zu,curmsg=%p", + conn, tpcb, cpcb->write_offset, cpcb->current_msg); + SET_MSG_ERR(m, ERR_CONN); + return; + } + + if (conn->state == SPL_NETCONN_CONNECT) + { + if (cpcb->current_msg != NULL + && cpcb->current_msg->param.minor_type == + SPL_API_DO_CONNECT) + { + SET_MSG_ERR(m, ERR_RST); + SYNC_MSG_ACK(cpcb->current_msg); + } + else + { + NSTCP_LOGINF + ("already in connecting]conn=%p,cpcb=%p,msg=%p", conn, + cpcb, cpcb->current_msg); + } + /* maybe need to clean cpcb->msg_head */ + } + + conn->state = SPL_NETCONN_CLOSE; + cpcb->current_msg = m; + (void) do_close_internal(cpcb, 1); + + if (SPL_NETCONN_SHUT_RD == cmsg->shut + || SPL_NETCONN_SHUT_RDWR == cmsg->shut) + { + SPL_API_EVENT(conn, SPL_NETCONN_EVT_RCVPLUS, 1); + } + + return; + } + } + else + { + SET_MSG_ERR(m, ERR_VAL); + } +} + +/*trans kerner option to stackx option*/ +int ks_to_stk_opt(int opt) +{ + int stack_opt = opt; + switch (opt) + { + case SO_DEBUG: + stack_opt = SOF_DEBUG; + break; + case SO_ACCEPTCONN: + stack_opt = SOF_ACCEPTCONN; + break; + case SO_BROADCAST: + stack_opt = SOF_BROADCAST; + break; + case SO_KEEPALIVE: + stack_opt = SOF_KEEPALIVE; + break; + case SO_REUSEADDR: + stack_opt = SOF_REUSEADDR; + break; + case SO_DONTROUTE: + stack_opt = SOF_DONTROUTE; + break; + case SO_USELOOPBACK: + stack_opt = SOF_USELOOPBACK; + break; + case SO_OOBINLINE: + stack_opt = SOF_OOBINLINE; + break; + default: + stack_opt = opt; + break; + } + return stack_opt; +} + +void +do_get_tcpproto_getsockopt_internal(struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + void *optval; + struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + case SPL_TCP_NODELAY: + *(int *) optval = tcp_nagle_disabled(tpcb); + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,TCP_NODELAY=%s", + cpcb->socket, (*(int *) optval) ? "on" : "off"); + break; + + case SPL_TCP_KEEPIDLE: + *(int *) optval = (int) (tpcb->keep_idle / 1000); + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPIDLE=%d", + cpcb->socket, *(int *) optval); + break; + case SPL_TCP_KEEPINTVL: + *(int *) optval = (int) (tpcb->keep_intvl / 1000); + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPINTVL=%d", + cpcb->socket, *(int *) optval); + break; + case SPL_TCP_KEEPCNT: + *(int *) optval = (int) tpcb->keep_cnt; + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPCNT=%d", + cpcb->socket, *(int *) optval); + break; + case SPL_TCP_INFO: + ((struct tcp_info *) optval)->tcpi_total_retrans = + (int) tpcb->nrtx; + ((struct tcp_info *) optval)->tcpi_snd_mss = (int) tpcb->mss; + ((struct tcp_info *) optval)->tcpi_rtt = (int) tpcb->sa; + ((struct tcp_info *) optval)->tcpi_snd_cwnd = (int) tpcb->cwnd; + break; + default: + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]optname=%d", optname); + SET_MSG_ERR(m, EOPNOTSUPP); + break; + } +} + +void +do_get_ipproto_getsockopt_internal(struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + u32_t optlen; + void *optval; + + struct ip_pcb *ipcb = (struct ip_pcb *) (cpcb); + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + optlen = smsg->optlen; + + switch (optname) + { + case IP_TTL: + *(int *) optval = ipcb->ttl; + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,IP_TTL=%d", + cpcb->socket, *(int *) optval); + break; + case IP_TOS: + smsg->optlen = + (optlen < sizeof(u32_t)) ? sizeof(u8_t) : sizeof(u32_t); + if (smsg->optlen == sizeof(u8_t)) + { + *(u8_t *) optval = ipcb->tos; + } + else + { + *(u32_t *) optval = (u32_t) ipcb->tos; + } + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,IP_TOS=%d", + cpcb->socket, *(int *) optval); + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + +void +do_get_solsocket_getsockopt_internal(struct common_pcb *cpcb, + msg_setgetsockopt * smsg) +{ + int optname; + void *optval; + struct tcp_pcb *tpcb = NULL; + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data; + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + /* The option flags */ + case SO_BROADCAST: + case SO_KEEPALIVE: + case SO_REUSEADDR: + *(int *) optval = + (ip_get_option + ((struct ip_pcb *) cpcb, ks_to_stk_opt(optname))) ? 1 : 0; + NSPOL_LOGDBG(SOCKETS_DEBUG, "]fd=%d,optname=%d,optval=%s", + cpcb->socket, optname, + (*(int *) optval ? "on" : "off")); + break; + case SO_ACCEPTCONN: + tpcb = (struct tcp_pcb *) cpcb->conn->private_data; + if ((smsg->optlen < sizeof(int)) || (NULL == tpcb)) + { + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_ACCEPTCONN) failed]fd=%d,tcp=%p,optlen=%u", + cpcb->socket, cpcb, smsg->optlen); + break; + } + if (tpcb->state == LISTEN) + { + *(int *) optval = 1; + } + else + { + *(int *) optval = 0; + } + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_ACCEPTCONN)]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_TYPE: + switch (cpcb->type) + { + case SPL_NETCONN_RAW: + *(int *) optval = SOCK_RAW; + break; + case SPL_NETCONN_TCP: + *(int *) optval = SOCK_STREAM; + break; + case SPL_NETCONN_UDP: + *(int *) optval = SOCK_DGRAM; + break; + default: /* unrecognized socket type */ + *(int *) optval = cpcb->type; + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_TYPE): unrecognized socket type]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + } /* switch (sock->conn->type) */ + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_TYPE)]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_RCVTIMEO: + (*(struct timeval *) optval).tv_sec = + spl_netconn_get_recvtimeout(cpcb) / 1000; + (*(struct timeval *) optval).tv_usec = + (spl_netconn_get_recvtimeout(cpcb) % 1000) * 1000; + NSPOL_LOGDBG(SOCKETS_DEBUG, + "stackx_getsockopt(SOL_SOCKET, SO_RCVTIMEO)]fd=%d,sec=%ld,usec=%ld", + cpcb->socket, (*(struct timeval *) optval).tv_sec, + (*(struct timeval *) optval).tv_usec); + break; + case SO_SNDTIMEO: + (*(struct timeval *) optval).tv_sec = + spl_netconn_get_sendtimeout(cpcb) / 1000; + (*(struct timeval *) optval).tv_usec = + (spl_netconn_get_sendtimeout(cpcb) % 1000) * 1000; + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_SNDTIMEO)]fd=%dsec=%ld,usec=%ld", + cpcb->socket, (*(struct timeval *) optval).tv_sec, + (*(struct timeval *) optval).tv_usec); + break; + case SO_SNDBUF: + { + u16_t mss = (pcb->mss > TCP_MSS + || pcb->mss == 0) ? TCP_MSS : pcb->mss; + *(int *) optval = + spl_netconn_get_sendbufsize(cpcb->conn) * mss; + /*If user has not configured any sendbuffer value then we should return minimum + promissed for the connection based on the flow control. */ + if (*(int *) optval == 0) + { + *(int *) optval = CONN_TCP_MEM_MIN_LINE * mss; + } + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_SNDBUF)]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + } + case SO_NO_CHECK: + *(int *) optval = + (udp_flags((struct udp_pcb *) cpcb->conn->private_data) & + UDP_FLAGS_NOCHKSUM) ? 1 : 0; + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_NO_CHECK)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_SNDLOWAT: + *(int *) optval = 1; + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_SNDLOWAT)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + + case SO_RCVLOWAT: + *(int *) optval = spl_netconn_get_reclowbufsize(cpcb); + NSPOL_LOGDBG(SOCKETS_DEBUG, + "(SOL_SOCKET, SO_RCVLOWAT)fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + case SO_ERROR: + *(int *) optval = GET_MSG_ERR(m); + SET_MSG_ERR(m, 0); + NSPOL_LOGDBG(SOCKETS_DEBUG, "SOL_SOCKET]fd=%d,optval=%d", + cpcb->socket, *(int *) optval); + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported opt]optname=%d", + optname); + break; + } +} + +void do_getsockopt_internal(struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + int level; + + if (NULL == smsg) + { + NSTCP_LOGERR("arg NULL"); + return; + } + + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + + level = smsg->level; + switch (level) + { + /* Level: SOL_SOCKET */ + case SOL_SOCKET: + do_get_solsocket_getsockopt_internal(cpcb, smsg); + + break; + + /* Level: IPPROTO_IP */ + case IPPROTO_IP: + do_get_ipproto_getsockopt_internal(cpcb, smsg); + + break; + /* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + do_get_tcpproto_getsockopt_internal(cpcb, smsg); + + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported level]level=%d", level); + break; + } /* switch (level) */ +} + +void do_tcpsock_setsockopt(spl_netconn_t * conn, msg_setgetsockopt * smsg) +{ + const void *optval; + int optname; + struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data; + struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data; + + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + + optname = smsg->optname; + optval = &smsg->optval; + + switch (optname) + { + case SPL_TCP_NODELAY: + if (*(int *) optval) + { + tcp_nagle_disable(tpcb); + } + else + { + tcp_nagle_enable(tpcb); + } + + NSTCP_LOGDBG("IPPROTO_TCP, TCP_NODELAY]fd=%d,optval=%s", + cpcb->socket, (*(int *) optval) ? "on" : "off"); + break; + + case SPL_TCP_KEEPIDLE: + /* CID 52121 (#2 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */ + if ((u32_t) (*(int *) optval) >= INT_MAX / 1000) + { + NSTCP_LOGWAR("optval too big]optval=%u", + (u32_t) (*(int *) optval)); + *(int *) optval = INT_MAX / 1000; + } + + tpcb->keep_idle = 1000 * (u32_t) (*(int *) optval); + + if (tpcb->keep_idle > TCP_KEEPIDLE_DEFAULT) + { + NSTCP_LOGWAR + ("(%d, IPPROTO_TCP, SPL_TCP_KEEPIDLE. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %" + U32_F " ", cpcb->socket, tpcb->keep_idle); + tpcb->keep_idle = TCP_KEEPIDLE_DEFAULT; + } + + NSTCP_LOGDBG("IPPROTO_TCP, SPL_TCP_KEEPIDLE](fd=%d,keep_idle=%" + U32_F " ", cpcb->socket, tpcb->keep_idle); + + /* Not required lwip_slowtmr will take care about timer. */ + break; + case SPL_TCP_KEEPINTVL: + /* CID 52121 (#1 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */ + if ((u32_t) (*(int *) optval) >= INT_MAX / 1000) + { + NSTCP_LOGWAR("optval too big]optval=%u", + (u32_t) (*(int *) optval)); + *(int *) optval = INT_MAX / 1000; + } + + tpcb->keep_intvl = 1000 * (u32_t) (*(int *) optval); + + if (tpcb->keep_intvl > TCP_KEEPIDLE_DEFAULT) /*max timer value supported */ + { + NSTCP_LOGWAR + ("(%d, IPPROTO_TCP, SPL_TCP_KEEPINTVL. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %" + U32_F " ", cpcb->socket, tpcb->keep_intvl); + tpcb->keep_intvl = TCP_KEEPIDLE_DEFAULT; + } + NSTCP_LOGDBG("IPPROTO_TCP, SPL_TCP_KEEPINTVL]fd=%d,keep_intvl=%" + U32_F " ", cpcb->socket, tpcb->keep_intvl); + break; + case SPL_TCP_KEEPCNT: + tpcb->keep_cnt = (u32_t) (*(int *) optval); + NSTCP_LOGDBG("IPPROTO_TCP, SPL_TCP_KEEPCNT]fd=%d,keep_cnt=%" U32_F + " ", cpcb->socket, tpcb->keep_cnt); + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + +void do_ipsock_setsockopt(struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + const void *optval; + u32_t optlen; + int optname; + + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + + struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data; + struct ip_pcb *ipcb = (struct ip_pcb *) upcb; + + optname = smsg->optname; + optval = &smsg->optval; + optlen = smsg->optlen; + + int val = 0; + int bNotAllowSet = 0; + switch (optname) + { + case IP_TTL: + ipcb->ttl = (u8_t) (*(int *) optval); + NSIP_LOGDBG("IPPROTO_IP,IP_TTL]fd=%d,ttl=%u", cpcb->socket, + ipcb->ttl); + break; + case IP_TOS: + bNotAllowSet = (cpcb->dataSentFlag != 0) + && ((SPL_NETCONN_TCP == cpcb->type) + || (SPL_NETCONN_UDP == cpcb->type) + || (SPL_NETCONN_RAW == cpcb->type)); + /*not allow set tos value when sending data */ + if (bNotAllowSet) + { + SET_MSG_ERR(m, ERR_VAL); + break; + } + + if (optlen >= sizeof(u32_t)) + { + val = (int) (*(const int *) optval); + } + else if (optlen >= sizeof(u8_t)) + { + val = (int) (*(const u8_t *) optval); + } + + if (SPL_NETCONN_TCP == cpcb->type) + { + val &= ~INET_ECN_MASK; + val |= ipcb->tos & INET_ECN_MASK; + } + ipcb->tos = (u8_t) (val); + + smsg->msg_box = (get_msgbox((u8_t) val))->llring; + + NSIP_LOGDBG("IPPROTO_IP,IP_TOS]]fd=%d,tos=%u", cpcb->socket, + ipcb->tos); + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } +} + + /*Made seperate functions to reduce code complexity */ +void +do_setsockopt_recvtimeout_internal(const void *optval, + struct common_pcb *cpcb) +{ + if ((*(struct timeval *) optval).tv_sec < 0) + { + spl_netconn_set_recvtimeout(cpcb, 0); + } + else + { + spl_netconn_set_recvtimeout(cpcb, MAX_WAIT_TIMEOUT); + if ((*(struct timeval *) optval).tv_sec != 0 + || (*(struct timeval *) optval).tv_usec != 0) + { + if ((*(struct timeval *) optval).tv_sec < + ((MAX_WAIT_TIMEOUT / 1000) - 1)) + { + spl_netconn_set_recvtimeout(cpcb, + (*(struct timeval *) + optval).tv_sec * 1000 + + (*(struct timeval *) + optval).tv_usec / 1000); + } + } + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, + "SOL_SOCKET, SO_RCVTIMEO]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->recv_timeout); +} + +void +do_setsockopt_sndtimeout_internal(const void *optval, struct common_pcb *cpcb) +{ + if ((*(struct timeval *) optval).tv_sec < 0) + { + spl_netconn_set_sendtimeout(cpcb, 0); + } + else + { + spl_netconn_set_sendtimeout(cpcb, MAX_WAIT_TIMEOUT); + if ((*(struct timeval *) optval).tv_sec != 0 + || (*(struct timeval *) optval).tv_usec != 0) + { + if ((*(struct timeval *) optval).tv_sec < + ((MAX_WAIT_TIMEOUT / 1000) - 1)) + { + spl_netconn_set_sendtimeout(cpcb, + (*(struct timeval *) + optval).tv_sec * 1000 + + (*(struct timeval *) + optval).tv_usec / 1000); + } + } + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, + "SOL_SOCKET, SO_SNDTIMEO]conn=%p,fd=%d,optval=%d", cpcb, + cpcb->socket, cpcb->send_timeout); +} + +#define IS_TCP_PCB(cpcb) (cpcb && (cpcb->conn) && (SPL_NETCONN_TCP == cpcb->conn->type)) +NSTACK_STATIC inline void +set_opt_sol_socket(struct common_pcb *cpcb, struct tcp_pcb *pcb, + data_com_msg * m, int level, int optname, + const void *optval) +{ + switch (optname) + { + /* The option flags */ + case SO_BROADCAST: + + /* UNIMPL case SO_DEBUG: */ + /* UNIMPL case SO_DONTROUTE: */ + case SO_KEEPALIVE: + case SO_REUSEADDR: + + if (NULL == pcb) + { + NSPOL_LOGERR("conn->pcb.ip is null"); + break; + } + + if (*(const int *) optval) + { + ip_set_option((struct ip_pcb *) pcb, ks_to_stk_opt(optname)); + } + else + { + ip_reset_option((struct ip_pcb *) pcb, + ks_to_stk_opt(optname)); + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, + "]conn=%p,fd=%d,optname=0x%x,optval=%s", cpcb, + cpcb->socket, optname, + (*(const int *) optval ? "on" : "off")); + + /* No use now, since tcp_slowtmr will take care about not sending/sending of keepalive */ + break; + + case SO_RCVLOWAT: + spl_netconn_set_reclowbufsize(cpcb, *(int *) optval); + NSPOL_LOGDBG(SOCKETS_DEBUG, + "SOL_SOCKET, SO_RCVLOWAT]conn=%p,fd=%d,optval=%d", + cpcb, cpcb->socket, cpcb->sk_rcvlowat); + break; + + case SO_RCVTIMEO: + /*to reduce code complexity */ + do_setsockopt_recvtimeout_internal(optval, cpcb); + break; + + case SO_SNDTIMEO: + /*to reduce code complexity */ + do_setsockopt_sndtimeout_internal(optval, cpcb); + break; + + case SO_SNDBUF: + { + /* udp pcb invalid access will cause coredump */ + if (!IS_TCP_PCB(cpcb)) + { + NSPOL_LOGDBG(SOCKETS_DEBUG, + "not support for non tcp socket]optname=%d, level=%d", + optname, level); + return; + } + + u16_t mss = (pcb->mss > TCP_MSS + || pcb->mss == 0) ? TCP_MSS : pcb->mss; + + if (*(int *) optval < (int) mss) + { + /*set value of one TCP_MSS */ + spl_netconn_set_sendbufsize(cpcb->conn, 1); + } + else + { + spl_netconn_set_sendbufsize(cpcb->conn, + (*(int *) optval) / + (int) mss); + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, + "SOL_SOCKET, SO_SNDBUF]conn=%p,fd=%d,optval=%d", + cpcb, cpcb->socket, + cpcb->conn->send_bufsize * mss); + break; + } + + case SO_NO_CHECK: + /* How udp is coming here.. ?? @TODO: May be move to someother function.? */ + /* solve segment issue when the PCB is not exist */ + if (NULL == cpcb) + { + NSPOL_LOGERR("conn->pcb.udp is null"); + break; + } + + struct udp_pcb *upcb = (struct udp_pcb *) pcb; + + if (*(int *) optval) + { + udp_setflags(upcb, udp_flags(upcb) | UDP_FLAGS_NOCHKSUM); + } + else + { + udp_setflags(upcb, udp_flags(upcb) & ~UDP_FLAGS_NOCHKSUM); + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, + "SOL_SOCKET, SO_NO_CHECK]conn=%p,fd=%d,optval=0x%x", + cpcb, cpcb->socket, upcb->flags); + break; + + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]optname=%d", optname); + break; + } /* switch (optname) */ + +} + +void do_setsockopt_internal(struct common_pcb *cpcb, msg_setgetsockopt * smsg) +{ + int level, optname; + const void *optval; + + data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer); + struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data; + + if (NULL == smsg) + { + NSTCP_LOGERR("arg null!"); + return; + } + + level = smsg->level; + optname = smsg->optname; + optval = &smsg->optval; + + switch (level) + { + /* Level: SOL_SOCKET */ + case SOL_SOCKET: + set_opt_sol_socket(cpcb, pcb, m, SOL_SOCKET, optname, optval); + break; + + /* Level: IPPROTO_IP */ + case IPPROTO_IP: + + if (NULL == cpcb) + { + NSPOL_LOGERR("conn->pcb.ip is null"); + break; + } + + do_ipsock_setsockopt(cpcb, smsg); + + break; + /* Level: IPPROTO_TCP */ + case IPPROTO_TCP: + /* udp pcb invalid access will cause coredump */ + if (!IS_TCP_PCB(cpcb)) + { + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, + "not support for non tcp socket]optname=%d,level=%d", + optname, level); + return; + } + + if (NULL == cpcb) + { + NSPOL_LOGERR("conn->pcb.tcp is null"); + break; + } + + do_tcpsock_setsockopt(cpcb->conn, smsg); + + break; + default: + SET_MSG_ERR(m, ERR_VAL); + NSPOL_LOGDBG(SOCKETS_DEBUG, "unsupported]level=%d", level); + break; + } /* switch (level) */ +} + +/*app send its version info to nStackMain */ +void do_app_touch(msg_app_touch * smsg) +{ + //write app version info to running.log + NSPOL_LOGINF(SOCKETS_DEBUG, "hostpid=%u,app_version=%s", smsg->hostpid, + smsg->app_version); +} + +void tcp_free_accept_ring(spl_netconn_t * conn) +{ + err_t de_err = ERR_OK; + spl_netconn_t *newconn; + while (1) + { + newconn = NULL; + /* -1 means nonblocking */ + de_err = accept_dequeue(conn, (void **) &newconn, (u32_t) - 1); + if (de_err == ERR_WOULDBLOCK || newconn == NULL) + return; + + tcp_drop_conn(newconn); + } +} + +void tcp_drop_conn(spl_netconn_t * conn) +{ + /* usually we should not access pcb by recv_obj, but no choice */ + struct tcp_pcb *pcb = (struct tcp_pcb *) conn->private_data; + + /* free conn first, even pcb is NULL */ + free_conn_by_spl(conn); + + if (pcb == NULL) + { + NSTCP_LOGWAR + ("a tcp connection in accept queue without pcb!]newconn=%p", + conn); + return; + } + + /* tell peer conneciton is reset */ + NSTCP_LOGWAR("sending RST in accept waiting queue!]pcb=%p", pcb); + + tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip, + pcb->local_port, pcb->remote_port); + + tcp_pcb_remove(&tcp_active_pcbs, pcb); + memp_free(MEMP_TCP_PCB, pcb); +} + +void update_tcp_state(spl_netconn_t * conn, enum tcp_state state) +{ + spl_tcp_state_t spl_state; + + if (conn != NULL) + { + switch (state) + { + case CLOSED: + spl_state = SPL_CLOSED; + break; + case LISTEN: + spl_state = SPL_LISTEN; + break; + case SYN_SENT: + spl_state = SPL_SYN_SENT; + break; + case SYN_RCVD: + spl_state = SPL_SYN_RCVD; + break; + case ESTABLISHED: + spl_state = SPL_ESTABLISHED; + break; + case FIN_WAIT_1: + spl_state = SPL_FIN_WAIT_1; + break; + case FIN_WAIT_2: + spl_state = SPL_FIN_WAIT_2; + break; + case CLOSE_WAIT: + spl_state = SPL_CLOSE_WAIT; + break; + case CLOSING: + spl_state = SPL_CLOSING; + break; + case LAST_ACK: + spl_state = SPL_LAST_ACK; + break; + case TIME_WAIT: + spl_state = SPL_TIME_WAIT; + break; + default: + spl_state = SPL_CLOSED; + break; + } + if (conn->tcp_state != spl_state) + { + conn->tcp_state = spl_state; + NSTCP_LOGINF("conn=%p,private_data=%p,state=%d", conn, + conn->private_data, spl_state); + } + } +} + +void do_update_pcbstate() +{ + struct tcp_pcb *tpcb; + int i; + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) + { + for (tpcb = *tcp_pcb_lists[i]; tpcb != NULL; tpcb = tpcb->next) + { + if (tpcb->callback_arg) + { + update_tcp_state((spl_netconn_t *) tpcb->callback_arg, + tpcb->state); + } + } + } + + return; +} + +void init_stackx_lwip() +{ + lwip_init(); + sys_timeouts_init(); + return; +} + +void free_common_pcb(struct common_pcb *cpcb) +{ + if (res_free(&cpcb->res_chk)) + { + NSFW_LOGERR("conn refree!]conn=%p", cpcb->conn); + return; + } + + common_pcb_reset(cpcb); + + mring_handle pool = p_def_stack_instance->cpcb_seg; + if (nsfw_mem_ring_enqueue(pool, (void *) cpcb) != 1) + { + NSSBR_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + } + return; +} + +struct common_pcb *alloc_common_pcb(enum spl_netconn_type type) +{ + struct common_pcb *cpcb = NULL; + + if (nsfw_mem_ring_dequeue(p_def_stack_instance->cpcb_seg, (void **) &cpcb) + != 1) + { + NSSBR_LOGERR("malloc conn failed"); + return NULL; + } + + NSFW_LOGINF("alloc_common_pcb]cpcb=%p", cpcb); + + common_pcb_init(cpcb); + cpcb->type = type; + + res_alloc(&cpcb->res_chk); + return cpcb; +} diff --git a/stacks/lwip_stack/lwip_src/api/spl_netbuf.c b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c new file mode 100644 index 0000000..602e48d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c @@ -0,0 +1,57 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +//#include "sc_dpdk.h" +#include "spl_netbuf.h" + +void spl_netbuf_delete(struct spl_netbuf *buf) +{ + if (likely(buf != NULL)) + { + spl_pbuf_free(PTR_SHTOL(struct spl_pbuf *, buf->p)); + } +} diff --git a/stacks/lwip_stack/lwip_src/api/spl_netifapi.c b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c new file mode 100644 index 0000000..82ac27b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c @@ -0,0 +1,279 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" + +#if STACKX_NETIF_API + +#include "nsfw_msg_api.h" +#include "netifapi.h" +#include +//#include + +#include "stackx_spl_share.h" +#include "spl_sbr.h" +#include "stackx/spl_api.h" +#include "tcpip.h" +#include "sc_dpdk.h" +#include "spl_instance.h" +#include "spl_hal.h" +#include "spl_def.h" +#include + +struct netifExt *gNetifExt = NULL; + +/** + * common operation for sbr message. + * + * @param msg the api_msg_msg describing the connection type + */ +int do_halmsg(data_com_msg * m) +{ + NSPOL_LOGDBG(TESTSOCKET_DEBUG | STACKX_DBG_TRACE, + "the msg is from HAL module, minor(%u)", + m->param.minor_type); + return 0; +} + +static int _do_add_netif(data_com_msg * m) +{ + NSPOL_LOGINF(NETIF_DEBUG, "_do_add_netif\n"); + + m->param.err = ERR_OK; + msg_add_netif *_m = (msg_add_netif *) m->buffer; + _m->function(_m); + SYNC_MSG_ACK(m); + return 0; +} + +struct netif *find_netif_by_if_name(char *if_name) +{ + + struct netifExt *netifEx = gNetifExt; + struct netif *netif = NULL; + + while (netifEx != NULL) + { + if (!(strcmp(netifEx->if_name, if_name))) + { + for (netif = netif_list; netif != NULL; netif = netif->next) + { + if (netifEx->id == netif->num) + return netif; + } + + } + netifEx = netifEx->next; + } + + return NULL; +} + +/*@TODO: May be moved to some other file ? Like HAL*/ +struct netif *get_netif_by_ip(unsigned int ip) +{ + struct netif *netif; + + if (ip == 0) + { + return NULL; + } + + for (netif = netif_list; netif != NULL; netif = netif->next) + { + if (ip == netif->ip_addr.addr) + { + NSPOL_LOGINF(NETIF_DEBUG, "netif_find: found %x %c %c", ip, + netif->name[0], netif->name[1]); + return netif; + } + } + NSPOL_LOGINF(NETIF_DEBUG, "netif_find: Not found %x", ip); + return NULL; +} + +/* +@TODO: +*/ +struct netif *netif_check_broadcast_addr(spl_ip_addr_t * addr) +{ + return NULL; +} + +struct netifExt *getNetifExt(u16_t id) +{ + + struct netifExt *netifEx; + netifEx = gNetifExt; + + while (netifEx != NULL) + { + if (netifEx->id == id) + { + return netifEx; + } + netifEx = netifEx->next; + } + + return NULL; +} + +int netifExt_add(struct netif *netif) +{ + + /* If Netif Ext already created for it then just return sucess */ + if (getNetifExt(netif->num)) + return 0; + + struct netifExt *netifEx = malloc(sizeof(struct netifExt)); + if (!netifEx) + { + return -1; + } + + if (memset(netifEx, 0, sizeof(struct netifExt)) < 0) + { + return -1; + } + + NSPOL_LOGINF(NETIF_DEBUG, "netifExt_added \n"); + + netifEx->id = netif->num; + + /* add this netif to the list */ + netifEx->next = gNetifExt; + gNetifExt = netifEx; + return 0; +} + +void do_netifapi_netif_add(msg_add_netif * pmsg) +{ + struct netif *netif = NULL; + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gw; + + data_com_msg *m = MSG_ENTRY(pmsg, data_com_msg, buffer); + ipaddr.addr = pmsg->ipaddr->addr; + netmask.addr = pmsg->netmask->addr; + gw.addr = pmsg->gw->addr; + + NSPOL_LOGINF(NETIF_DEBUG, "do_netifapi_netif_add \n"); + netif = netif_add(pmsg->netif, + &ipaddr, + &netmask, &gw, pmsg->state, pmsg->init, pmsg->input); + + if (NULL == netif) + { + SET_MSG_ERR(m, ERR_IF); + } + else + { + + SET_MSG_ERR(m, ERR_OK); + NSPOL_LOGINF(NETIF_DEBUG, "netif created name %c%c%d\n", + netif->name[0], netif->name[1], netif->num); + pmsg->voidfunc(pmsg->netif); + add_disp_netif(pmsg->netif); + } + +} + +err_t +spl_netifapi_netif_add(struct netif *pnetif, + spl_ip_addr_t * ipaddr, + spl_ip_addr_t * netmask, + spl_ip_addr_t * gw, + void *state, + netif_init_fn init, + netif_input_fn input, netifapi_void_fn voidfunc) +{ + msg_add_netif stmsg; + + stmsg.function = do_netifapi_netif_add; + stmsg.netif = pnetif; + stmsg.ipaddr = ipaddr; + stmsg.netmask = netmask; + stmsg.gw = gw; + stmsg.state = state; + stmsg.init = init; + stmsg.input = input; + stmsg.voidfunc = voidfunc; + return tcpip_netif_add(&stmsg); +} + +int add_netif_ip(char *netif_name, unsigned int ip, unsigned int mask) +{ + struct netif *pnetif; + int retval; + + if (get_netif_by_ip(ip)) + { + NSPOL_LOGERR("ip is exist]IP=%s", inet_ntoa(ip)); + return -1; + } + NSPOL_LOGINF(NETIF_DEBUG, "add_netif_ip] IP=%s", inet_ntoa(ip)); + + pnetif = find_netif_by_if_name(netif_name); + if (pnetif == NULL) + { + return -1; + } + + pnetif->ip_addr.addr = ip; + pnetif->netmask.addr = mask; + + if (ip) + { + retval = etharp_request(pnetif, &pnetif->ip_addr); + + if (ERR_OK != retval) + { + NSPOL_LOGERR("etharp_request failed]retval=%d,netif=%p,ip=%u", retval, pnetif, pnetif->ip_addr.addr); //inet_ntoa is not thread-safe, print u32 instead. + } + } + + NSPOL_LOGINF(NETIF_DEBUG, "add_netif_ip]netif_name=%s,IP=%s,mask=0x%08x", + netif_name, inet_ntoa(ip), spl_htonl(mask)); + return 0; +} + +/*lint -e438*/ +int del_netif_ip(char *netif_name, unsigned int ip) +{ + struct netif *pnetif; + //struct netif* vnetif = NULL; + //struct netif** ref; + + pnetif = find_netif_by_if_name(netif_name); + if (NULL == pnetif) + { + return -1; + } + + NSPOL_LOGINF(NETIF_DEBUG, "del_netif_ip] IP=%s", inet_ntoa(ip)); + + pnetif->ip_addr.addr = 0; + pnetif->netmask.addr = 0; + return 0; +} + +REGIST_MSG_MODULE_MAJOR_FUN(MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI, + do_halmsg); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI, + NETIF_DO_ADD, _do_add_netif); + +#endif /* STACKX_NETIF_API */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_sbr.c b/stacks/lwip_stack/lwip_src/api/spl_sbr.c new file mode 100644 index 0000000..58c25a1 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_sbr.c @@ -0,0 +1,477 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_spl_share.h" +#include "spl_api.h" +#include "ip.h" +#include "spl_api_msg.h" +#include "stackx_spl_msg.h" +#include "internal_msg.h" +#include "spl_sbr.h" +#include "spl_pbuf.h" + +/** + * common operation for sbr message. + * + * @param msg the api_msg_msg describing the connection type + */ +int do_sbrmsg(data_com_msg * m) +{ + return 0; +} + +/** + * Create a new pcb of a specific type inside a netconn. + * Called from netconn_new_with_proto_and_callback. + * + * @param msg the api_msg_msg describing the connection type + */ +static int _do_newconn(data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_new_netconn *_m = (msg_new_netconn *) m->buffer; + m->param.err = spl_pcb_new(_m); + + if (ERR_OK != m->param.err) + { + NSPOL_LOGERR("pcb_new err]conn=%p,pid=%u,err=%d", _m->conn, + m->param.recycle_pid, m->param.err); + goto ERROR; + } + + NSFW_LOGINF("alloc pcb]conn=%p,pcb=%p,pid=%u", _m->conn, + _m->conn->private_data, m->param.recycle_pid); + + /* sbr use it to set receiver after new connction */ + m->param.receiver = (i64) & _m->conn->private_data; + m->param.comm_receiver = (i64) & _m->conn->comm_pcb_data; + _m->conn->recv_obj = m->param.receiver; + + SYNC_MSG_ACK(m); + return 0; + + ERROR: + SYNC_MSG_ACK(m); + return 0; +} + +int _do_connect(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + m->param.err = ERR_CLSD; + SYNC_MSG_ACK(m); + return 0; + } + + msg_connect *_m = (msg_connect *) m->buffer; + do_connect(cpcb, _m); + + /** + * err == ERR_OK only applies for blocking connction, so others mean + * in progress for nonblocking connection or failed to connect + * cpcb may be NULL, so don't change the order of the 2 ifs. + */ + if (m->param.err != ERR_OK || cpcb->type != SPL_NETCONN_TCP) + SYNC_MSG_ACK(m); + + return 0; +} + +/** + * Close a TCP pcb contained in a netconn + * Called from netconn_close + * + * @param msg the api_msg_msg pointing to the connection + */ +int _do_close(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb != NULL) + { + msg_close *_m = (msg_close *) m->buffer; + do_close(cpcb, _m); + } + + /* if cpcb == NULL, assuming the close is okay, err = ERR_OK */ + SYNC_MSG_ACK(m); + + return 0; +} + +/** + * Delete the pcb inside a netconn. + * Called from netconn_delete. + * + * @param msg the data_com_msg to handle + */ +static int _do_delconn(data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_delete_netconn *_m = (msg_delete_netconn *) m->buffer; + + if (0 == (--_m->msg_box_ref)) + { + /* the aync msg is released inside */ + ss_recycle_conn((void *) _m, do_try_delconn); + } + + return 0; +} + +/** + * handle message to send UDP packets. + * + * @param msg the data_com_msg to handle + */ +static int _do_send(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + msg_send_buf *_m = (msg_send_buf *) m->buffer; + if (cpcb == NULL) + { + NS_LOG_CTRL(LOG_CTRL_SEND, STACKPOOL, "NSLWIP", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free(_m->p); + _m->p = NULL; + ASYNC_MSG_FREE(m); + return -1; + } + + do_send(cpcb, _m); + + ASYNC_MSG_FREE(m); + + return 0; +} + +/** + * handle message to send TCP packets. + * + * @param msg the data_com_msg to handle + */ +static int _do_write(data_com_msg * m) +{ + m->param.err = ERR_OK; + + void *tpcb = TCP_PRIVATE_PTR(m); + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + + msg_write_buf *_m = (msg_write_buf *) m->buffer; + if ((tpcb == NULL) || (cpcb == NULL)) + { + NS_LOG_CTRL(LOG_CTRL_WRITE, STACKPOOL, "NSLWIP", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free(_m->p); + _m->p = NULL; + ASYNC_MSG_FREE(m); + return -1; + } + + do_write(cpcb, _m); + + return 0; +} + +/** + * handle message to receive. + * + * @param msg the data_com_msg to handle + */ +static int _do_recv(data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_recv_buf *_m = (msg_recv_buf *) m->buffer; + void *tpcb = TCP_PRIVATE_PTR(m); + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + + if ((tpcb == NULL) || (cpcb == NULL)) + { + NS_LOG_CTRL(LOG_CTRL_RECV, STACKPOOL, "NSLWIP", NSLOG_ERR, + "failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + spl_pbuf_free(_m->p); + _m->p = NULL; + ASYNC_MSG_FREE(m); + return -1; + } + + do_recv(cpcb, _m); + ASYNC_MSG_FREE(m); + return 0; +} + +/** + * handle message to bind local address. + * + * @param msg the data_com_msg to handle + */ +static int _do_bind(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + NSPOL_LOGERR("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK(m); + return -1; + } + + msg_bind *_m = (msg_bind *) m->buffer; + do_bind(cpcb, _m); + + SYNC_MSG_ACK(m); + + return 0; +} + +/** + * handle message to listen for new connection. + * + * @param msg the data_com_msg to handle + */ +static int _do_listen(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + NSPOL_LOGERR("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_CONN; + SYNC_MSG_ACK(m); + return -1; + } + + msg_listen *_m = (msg_listen *) m->buffer; + do_listen(cpcb, _m); + + /* Update since pcb may have been changed */ + //m->param.receiver = (i64)&_m->conn->private_data; + SYNC_MSG_ACK(m); + return 0; +} + +/** + * handle message to set socket option. + * + * @param msg the data_com_msg to handle + */ +static int _do_setsockopt(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + + NSPOL_LOGERR("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK(m); + return -1; + } + + msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer; + do_setsockopt_internal(cpcb, _m); + + SYNC_MSG_ACK(m); + + return 0; +} + +/** + * handle message to get socket option. + * + * @param msg the data_com_msg to handle + */ +static int _do_getsockopt(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + NSPOL_LOGERR("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK(m); + return -1; + } + + msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer; + do_getsockopt_internal(cpcb, _m); + + SYNC_MSG_ACK(m); + + return 0; +} + +/** + * handle message to free pbuf which never used afterwards by application. + * + * @param msg the data_com_msg to handle + */ + +static int _do_pbuf_free(data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_free_buf *_m = (msg_free_buf *) m->buffer; + do_pbuf_free(_m->buf); + + ASYNC_MSG_FREE(m); + + return 0; +} + +static int _do_getsock_name(data_com_msg * m) +{ + m->param.err = ERR_OK; + + struct common_pcb *cpcb = COMM_PRIVATE_PTR(m); + if (cpcb == NULL) + { + NSPOL_LOGERR("failed to find target pcb, drop the message]" + "module=%u, major=%u, minor=%u", + m->param.module_type, + m->param.major_type, m->param.minor_type); + + m->param.err = ERR_VAL; + SYNC_MSG_ACK(m); + return -1; + } + + msg_getaddrname *_m = (msg_getaddrname *) m->buffer; + do_getsockname(cpcb, _m); + + SYNC_MSG_ACK(m); + + return 0; +} + +/* app send its version info to nStackMain */ +static int _do_app_touch(data_com_msg * m) +{ + m->param.err = ERR_OK; + + msg_app_touch *_m = (msg_app_touch *) m->buffer; + do_app_touch(_m); + + ASYNC_MSG_FREE(m); + return 0; +} + +/** + * process message from sbr module, all the processing function + * is registered when nstack is up. + * + * @param msg the api_msg_msg pointing to the connection + */ +int spl_sbr_process(data_com_msg * m) +{ + if (m == NULL) + { + NSPOL_LOGERR("message is NULL"); + return -1; + } + + return call_msg_fun(m); +} + +int spl_unsupport_process(data_com_msg * m) +{ + NSPOL_LOGINF(TCPIP_DEBUG, "module_type=%u,major_type=%u,minor_type=%u", + m->param.module_type, m->param.major_type, + m->param.minor_type); + if (MSG_SYN_POST == m->param.op_type) + { + m->param.err = ERR_EPROTONOSUPPORT; + SYNC_MSG_ACK(m); + } + else + { + ASYNC_MSG_FREE(m); + } + + return -1; +} + +REGIST_MSG_UNSUPPORT_FUN(spl_unsupport_process); +REGIST_MSG_MODULE_MAJOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, do_sbrmsg); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_NEWCONN, _do_newconn); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_CONNECT, _do_connect); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_CLOSE, _do_close); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_DELCON, _do_delconn); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_SEND, _do_send); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_WRITE, _do_write); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_RECV, _do_recv); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_BIND, _do_bind); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_LISTEN, _do_listen); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_GET_SOCK_OPT, _do_getsockopt); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_SET_SOCK_OPT, _do_setsockopt); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_PBUF_FREE, _do_pbuf_free); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, + SPL_API_DO_GETSOCK_NAME, _do_getsock_name); +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_APP_TOUCH, _do_app_touch); /* app send its version info to nStackMain */ diff --git a/stacks/lwip_stack/lwip_src/api/spl_tcpip.c b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c new file mode 100644 index 0000000..f3f0e70 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c @@ -0,0 +1,1531 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" +#include +#include +#include +#include "memp.h" +#include "mem.h" +#include "spl_pbuf.h" +//#include "sockets.h" +//#include + +#include "stackx_spl_share.h" +#include "spl_api.h" +#include "spl_tcpip.h" +#include "init.h" +#include "stackx/internal_msg.h" +#include "netif/sc_dpdk.h" +#include "sharedmemory.h" +#include "stackx_instance.h" +#include "netif/common.h" +//#include "nettool/nettool.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "spl_sbr.h" +#include "spl_tcpip.h" + +#include "spl_instance.h" +#include "nsfw_mem_api.h" +#include "nsfw_msg_api.h" +#include "configuration_reader.h" + +#include "nsfw_ps_api.h" +#include "alarm_api.h" +#include "nstack_share_res.h" +#include "spl_timers.h" + +#include "etharp.h" +#include "raw.h" +#include "udp.h" +#include "tcp.h" +#include "igmp.h" +#include "memp.h" +#include "inet.h" +#include "sys_arch.h" + +#include "sys.h" + +#define NSTACK_MAIN_MAX_PARA 32 +#define NSTACK_MAIN_MIN_PARA 1 + +#define DPDK_DEFAULT_EAL_MEM_SIZE (1024) + +#define OPT_EAL_MEM_SIZE "--eal-mem-size=" + +/********************/ +/* extern variables */ +/********************/ +extern mring_handle spl_get_msg_pool(); +extern mring_handle spl_get_conn_pool(); +extern u32 spl_get_conn_num(); +extern err_t ethernet_input(struct pbuf *p, struct netif *netif); +extern int nstack_epoll_init(int flag, int ns_sync_mod); + +/* tcpip main thread sleep time, configured by user(nStackMain "-sleep" option) */ +extern int g_tcpip_thread_sleep_time; + +/* netif related */ +extern struct stackx_port_info *head_used_port_list; + +extern u32_t uStackArgIndex; + +extern int g_tcpip_thread_stat; + +/********************/ +/* global variables */ +/********************/ + +/* timer thread id */ +sys_thread_t g_timerThread_id = 0; + +/*Add an associative mapping relationship to p_stackx_instance based on lcore_id */ + +int globalArgc = 0; + +/* Set different mem args to PAL and EAL */ +char **gArgv = NULL; + +int g_dpdk_argc = 0; +char **g_dpdk_argv = NULL; + +/*The sum of the four queue processing messages does not exceed TASK_BURST*/ +static u32 g_highestMboxNum = 12; +static u32 g_mediumMboxNum = 8; +static u32 g_lowestMboxNum = 4; +static u32 g_primaryMboxNum = 8; + +/* [set ip_tos2prio size to IPTOS_TOS_MASK >> 1) + 1] */ +u8_t ip_tos2prio[(IPTOS_TOS_MASK >> 1) + 1] = { + TC_PRIO_BESTEFFORT, + ECN_OR_COST(FILLER), + TC_PRIO_BESTEFFORT, + ECN_OR_COST(BESTEFFORT), + TC_PRIO_BULK, + ECN_OR_COST(BULK), + TC_PRIO_BULK, + ECN_OR_COST(BULK), + TC_PRIO_INTERACTIVE, + ECN_OR_COST(INTERACTIVE), + TC_PRIO_INTERACTIVE, + ECN_OR_COST(INTERACTIVE), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST(INTERACTIVE_BULK), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST(INTERACTIVE_BULK) +}; + +/********************/ +/* extern functions */ +/********************/ +extern err_t ethernetif_init(struct netif *pnetif); +extern int nstack_stackx_init(int flag); +extern void tcp_sys_rmem_init(); +extern void ethernetif_packets_input(struct netif *pstnetif); + +/********************************/ +/* function forward declaration */ +/********************************/ + +static inline u32 priority_sched_mbox(struct stackx_stack *share_memory, + void **box, u32 n); +static inline char rt_tos2priority(u8_t tos) +{ + return ip_tos2prio[IPTOS_TOS(tos) >> 1]; +} + +u64 timer_get_threadid() +{ + return g_timerThread_id; +} + +#if (DPDK_MODULE != 1) +NSTACK_STATIC inline void +do_recv_task(struct disp_netif_list *dnlist, u16 index_task) +{ + struct netifExt *pnetifExt = NULL; + + while (dnlist) + { + struct netif *currentNetif = dnlist->netif; + dnlist = dnlist->next; + + pnetifExt = getNetifExt(currentNetif->num); + if (NULL == pnetifExt) + return; + + if (currentNetif != NULL && pnetifExt->num_packets_recv > index_task) + { + ethernetif_packets_input(currentNetif); + } + } +} + +static inline int is_valid_sleep_time(int sleep_time) +{ +#define TCP_IP_THREAD_MAX_SLEEP_TIME 500 + if ((sleep_time < 0) || (sleep_time > TCP_IP_THREAD_MAX_SLEEP_TIME)) + { + return 0; + } + + return 1; +} + +static int thread_init() +{ + sigset_t mask; + + if (0 != sigemptyset(&mask)) + { + NSTCP_LOGERR("sigemptyset function call error"); + return -1; + } + + if (0 != sigaddset(&mask, SIGRTMIN)) + { + NSTCP_LOGERR("sigaddset function call error"); + return -1; + } + + if ((pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + || (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)) + { + NSTCP_LOGERR("pthread setcancel function call error"); + return -1; + } + + if (pthread_sigmask(SIG_BLOCK, &mask, NULL) != 0) + { + NSPOL_LOGERR("pthread_sigmask function call error"); + return -1; + } + + return 0; +} + +alarm_result spl_socket_resource_check_func(void) +{ + + mring_handle conn_ring = spl_get_conn_pool(); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + u32 socket_num = spl_get_conn_num(); + + ring_size = nsfw_mem_ring_size(conn_ring); + + if (0 == socket_num) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count(conn_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / socket_num; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + NSPOL_LOGWAR(TCPIP_DEBUG, + "app using too much socket resources,the rate is bigger than 80%"); + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_SOCKET; + + return ret_alarm; + +} + +alarm_result spl_msg_buf_resource_check_func(void) +{ + + mring_handle msg_ring = spl_get_msg_pool(); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + + ring_size = nsfw_mem_ring_size(msg_ring); + + if (0 == ring_size) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count(msg_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / ring_size; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_MSG_BUF; + + return ret_alarm; + +} + +NSTACK_STATIC int tcpip_thread_init() +{ + if (thread_init() != 0) + { + return -1; + } + + if (!is_valid_sleep_time(g_tcpip_thread_sleep_time)) + { + g_tcpip_thread_sleep_time = 0; + } + + alarm_para tcp_alarm_para; + tcp_alarm_para.period_alarm.time_length = 5; /* 5 second period */ + tcp_alarm_para.alarm_reason_count = 2; /*both resource */ + tcp_alarm_para.func_alarm_check_period[0] = + spl_socket_resource_check_func; + tcp_alarm_para.alarm_reason_set[0] = ALARM_REASON_SOCKET; + tcp_alarm_para.func_alarm_check_period[1] = + spl_msg_buf_resource_check_func; + tcp_alarm_para.alarm_reason_set[1] = ALARM_REASON_MSG_BUF; + (void) ns_reg_alarm(ALARM_EVENT_NSTACK_RESOURCE_ALARM, ALARM_PERIOD_CHECK, + &tcp_alarm_para); + + ns_send_init_alarm(ALARM_EVENT_NSTACK_RESOURCE_ALARM); + + printmeminfo(); + return 0; +} + +sys_mbox_t get_primary_box() +{ + return &p_def_stack_instance->lstack.primary_mbox; +} + +NSTACK_STATIC inline u16 tcpip_netif_recv(struct disp_netif_list * nif_list) +{ + + u16 num_recv_task = 0, netif_packet_num; + + struct netif *tmpnetif = NULL; + struct netifExt *pnetifExt = NULL; + + while (nif_list) + { + tmpnetif = nif_list->netif; + + netif_packet_num = spl_hal_recv(tmpnetif, 0); + pnetifExt = getNetifExt(tmpnetif->num); + if (NULL == pnetifExt) + return 0; + + /* store the packet number in each netif */ + pnetifExt->num_packets_recv = netif_packet_num; + + /** + * num_recv_task is the maximum packets of the netif among + * all the netifs. + */ + if (num_recv_task < netif_packet_num) + { + num_recv_task = netif_packet_num; + } + + nif_list = nif_list->next; + } + + return num_recv_task; +} + +NSTACK_STATIC inline void no_task_in_one_loop() +{ +} + +#endif + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * SPL_NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t spl_tcpip_input(struct pbuf *p, struct netif *inp) +{ + err_t ret; + NSPOL_LOGINF(TCPIP_DEBUG, "PACKET]p=%p,inp=%p", (void *) p, (void *) inp); + print_pbuf_payload_info(p, false); + + /* every netif has been set NETIF_FLAG_ETHARP flag, no need else branch */ + ret = ethernet_input(p, inp); + return ret; +} + +int _do_spl_callback_msg(data_com_msg * m) +{ + NSPOL_LOGDBG(TCPIP_DEBUG, "tcpip_thread: CALLBACK]msg=%p", (void *) m); + + m->param.err = ERR_OK; + + msg_internal_callback *callback = (msg_internal_callback *) (m->buffer); + if (!callback->function) + { + NSTCP_LOGERR("function ptr is null in SPL_TCPIP_MSG_CALLBACK msg"); + ASYNC_MSG_FREE(m); + return 0; + } + + callback->function(callback->ctx); + ASYNC_MSG_FREE(m); + + return 0; +} + +/***************************************************************************** +* Prototype : get_msgbox +* Description : According to the socket tos value to determine which priority queue to send +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +struct queue *get_msgbox(int tos) +{ + struct stackx_stack *sharedmemory = &p_def_stack_instance->lstack; + + if ((MSG_PRIO_QUEUE_NUM < 3) || (0 == tos)) + { + return &sharedmemory->primary_mbox; + } + + char prio = rt_tos2priority((u8_t) tos); + if ((TC_PRIO_INTERACTIVE == prio)) + { + NSPOL_LOGDBG(SOCKETS_DEBUG, "sent to the highest mbox....."); + return &sharedmemory->priority_mbox[0]; + } + else if ((TC_PRIO_BESTEFFORT == prio) + || (TC_PRIO_INTERACTIVE_BULK == prio)) + { + NSPOL_LOGDBG(SOCKETS_DEBUG, "sent to the medium mbox....."); + return &sharedmemory->priority_mbox[1]; + } + else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio)) + { + NSPOL_LOGDBG(SOCKETS_DEBUG, "sent to the lowest mbox....."); + return &sharedmemory->priority_mbox[2]; + } + + NSPOL_LOGDBG(SOCKETS_DEBUG, "sent to the primary mbox....."); + return &sharedmemory->primary_mbox; +} + +/***************************************************************************** +* Prototype : priority_sched_mbox +* Description : According to the priority from the message queue to take +* the message to deal with each cycle to take the total number of messages +* not exceed to TASK_BURST +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +static inline u32 +priority_sched_mbox(struct stackx_stack *share_memory, void **box, u32 n) +{ + /* high:primary:medium:low -> 3:2:2:1(total:TASK_BURST) */ + if (unlikely + ((g_highestMboxNum + g_mediumMboxNum + g_primaryMboxNum + + g_lowestMboxNum) != n)) + { + g_mediumMboxNum = n >> 2; + g_lowestMboxNum = n >> 3; + g_primaryMboxNum = n >> 2; + g_highestMboxNum = + n - g_mediumMboxNum - g_primaryMboxNum - g_lowestMboxNum; + } + + u32 highestMboxNum = g_highestMboxNum; + u32 primaryMboxNum = g_primaryMboxNum; + u32 lowestMboxNum = g_lowestMboxNum; + u32 mediumMboxNum = g_mediumMboxNum; + + u32 totalNum = 0; + u32 num = 0; + u32 oldLowestNum = 0; + + num = nsfw_mem_ring_dequeuev(share_memory->priority_mbox[0].llring, + (box + totalNum), highestMboxNum); + if (unlikely(num > highestMboxNum)) + { + num = highestMboxNum; + NSTCP_LOGERR + ("something wrong:num>highestMboxNum]num=%u,highestMboxNum=%u", + num, highestMboxNum); + } + + totalNum += num; + + u32 temp = highestMboxNum - num; + /* bisect the left number of highest */ + primaryMboxNum += (temp >> 1); + mediumMboxNum += temp - (temp >> 1); + + num = nsfw_mem_ring_dequeuev(share_memory->priority_mbox[1].llring, + (box + totalNum), mediumMboxNum); + if (unlikely(num > mediumMboxNum)) + { + num = mediumMboxNum; + NSTCP_LOGERR + ("something wrong.num>mediumMboxNum]num=%u,mediumMboxNum=%u", num, + mediumMboxNum); + } + + totalNum += num; + primaryMboxNum += mediumMboxNum - num; //occupy the left number of medium + + /* dynamically adjust g_mediumMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_mediumMboxNum; + if (0 == num) + { + g_mediumMboxNum = 1; + } + else if (num < g_mediumMboxNum) + { + g_mediumMboxNum = num; + } + else + { + g_mediumMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_mediumMboxNum; + + num = nsfw_mem_ring_dequeuev(share_memory->primary_mbox.llring, + (box + totalNum), primaryMboxNum); + if (unlikely(num > primaryMboxNum)) + { + num = primaryMboxNum; + NSTCP_LOGERR + ("something wrong.num>primaryMboxNum]num=%u,primaryMboxNum=%u", + num, primaryMboxNum); + } + + totalNum += num; + lowestMboxNum += primaryMboxNum - num; //occupy the left number of primary + + /* dynamically adjust g_primaryMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_primaryMboxNum; + if (0 == num) + { + g_primaryMboxNum = 1; + } + else if (num < g_primaryMboxNum) + { + g_primaryMboxNum = num; + } + else + { + g_primaryMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_primaryMboxNum; + + if (lowestMboxNum > (n - totalNum)) + { + lowestMboxNum = n - totalNum; + } + + num = nsfw_mem_ring_dequeuev(share_memory->priority_mbox[2].llring, + (box + totalNum), lowestMboxNum); + if (unlikely(num > lowestMboxNum)) + { + num = lowestMboxNum; + NSTCP_LOGERR + ("something wrong.num>lowestMboxNum]num=%u,lowestMboxNum=%u", num, + lowestMboxNum); + } + + totalNum += num; + + /* dynamically adjust g_lowestMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_lowestMboxNum; + if (0 == num) + { + g_lowestMboxNum = 1; + } + else if (num < g_lowestMboxNum) + { + g_lowestMboxNum = num; + } + else + { + g_lowestMboxNum = n >> 3; + } + + g_highestMboxNum += oldLowestNum - g_lowestMboxNum; + + return totalNum; +} + +/** + * call ltt_apimsg in STACKX TIMER THREAD + * + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return error code given back by the function that was called + */ +err_t ltt_apimsg(sys_timeout_handler h, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box(); + if (sys_mbox_valid(&mbox)) + { + if (-1 == spl_msg_malloc(&p_msg_entry)) + { + NSPOL_LOGERR("ltt_apimsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_TIMEOUT; + p_msg_entry->param.op_type = MSG_ASYN_POST; + + sys_sem_init(&p_msg_entry->param.op_completed); + + msg_timer *tmsg = (msg_timer *) (p_msg_entry->buffer); + tmsg->act = h; + tmsg->arg = arg; + + if (msg_post(p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, + p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free(p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR("mbox is invalid"); + return ERR_VAL; +} + +int _do_spl_timer_msg(data_com_msg * m) +{ + NSPOL_LOGDBG(TESTSOCKET_DEBUG | STACKX_DBG_TRACE, + "the msg is from TIMER module, minor(%u)", + m->param.minor_type); + return 0; +} + +static int _do_timeout_handle(data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_timer *tmo_msg = (msg_timer *) m->buffer; + if (!tmo_msg->act) + { + NSTCP_LOGERR("TIMER_MSG_TIMEOUT msg act is NULL"); + ASYNC_MSG_FREE(m); + return -1; + } + + timeout_phandler(tmo_msg->act, tmo_msg->arg); + ASYNC_MSG_FREE(m); + return 0; +} + +static int _do_clear_timer(data_com_msg * m) +{ + NSTCP_LOGDBG("TIMER_CLEAR API]msg=%p", (void *) m); + + msg_timer *handle = (msg_timer *) (m->buffer); + if (!handle->act) + { + NSTCP_LOGERR("function ptr is null in TIMER_MSG_CLEAR msg"); + SET_MSG_ERR(m, ERR_VAL); + return 0; + } + + //stackxTcpPcbClearTimer((struct tcp_pcb *)handle->act, (unsigned long)handle->arg); + spl_msg_free(m); + + return 0; +} + +err_t ltt_clearTmrmsg(void *pcb, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box(); + if (sys_mbox_valid(&mbox)) + { + if (-1 == spl_msg_malloc(&p_msg_entry) || (NULL == p_msg_entry)) + { + NSPOL_LOGERR("ltt_clearTmrmsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_CLEAR; + p_msg_entry->param.op_type = MSG_ASYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init(&p_msg_entry->param.op_completed); + + msg_timer *tmo = (msg_timer *) (p_msg_entry->buffer); + tmo->act = pcb; + tmo->arg = arg; + + if (msg_post(p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, + p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free(p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR("mbox is invalid"); + return ERR_VAL; +} + +#if STACKX_NETIF_API +err_t tcpip_netif_post(data_com_msg * m) +{ + err_t err = ERR_OK; + sys_mbox_t mbox = get_primary_box(); + + if (NULL == mbox || !sys_mbox_valid(&mbox)) + { + NSPOL_LOGERR("mbox not initialed well"); + err = ERR_MEM; + goto err_exit; + } + + if (NULL == mbox->llring) + { + int tryCount = 0; +#define TCP_NETIF_WAITINIT_MAX_COUNT 10 + NSPOL_LOGWAR(TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns(0, 100000000); + while (!mbox->llring && (++tryCount < TCP_NETIF_WAITINIT_MAX_COUNT)) + { + NSPOL_LOGWAR(TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns(0, 100000000); + } + + if (NULL == mbox->llring) + { + NSPOL_LOGERR("failed to get a valid mbox->llring"); + err = ERR_MEM; + goto err_exit; + } + } + + NSPOL_LOGINF(TCPIP_DEBUG, "post tcpip_netif_msg..."); + + if (msg_post_with_lock_rel(m, mbox->llring) < 0) + { + err = ERR_VAL; + } + else + { + err = m->param.err; + } + + err_exit: + /* it's a sync message */ + spl_msg_free(m); + return err; +} + +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t tcpip_netif_add(msg_add_netif * tmp) +{ + data_com_msg *p_msg_entry = NULL; + msg_add_netif *nmsg = NULL; + + if (spl_msg_malloc(&p_msg_entry) == -1) + { + NSPOL_LOGERR("tcpip_netifapi:spl_msg_malloc failed."); + return ERR_MEM; + } + + p_msg_entry->param.module_type = MSG_MODULE_HAL; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_NETIFAPI; + p_msg_entry->param.minor_type = NETIF_DO_ADD; + p_msg_entry->param.op_type = MSG_SYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init(&p_msg_entry->param.op_completed); + + nmsg = (msg_add_netif *) p_msg_entry->buffer; + nmsg->function = tmp->function; + nmsg->netif = tmp->netif; + nmsg->ipaddr = tmp->ipaddr; + nmsg->netmask = tmp->netmask; + nmsg->gw = tmp->gw; + nmsg->state = tmp->state; + nmsg->init = tmp->init; + nmsg->input = tmp->input; + nmsg->voidfunc = tmp->voidfunc; + + return tcpip_netif_post(p_msg_entry); +} + +#endif /* STACKX_NETIF_API */ + +/* Added for congestion control, maybe not used end */ + +extern err_t init_ptimer(void); +extern struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM]; + +/*=========== set share config for nStackMain =============*/ +static inline mzone_handle create_mem_zone(nsfw_mem_zone * zone_info) +{ + return nsfw_mem_zone_create(zone_info); +} + +static inline int +set_zone_info(nsfw_mem_zone * zone_info, nsfw_mem_name * name_info, u32 len) +{ + if (EOK != + memcpy_s(&(zone_info->stname), sizeof(nsfw_mem_name), name_info, + sizeof(nsfw_mem_name))) + { + NSPOL_DUMP_LOGERR("create pool failed, MEMCPY_S failed."); + return -1; + } + + zone_info->lenth = len; + zone_info->isocket_id = NSFW_SOCKET_ANY; + + return 0; +} + +int set_share_config() +{ + static nsfw_mem_name g_cfg_mem_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG }; + + nsfw_mem_zone zone_info; + if (set_zone_info(&zone_info, &g_cfg_mem_info, get_cfg_share_mem_size()) < + 0) + { + return -1; + } + + mzone_handle base_cfg_mem = create_mem_zone(&zone_info); + if (NULL == base_cfg_mem) + { + NSPOL_LOGERR("get config share mem failed."); + return -1; + } + + if (set_share_cfg_to_mem(base_cfg_mem) < 0) + { + NSPOL_LOGERR("set share config failed."); + return -1; + } + + return 0; +} + +int init_by_tcpip_thread() +{ + if (spl_init_app_res() != 0) + { + NSPOL_LOGERR("spl_init_app_res failed"); + return -1; + } + + if (init_instance() != 0) + { + return -1; + } + if (tcpip_thread_init() != 0) + { + NSTCP_LOGERR("tcpip_thread_init failed!"); + return -1; + } + + init_stackx_lwip(); + + return 0; +} + +void spl_tcpip_thread(void *arg) +{ + g_tcpip_thread_stat = 1; + + if (init_by_tcpip_thread() != 0) + { + return; + } + + struct stackx_stack *share_memory = &p_def_stack_instance->lstack; + struct disp_netif_list **iflist = &p_def_stack_instance->netif_list; + + u32 run_count = 0; + u16 task_loop; + u16 num_recv_task = 0, num_send_timer_task = 0; + u16 index_task = 0; + //int tcpip_thread_sleep_interval = g_tcpip_thread_sleep_time * 1000; + void *task_queue[TASK_BURST]; + data_com_msg *msg; + + while (1) + { + /* try to receive packet from hal layer */ + num_recv_task = tcpip_netif_recv(*iflist); + + /* try to receive message from sbr layer */ + num_send_timer_task = priority_sched_mbox(share_memory, + task_queue, TASK_BURST); + + if (num_recv_task) + { + NSPOL_LOGINF(TCPIP_DEBUG, "num_recv_task %d", num_recv_task); + } + + /* Statistics the total number of messages */ + + /* Separate statistics on socket api messages */ + /* handle the request from upper layer and lower layer one by one */ + task_loop = (num_send_timer_task > num_recv_task ? + num_send_timer_task : num_recv_task); + if (task_loop == 0) + { + no_task_in_one_loop(); + + if (run_count++ > 20) + { + //sys_sleep_ns (0, tcpip_thread_sleep_interval); + } + continue; + } + + run_count = 0; + index_task = 0; + + /* at least one task to be handled */ + while (task_loop > index_task) + { + /* handle one packet from hal layer (for multi-nic case, do it for each) */ + if (num_recv_task > index_task) + { + do_recv_task(*iflist, index_task); + } + + /* handle one message from sbr layer */ + if (num_send_timer_task > index_task) + { + msg = (data_com_msg *) (task_queue[index_task]); + + spl_process(msg); + } + + do_update_pcbstate(); + + index_task++; + } + } +} + +int create_tcpip_thread() +{ + int ret; + u64 arg = 0; + + /* main tcpip thread */ + char thread_name[32] = TCPIP_THREAD_NAME; + + sys_thread_t thread = sys_thread_new(thread_name, spl_tcpip_thread, + (void *) arg, + TCPIP_THREAD_STACKSIZE, + g_cfg_item_info[CFG_SEG_PRI] + [CFG_ITEM_THREAD_PRI_PRI].value); + + cpu_set_t cpuset; + CPU_ZERO(&cpuset); /*lint !e534 */ + CPU_SET(g_nstack_bind_cpu, &cpuset); /*lint !e522 */ + ret = pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset); + if (ret != 0) + { + NSPOL_LOGERR("pthread_setaffinity_np failed]thread_name=%s,ret=%d", + TCPIP_THREAD_NAME, ret); + } + + return 0; +} + +int create_timer_thread() +{ +#if 1 + if (init_ptimer() != ERR_OK) + { + NSPOL_LOGERR("init_ptimer failed"); + return -1; + } + + sys_thread_t thread_timer = + sys_thread_new(PTIMER_THREAD_NAME, ptimer_thread, NULL, + TCPIP_THREAD_STACKSIZE, 0); + cpu_set_t cpuset_timer; + CPU_ZERO(&cpuset_timer); + CPU_SET(1, &cpuset_timer); + int ret = pthread_setaffinity_np(thread_timer, sizeof(cpuset_timer), + &cpuset_timer); + if (ret != 0) + { + NSPOL_LOGERR("TCP init Timer Trhead Failed!"); + } + + g_timerThread_id = thread_timer; +#endif + return 0; +} + +int init_ip_module_reader() +{ + output_api api = { 0 }; + api.post_to = post_ip_module_msg; + api.add_netif_ip = add_netif_ip; + api.del_netif_ip = del_netif_ip; + regist_output_api(&api); + + if (init_configuration_reader() < 0) + { + NSPOL_LOGERR("init_configuration_reader failed"); + return -1; + } + + return 0; +} + +extern int init_unmatch_version(void); +extern int init_stackx_global_tick(void); + +int init_by_main_thread() +{ + NSPOL_LOGINF(TCPIP_DEBUG, "init_by_main_thread start version 1.4"); + + uStackArgIndex++; + if (spl_hal_init(g_dpdk_argc, (char **) g_dpdk_argv) < 0) + { + NSPOL_LOGERR("spl_hal_init failed"); + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 1"); + + if (init_unmatch_version() != 0) + { + return -1; + } + + NSPOL_LOGINF(TCPIP_DEBUG, "stage 2"); + if (init_stackx_global_tick() != 0) + { + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 3"); + + if (spl_init_group_array() != 0) + { + NSPOL_LOGERR("spl_init_group_array failed"); + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 4"); + + if (nstack_epoll_init(0, 0) != 0) + { + NSPOL_LOGERR("nstack_epoll_init failed"); + return -1; + } + + if (set_share_config() != 0) + { + NSPOL_LOGERR("set_share_config failed."); + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 5"); + + if (create_timer_thread() != 0) + { + //NSPOL_LOGERR(TCPIP_DEBUG,"init_timer_thread failed."); + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 6"); + + if (create_tcpip_thread() != 0) + { + NSPOL_LOGERR("init_tcpip_thread failed."); + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage 7"); + + if (init_ip_module_reader() != 0) + { + return -1; + } + NSPOL_LOGINF(TCPIP_DEBUG, "stage end"); + + return 0; +} + +void create_netif(struct stackx_port_info *p_port_info) +{ + int ret; + struct spl_ip_addr ip, mask, gw; + struct netifExt *netifEx = NULL; + struct netif *netif = malloc(sizeof(struct netif)); + if (!netif) + { + NSPOL_LOGERR("malloc failed"); + return; + } + + if (memset_s(netif, sizeof(struct netif), 0, sizeof(struct netif)) < 0) + { + NSPOL_LOGERR("MEMSET_S failed"); + goto error; + } + + NSPOL_LOGINF(TCPIP_DEBUG, "I get netif]ip=%s,gw=%s,mask=%s,name=%c %c", + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.mask_linux, + netif->name[0], netif->name[1]); + + if (inet_aton(p_port_info->linux_ip.ip_addr_linux, &ip) + && inet_aton(p_port_info->linux_ip.ip_addr_linux, &gw) + && inet_aton(p_port_info->linux_ip.mask_linux, &mask)) + { + ret = + spl_netifapi_netif_add(netif, &ip, &mask, &gw, NULL, + ethernetif_init, spl_tcpip_input, + netif_set_up); + if (ERR_OK != ret) + { + NSPOL_LOGERR("netifapi_netif_add failed]ret=%d", ret); + goto error; + } +#if 1 + if (0 != netifExt_add(netif)) + return; + +#endif + netifEx = getNetifExt(netif->num); + if (NULL == netifEx) + return; + + netifEx->hdl = p_port_info->linux_ip.hdl; + ret = + strcpy_s(netifEx->if_name, sizeof(netifEx->if_name), + p_port_info->linux_ip.if_name); + if (EOK != ret) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", ret); + goto error; + } + return; + } + + error: + free(netif); +} + +int +post_ip_module_msg(void *arg, ip_module_type Type, + ip_module_operate_type operate_type) +{ + data_com_msg *p_msg_entry; + msg_ip_module *imsg; + sys_mbox_t mbox = get_primary_box(); + + if (!mbox) + { + NSOPR_LOGERR("get_cur_mbox failed"); + return ERR_MEM; + } + + if (sys_mbox_valid(&mbox)) + { + if (spl_msg_malloc(&p_msg_entry) == -1) + { + NSOPR_LOGERR("ip_route_apimsg:spl_msg_malloc failed."); + return ERR_MEM; + } + + sys_sem_init(&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = MSG_MODULE_IP; + p_msg_entry->param.op_type = MSG_SYN_POST; + + imsg = (msg_ip_module *) (p_msg_entry->buffer); + imsg->arg = arg; + imsg->type = Type; + imsg->operate_type = operate_type; + + NSOPR_LOGINF("post ip_module msg to tcpip_thread]action=%d,type=%d", + operate_type, Type); + + if (msg_post(p_msg_entry, mbox->llring) != 0) + { + NSOPR_LOGERR + ("msg_post failed,this can not happen]action=%d,type=%d", + operate_type, Type); + } + + spl_msg_free(p_msg_entry); + + return ERR_OK; + } + + NSOPR_LOGERR("mbox is invalid"); + return ERR_VAL; +} + +int +process_ip_module_msg(void *arg, ip_module_type module_type, + ip_module_operate_type operate_type) +{ + int retval = process_configuration(arg, module_type, operate_type); + + NSOPR_LOGINF("tcpip_thread: ip_module cmd exec over, send SYNC_MSG_ACK"); + return retval; +} + +int init_new_network_configuration() +{ + if (spl_hal_port_init() < 0) + { + return -1; + } + + return 0; +} + +static int _process_ip_module_msg(data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_ip_module *_m = (msg_ip_module *) m->buffer; + int ret = process_ip_module_msg(_m->arg, _m->type, _m->operate_type); + SYNC_MSG_ACK(m); + return ret; +} + +int +spl_post_msg(u16 mod, u16 maj, u16 min, u16 op, char *data, u16 data_len, + u32 src_pid) +{ + data_com_msg *p_msg_entry; + + sys_mbox_t mbox = get_primary_box(); + if (!sys_mbox_valid(&mbox)) + { + NSPOL_LOGERR + ("get mbox null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, + maj, min, op, data, data_len); + return ERR_MEM; + } + + if (spl_msg_malloc(&p_msg_entry) == -1) + { + NSPOL_LOGERR + ("get msg null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, + maj, min, op, data, data_len); + return ERR_MEM; + } + + sys_sem_init(&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = mod; + p_msg_entry->param.major_type = maj; + p_msg_entry->param.minor_type = min; + p_msg_entry->param.op_type = op; + p_msg_entry->param.src_pid = src_pid; + + int retVal; + if (NULL != data) + { + retVal = + memcpy_s((char *) p_msg_entry->buffer, + sizeof(p_msg_entry->buffer), data, data_len); + if (EOK != retVal) + { + NSPOL_LOGERR("MEMCPY_S failed %d.", retVal); + spl_msg_free(p_msg_entry); + return ERR_MEM; + } + } + + if (msg_post_with_lock_rel(p_msg_entry, mbox->llring) != 0) + { + NSPOL_LOGERR + ("post msg error!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, + maj, min, op, data, data_len); + spl_msg_free(p_msg_entry); + return ERR_MEM; + } + + if (MSG_SYN_POST == op) + { + spl_msg_free(p_msg_entry); + } + + NSOPR_LOGDBG("post msg suc!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", + mod, maj, min, op, data, data_len); + return ERR_OK; +} + +/* +* Added by eliminate duplicated code degree, the function is moved to the public places +*adjust memory size for pal and eal mem size: this func do the following things: +*1. copy argv to gArgv and g_dpdk_argv +*2. remove OPT_EAL_MEM_SIZE option so that the rtp and rte options process won't reprt unrecognized option error. +*3. set eal mem size and pal_mem_size = mem - eal_mem_size +*/ +int adjust_mem_arg(int argc, char *argv[]) +{ + int i = 0; + int j = 0; + int retVal; + char *tmp = NULL; + char *tmp2 = NULL; + int arg_mem_index = -1; + char *saveptr1 = NULL; + int mem_size = 0; + int mem_size_parsed = 0; // if multi -m argument is set, then only deal with the first one + int eal_mem_size = DPDK_DEFAULT_EAL_MEM_SIZE; // Default + + if ((argc < NSTACK_MAIN_MIN_PARA) || (argc > NSTACK_MAIN_MAX_PARA)) + { + NSPOL_LOGERR("The number of parameters is incorrect"); + return -1; + } + + globalArgc = argc; + g_dpdk_argc = argc; + gArgv = (char **) malloc(sizeof(char *) * argc); + if (gArgv == NULL) + { + NSPOL_LOGERR("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + g_dpdk_argv = (char **) malloc(sizeof(char *) * argc); + if (g_dpdk_argv == NULL) + { + NSPOL_LOGERR("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + retVal = memset_s(gArgv, sizeof(char *) * argc, 0, sizeof(char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + retVal = + memset_s(g_dpdk_argv, sizeof(char *) * argc, 0, + sizeof(char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + + for (i = 0; i < argc; i++) + { + if (!strcmp("-m", argv[i]) && !mem_size_parsed && (i + 1 < argc)) + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + i++; + j++; + gArgv[j] = (char *) malloc(32); + g_dpdk_argv[j] = (char *) malloc(32); + /* gArgv[j] is NULL and g_dpdk_argv[j] isnot NULL, need free g_dpdk_argv[j] */ + arg_mem_index = j; + if ((!gArgv[j]) || (!g_dpdk_argv[j])) + { + NSPOL_LOGERR("malloc failed."); + goto ERROR_PARSE_MALLOC; + } + mem_size = atoi(argv[i]); + /* add memory range check,avoid handle wrongly later begin */ + if (mem_size < 0) + { + goto ERROR_PARSE_MALLOC; + } + + j++; + mem_size_parsed = 1; + } + else if (!strncmp + (OPT_EAL_MEM_SIZE, argv[i], strlen(OPT_EAL_MEM_SIZE))) + { + tmp = strdup(argv[i]); + if (tmp == NULL) + { + goto ERROR_PARSE_MALLOC; + } + /* Always use re-entrant functions in multi-threaded environments */ + tmp2 = strtok_r(tmp, "=", &saveptr1); + tmp2 = strtok_r(NULL, "=", &saveptr1); + if (tmp2) + { + eal_mem_size = atoi(tmp2); + /* add memory range check,avoid handle wrongly later */ + if (eal_mem_size < 0) + { + free(tmp); + goto ERROR_PARSE_MALLOC; + } + } + free(tmp); + tmp = NULL; + /*remove this option since dpdk can't recognize it and may cause error. */ + /*so we should deduct the count by 1. */ + globalArgc -= 1; + g_dpdk_argc -= 1; + } + else + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + j++; + } + } + + /* -m arg is set */ + if (arg_mem_index >= 0) + { + retVal = + sprintf_s(gArgv[arg_mem_index], 32, "%d", + mem_size - eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + retVal = + sprintf_s(g_dpdk_argv[arg_mem_index], 32, "%d", eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + } + else + { + // do nothing for no mem arg and leave it for default process of pal and eal. + } + + return 0; + ERROR_PARSE_MALLOC: + if (arg_mem_index >= 0 && gArgv[arg_mem_index]) + { + free(gArgv[arg_mem_index]); + gArgv[arg_mem_index] = NULL; + } + + if (arg_mem_index >= 0 && g_dpdk_argv[arg_mem_index]) + { + free(g_dpdk_argv[arg_mem_index]); + g_dpdk_argv[arg_mem_index] = NULL; + } + + ERROR_INIT: + if (gArgv) + { + free(gArgv); + gArgv = NULL; + globalArgc = 0; + } + + if (g_dpdk_argv) + { + free(g_dpdk_argv); + g_dpdk_argv = NULL; + g_dpdk_argc = 0; + } + + return -1; +} + +REGIST_MSG_MODULE_FUN(MSG_MODULE_IP, _process_ip_module_msg); + +REGIST_MSG_MODULE_MAJOR_FUN(MSG_MODULE_SPL, SPL_TCPIP_MSG_CALLBACK, + _do_spl_callback_msg); + +REGIST_MSG_MODULE_MAJOR_FUN(MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + _do_spl_timer_msg); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_TIMEOUT, _do_timeout_handle); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN(MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_CLEAR, _do_clear_timer); diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.c b/stacks/lwip_stack/lwip_src/common/rb_tree.c new file mode 100644 index 0000000..aecdd37 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/rb_tree.c @@ -0,0 +1,389 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "rb_tree.h" + +static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *left = node->rb_left; + struct rb_node *parent = rb_parent(node); + + if ((node->rb_left = left->rb_right)) + { + rb_set_parent(left->rb_right, node); + } + + left->rb_right = node; + + rb_set_parent(left, parent); + + if (parent) + { + if (node == parent->rb_right) + { + parent->rb_right = left; + } + else + { + parent->rb_left = left; + } + } + else + { + root->rb_node = left; + } + + rb_set_parent(node, left); +} + +static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *parent = rb_parent(node); + + struct rb_node *right = node->rb_right; + + if ((node->rb_right = right->rb_left)) + { + rb_set_parent(right->rb_left, node); + } + + right->rb_left = node; + rb_set_parent(right, parent); + + if (parent) /* judge parent node */ + { + if (node == parent->rb_left) + { + parent->rb_left = right; + } + else + { + parent->rb_right = right; + } + } + else + { + root->rb_node = right; + } + + rb_set_parent(node, right); +} + +static void +__rb_erase_color(struct rb_node *rb_tree_node, + struct rb_node *rb_tree_parent, struct rb_root *rb_tree_root) +{ + struct rb_node *rb_tree_other; + + while ((!rb_tree_node || rb_is_black(rb_tree_node)) + && (rb_tree_node != rb_tree_root->rb_node)) + { + if (rb_tree_parent == NULL) + { + break; + } + + if (rb_tree_parent->rb_left == rb_tree_node) + { + rb_tree_other = rb_tree_parent->rb_right; + if (rb_is_red(rb_tree_other)) + { + rb_set_black(rb_tree_other); + rb_set_red(rb_tree_parent); + __rb_rotate_left(rb_tree_parent, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_right; + } + + if ((!rb_tree_other->rb_left + || rb_is_black(rb_tree_other->rb_left)) + && (!rb_tree_other->rb_right + || rb_is_black(rb_tree_other->rb_right))) + { + rb_set_red(rb_tree_other); + rb_tree_node = rb_tree_parent; + rb_tree_parent = rb_parent(rb_tree_node); + } + else + { + if (!rb_tree_other->rb_right + || rb_is_black(rb_tree_other->rb_right)) + { + rb_set_black(rb_tree_other->rb_left); + rb_set_red(rb_tree_other); + __rb_rotate_right(rb_tree_other, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_right; + } + + rb_set_color(rb_tree_other, rb_color(rb_tree_parent)); + rb_set_black(rb_tree_parent); + rb_set_black(rb_tree_other->rb_right); + __rb_rotate_left(rb_tree_parent, rb_tree_root); + rb_tree_node = rb_tree_root->rb_node; + break; + } + } + else + { + rb_tree_other = rb_tree_parent->rb_left; + if (rb_is_red(rb_tree_other)) + { + rb_set_black(rb_tree_other); + rb_set_red(rb_tree_parent); + __rb_rotate_right(rb_tree_parent, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_left; + } + + if ((!rb_tree_other->rb_left + || rb_is_black(rb_tree_other->rb_left)) + && (!rb_tree_other->rb_right + || rb_is_black(rb_tree_other->rb_right))) + { + rb_set_red(rb_tree_other); + rb_tree_node = rb_tree_parent; + rb_tree_parent = rb_parent(rb_tree_node); + } + else + { + if (!rb_tree_other->rb_left + || rb_is_black(rb_tree_other->rb_left)) + { + rb_set_black(rb_tree_other->rb_right); + rb_set_red(rb_tree_other); + __rb_rotate_left(rb_tree_other, rb_tree_root); + rb_tree_other = rb_tree_parent->rb_left; + } + + rb_set_color(rb_tree_other, rb_color(rb_tree_parent)); + rb_set_black(rb_tree_parent); + rb_set_black(rb_tree_other->rb_left); + __rb_rotate_right(rb_tree_parent, rb_tree_root); + rb_tree_node = rb_tree_root->rb_node; + break; + } + } + } + + if (rb_tree_node) + { + rb_set_black(rb_tree_node); + } +} + +void +rb_insert_color(struct rb_node *rb_tree_node, struct rb_root *rb_tree_root) +{ + struct rb_node *rb_tree_parent, *rb_tree_gparent; + + if (!rb_tree_node || !rb_tree_root) + return; + + while ((rb_tree_parent = rb_parent(rb_tree_node)) + && rb_is_red(rb_tree_parent)) + { + rb_tree_gparent = rb_parent(rb_tree_parent); + + if (rb_tree_parent == rb_tree_gparent->rb_left) + { + { + register struct rb_node *rb_tree_uncle = + rb_tree_gparent->rb_right; + if (rb_tree_uncle && rb_is_red(rb_tree_uncle)) + { + rb_set_black(rb_tree_uncle); + rb_set_black(rb_tree_parent); + rb_set_red(rb_tree_gparent); + rb_tree_node = rb_tree_gparent; + continue; + } + } + + if (rb_tree_parent->rb_right == rb_tree_node) + { + register struct rb_node *rb_tree_tmp; + __rb_rotate_left(rb_tree_parent, rb_tree_root); + rb_tree_tmp = rb_tree_parent; + rb_tree_parent = rb_tree_node; + rb_tree_node = rb_tree_tmp; + } + + rb_set_black(rb_tree_parent); + rb_set_red(rb_tree_gparent); + __rb_rotate_right(rb_tree_gparent, rb_tree_root); + } + else + { + { + register struct rb_node *rb_tree_uncle = + rb_tree_gparent->rb_left; + if (rb_tree_uncle && rb_is_red(rb_tree_uncle)) + { + rb_set_black(rb_tree_uncle); + rb_set_black(rb_tree_parent); + rb_set_red(rb_tree_gparent); + rb_tree_node = rb_tree_gparent; + continue; + } + } + + if (rb_tree_parent->rb_left == rb_tree_node) + { + register struct rb_node *rb_tree_tmp; + __rb_rotate_right(rb_tree_parent, rb_tree_root); + rb_tree_tmp = rb_tree_parent; + rb_tree_parent = rb_tree_node; + rb_tree_node = rb_tree_tmp; + } + + rb_set_black(rb_tree_parent); + rb_set_red(rb_tree_gparent); + __rb_rotate_left(rb_tree_gparent, rb_tree_root); + } + } + + rb_set_black(rb_tree_root->rb_node); +} + +void rb_erase(struct rb_node *node, struct rb_root *root) +{ + struct rb_node *child, *parent; + int color; + + if (!node || !root) + return; + + if (!node->rb_left) + { + child = node->rb_right; + } + else if (!node->rb_right) + { + child = node->rb_left; + } + else + { + struct rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + { + node = left; + } + + if (rb_parent(old)) + { + if (rb_parent(old)->rb_left == old) + { + rb_parent(old)->rb_left = node; + } + else + { + rb_parent(old)->rb_right = node; + } + } + else + { + root->rb_node = node; + } + + child = node->rb_right; + parent = rb_parent(node); + color = rb_color(node); + + if (parent == old) + { + parent = node; + } + else + { + if (child) + { + rb_set_parent(child, parent); + } + + parent->rb_left = child; + + node->rb_right = old->rb_right; + rb_set_parent(old->rb_right, node); + } + + node->rb_parent_color = old->rb_parent_color; + node->rb_left = old->rb_left; + rb_set_parent(old->rb_left, node); + + goto color; + } + + parent = rb_parent(node); + color = rb_color(node); + + if (child) + { + rb_set_parent(child, parent); + } + + if (parent) + { + if (parent->rb_left == node) + { + parent->rb_left = child; + } + else + { + parent->rb_right = child; + } + } + else + { + root->rb_node = child; + } + + color: + if (color == RB_BLACK) + { + __rb_erase_color(child, parent, root); + } +} + +struct rb_node *rb_next(const struct rb_node *node) +{ + struct rb_node *parent; + + if (!node) + return NULL; + + if (rb_parent(node) == node) + { + return NULL; + } + + if (node->rb_right) + { + node = node->rb_right; + while (node->rb_left) + { + node = node->rb_left; + } + + return (struct rb_node *) node; + } + + while ((parent = rb_parent(node)) && (node == parent->rb_right)) + { + node = parent; + } + + return parent; +} diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.h b/stacks/lwip_stack/lwip_src/common/rb_tree.h new file mode 100644 index 0000000..ce156e8 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/rb_tree.h @@ -0,0 +1,110 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _UNX_RBTREE_H +#define _UNX_RBTREE_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif +#include +#include "types.h" +#include "common_pal_bitwide_adjust.h" + +#define rb_parent(a) ((struct rb_node *)((a)->rb_parent_color & ~3)) +#define rb_color(a) ((a)->rb_parent_color & 1) + +struct rb_node +{ + union + { + unsigned long rb_parent_color; + u64 rb_parent_color_a; + }; + +#define RB_RED 0 +#define RB_BLACK 1 + union + { + struct rb_node *rb_right; + u64 rb_right_a; + }; + + union + { + struct rb_node *rb_left; + u64 rb_left_a; + }; +}; + +#define rb_set_red(c) do { (c)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(c) do { (c)->rb_parent_color |= 1; } while (0) + +/* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct rb_root +{ + union + { + struct rb_node *rb_node; + u64 rb_node_a; + }; +}; + +#define rb_is_red(e) (!rb_color(e)) +#define rb_is_black(e) rb_color(e) + +static inline void rb_set_color(struct rb_node *rb1, int color2) +{ + rb1->rb_parent_color = (rb1->rb_parent_color & ~1) | color2; +} + +static inline void rb_set_parent(struct rb_node *rb1, struct rb_node *pa) +{ + rb1->rb_parent_color = (rb1->rb_parent_color & 3) | (unsigned long) pa; +} + +#define RB_ROOT (struct rb_root) { NULL, } + +extern void rb_erase(struct rb_node *, struct rb_root *); + +extern void rb_insert_color(struct rb_node *, struct rb_root *); + +extern struct rb_node *rb_next(const struct rb_node *); + +#define rb_entry(ptr, type, member) container_of(ptr, type, member) + +#define RB_EMPTY_ROOT(root1) ((root1)->rb_node == NULL) +#define RB_CLEAR_NODE(node2) (rb_set_parent(node2, node2)) +#define RB_EMPTY_NODE(node1) (rb_parent(node1) == node1) + +static inline void +rb_link_node(struct rb_node *node1, struct rb_node *parent1, + struct rb_node **rb_link1) +{ + node1->rb_left = node1->rb_right = NULL; + node1->rb_parent_color = (unsigned long) parent1; + *rb_link1 = node1; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* _UNX_RBTREE_H */ diff --git a/stacks/lwip_stack/lwip_src/common/spl_def.h b/stacks/lwip_stack/lwip_src/common/spl_def.h new file mode 100644 index 0000000..06eb5b2 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/spl_def.h @@ -0,0 +1,138 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_DEF_H__ +#define __STACKX_DEF_H__ + +/* arch.h might define NULL already */ +//#include "lwip/arch.h" +#include "spl_opt.h" +#include "stackx_types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define STACKX_MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define STACKX_MIN(x, y) (((x) < (y)) ? (x) : (y)) + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define STACKX_MAKE_U16(a, b) ((a << 8) | b) +#else +#define STACKX_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef STACKX_PLATFORM_BYTESWAP +#define STACKX_PLATFORM_BYTESWAP 0 +#endif + +#ifndef STACKX_PREFIX_BYTEORDER_FUNCS + +/* workaround for naming collisions on some platforms */ + +#ifdef spl_htons +#undef spl_htons +#endif /* htons */ +#ifdef spl_htonl +#undef spl_htonl +#endif /* spl_htonl */ +#ifdef spl_ntohs +#undef spl_ntohs +#endif /* spl_ntohs */ +#ifdef spl_ntohl +#undef spl_ntohl +#endif /* spl_ntohl */ + +#define spl_htons(x) stackx_htons(x) +#define spl_ntohs(x) stackx_ntohs(x) +#define spl_htonl(x) stackx_htonl(x) +#define spl_ntohl(x) stackx_ntohl(x) +#endif /* STACKX_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define stackx_htons(x) (x) +#define stackx_ntohs(x) (x) +#define stackx_htonl(x) (x) +#define stackx_ntohl(x) (x) +#define SPL_PP_HTONS(x) (x) +#define SPL_PP_NTOHS(x) (x) +#define SPL_PP_HTONL(x) (x) +#define SPL_PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if STACKX_PLATFORM_BYTESWAP +#define stackx_htons(x) STACKX_PLATFORM_HTONS(x) +#define stackx_ntohs(x) STACKX_PLATFORM_HTONS(x) +#define stackx_htonl(x) STACKX_PLATFORM_HTONL(x) +#define stackx_ntohl(x) STACKX_PLATFORM_HTONL(x) +#else /* STACKX_PLATFORM_BYTESWAP */ + /** + * Convert an u16_t from host- to network byte order. + * + * @param n u16_t in host byte order + * @return n in network byte order + */ +static inline u16_t stackx_htons(u16_t x) +{ + return ((x & 0xff) << 8) | ((x & 0xff00) >> 8); +} + +static inline u16_t stackx_ntohs(u16_t x) +{ + return stackx_htons(x); +} + + /** + * Convert an u32_t from host- to network byte order. + * + * @param n u32_t in host byte order + * @return n in network byte order + */ +static inline u32_t stackx_htonl(u32_t x) +{ + return ((x & 0xff) << 24) | + ((x & 0xff00) << 8) | + ((x & 0xff0000UL) >> 8) | ((x & 0xff000000UL) >> 24); +} + +static inline u32_t stackx_ntohl(u32_t x) +{ + return stackx_htonl(x); +} +#endif /* STACKX_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define SPL_PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define SPL_PP_NTOHS(x) SPL_PP_HTONS(x) +#define SPL_PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define SPL_PP_NTOHL(x) SPL_PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_DEF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/spl_opt.h b/stacks/lwip_stack/lwip_src/common/spl_opt.h new file mode 100644 index 0000000..98e6466 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/spl_opt.h @@ -0,0 +1,329 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_OPT_H__ +#define __STACKX_OPT_H__ + +#include "stackxopts.h" +#include "stackx_debug.h" +#include "compiling_check.h" + +#define PBUF_VLAN_HLEN 0 + +//#define SIZEOF_ETH_HDR (14) + +#ifndef STACKX_NETIF_API +#define STACKX_NETIF_API 1 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ + */ + +#define PTIMER_THREAD_NAME "ptimer_thread" + +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "spl_tcpip_thread" +#endif + +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef INT_64_MAX +#define INT_64_MAX 9223372036854775807 +#endif + +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- + */ + +#ifndef STACKX_DBG_TYPES_ON +#define STACKX_DBG_TYPES_ON STACKX_DBG_ON //ON +#endif + +#ifndef INTERRUPT_DEBUG +#define INTERRUPT_DEBUG STACKX_DBG_ON //ON +#endif + +#ifndef TESTSOCKET_DEBUG +#define TESTSOCKET_DEBUG STACKX_DBG_ON //ON +#endif + +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG STACKX_DBG_ON +#endif + +#ifndef NETIF_DEBUG +#define NETIF_DEBUG STACKX_DBG_ON +#endif + +#ifndef PBUF_DEBUG +#define PBUF_DEBUG STACKX_DBG_ON +#endif + +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG STACKX_DBG_ON +#endif + +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG STACKX_DBG_ON +#endif + +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG STACKX_DBG_ON +#endif + +#ifndef NS_EPOLL_DBG +#define NS_EPOLL_DBG STACKX_DBG_ON +#endif + +#ifndef ICMP_DEBUG +#define ICMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef IGMP_DEBUG +#define IGMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef INET_DEBUG +#define INET_DEBUG STACKX_DBG_ON +#endif + +#ifndef IP_DEBUG +#define IP_DEBUG STACKX_DBG_ON +#endif + +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG STACKX_DBG_ON +#endif + +#ifndef RAW_DEBUG +#define RAW_DEBUG STACKX_DBG_ON +#endif + +#ifndef MEMP_DEBUG +#define MEMP_DEBUG STACKX_DBG_ON +#endif + +#ifndef SYS_DEBUG +#define SYS_DEBUG STACKX_DBG_OFF +#endif + +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_DEBUG +#define TCP_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_TEST_DEBUG +#define TCP_TEST_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_FLOW_CTL_DEBUG +#define TCP_FLOW_CTL_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG STACKX_DBG_ON +#endif + +#ifndef UDP_DEBUG +#define UDP_DEBUG STACKX_DBG_ON +#endif + +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG STACKX_DBG_ON +#endif + +#ifndef NEW_RING_DEBUG +#define NEW_RING_DEBUG STACKX_DBG_ON +#endif + +#ifndef PACKET_DISPATCH +#define PACKET_DISPATCH 1 +#endif + +#ifndef NETSTAT_SWITCH +#define NETSTAT_SWITCH 1 +#endif + +#ifndef DISTRIBUTOR_DEBUG + +#define DISTRIBUTOR_DEBUG STACKX_DBG_ON +#endif +#define PBUF_REF_DEBUG STACKX_DBG_ON + +#ifndef CONTEXT_TIMER_DEBUG +#define CONTEXT_TIMER_DEBUG STACKX_DBG_OFF +#endif + +#if (DISTRIBUTOR_DEBUG == STACKX_DBG_ON) +#define PD_DISTRIBUTOR_DEBUG + +#define DISTRIBUTOR_SINGLE +#ifdef DISTRIBUTOR_SINGLE + +#ifndef __STACKX_DEBUG_H__ +#define STACKX_DBG_OFF 0x80U +#define STACKX_DBG_ON 0x00U +#endif + +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG STACKX_DBG_ON +#endif +#ifndef NETIF_DEBUG +#define NETIF_DEBUG STACKX_DBG_ON +#endif +#ifndef PBUF_DEBUG +#define PBUF_DEBUG STACKX_DBG_ON +#endif +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG STACKX_DBG_ON +#endif +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG STACKX_DBG_ON +#endif +#ifndef ICMP_DEBUG +#define ICMP_DEBUG STACKX_DBG_ON +#endif +#ifndef IGMP_DEBUG +#define IGMP_DEBUG STACKX_DBG_ON +#endif +#ifndef INET_DEBUG +#define INET_DEBUG STACKX_DBG_ON +#endif +#ifndef IP_DEBUG +#define IP_DEBUG STACKX_DBG_ON +#endif +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG STACKX_DBG_ON +#endif +#ifndef RAW_DEBUG +#define RAW_DEBUG STACKX_DBG_ON +#endif +#ifndef MEMP_DEBUG +#define MEMP_DEBUG STACKX_DBG_ON +#endif +#ifndef SYS_DEBUG +#define SYS_DEBUG STACKX_DBG_ON +#endif +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_DEBUG +#define TCP_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_TEST_DEBUG +#define TCP_TEST_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG STACKX_DBG_ON +#endif +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG STACKX_DBG_ON +#endif +#ifndef UDP_DEBUG +#define UDP_DEBUG STACKX_DBG_ON +#endif +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG STACKX_DBG_ON +#endif + +#define SC_DPDK_INFO STACKX_DBG_ON +#define SOCK_INFO STACKX_DBG_ON +#ifndef STACKX_DBG_OFF +#define STACKX_DBG_OFF 0x00U +#endif + +#ifndef NS_EPOLL_DBG +#define NS_EPOLL_DBG STACKX_DBG_ON +#endif + +#ifndef DFX_DBG +#define DFX_DBG STACKX_DBG_ON +#endif + +#endif +#endif /* DISTRIBUTOR_DEBUG */ + +#ifndef STACKX_FLOW_CTL +#define STACKX_FLOW_CTL 0 +#endif + +#endif /* __STACKX_OPT_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/spl_rti.c b/stacks/lwip_stack/lwip_src/common/spl_rti.c new file mode 100644 index 0000000..d15d25f --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/spl_rti.c @@ -0,0 +1,91 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init_api.h" +#include "nstack_log.h" +#include "nsfw_maintain_api.h" +#include "nsfw_mem_api.h" +#include "nsfw_rti.h" +#include "nsfw_msg.h" +#ifdef HAL_LIB +#else +#include "common_pal_bitwide_adjust.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +char g_dfx_switch = 1; + +struct rti_queue *g_nsfw_rti_primary_stat = NULL; + +void nsfw_rti_stat(nsfw_rti_stat_type_t statType, const data_com_msg * m) +{ + if (!g_nsfw_rti_primary_stat || !m) + { + return; + } + + struct rti_queue *primary_stat = ADDR_SHTOL(g_nsfw_rti_primary_stat); + + switch (statType) + { + case NSFW_STAT_PRIMARY_DEQ: + if ((m->param.major_type >= MAX_MAJOR_TYPE) + || (m->param.minor_type >= MAX_MINOR_TYPE)) + { + return; + } + /*call_msg_fun() is only called in nStackMain, no reentrance risk, ++ operation is ok */ + primary_stat->tcpip_msg_deq[m->param.major_type]++; + if (0 == m->param.major_type) //SPL_TCPIP_NEW_MSG_API + { + primary_stat->api_msg_deq[m->param.minor_type]++; + } + break; + case NSFW_STAT_PRIMARY_ENQ_FAIL: + if ((m->param.major_type >= MAX_MAJOR_TYPE) + || (m->param.minor_type >= MAX_MINOR_TYPE)) + { + return; + } + __sync_fetch_and_add(&primary_stat->tcpip_msg_enq_fail + [m->param.major_type], 1); + if (0 == m->param.major_type) //SPL_TCPIP_NEW_MSG_API + { + __sync_fetch_and_add(&primary_stat->api_msg_enq_fail + [m->param.minor_type], 1); + } + break; + case NSFW_STAT_PRIMARY_ENQ: + //not use + break; + default: + break; + } +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.c b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c new file mode 100644 index 0000000..84c1451 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c @@ -0,0 +1,951 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_app_res.h" +#include "nstack_securec.h" +#include "common_pal_bitwide_adjust.h" +#include "nstack_log.h" +#include "stackx_common.h" +#include "nsfw_maintain_api.h" +#include "stackx_tx_box.h" +#include "nsfw_msg_api.h" +#include "nsfw_recycle_api.h" +#include "common_mem_mbuf.h" +#include "stackx_pbuf.h" +#include "nsfw_mt_config.h" +#include "nsfw_mem_api.h" +#include "spl_opt.h" +#include "nsfw_shmem_mng.h" +#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM) + +spl_app_res_group *g_spl_app_res_group = NULL; + +spl_app_res_group_array *g_res_group_array = NULL; + +#ifdef SYS_MEM_RES_STAT +mpool_handle g_app_tx_pool[SBR_TX_POOL_NUM]; +#endif + +/*************************************************** +* description: +***************************************************/ +int spl_init_group_array() +{ + g_res_group_array = + (spl_app_res_group_array *) sbr_create_mzone(SPL_RES_GROUP_ARRAY, + sizeof + (spl_app_res_group_array)); + if (!g_res_group_array) + { + NSPOL_LOGERR("create g_res_group_array failed"); + return -1; + } + + u32 i; + for (i = 0; i < SBR_TX_POOL_NUM; ++i) + { + g_res_group_array->pid_array[i] = 0; + } + + for (i = 0; i < MAX_THREAD_NUM; ++i) + { + g_res_group_array->res_group[i] = NULL; + } + + g_res_group_array->thread_num = 0; + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int sbr_attach_group_array() +{ + g_res_group_array = + (spl_app_res_group_array *) sbr_lookup_mzone(SPL_RES_GROUP_ARRAY); + if (!g_res_group_array) + { + NSPOL_LOGERR("attach g_res_group_array failed"); + return -1; + } + + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int spl_add_instance_res_group(u32 thread_index, spl_app_res_group * group) +{ + if (thread_index >= MAX_THREAD_NUM) + { + NSPOL_LOGERR + ("thread_index >= MAX_THREAD_NUM]thread_index=%u, MAX_THREAD_NUM=%u", + thread_index, MAX_THREAD_NUM); + return -1; + } + + if (g_res_group_array->res_group[thread_index] != NULL) + { + NSPOL_LOGERR + ("g_res_group_array in thread_index is not NULL, this can not happen"); + return -1; + } + + g_res_group_array->res_group[thread_index] = group; + __sync_add_and_fetch(&g_res_group_array->thread_num, 1); + return 0; +} + +/*************************************************** +* description: +***************************************************/ +int spl_add_mbox(mring_handle mbox_array[], u32 array_size) +{ + if (array_size != SPL_MSG_BOX_NUM) + { + NSPOL_LOGERR("array_size must be %u, but not", SPL_MSG_BOX_NUM); + return -1; + } + + u32 i; + for (i = 0; i < array_size; ++i) + { + g_spl_app_res_group->mbox_array[i] = mbox_array[i]; + } + + return 0; +} + +/***************************************************************************** +* Prototype : spl_create_group +* Description : create group +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +spl_app_res_group *spl_create_group() +{ + spl_app_res_group *group = + (spl_app_res_group *) sbr_create_mzone(SPL_APP_RES_GROUP_NAME, + sizeof(spl_app_res_group)); + if (!group) + { + NSPOL_LOGERR("Create app_res_group zone fail]name=%s, size=%u", + SPL_APP_RES_GROUP_NAME, sizeof(spl_app_res_group)); + return NULL; + } + + group->msg_pool = NULL; + group->conn_pool = NULL; + group->conn_array = NULL; + group->recv_ring_pool = NULL; + + u32 i; + for (i = 0; i < SBR_TX_POOL_NUM; ++i) + { + group->tx_pool_array[i] = NULL; + } + + for (i = 0; i < SPL_MSG_BOX_NUM; ++i) + { + group->mbox_array[i] = NULL; + } + + group->extend_member_bit = 0; + + NSPOL_LOGINF(SC_DPDK_INFO, + "Create app_res_group zone ok]name=%s, size=%u", + SPL_APP_RES_GROUP_NAME, sizeof(spl_app_res_group)); + MEM_STAT(SPL_APP_RES, SPL_APP_RES_GROUP_NAME, NSFW_SHMEM, + sizeof(spl_app_res_group)); + return group; +} + +/***************************************************************************** +* Prototype : _spl_create_ring_pool +* Description : create ring pool +* Input : char* pool_name +* char* array_name +* nsfw_mpool_type type +* Output : None +* Return Value : static inline mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +static inline mring_handle +_spl_create_ring_pool(char *pool_name, char *array_name, + nsfw_mpool_type type, u32 num, u32 ring_size) +{ + mring_handle pool = sbr_create_ring(pool_name, num - 1); + + if (!pool) + { + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "Create ring pool ok]name=%s, num=%u, size=%d", + pool_name, num, nsfw_mem_get_len(pool, NSFW_MEM_RING)); + MEM_STAT(SPL_APP_RES, pool_name, NSFW_SHMEM, + nsfw_mem_get_len(pool, NSFW_MEM_RING)); + + mring_handle *array = malloc(num * sizeof(mring_handle)); + if (!array) + { + NSPOL_LOGERR("malloc fail]size=%u", num * sizeof(mring_handle)); + return NULL; + } + + if (sbr_create_multi_ring(array_name, ring_size - 1, num, + array, type) != 0) + { + free(array); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "Create multi rings ok]name=%s, ring_size=%u, ring_num=%u, total_mem=%d", + array_name, ring_size, num, + (nsfw_mem_get_len(array[0], NSFW_MEM_RING) * num)); + MEM_STAT(SPL_APP_RES, array_name, NSFW_SHMEM, + nsfw_mem_get_len(array[0], NSFW_MEM_RING) * num); + + unsigned int i = 0; + while (i < num) + { + if (nsfw_mem_ring_enqueue(pool, (void *) array[i]) != 1) + { + NSPOL_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + free(array); + return NULL; + } + + i++; + } + + free(array); + return pool; +} + +/***************************************************************************** +* Prototype : spl_create_ring_pool +* Description : create ring pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_create_ring_pool(spl_app_res_group * group) +{ + group->recv_ring_pool = + _spl_create_ring_pool(SPL_RECV_RING_POOL_NAME, + SPL_RECV_RING_ARRAY_NAME, NSFW_MRING_SPSC, + CUR_CFG_SOCKET_NUM, SPL_MAX_RING_SIZE); + if (!group->recv_ring_pool) + { + NSPOL_LOGERR("Create recv ring pool failed"); + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "Create recv ring pool ok]name=%s", + SPL_RECV_RING_POOL_NAME); + return 0; +} + +int spl_force_netconn_free(void *data) +{ + spl_netconn_t *conn = (spl_netconn_t *) data; + if (TRUE == conn->res_chk.alloc_flag) + { + if (NULL != conn->recycle.accept_from) + { + return FALSE; + } + + if (TRUE != nsfw_pidinfo_empty(&conn->recycle.pid_info)) + { + return FALSE; + } + } + ss_reset_conn(conn); + (void) res_free(&conn->res_chk); + + if (nsfw_mem_ring_enqueue(ss_get_conn_pool(conn), (void *) conn) != 1) + { + NSSBR_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + } + NSFW_LOGINF("force free conn]conn=%p", conn); + return TRUE; +} + +/***************************************************************************** +* Prototype : spl_create_netconn_pool +* Description : create netconn pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_create_netconn_pool(spl_app_res_group * group) +{ + spl_netconn_t **conn_array = + (spl_netconn_t **) sbr_create_mzone(SPL_CONN_ARRAY_NAME, + sizeof(spl_netconn_t *) * + CUR_CFG_SOCKET_NUM); + + if (!conn_array) + { + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "Create connn_array zone ok]name=%s, size=%zu", + SPL_CONN_ARRAY_NAME, + sizeof(spl_netconn_t *) * CUR_CFG_SOCKET_NUM); + mring_handle pool = + sbr_create_pool(SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM - 1, + SBR_FD_NETCONN_SIZE); + + if (!pool) + { + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "Create conn_pool ok]name=%s, num=%u, total_mem=%d", + SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM, + nsfw_mem_get_len(pool, NSFW_MEM_SPOOL)); + + sbr_recycle_group *recycle_group = + (sbr_recycle_group *) sbr_create_mzone(SPL_RECYCLE_GROUP, + sizeof(sbr_recycle_group)); + if (!recycle_group) + { + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "Create recycle_group zone ok]name=%s, size=%u", + SPL_RECYCLE_GROUP, sizeof(sbr_recycle_group)); + + recycle_group->conn_array = conn_array; + recycle_group->conn_num = spl_get_conn_num(); + recycle_group->conn_pool = pool; + recycle_group->extend_member_bit = 0; + recycle_group->msg_pool = group->msg_pool; + + spl_netconn_t *conn = NULL; + unsigned int i = 0; + while (i < CUR_CFG_SOCKET_NUM) + { + if (nsfw_mem_ring_dequeue(pool, (void **) &conn) != 1) + { + NSPOL_LOGERR("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + ss_reset_conn(conn); + conn->recycle.group = recycle_group; + + if (nsfw_mem_ring_dequeue(group->recv_ring_pool, &conn->recv_ring) != + 1) + { + NSPOL_LOGERR("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + conn_array[i] = conn; + + if (nsfw_mem_ring_enqueue(pool, (void *) conn) != 1) + { + NSPOL_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + return -1; + } + + i++; + } + + group->conn_pool = pool; + group->conn_array = conn_array; + + MEM_STAT(SPL_APP_RES, SPL_RECYCLE_GROUP, NSFW_SHMEM, + sizeof(sbr_recycle_group)); + MEM_STAT(SPL_APP_RES, SPL_CONN_ARRAY_NAME, NSFW_SHMEM, + sizeof(spl_netconn_t *) * CUR_CFG_SOCKET_NUM); + MEM_STAT(SPL_APP_RES, SPL_CONN_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len(group->conn_pool, NSFW_MEM_SPOOL)); + return 0; +} + +int spl_force_msg_free(void *data) +{ + data_com_msg *m = (data_com_msg *) data; + if (NULL == m) + { + return FALSE; + } + + NSFW_LOGINF("force free msg]msg=%p", data); + (void) res_free(&m->param.res_chk); + m->param.recycle_pid = 0; + if (nsfw_mem_ring_enqueue(m->param.msg_from, (void *) m) != 1) + { + NSFW_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : spl_create_msg_pool +* Description : create msg pool +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_create_msg_pool(spl_app_res_group * group) +{ + mring_handle pool = + sbr_create_pool(SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM - 1, MAX_MSG_SIZE); + + if (!pool) + { + return -1; + } + + data_com_msg *m = NULL; + unsigned int i = 0; + while (i < SPL_MAX_MSG_NUM) + { + if (nsfw_mem_ring_dequeue(pool, (void **) &m) != 1) + { + NSPOL_LOGERR("nsfw_mem_ring_dequeue failed,this can not happen"); + return -1; + } + + m->param.msg_from = pool; + m->param.recycle_pid = 0; + sys_sem_init(&m->param.op_completed); + + if (nsfw_mem_ring_enqueue(pool, (void *) m) != 1) + { + NSPOL_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + return -1; + } + + i++; + } + + group->msg_pool = pool; + + NSPOL_LOGINF(SC_DPDK_INFO, + "Create app msg pool ok]name=%s, num=%u, size=%u, total_mem=%d", + SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM, MAX_MSG_SIZE, + nsfw_mem_get_len(group->msg_pool, NSFW_MEM_SPOOL)); + MEM_STAT(SPL_APP_RES, SPL_MSG_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len(group->msg_pool, NSFW_MEM_SPOOL)); + return 0; +} + +/***************************************************************************** +* Prototype : spl_regist_recycle +* Description : regist recycle +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_regist_recycle(spl_app_res_group * group) +{ + void *ret = + nsfw_recycle_reg_obj(NSFW_REC_PRO_DEFALUT, NSFW_REC_SBR_SOCKET, NULL); + + if (!ret) + { + NSSBR_LOGERR("failed"); + return -1; + } + + if (NULL == group) + { + NSSBR_LOGERR("g_spl_app_res_group null"); + return -1; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_SPOOL, 90, 3, 16, + CUR_CFG_SOCKET_NUM / 128, CUR_CFG_SOCKET_NUM - 1, + SBR_FD_NETCONN_SIZE, + offsetof(spl_netconn_t, res_chk), + (void *) group->conn_pool, + (void *) group->conn_pool, + spl_force_netconn_free + }; + + (void) nsfw_res_mgr_reg(&scn_cfg); + + nsfw_res_scn_cfg scn_cfg_msg = { NSFW_RES_SCAN_SPOOL, 60, 3, 16, + SPL_MAX_MSG_NUM / 128, SPL_MAX_MSG_NUM, + MAX_MSG_SIZE, + offsetof(data_com_msg, param.res_chk), + (void *) group->msg_pool, + (void *) group->msg_pool, + spl_force_msg_free + }; + (void) nsfw_res_mgr_reg(&scn_cfg_msg); + + return 0; +} + +void spl_reg_tx_pool_mgr(mpool_handle pool_array[], u32 num) +{ + u32 loop; + for (loop = 0; loop < num; loop++) + { + (void) spl_reg_res_txrx_mgr(pool_array[loop]); // will only return 0, no need to check return value + } + + return; +} + +/***************************************************************************** +* Prototype : sbr_create_tx_pool +* Description : create tx pool,spl call this fun +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_create_tx_pool(mpool_handle pool_array[], u32 array_size) +{ + data_com_msg *tx_msg_array = + (data_com_msg *) sbr_create_mzone(SBR_TX_MSG_ARRAY_NAME, + (size_t) sizeof(data_com_msg) * + SBR_TX_MSG_NUM); + + if (!tx_msg_array) + { + NSSBR_LOGERR("Create tx_msg_array zone fail]name=%s, num=%u, size=%u", + SBR_TX_MSG_ARRAY_NAME, SBR_TX_MSG_NUM, + (size_t) sizeof(data_com_msg) * SBR_TX_MSG_NUM); + return -1; + } + + MEM_STAT(SBR_TX_POOL_NAME, SBR_TX_MSG_ARRAY_NAME, NSFW_SHMEM, + (size_t) sizeof(data_com_msg) * SBR_TX_MSG_NUM); + NSSBR_LOGINF + ("Create tx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%u", + SBR_TX_MSG_ARRAY_NAME, tx_msg_array, SBR_TX_MSG_NUM, + sizeof(data_com_msg) * SBR_TX_MSG_NUM); + + mpool_handle mp; + int ret; + char tx_pool_name[64]; + u32 loop; + for (loop = 0; loop < array_size; loop++) + { + ret = + sprintf_s(tx_pool_name, sizeof(tx_pool_name), "%s_%d", + SBR_TX_POOL_NAME, loop); + if (-1 == ret) + { + NSSBR_LOGERR("SPRINTF_S failed]ret=%d", ret); + return -1; + } + + nsfw_mem_mbfpool pool_param; + if (strcpy_s + (pool_param.stname.aname, NSFW_MEM_NAME_LENTH, tx_pool_name) != 0) + { + NSSBR_LOGERR("STRCPY_S failed]name=%s", tx_pool_name); + return -1; + } + + pool_param.isocket_id = -1; + pool_param.stname.entype = NSFW_SHMEM; + pool_param.enmptype = NSFW_MRING_MPMC; + pool_param.uscash_size = 0; + pool_param.uspriv_size = 0; + pool_param.usdata_room = TX_MBUF_MAX_LEN; + pool_param.usnum = SBR_TX_POOL_MBUF_NUM - 1; + + mp = nsfw_mem_mbfmp_create(&pool_param); + if (!mp) + { + NSSBR_LOGERR("Create tx_mbuf_pool fail]name=%s, num=%u, room=%u", + tx_pool_name, SBR_TX_POOL_MBUF_NUM, + pool_param.usdata_room); + return -1; + } + else + { + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + int i = 0; + while (i < (int) SBR_TX_POOL_MBUF_NUM) + { + mbuf = nsfw_shmem_mbfalloc(mp); + if (!mbuf) + { + NSSBR_LOGERR + ("nsfw_mem_mbf_alloc failed,this can not happen"); + return -1; + } + + buf = + (struct spl_pbuf *) ((char *) mbuf + + sizeof(struct common_mem_mbuf)); + int idx = loop * (int) SBR_TX_POOL_MBUF_NUM + i; + sys_sem_init(&tx_msg_array[idx].param.op_completed); + tx_msg_array[idx].param.msg_from = NULL; + buf->msg = (void *) &tx_msg_array[idx]; + (void) res_free(&buf->res_chk); //no need to check return value, as it will do free operation depends on alloc_flag + + if (nsfw_shmem_mbffree(mbuf) < 0) + { + NSSBR_LOGERR + ("nsfw_mem_mbf_free failed,this can not happen"); + return -1; + } + + i++; + } + + pool_array[loop] = mp; +#ifdef SYS_MEM_RES_STAT + g_app_tx_pool[loop] = mp; +#endif + } + } + + spl_reg_tx_pool_mgr(pool_array, array_size); + + NSSBR_LOGINF("Create all tx_mbuf_pool ok]pool_num=%d, total_mem=%d", + array_size, nsfw_mem_get_len(pool_array[0], + NSFW_MEM_MBUF) * array_size); + MEM_STAT(SBR_TX_POOL_NAME, SBR_TX_POOL_NAME, NSFW_SHMEM, + nsfw_mem_get_len(pool_array[0], NSFW_MEM_MBUF) * array_size); + return 0; +} + +spl_app_res_group *spl_create_res_group() +{ + spl_app_res_group *group = spl_create_group(); + if (NULL == group) + { + NSPOL_LOGERR("spl_create_group failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_create_group ok"); + + if (spl_create_ring_pool(group) != 0) + { + NSPOL_LOGERR("spl_create_ring_pool failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_create_ring_pool ok"); + + if (spl_create_msg_pool(group) != 0) + { + NSPOL_LOGERR("spl_create_msg_pool failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_create_msg_pool ok"); + + if (spl_create_netconn_pool(group) != 0) + { + NSPOL_LOGERR("spl_create_netconn_pool failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_create_netconn_pool ok"); + + if (spl_regist_recycle(group) != 0) + { + NSPOL_LOGERR("spl_regist_recycle failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_regist_recycle ok"); + + if (spl_create_tx_pool(group->tx_pool_array, SBR_TX_POOL_NUM) != 0) + { + NSPOL_LOGERR("spl_create_tx_pool failed"); + return NULL; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "spl_create_tx_pool ok"); + + return group; +} + +/***************************************************************************** +* Prototype : spl_init_app_res +* Description : init app res +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int spl_init_app_res() +{ + g_spl_app_res_group = spl_create_res_group(); + if (NULL == g_spl_app_res_group) + { + NSPOL_LOGERR("spl_create_group failed"); + return -1; + } + + return spl_add_instance_res_group(0, g_spl_app_res_group); +} + +/***************************************************************************** +* Prototype : spl_get_conn_array +* Description : get conn array +* Input : u32 pid +* Output : None +* Return Value : spl_netconn_t** +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t **spl_get_conn_array(u32 pid) +{ + return (spl_netconn_t **) ADDR_SHTOL(g_spl_app_res_group->conn_array); +} + +/***************************************************************************** +* Prototype : spl_get_conn_pool +* Description : get conn pool +* Input : None +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle spl_get_conn_pool() +{ + return (mring_handle) ADDR_SHTOL(g_spl_app_res_group->conn_pool); +} + +/***************************************************************************** +* Prototype : spl_get_msg_pool +* Description : get msg pool +* Input : None +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle spl_get_msg_pool() +{ + return (mring_handle) ADDR_SHTOL(g_spl_app_res_group->msg_pool); +} + +/***************************************************************************** +* Prototype : spl_recycle_msg +* Description : recycle msg +* Input : void *data +* void* argv +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int spl_recycle_msg(void *data, void *argv) +{ + if (!data) + { + NSPOL_LOGERR("data is NULL]data=%p,pid=%p", data, argv); + return -1; + } + + data_com_msg *m = (data_com_msg *) data; + u64 pid_64 = (u64) argv; + u32 pid = (u32) pid_64; + if (pid == m->param.recycle_pid) + { + ASYNC_MSG_FREE(m); + } + + return 0; +} + +/***************************************************************************** +* Prototype : spl_recycle_msg_pool +* Description : recycle msg pool +* Input : u32 pid +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void spl_recycle_msg_pool(u32 pid) +{ + mring_handle msg_pool = spl_get_msg_pool(); + if (!msg_pool) + { + NSPOL_LOGERR("msg_pool is NULL,this can not happen]pid=%u", pid); + return; + } + + u64 pid_64 = pid; + (void) nsfw_mem_sp_iterator(msg_pool, 0, SPL_MAX_MSG_NUM, spl_recycle_msg, + (void *) pid_64); +} + +/***************************************************************************** +* Prototype : spl_get_conn_num +* Description : get conn num +* Input : None +* Output : None +* Return Value : u32 +* Calls : +* Called By : +* +*****************************************************************************/ +u32 spl_get_conn_num() +{ + return CUR_CFG_SOCKET_NUM; +} + +/*************************************************** +* description: +***************************************************/ +int sbr_malloc_tx_pool(u32 pid, mpool_handle pool[], u32 pool_num) +{ + int loop; + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + if ((0 == g_res_group_array->pid_array[loop]) + && + __sync_bool_compare_and_swap(&g_res_group_array->pid_array[loop], + 0, pid)) + { + u32 i; + for (i = 0; i < g_res_group_array->thread_num && i < pool_num; + ++i) + { + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL(g_res_group_array->res_group[i]); + pool[i] = ADDR_SHTOL(group->tx_pool_array[loop]); + } + + NSSBR_LOGINF("get tx pool]pid=%d,loop=%d.", pid, loop); + return 0; + } + } + + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + NSSBR_LOGERR("no free pool]loop=%d,pid=%d", loop, + g_res_group_array->pid_array[loop]); + } + + return -1; +} + +/*************************************************** +* description: +***************************************************/ +void spl_free_tx_pool(u32 pid) +{ + int loop; + for (loop = 0; loop < SBR_TX_POOL_NUM; loop++) + { + if (pid == g_res_group_array->pid_array[loop]) + { + u32 i; + for (i = 0; i < g_res_group_array->thread_num; ++i) + { + (void) + nsfw_shmem_mbuf_recycle(g_res_group_array->res_group + [i]->tx_pool_array[loop]); + } + + if (!__sync_bool_compare_and_swap + (&g_res_group_array->pid_array[loop], pid, 0)) + { + NSSBR_LOGERR("free tx_pool failed]loop=%d,pid=%d", loop, pid); + } + else + { + NSSBR_LOGDBG("free tx_pool ok]loop=%d,pid=%d", loop, pid); + } + + break; + } + } +} + +/*************************************************** +* description: +***************************************************/ +mring_handle sbr_get_instance_conn_pool(u32 thread_index) +{ + if (thread_index >= g_res_group_array->thread_num) + { + return NULL; + } + + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL(g_res_group_array->res_group[thread_index]); + return ADDR_SHTOL(group->conn_pool); +} + +/*************************************************** +* description: +***************************************************/ +mring_handle *ss_get_instance_msg_box(u16 thread_index, u16 idx) +{ + if (thread_index >= g_res_group_array->thread_num) + { + thread_index = 0; + } + + if (idx >= SPL_MSG_BOX_NUM) + { + idx = 0; + } + + spl_app_res_group *group = + (spl_app_res_group *) + ADDR_SHTOL(g_res_group_array->res_group[thread_index]); + return ADDR_SHTOL(group->mbox_array[idx]); +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.h b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h new file mode 100644 index 0000000..776edb4 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h @@ -0,0 +1,103 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_APP_RES_H +#define STACKX_APP_RES_H +#include "types.h" +#include "nsfw_mem_api.h" +#include "stackxopts.h" +#include "stackx_spl_share.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SPL_RES_GROUP_ARRAY "spl_res_group_array" + +#define SPL_APP_RES "spl_app_res" +#define SPL_APP_RES_GROUP_NAME "spl_app_res_group" +#define SPL_TX_POOL_NAME "spl_tx_pool" +#define SPL_CONN_POOL_NAME "spl_conn_pool" +#define SPL_CONN_ARRAY_NAME "spl_conn_array" +#define SPL_DFX_ARRAY_NAME "spl_dfx_array" +#define SPL_MSG_POOL_NAME "spl_msg_pool" +#define SPL_RECYCLE_GROUP "spl_recycle_group" +#define SPL_RECV_RING_POOL_NAME "spl_recv_ring_pool" +#define SPL_RECV_RING_ARRAY_NAME "spl_recv_array" + +#define SBR_TX_POOL_NUM APP_POOL_NUM +#define SBR_TX_POOL_MBUF_NUM TX_MBUF_POOL_SIZE +#define SBR_TX_MSG_NUM (SBR_TX_POOL_NUM * SBR_TX_POOL_MBUF_NUM) + +#define SBR_TX_POOL_ARRAY_NAME "sbr_tx_pool_array" +#define SBR_TX_POOL_NAME "sbr_tx_pool" +#define SBR_TX_MSG_ARRAY_NAME "sbr_tx_msg_array" + +#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM) + +typedef struct +{ + PRIMARY_ADDR mring_handle msg_pool; + PRIMARY_ADDR mring_handle conn_pool; + PRIMARY_ADDR spl_netconn_t **conn_array; + PRIMARY_ADDR mring_handle recv_ring_pool; + PRIMARY_ADDR mpool_handle tx_pool_array[SBR_TX_POOL_NUM]; + PRIMARY_ADDR mring_handle mbox_array[SPL_MSG_BOX_NUM]; + i64 extend_member_bit; +} spl_app_res_group; + +typedef struct +{ + u32 pid_array[SBR_TX_POOL_NUM]; + PRIMARY_ADDR spl_app_res_group *res_group[MAX_THREAD_NUM]; + u16 thread_num; +} spl_app_res_group_array; + +extern spl_app_res_group *g_spl_app_res_group; +extern spl_app_res_group_array *g_res_group_array; + +/* call it main thread */ +int spl_init_group_array(); + +/* call these in tcpip thread */ +int spl_init_app_res(); +spl_netconn_t **spl_get_conn_array(u32 pid); +mring_handle spl_get_conn_pool(); +mring_handle spl_get_msg_pool(); +void spl_recycle_msg_pool(u32 pid); +u32 spl_get_conn_num(); +void spl_free_tx_pool(u32 pid); +int spl_add_mbox(mring_handle mbox_array[], u32 array_size); +int spl_add_instance_res_group(u32 thread_index, spl_app_res_group * group); + +/* call these in app */ +int sbr_malloc_tx_pool(u32 pid, mpool_handle pool[], u32 pool_num); +int sbr_attach_group_array(); +mring_handle sbr_get_instance_conn_pool(u32 thread_index); + +/* call these in app and spl */ +mring_handle *ss_get_instance_msg_box(u16 thread_index, u16 index); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.c b/stacks/lwip_stack/lwip_src/common/stackx_common.c new file mode 100644 index 0000000..30567ee --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common.c @@ -0,0 +1,351 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "stackx_common.h" +#include "nstack_securec.h" +#include "nstack_log.h" +#include "types.h" +#include "stackx_types.h" + +int spl_snprintf(char *buffer, int buflen, const char *format, ...) +{ + int len; + va_list ap; + + if ((NULL == buffer) || (0 >= buflen)) + { + return -1; + } + + if (format == NULL) + { + buffer[0] = '\0'; + return -1; + } + + (void) va_start(ap, format); + len = vsnprintf_s(buffer, buflen, buflen - 1, format, ap); + if (-1 == len) + { + va_end(ap); + return -1; + } + + va_end(ap); + if ((len >= buflen) && (buflen > 0) && (buffer != NULL)) + { + buffer[buflen - 1] = '\0'; + } + + return len; +} + +/***************************************************************************** +* Prototype : sbr_create_mzone +* Description : create mzone +* Input : const char* name +* size_t size +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle sbr_create_mzone(const char *name, size_t size) +{ + if (!name) + { + NSFW_LOGERR("name is NULL"); + return NULL; + } + + mzone_handle zone; + nsfw_mem_zone param; + + param.isocket_id = -1; + param.lenth = size; + param.stname.entype = NSFW_SHMEM; + + if (strcpy_s(param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR("STRCPY_S failed]name=%s", name); + return NULL; + } + + zone = nsfw_mem_zone_create(¶m); + if (!zone) + { + NSFW_LOGERR("nsfw_mem_zone_create failed]name=%s, size:%zu", name, + size); + return NULL; + } + + return zone; +} + +/***************************************************************************** +* Prototype : sbr_lookup_mzone +* Description : lookup mzone +* Input : const char* name +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle sbr_lookup_mzone(const char *name) +{ + if (!name) + { + NSFW_LOGERR("name is NULL"); + return NULL; + } + + mzone_handle zone; + nsfw_mem_name param; + + param.entype = NSFW_SHMEM; + param.enowner = NSFW_PROC_MAIN; + if (strcpy_s(param.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR("STRCPY_S failed]name=%s", name); + return NULL; + } + + zone = nsfw_mem_zone_lookup(¶m); + if (!zone) + { + NSFW_LOGERR("nsfw_mem_zone_lookup failed]name=%s", name); + return NULL; + } + + return zone; +} + +/***************************************************************************** +* Prototype : sbr_create_pool +* Description : create pool +* Input : const char* name +* i32 num +* u16 size +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle sbr_create_pool(const char *name, i32 num, u16 size) +{ + if (!name) + { + NSFW_LOGERR("name is NULL"); + return NULL; + } + + nsfw_mem_sppool param; + if (EOK != memset_s(¶m, sizeof(param), 0, sizeof(param))) + { + NSFW_LOGERR("memset error]name=%s", name); + return NULL; + } + + param.enmptype = NSFW_MRING_MPMC; + param.useltsize = size; + param.usnum = num; + param.stname.entype = NSFW_SHMEM; + param.isocket_id = -1; + if (strcpy_s(param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_sp_create(¶m); + if (!ring) + { + NSFW_LOGERR("Create pool failed]name=%s, num=%d, size=%u", name, num, + size); + } + + return ring; +} + +/***************************************************************************** +* Prototype : sbr_create_ring +* Description : create ring +* Input : const char* name +* i32 num +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle sbr_create_ring(const char *name, i32 num) +{ + if (!name) + { + NSFW_LOGERR("name is NULL"); + return NULL; + } + + nsfw_mem_mring param; + if (EOK != memset_s(¶m, sizeof(param), 0, sizeof(param))) + { + NSFW_LOGERR("memset error]name=%s", name); + return NULL; + } + + param.enmptype = NSFW_MRING_MPMC; + param.isocket_id = -1; + param.usnum = num; + param.stname.entype = NSFW_SHMEM; + + if (strcpy_s(param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_ring_create(¶m); + if (!ring) + { + NSFW_LOGERR("Create ring failed]name=%s, num=%d", name, num); + } + + return ring; +} + +/***************************************************************************** +* Prototype : sbr_create_multi_ring +* Description : create multi ring +* Input : const char* name +* u32 ring_size +* i32 ring_num +* mring_handle* array +* nsfw_mpool_type type +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_create_multi_ring(const char *name, u32 ring_size, i32 ring_num, + mring_handle * array, nsfw_mpool_type type) +{ + if (!name) + { + NSFW_LOGERR("name is NULL"); + return -1; + } + + if (!array) + { + NSFW_LOGERR("array is NULL"); + return -1; + } + + nsfw_mem_mring param; + + if (EOK != memset_s(¶m, sizeof(param), 0, sizeof(param))) + { + NSSBR_LOGERR("Error to memset]name=%s", name); + return -1; + } + + param.enmptype = type; + param.stname.entype = NSFW_SHMEM; + if (strcpy_s(param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSSBR_LOGERR("STRCPY_S failed]name=%s", name); + return -1; + } + + param.usnum = ring_size; + param.isocket_id = -1; + if (nsfw_mem_sp_ring_create(¶m, array, ring_num) != 0) + { + NSSBR_LOGERR("Create ring pool failed]name=%s, ring_num=%d", name, + ring_num); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_lookup_ring +* Description : lookup ring +* Input : const char* name +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle sbr_lookup_ring(const char *name) +{ + nsfw_mem_name param; + + param.entype = NSFW_SHMEM; + param.enowner = NSFW_PROC_MAIN; + if (strcpy_s(param.aname, NSFW_MEM_NAME_LENTH, name) != 0) + { + NSFW_LOGERR("STRCPY_S failed]name=%s", name); + return NULL; + } + + mring_handle ring = nsfw_mem_ring_lookup(¶m); + if (!ring) + { + NSFW_LOGERR("lookup ring failed]name=%s", name); + } + + return ring; +} + +int sbr_timeval2msec(struct timeval *pTime, u64 * msec) +{ + if ((pTime->tv_sec < 0) || (pTime->tv_usec < 0)) + { + NSFW_LOGERR("time->tv_sec is nagative"); + return -1; + } + + if (STACKX_MAX_U64_NUM / 1000 < (u64_t) pTime->tv_sec) + { + NSFW_LOGERR("tout.tv_sec is too large]tout.tv_sec=%lu", + pTime->tv_sec); + return -1; + } + + u64 sec2msec = 1000 * pTime->tv_sec; + u64 usec2msec = pTime->tv_usec / 1000; + + if (STACKX_MAX_U64_NUM - sec2msec < usec2msec) + { + NSFW_LOGERR + ("nsec2msec plus sec2usec is too large]usec2msec=%lu,usec2msec=%lu", + usec2msec, sec2msec); + return -1; + } + + *msec = sec2msec + usec2msec; + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.h b/stacks/lwip_stack/lwip_src/common/stackx_common.h new file mode 100644 index 0000000..1293c9e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common.h @@ -0,0 +1,44 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_COMMON_H +#define STACKX_COMMON_H +#include "nsfw_mem_api.h" +//#include "lwip/cc.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +int spl_snprintf(char *buffer, int buflen, const char *format, ...); +mzone_handle sbr_create_mzone(const char *name, size_t size); +mzone_handle sbr_lookup_mzone(const char *name); +mring_handle sbr_create_pool(const char *name, i32 num, u16 size); +mring_handle sbr_create_ring(const char *name, i32 num); +int sbr_create_multi_ring(const char *name, u32 ring_size, i32 ring_num, + mring_handle * array, nsfw_mpool_type type); +mring_handle sbr_lookup_ring(const char *name); +int sbr_timeval2msec(struct timeval *pTime, u64 * msec); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h new file mode 100644 index 0000000..f911ba3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h @@ -0,0 +1,147 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_COMMON_OPT_H +#define STACKX_COMMON_OPT_H +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef O_NONBLOCK +#define O_NONBLOCK 0X800 /* nonblocking I/O */ +#endif + +#if !defined (FIONREAD) || !defined (FIONBIO) +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */ +#define _IO(x, y) (((x) << 8) | (y) | IOC_VOID) +#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#endif + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) +#endif + +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) +#endif + +#ifndef F_GETFL +#define F_GETFL 3 +#endif + +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +#ifndef SPL_SHUT_RD +#define SPL_SHUT_RD 0 +#define SPL_SHUT_WR 1 +#define SPL_SHUT_RDWR 2 +#endif + +/* Flags for struct netconn.flags (u8_t) */ + +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01 + +/** Should this netconn avoid blocking? */ +#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02 + +/** Was the last connect action a non-blocking one? */ +#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 + +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08 + +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define SPL_NETCONN_FLAG_CHECK_WRITESPACE 0x10 + +/* For the netconn API, these values are use as a bitmask! */ +#define SPL_NETCONN_SHUT_RD 1 +#define SPL_NETCONN_SHUT_WR 2 +#define SPL_NETCONN_SHUT_RDWR (SPL_NETCONN_SHUT_RD | SPL_NETCONN_SHUT_WR) +#define STACKX_TIMER_THREAD_SUPPORT 1 + +/* Flags for netconn_write (u8_t) */ +#define SPL_NETCONN_NOFLAG 0x00 +#define SPL_NETCONN_NOCOPY 0x00 +#define SPL_NETCONN_COPY 0x01 +#define SPL_NETCONN_MORE 0x02 +#define SPL_NETCONN_DONTBLOCK 0x04 + +#define SPL_TCP_NODELAY 0x01 +#define SPL_TCP_KEEPALIVE 0x02 +#define SPL_TCP_KEEPIDLE 0x04 +#define SPL_TCP_KEEPINTVL 0x05 +#define SPL_TCP_KEEPCNT 0x06 +#define SPL_TCP_LINGER2 0x08 +#define SPL_TCP_DEFER_ACCEPT 0x09 +#define SPL_TCP_INFO 0x0B + +typedef enum spl_netconn_type +{ + SPL_NETCONN_INVALID = 0, + SPL_NETCONN_TCP = 0x10, + SPL_NETCONN_UDP = 0x20, + SPL_NETCONN_UDPLITE = 0x21, + SPL_NETCONN_UDPNOCHKSUM = 0x22, + SPL_NETCONN_RAW = 0x40, +} spl_netconn_type_t; + +typedef enum spl_netconn_state +{ + SPL_NETCONN_NONE, + SPL_NETCONN_WRITE, + SPL_NETCONN_LISTEN, + SPL_NETCONN_CONNECT, + SPL_NETCONN_CLOSE, +} spl_netconn_state_t; + +typedef enum spl_tcp_state +{ + SPL_CLOSED = 0, + SPL_LISTEN = 1, + SPL_SYN_SENT = 2, + SPL_SYN_RCVD = 3, + SPL_ESTABLISHED = 4, + SPL_FIN_WAIT_1 = 5, + SPL_FIN_WAIT_2 = 6, + SPL_CLOSE_WAIT = 7, + SPL_CLOSING = 8, + SPL_LAST_ACK = 9, + SPL_TIME_WAIT = 10 +} spl_tcp_state_t; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_debug.h b/stacks/lwip_stack/lwip_src/common/stackx_debug.h new file mode 100644 index 0000000..bdad724 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_debug.h @@ -0,0 +1,70 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_DEBUG_H__ +#define __STACKX_DEBUG_H__ + +//#include "lwip/arch.h" +#include + +#include + +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** lower two bits indicate dbug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define STACKX_DBG_LEVEL_ALL 0x00 +#define STACKX_DBG_LEVEL_OFF STACKX_DBG_LEVEL_ALL /* compatibility define only */ +#define STACKX_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define STACKX_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define STACKX_DBG_LEVEL_SEVERE 0x03 +#define STACKX_DBG_MASK_LEVEL 0x00 + +/** flag to enable that dbug message */ +#define STACKX_DBG_ON NS_LOG_STACKPOOL_ON + +/** flag to disable that dbug message */ +#define STACKX_DBG_OFF NS_LOG_STACKPOOL_OFF + +/** flag for indicating a tracing_message (to follow program flow) */ +#define STACKX_DBG_TRACE NS_LOG_STACKPOOL_TRACE + +/** flag for indicating a state dbug message (to follow module states) */ +#define STACKX_DBG_STATE NS_LOG_STACKPOOL_STATE + +/** flag for indicating newly added code, not thoroughly tested yet */ +#define STACKX_DBG_FRESH NS_LOG_STACKPOOL_FRESH + +/** flag for to halt after printing this dbug message */ +#define STACKX_DBG_HALT NS_LOG_STACKPOOL_HALT + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_DEBUG_H__ */ diff --git a/stacks/lwip_stack/lwip_src/common/stackx_err.h b/stacks/lwip_stack/lwip_src/common/stackx_err.h new file mode 100644 index 0000000..1d0fc20 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_err.h @@ -0,0 +1,68 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_ERR_H +#define STACKX_ERR_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ + +#define SPL_ERR_IS_FATAL(e) ((e) < ERR_ISCONN) + +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ + +#define ERR_ARG -14 /* Illegal argument. */ + +#define ERR_IF -15 /* Low-level netif error */ +#define ERR_ALREADY -16 /* previous connect attemt has not yet completed */ +#define ERR_PROTOTYPE -17 /* prototype error or some other generic error. + the operation is not allowed on current socket */ + +#define ERR_CALLBACK -18 /* callback error */ +#define ERR_CANTASSIGNADDR -19 /* Cannot assign requested address */ +#define ERR_CONTAINER_ID -20 /*Illegal container id */ +#define ERR_NOTSOCK -21 /*not a socket */ + +#define ERR_CLOSE_WAIT -22 /*closed in established state */ + +#define ERR_EPROTONOSUPPORT -23 /* Protocol not supported */ + +#define ERR_FAULTRECOVERY -24 /*SPL just recovered from a fatal fault */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c new file mode 100644 index 0000000..86f0b39 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c @@ -0,0 +1,276 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "stackx_ip_addr.h" +#include "nstack_log.h" +#include "spl_def.h" + +/* Here for now until needed in other places in stackx*/ +#ifndef isprint +#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up) +#define isprint(c) in_range(c, 0x20, 0x7f) +#define isdigit(c) in_range(c, '0', '9') +#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F')) +#define islower(c) in_range(c, 'a', 'z') +#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') +#endif + +/** + * Ascii internet address interpretation routine. + * The value returned is in network order. + * + * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1") + * @return ipaddress in network order + */ +u32 spl_ipaddr_addr(const char *cp) +{ + spl_ip_addr_t val; + + if (spl_ipaddr_aton(cp, &val)) + { + return ip4_addr_get_u32(&val); + } + + return (SPL_IPADDR_NONE); +} + +/** + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broad cast address. + * + * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1") + * @param addr pointer to which to save the ipaddress in network order + * @return 1 if cp could be converted to addr, 0 on failure + */ +int spl_ipaddr_aton(const char *cp, spl_ip_addr_t * addr) +{ + u32 val; + u8 base; + char c; + u32 parts[4]; + u32 *pp = parts; + + if (cp == NULL) + { + return 0; + } + + c = *cp; + for (;;) + { + /* + * Get number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, 1-9=decimal. + */ + if (!isdigit(c)) + { + return (0); + } + + val = 0; + base = 10; + if (c == '0') + { + c = *++cp; + if ((c == 'x') || (c == 'X')) + { + base = 16; + c = *++cp; + } + else + { + base = 8; + } + } + + for (;;) + { + if (isdigit(c)) + { + val = (val * base) + (int) (c - '0'); + c = *++cp; + } + else if ((base == 16) && isxdigit(c)) + { + val = (val << 4) | (int) (c + 10 - (islower(c) ? 'a' : 'A')); + c = *++cp; + } + else + { + break; + } + } + + if (c == '.') + { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + { + return (0); + } + + *pp++ = val; + c = *++cp; + } + else + { + break; + } + } + + /* + * Check for trailing characters. + */ + if ((c != '\0') && !isspace(c)) + { + return (0); + } + + /* + * Concoct the address according to + * the number of parts specified. + */ + switch (pp - parts + 1) + { + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffffUL) + { + return (0); + } + + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + { + return (0); + } + + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + { + return (0); + } + + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + default: + NSPOL_LOGERR("unhandled"); + + return (0); + } + + if (addr) + { + ip4_addr_set_u32(addr, spl_htonl(val)); + } + + return (1); +} + +/** + * Convert numeric IPaddress into decimal dotted ASCII representation. + * returns ptr to static buffer; not reentrant! + * + * @param addr ipaddress in network order to convert + * @return pointer to a global static (!) buffer that holds the ASCII + * represenation of addr + */ +char *spl_ipaddr_ntoa(const spl_ip_addr_t * addr) +{ + static char str[16]; + + return spl_ipaddr_ntoa_r(addr, str, 16); +} + +/** + * Same as spl_ipaddr_ntoa, but reentrant since a user-supplied buffer is used. + * + * @param addr ipaddress in network order to convert + * @param buf target buffer where the string is stored + * @param buflen length of buf + * @return either pointer to buf which now holds the ASCII + * representation of addr or NULL if buf was too small + */ +char *spl_ipaddr_ntoa_r(const spl_ip_addr_t * addr, char *buf, int buflen) +{ + u32 s_addr; + char inv[3]; + char *rp; + u8 *ap; + u8 rem; + u8 n; + u8 i; + int len = 0; + + s_addr = ip4_addr_get_u32(addr); + + rp = buf; + ap = (u8 *) & s_addr; + for (n = 0; n < 4; n++) + { + i = 0; + do + { + rem = *ap % (u8) 10; + *ap /= (u8) 10; + inv[i++] = '0' + rem; + } + while (*ap); + + while (i--) + { + if (len++ >= buflen) + { + return NULL; + } + + *rp++ = inv[i]; + } + + if (len++ >= buflen) + { + return NULL; + } + + *rp++ = '.'; + ap++; + } + + *--rp = 0; + return buf; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h new file mode 100644 index 0000000..43dcb3a --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h @@ -0,0 +1,82 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_IP_ADDR_H +#define STACKX_IP_ADDR_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +typedef struct spl_ip_addr +{ + u32 addr; +} spl_ip_addr_t; + +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) + +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) + +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define SPL_IPADDR_NONE ((u32)0xffffffffUL) + +/** Set address to IPADDR_ANY (no need for spl_htonl()) */ +#define spl_ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) + +/** Set complete address to zero */ +#define spl_ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) + +/** IPv4 only: set the IPaddress given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) + +/** IPv4 only: get the IPaddress as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) + +/** For backwards compatibility */ +#define spl_ip_ntoa(ipaddr) spl_ipaddr_ntoa(ipaddr) + +u32 spl_ipaddr_addr(const char *cp); +int spl_ipaddr_aton(const char *cp, spl_ip_addr_t * addr); + +/** returns ptr to static buffer; not reentrant! */ +char *spl_ipaddr_ntoa(const spl_ip_addr_t * addr); +char *spl_ipaddr_ntoa_r(const spl_ip_addr_t * addr, char *buf, int buflen); + +#define spl_inet_addr(cp) spl_ipaddr_addr(cp) +#define spl_inet_aton(cp, paddr) spl_ipaddr_aton(cp, (spl_ip_addr_t*)(paddr)) +#define spl_inet_ntoa(paddr) spl_ipaddr_ntoa((spl_ip_addr_t*)&(paddr)) +#define spl_inet_ntoa_r(addr, buf, buflen) spl_ipaddr_ntoa_r((spl_ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h new file mode 100644 index 0000000..5a646ae --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h @@ -0,0 +1,145 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_IP_TOS_H +#define STACKX_IP_TOS_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_LOWCOST 0x02 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_MINCOST IPTOS_LOWCOST +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_ROUTINE 0x00 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) + +#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3) + +#define TC_PRIO_BESTEFFORT 0 +#define TC_PRIO_FILLER 1 +#define TC_PRIO_BULK 2 +#define TC_PRIO_INTERACTIVE_BULK 4 +#define TC_PRIO_INTERACTIVE 6 +#define TC_PRIO_CONTROL 7 +#define TC_PRIO_MAX 15 + +#define ECN_OR_COST(class ) TC_PRIO_ ## class + +static u8 stackx_ip_tos2prio[(IPTOS_TOS_MASK >> 1) + 1] = { + TC_PRIO_BESTEFFORT, + ECN_OR_COST(FILLER), + TC_PRIO_BESTEFFORT, + ECN_OR_COST(BESTEFFORT), + TC_PRIO_BULK, + ECN_OR_COST(BULK), + TC_PRIO_BULK, + ECN_OR_COST(BULK), + TC_PRIO_INTERACTIVE, + ECN_OR_COST(INTERACTIVE), + TC_PRIO_INTERACTIVE, + ECN_OR_COST(INTERACTIVE), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST(INTERACTIVE_BULK), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST(INTERACTIVE_BULK) +}; + +static inline char stackx_rt_tos2priority(u8 tos) +{ + return stackx_ip_tos2prio[IPTOS_TOS(tos) >> 1]; +} + +typedef enum +{ + STACKX_PRIM, + STACKX_HIGH, + STACKX_MEDIUM, + STACKX_LOW +} stackx_prio; + +static inline stackx_prio stackx_get_prio(u8 tos) +{ + if (0 == tos) + { + return STACKX_PRIM; + } + char prio = stackx_rt_tos2priority(tos); + if ((TC_PRIO_INTERACTIVE == prio)) + { + return STACKX_HIGH; + } + else if ((TC_PRIO_BESTEFFORT == prio) + || (TC_PRIO_INTERACTIVE_BULK == prio)) + { + return STACKX_MEDIUM; + } + else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio)) + { + return STACKX_LOW; + } + + return STACKX_PRIM; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h new file mode 100644 index 0000000..67f0925 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h @@ -0,0 +1,43 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_NETBUF_H +#define STACKX_NETBUF_H +#include "stackx_pbuf.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct spl_netbuf +{ + struct spl_pbuf *p; + spl_ip_addr_t addr; + u16 port; +} spl_netbuf; + +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_fromport(buf) ((buf)->port) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c new file mode 100644 index 0000000..b1478b8 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c @@ -0,0 +1,220 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_spl_share.h" +#include "stackx_pbuf.h" +#include "common_mem_mbuf.h" +#include "nstack_securec.h" +#include "nsfw_maintain_api.h" +#include "stackx_tcp_opt.h" +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif +#include "nsfw_shmem_mng.h" +/***************************************************************************** +* Prototype : sbr_malloc_pbuf +* Description : malloc spl_pbuf,use it in app +* Input : mpool_handle mp +* u16 len +* u32 mbuf_data_size +* u16 offset +* Output : None +* Return Value : struct pbuf* +* Calls : +* Called By : +* +*****************************************************************************/ +struct spl_pbuf *sbr_malloc_pbuf(mpool_handle mp, u16 len, u32 mbuf_data_size, + u16 offset) +{ + if ((len < offset) || (len > mbuf_data_size)) + { + NSSBR_LOGERR("len is invalid]len=%u", len); + return NULL; + } + + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + + mbuf = nsfw_shmem_mbfalloc(mp); + if (unlikely(mbuf == NULL)) + { + NS_LOG_CTRL(LOG_CTRL_HUGEPAGE_ALLOC_FAIL, LOGSBR, "NSSBR", NSLOG_WAR, + "alloc mbuf failed"); + return NULL; + } + + mbuf->data_len = len; + mbuf->next = NULL; + mbuf->nb_segs = 1; + mbuf->pkt_len = len; + buf = + (struct spl_pbuf *) ((char *) mbuf + sizeof(struct common_mem_mbuf)); + res_alloc(&buf->res_chk); + buf->next = 0; + void *tmp = common_pktmbuf_mtod(mbuf, void *); + buf->payload = (void *) (ADDR_LTOSH(tmp) + offset); + buf->tot_len = len - offset; + buf->len = len - offset; + buf->type = SPL_PBUF_HUGE; + buf->flags = 0; + buf->freeNext = NULL; + buf->conn_a = 0; + buf->proto_type = SPL_PBUF_PROTO_NONE; + NSSBR_LOGDBG("malloc pbuf ok]buf=%p,PRIMARY_ADDR=%p", buf, + ADDR_LTOSH(buf)); + return buf; +} + +u32_t +spl_pbuf_copy_partial(struct spl_pbuf * buf, void *dataptr, u32_t len, + u32_t offset) +{ + struct spl_pbuf *p = buf; + u32_t buf_copy_len; + u32_t copied_total = 0; + char *databuf = (char *) dataptr; + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; + p = PTR_SHTOL(struct spl_pbuf *, p->next_a)) + { + if (offset != 0 && offset >= p->len) + { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } + else if (p->len - offset > len) + { + /* copy from this buffer. maybe only partially. */ + (void) common_memcpy(databuf, ADDR_SHTOL(p->payload_a + offset), + len); + copied_total += len; + break; + } + else + { + buf_copy_len = p->len - offset; + /* copy the necessary parts of the buffer */ + (void) common_memcpy(databuf, ADDR_SHTOL(p->payload_a + offset), + buf_copy_len); + + copied_total += buf_copy_len; + databuf += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + + return copied_total; +} + +int spl_tx_force_buf_free(void *data) +{ + struct common_mem_mbuf *mbuf = data; + if (NULL == mbuf) + { + return FALSE; + } + + struct spl_pbuf *p_buf = + (struct spl_pbuf *) (((char *) mbuf) + + sizeof(struct common_mem_mbuf)); + u8 tempflag = p_buf->res_chk.u8Reserve; + if ((mbuf->refcnt == 0) || (tempflag & DPDK_SEND_FLAG)) + { + return FALSE; + } + + NSFW_LOGINF("free mbuf]%p", data); + (void) nsfw_shmem_mbffree((mbuf_handle) mbuf); + return TRUE; +} + +int spl_force_buf_free(void *data) +{ + struct common_mem_mbuf *mbuf = data; + + if (NULL == mbuf || (mbuf->refcnt == 0)) + { + return FALSE; + } + + NSFW_LOGINF("free mbuf]%p", data); + (void) nsfw_shmem_mbffree((mbuf_handle) mbuf); + return TRUE; +} + +int spl_reg_res_tx_mgr(mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof(struct common_mem_mbuf) + offsetof(struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_tx_force_buf_free + }; + (void) nsfw_res_mgr_reg(&scn_cfg); + return 0; +} + +int spl_reg_res_rxmt_mgr(mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof(struct common_mem_mbuf) + offsetof(struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_tx_force_buf_free + }; /*Can use same function for time */ + (void) nsfw_res_mgr_reg(&scn_cfg); + return 0; +} + +int spl_reg_res_txrx_mgr(mpool_handle * pool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) pool; + if (NULL == mp) + { + return 0; + } + + nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16, + mp->size / 128, mp->size, + mp->elt_size, + sizeof(struct common_mem_mbuf) + offsetof(struct spl_pbuf, res_chk), + mp, + mp->pool_data, + spl_force_buf_free + }; + (void) nsfw_res_mgr_reg(&scn_cfg); + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h new file mode 100644 index 0000000..21a2abb --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_PBUF_H +#define STACKX_PBUF_H + +#include "common_mem_base_type.h" +#include "common_mem_mbuf.h" +#include "nsfw_mem_api.h" +#include "stackx_pbuf_comm.h" +#ifdef HAL_LIB +#else +#include "common_pal_bitwide_adjust.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NEED_ACK_FLAG 0x01 /* This spl_pbuf may have multiple references. */ +#define PBUF_FREE_FLAG 0x04 /* This spl_pbuf has been free. */ +#define DPDK_SEND_FLAG 0x10 /* This spl_pbuf has been sent to DPDK. */ +#define LOOP_SEND_FLAG 0x40 /* This spl_pbuf has been looped to IP layer and not received by app layer yet. */ + +struct spl_pbuf *sbr_malloc_pbuf(mpool_handle mp, u16 len, + u32 mbuf_data_size, u16 offset); +void sbr_free_pbuf(struct spl_pbuf *p); +u32 spl_pbuf_copy_partial(struct spl_pbuf *p, void *dataptr, u32_t len, + u32_t offset); +int spl_reg_res_txrx_mgr(mpool_handle * pool); +int spl_reg_res_tx_mgr(mpool_handle * pool); + +/* release buf hold by app on abnormal exit */ +/* + *For TX mbuf: recycle_flg can be: MBUF_UNUSED, MBUF_HLD_BY_APP, MBUF_HLD_BY_SPL. + *For TX mbuf: recycle_flg can be: MBUF_UNSUED, app pid. + */ +static inline void pbuf_set_recycle_flg(struct spl_pbuf *p, uint32_t flg) +{ + uint32_t *recycle_flg; + struct spl_pbuf *q = p; + struct common_mem_mbuf *m; + + while (q != NULL) + { + m = (struct common_mem_mbuf *) ((char *) q - + sizeof(struct common_mem_mbuf)); +#ifdef HAL_LIB +#else + recycle_flg = + (uint32_t *) ((char *) (m->buf_addr) + RTE_PKTMBUF_HEADROOM - + sizeof(uint32_t)); +#endif + *recycle_flg = flg; + q = (struct spl_pbuf *) ADDR_SHTOL(q->next_a); + } +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h new file mode 100644 index 0000000..a73565b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h @@ -0,0 +1,109 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_PBUF_COMM_H +#define STACKX_PBUF_COMM_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SPL_PBUF_TRANSPORT_HLEN 20 +#define SPL_PBUF_UDP_HLEN 8 +#define SPL_PBUF_IP_HLEN 20 + +#define SPL_PBUF_VLAN_HLEN 0 + +#ifndef SPL_PBUF_LINK_HLEN +#define SPL_PBUF_LINK_HLEN (14 + SPL_PBUF_VLAN_HLEN) +#endif + +typedef enum spl_pbuf_layer +{ + SPL_PBUF_TRANSPORT, + SPL_PBUF_UDP, + SPL_PBUF_IP, + SPL_PBUF_LINK, + SPL_PBUF_RAW, + SPL_PBUF_MAX_LAYER, +} spl_pbuf_layer; + +typedef enum spl_pbuf_type +{ + SPL_PBUF_RAM, /* pbuf data is stored in RAM */ + SPL_PBUF_ROM, /* pbuf data is stored in ROM */ + SPL_PBUF_REF, /* pbuf comes from the pbuf pool */ + SPL_PBUF_POOL, /* pbuf payload refers to RAM */ + SPL_PBUF_HUGE /* pbuf is stored in HugePage memory in struct common_mem_mbuf */ +} spl_pbuf_type; + +enum spl_pbuf_proto +{ + SPL_PBUF_PROTO_NONE, + SPL_PBUF_TCP_SEND, + SPL_PBUF_TCP_RECV +} spl_pbuf_proto; + +typedef struct spl_pbuf +{ + /** next pbuf in singly linked pbuf chain */ + union + { + struct spl_pbuf *next; + u64 next_a; + }; + + /** pointer to the actual data in the buffer */ + union + { + void *payload; + u64 payload_a; + }; + + union + { + void *msg; + u64 msg_a; + }; + + union + { + void *conn; + u64 conn_a; + }; + + struct spl_pbuf *freeNext; // This pointer will point to next pbuf you want to free in stackx + + u32 tot_len; + u32 len; + int proto_type; + u16 ref; + u8 type; + u8 flags; + nsfw_res res_chk; + +} spl_pbuf; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h new file mode 100644 index 0000000..d3b3c2e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h @@ -0,0 +1,241 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_SPL_MSG_H +#define STACKX_SPL_MSG_H +#include "nsfw_msg.h" +#include "stackx_ip_addr.h" +#include "stackx_spl_share.h" +#include "stackx_common_opt.h" +#include +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +enum spl_tcpip_msg_type +{ + SPL_TCPIP_NEW_MSG_API, +#if STACKX_TIMER_THREAD_SUPPORT + SPL_TCPIP_MSG_TIMER, +#endif +#if STACKX_NETIF_API + SPL_TCPIP_MSG_NETIFAPI, +#endif + SPL_TCPIP_MSG_CALLBACK, + SPL_TCPIP_MSG_IP_MODULE, + + SPL_TCPIP_MSG_MAX, //the number of enum + SPL_TCPIP_MSG_BOTTOM = MAX_MAJOR_TYPE //the max number of enum +}; + +enum api_msg_type +{ + SPL_API_DO_NEWCONN = 0, + SPL_API_DO_DELCON, + SPL_API_DO_RECV, + SPL_API_DO_GETADDR, + SPL_API_DO_BIND, + SPL_API_DO_CONNECT, + SPL_API_DO_LISTEN, + SPL_API_DO_CLOSE, + SPL_API_DO_SET_SOCK_OPT, + SPL_API_DO_GET_SOCK_OPT, + SPL_API_DO_SEND, + SPL_API_DO_WRITE, + SPL_API_DO_POST, + SPL_API_DO_SHOW, + SPL_API_DO_EXTREN_SOCK_SET, + SPL_API_DO_ENABLE_TRACE, + SPL_API_GET_PROTOCOL, + SPL_API_DO_IOCTL_OPT, + SPL_API_DO_GETSOCK_NAME, + SPL_API_DO_DUMP_L4, + SPL_API_DO_PBUF_FREE, + SPL_API_DO_APP_TOUCH, /* app send its version info to nStackMain */ + + SPL_API_MSG_MAX, //the number of enum + SPL_API_MSG_BOTTOM = MAX_MINOR_TYPE //the max number of enum +}; + +/* TODO: move thes to apporpriate file */ +#define TCP_RTO_MAX ((unsigned)(120*1000)) /* 120s */ +#define TCP_RTO_MIN ((unsigned)(200)) /* 200ms */ + +#define TCP_TIMEOUT_INIT ((unsigned)(1*1000)) /* RFC6298 2.1 initial RTO value */ +#define CONN_TCP_MEM_MIN_LINE ((TX_MBUF_POOL_SIZE)/1024) //conn level : min value of send_buf +#define CONN_TCP_MEM_DEF_LINE ((TX_MBUF_POOL_SIZE)/128) //conn level : default value of send_buf +#define CONN_TCP_MEM_MAX_LINE ((TX_MBUF_POOL_SIZE)/12) + +#define SOF_DEBUG 0x01U +#define SOF_ACCEPTCONN 0x02U +#define SOF_DONTROUTE 0x10U +#define SOF_USELOOPBACK 0x40U +#define SOF_LINGER 0x80U +#define SOF_OOBINLINE 0x0100U +#define SOF_REUSEPORT 0x0200U + +/* General structure for calling APIs*/ +typedef struct api_param_t +{ + data_com_msg *m; + i64 comm_private_data; +} api_param; + +/* SPL_API_DO_SEND */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *p; + spl_ip_addr_t local_ip; + spl_ip_addr_t addr; + spl_ip_addr_t srcAddr; + u16 port; + u16 srcPort; + u16 toport_chksum; + u8 tos; + u8 pad; + u8 flags; + i64 extend_member_bit; +} msg_send_buf; + +/* SPL_API_DO_BIND */ +typedef struct +{ + spl_ip_addr_t ipaddr; + u16 port; + i64 extend_member_bit; +} msg_bind; + +/* SPL_API_DO_CLOSE */ +typedef struct +{ + long time_started; + u8 shut; + i64 extend_member_bit; +} msg_close; + +/* SPL_API_DO_CONNECT */ +typedef struct +{ + spl_ip_addr_t local_ip; + spl_ip_addr_t ipaddr; + u16 port; + i64 extend_member_bit; +} msg_connect; + +/* SPL_API_DO_DELCON */ +typedef struct +{ + PRIMARY_ADDR struct spl_netconn *conn; + PRIMARY_ADDR struct spl_pbuf *buf; + long time_started; + pid_t pid; + u8 shut; + u8 msg_box_ref; /* use it for priority */ + u8 notify_omc; /* bool */ + i64 extend_member_bit; +} msg_delete_netconn; + +/* SPL_API_DO_WRITE */ +typedef struct msg_write_buf_T +{ + PRIMARY_ADDR struct spl_pbuf *p; + struct msg_write_buf_T *next; + size_t len; + u8 apiflags; + i64 extend_member_bit; +} msg_write_buf; + +/* SPL_API_DO_LISTEN */ +typedef struct +{ + mring_handle conn_pool; + u8 backlog; + i64 extend_member_bit; +} msg_listen; + +/* SPL_API_DO_NEWCONN */ +typedef struct +{ + PRIMARY_ADDR struct spl_netconn *conn; + spl_netconn_type_t type; + u8 proto; + int socket; + i64 extend_member_bit; +} msg_new_netconn; + +/* SPL_API_DO_RECV */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *p; + u32 len; + i64 extend_member_bit; +} msg_recv_buf; + +/* SPL_API_DO_GETSOCK_NAME */ +typedef struct +{ + struct sockaddr sock_addr; + u8 cmd; + i64 extend_member_bit; +} msg_getaddrname; + +/* SPL_API_DO_GET_SOCK_OPT,SPL_API_DO_SET_SOCK_OPT */ +typedef struct +{ + int level; + int optname; + PRIMARY_ADDR mring_handle msg_box; /* IP_TOS, spl will get new msg box for app */ + union + { + int int_optval; + //struct in_addr inaddr_optval; + //struct linger _linger; + struct timeval timeval_optval; + struct tcp_info tpinfo; + //ipmreq ipmreq_optval; //Multicast support later + } optval; + + u32 optlen; + i64 extend_member_bit; +} msg_setgetsockopt; + +/* SPL_API_DO_PBUF_FREE */ +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *buf; + i64 extend_member_bit; +} msg_free_buf; + +/* app send its version info to nStackMain */ +#define NSTACK_VERSION_LEN 128 +/* SPL_API_DO_APP_TOUCH */ +typedef struct +{ + u32_t hostpid; + char app_version[NSTACK_VERSION_LEN]; +} msg_app_touch; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c new file mode 100644 index 0000000..a0cb5f3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c @@ -0,0 +1,192 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_spl_msg.h" +#include "stackx_spl_share.h" +#include "nstack_log.h" +#include "nsfw_msg_api.h" +#include "nsfw_recycle_api.h" + +/***************************************************************************** +* Prototype : ss_reset_conn_recycle +* Description : reset conn recycle +* Input : netconn_recycle* recycle +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void ss_reset_conn_recycle(netconn_recycle * recycle) +{ + recycle->accept_from = NULL; + recycle->is_listen_conn = 0; + (void) nsfw_pidinfo_init(&recycle->pid_info); + recycle->fork_ref = 0; + recycle->delay_msg = NULL; + recycle->delay_flag = SS_DELAY_STOPPED; +} + +/***************************************************************************** +* Prototype : ss_reset_conn +* Description : reset conn +* Input : spl_netconn_t* conn +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void ss_reset_conn(spl_netconn_t * conn) +{ + conn->recv_obj = 0; + conn->private_data = 0; + conn->msg_box = NULL; + conn->snd_buf = 0; + conn->epoll_flag = 0; + conn->recv_avail_prod = 0; + conn->recv_avail_cons = 0; + conn->rcvevent = 0; + conn->state = SPL_NETCONN_NONE; + conn->sendevent = 0; + conn->errevent = 0; + conn->shut_status = 0xFFFF; + conn->flags = 0; + conn->last_err = 0; + conn->CanNotReceive = 0; + conn->bind_thread_index = 0; + conn->tcp_sndbuf = 0; + conn->tcp_wmem_alloc_cnt = 0; + conn->tcp_wmem_sbr_free_cnt = 0; + conn->tcp_wmem_spl_free_cnt = 0; + conn->mss = 0; + conn->remote_port = 0; + conn->remote_ip.addr = 0; + conn->local_ip.addr = 0; + conn->local_port = 0; + conn->type = SPL_NETCONN_INVALID; + conn->tcp_state = SPL_CLOSED; + ss_reset_conn_recycle(&conn->recycle); + conn->extend_member_bit = 0; + conn->epInfo = NULL; +} + +/***************************************************************************** +* Prototype : ss_init_conn +* Description : init conn +* Input : spl_netconn_t* conn +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_init_conn(spl_netconn_t * conn, mring_handle pool, spl_netconn_type_t type) +{ + res_alloc(&conn->res_chk); + + conn->type = type; + conn->recycle.fork_ref = 1; + conn->recv_ring_valid = 1; + sys_sem_init(&conn->close_completed); + NSSBR_LOGINF("malloc conn ok]conn=%p,pool=%p", conn, pool); +} + +/***************************************************************************** +* Prototype : ss_malloc_conn +* Description : malloc conn, only used in spl +* Input : mring_handle pool +* netconn_type_t type +* Output : None +* Return Value : spl_netconn_t* +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t *ss_malloc_conn(mring_handle pool, spl_netconn_type_t type) +{ + spl_netconn_t *conn = NULL; + + if (nsfw_mem_ring_dequeue(pool, (void **) &conn) != 1) + { + NSSBR_LOGERR("malloc conn failed"); + return NULL; + } + + ss_init_conn(conn, pool, type); + return conn; +} + +/***************************************************************************** +* Prototype : ss_malloc_conn_app +* Description : malloc conn, only used in app +* Input : mring_handle pool +* netconn_type_t type +* Output : None +* Return Value : spl_netconn_t* +* Calls : +* Called By : +* +*****************************************************************************/ +spl_netconn_t *ss_malloc_conn_app(mring_handle pool, spl_netconn_type_t type) +{ + spl_netconn_t *conn = NULL; + + if (nsfw_mem_ring_dequeue(pool, (void **) &conn) != 1) + { + NSSBR_LOGERR("malloc conn failed"); + return NULL; + } + + if (ss_add_pid(conn, get_sys_pid()) < 0) + { + NSSBR_LOGERR("ss_add_pid failed]conn=%p", conn); + } + + ss_init_conn(conn, pool, type); + return conn; +} + +/***************************************************************************** +* Prototype : ss_free_conn +* Description : free conn +* Input : spl_netconn_t* conn +* mring_handle pool +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void ss_free_conn(spl_netconn_t * conn) +{ + ss_reset_conn(conn); + + if (res_free(&conn->res_chk)) + { + NSFW_LOGERR("conn refree!]conn=%p", conn); + return; + } + + mring_handle pool = ss_get_conn_pool(conn); + if (nsfw_mem_ring_enqueue(pool, (void *) conn) != 1) + { + NSSBR_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + } + + NSSBR_LOGINF("free conn ok]conn=%p,pool=%p", conn, pool); +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h new file mode 100644 index 0000000..3dcaf70 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h @@ -0,0 +1,444 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_SPL_SHARE_H +#define STACKX_SPL_SHARE_H +#include "types.h" +#include "common_mem_api.h" +#include "nsfw_mem_api.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_ip_addr.h" +#include +#include "spl_opt.h" +#include "stackx_ip_tos.h" +#include "stackx_common_opt.h" +#include "stackx_tx_box.h" +#include "pidinfo.h" +//#include "stackx_dfx_api.h" +#include "compiling_check.h" +#include "nsfw_msg.h" +#include "stackx_spl_msg.h" +#include "nsfw_hal_api.h" +#include "stackx_types.h" +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MSG_PRIO_QUEUE_NUM 3 +COMPAT_PROTECT_RETURN(MSG_PRIO_QUEUE_NUM, 3); + +#define SPL_MSG_BOX_NUM (MSG_PRIO_QUEUE_NUM + 1) + +#define SBR_FD_NETCONN_SIZE (256 * 3) +COMPAT_PROTECT_RETURN(SBR_FD_NETCONN_SIZE, 256 * 3); + +#define SS_NETCONN_SIZE (256 * 2) +#define SBR_FD_SIZE (SBR_FD_NETCONN_SIZE - SS_NETCONN_SIZE) + +typedef struct +{ + PRIMARY_ADDR mring_handle msg_pool; + PRIMARY_ADDR mring_handle conn_pool; + PRIMARY_ADDR struct spl_netconn **conn_array; + u32 conn_num; + i64 extend_member_bit; +} sbr_recycle_group; + +typedef enum +{ + SS_DELAY_STARTED, + SS_DELAY_STOPPING, + SS_DELAY_STOPPED, + SS_DELAY_AGAIN +} ss_delay_flag; + +typedef enum +{ + NORMAL_RECV_RING = 0, + CUSTOM_RECV_RING = 1, +} recv_ring_type; + +typedef struct +{ + PRIMARY_ADDR sbr_recycle_group *group; + PRIMARY_ADDR struct spl_netconn *accept_from; /* for recycle fd in listen */ + void *delay_msg; + nsfw_pidinfo pid_info; + volatile i16 fork_ref; + i8 is_listen_conn; + i8 delay_flag; +} netconn_recycle; + +typedef struct spl_netconn +{ + i64 recv_obj; + i64 comm_pcb_data; /* only used by spl */ + i64 private_data; /* only used by spl */ + PRIMARY_ADDR mring_handle msg_box; + PRIMARY_ADDR mring_handle recv_ring; + volatile u32 snd_buf; + volatile i32 epoll_flag; + /*here using prod/cons to instead recv_avail, avoid atomic oper. */ + volatile u32_t recv_avail_prod; /*the product of recv_avail */ + volatile u32_t recv_avail_cons; /*the consume of recv_avail */ + volatile i32 rcvevent; + spl_netconn_state_t state; + u16 sendevent; + u16 errevent; + volatile u16 shut_status; + u8 flags; + i8 last_err; + u8 CanNotReceive; + u8 recv_ring_valid; + u16 bind_thread_index; + u16 mss; + sys_sem_st close_completed; + mring_handle conn_pool; /* where the conn in pcb is from */ + + void *epInfo; + + /* The following shared field access rules: protocol stack process + * is responsible for writing, socket api process read only + */ + i32 send_bufsize; + i32 tcp_sndbuf; + u32 tcp_wmem_alloc_cnt; + u32 tcp_wmem_sbr_free_cnt; + volatile u32 tcp_wmem_spl_free_cnt; + u16 remote_port; + u16 local_port; + spl_ip_addr_t remote_ip; + spl_ip_addr_t local_ip; + spl_netconn_type_t type; + spl_tcp_state_t tcp_state; + + /* for recycle */ + netconn_recycle recycle; + nsfw_res res_chk; + i64 extend_member_bit; +} spl_netconn_t; /* sizeof(spl_netconn_t) need < SS_NETCONN_SIZE */ +SIZE_OF_TYPE_PLUS8_NOT_LARGER_THAN_RETURN(spl_netconn_t, SS_NETCONN_SIZE); + +typedef struct +{ + /** + * it will increase after every restart which used for + * tell different runnings. + */ + u32 running_ref_no; + + /* only increased when fault to restart */ + u32 fault_ref_no; + + /* the procedures before upgrade are finished successfully */ + u32 prepare_upgrade_done; + +} spl_init_info_t; + +typedef struct netifExt +{ + struct netifExt *next; + u16_t id; + char if_name[HAL_MAX_NIC_NAME_LEN]; + hal_hdl_t hdl; + u16_t num_packets_recv; +} netifExt; + +static inline mring_handle ss_get_msg_pool(spl_netconn_t * sh) +{ + sbr_recycle_group *group = + (sbr_recycle_group *) ADDR_SHTOL(sh->recycle.group); + return ADDR_SHTOL(group->msg_pool); +} + +static inline mring_handle ss_get_conn_pool(spl_netconn_t * sh) +{ + sbr_recycle_group *group = + (sbr_recycle_group *) ADDR_SHTOL(sh->recycle.group); + return ADDR_SHTOL(group->conn_pool); +} + +static inline int ss_is_nonblock_flag(spl_netconn_t * sh) +{ + return (sh->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0; +} + +static inline int ss_get_nonblock_flag(spl_netconn_t * sh) +{ + return ss_is_nonblock_flag(sh) ? O_NONBLOCK : 0; +} + +static inline void ss_set_nonblock_flag(spl_netconn_t * sh, u32 flag) +{ + if (flag) + { + sh->flags |= SPL_NETCONN_FLAG_NON_BLOCKING; + } + else + { + sh->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING; + } +} + +static inline int ss_get_last_errno(spl_netconn_t * sh) +{ + return sh->last_err; +} + +static inline i32 ss_get_recv_event(spl_netconn_t * sh) +{ + return sh->rcvevent; +} + +static inline int ss_can_not_recv(spl_netconn_t * sh) +{ + return sh->CanNotReceive; +} + +static inline int ss_is_shut_rd(spl_netconn_t * sh) +{ + int status = sh->shut_status; + return ((SPL_SHUT_RD == status) || (SPL_SHUT_RDWR == status)); +} + +static inline void ss_set_shut_status(spl_netconn_t * sh, u16 how) +{ + sh->shut_status = how; +} + +static inline u16 ss_get_shut_status(spl_netconn_t * sh) +{ + return sh->shut_status; +} + +static inline void ss_sub_recv_event(spl_netconn_t * sh) +{ + __sync_fetch_and_sub(&sh->rcvevent, 1); +} + +static inline void ss_add_recv_event(spl_netconn_t * sh) +{ + __sync_fetch_and_add(&sh->rcvevent, 1); +} + +static inline i64 ss_get_recv_obj(spl_netconn_t * sh) +{ + return sh->recv_obj; +} + +static inline i64 ss_get_private_data(spl_netconn_t * sh) +{ + return sh->private_data; +} + +static inline i64 ss_get_comm_private_data(spl_netconn_t * sh) +{ + return sh->comm_pcb_data; +} + +static inline int ss_recv_ring_valid(spl_netconn_t * sh) +{ + return sh->recv_ring_valid; +} + +static inline mring_handle ss_get_recv_ring(spl_netconn_t * sh) +{ + return (mring_handle) ADDR_SHTOL(sh->recv_ring); +} + +static inline void ss_set_send_event(spl_netconn_t * sh, u16 value) +{ + sh->sendevent = value; +} + +static inline int ss_is_noautorecved_flag(spl_netconn_t * sh) +{ + return (sh->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0; +} + +static inline int ss_get_noautorecved_flag(spl_netconn_t * sh) +{ + return ss_is_noautorecved_flag(sh) ? SPL_NETCONN_FLAG_NO_AUTO_RECVED : 0; +} + +static inline void ss_set_noautorecved_flag(spl_netconn_t * sh, u8 flag) +{ + if (flag) + { + sh->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED; + } + else + { + sh->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED; + } +} + +static inline void ss_set_state(spl_netconn_t * sh, spl_netconn_state_t state) +{ + sh->state = state; +} + +static inline int ss_is_write_state(spl_netconn_t * sh) +{ + return (SPL_NETCONN_WRITE == sh->state); +} + +static inline int ss_is_listen_state(spl_netconn_t * sh) +{ + return (SPL_NETCONN_LISTEN == sh->state); +} + +static inline void ss_sub_recv_avail(spl_netconn_t * sh, int value) +{ + sh->recv_avail_cons += value; +} + +static inline i32 ss_get_recv_avail(spl_netconn_t * sh) +{ + return sh->recv_avail_prod - sh->recv_avail_cons; +} + +static inline u16 ss_get_mss(spl_netconn_t * sh) +{ + return sh->mss; +} + +static inline spl_ip_addr_t *ss_get_remote_ip(spl_netconn_t * sh) +{ + return &(sh->remote_ip); +} + +static inline u16 ss_get_remote_port(spl_netconn_t * sh) +{ + return sh->remote_port; +} + +static inline spl_tcp_state_t ss_get_tcp_state(spl_netconn_t * sh) +{ + return sh->tcp_state; +} + +static inline u16 ss_get_bind_thread_index(spl_netconn_t * sh) +{ + return sh->bind_thread_index; +} + +static inline void +ss_set_bind_thread_index(spl_netconn_t * sh, u16 bind_thread_index) +{ + sh->bind_thread_index = bind_thread_index; +} + +static inline void ss_set_msg_box(spl_netconn_t * sh, mring_handle box) +{ + sh->msg_box = (mring_handle) ADDR_LTOSH(box); +} + +static inline mring_handle ss_get_msg_box(spl_netconn_t * sh) +{ + return (mring_handle) ADDR_SHTOL(sh->msg_box); +} + +static inline spl_ip_addr_t *ss_get_local_ip(spl_netconn_t * sh) +{ + return &sh->local_ip; +} + +static inline void ss_set_local_ip(spl_netconn_t * sh, u32 addr) +{ + if (!sh) + { + return; + } + sh->local_ip.addr = addr; +} + +static inline u16 ss_get_local_port(spl_netconn_t * sh) +{ + return sh->local_port; +} + +static inline void ss_set_local_port(spl_netconn_t * sh, u16 local_port) +{ + sh->local_port = local_port; +} + +static inline void +ss_set_accept_from(spl_netconn_t * sh, spl_netconn_t * accept_from) +{ + sh->recycle.accept_from = accept_from; +} + +static inline void +ss_set_is_listen_conn(spl_netconn_t * sh, i8 is_listen_conn) +{ + sh->recycle.is_listen_conn = is_listen_conn; +} + +static inline i32 ss_inc_fork_ref(spl_netconn_t * sh) +{ + return __sync_add_and_fetch(&sh->recycle.fork_ref, 1); +} + +static inline i32 ss_dec_fork_ref(spl_netconn_t * sh) +{ + return __sync_sub_and_fetch(&sh->recycle.fork_ref, 1); +} + +static inline i32 ss_get_fork_ref(spl_netconn_t * sh) +{ + return sh->recycle.fork_ref; +} + +static inline int ss_add_pid(spl_netconn_t * sh, pid_t pid) +{ + return nsfw_add_pid(&sh->recycle.pid_info, pid); +} + +static inline int ss_del_pid(spl_netconn_t * sh, pid_t pid) +{ + return nsfw_del_pid(&sh->recycle.pid_info, pid); +} + +static inline int ss_is_pid_exist(spl_netconn_t * sh, pid_t pid) +{ + return nsfw_pid_exist(&sh->recycle.pid_info, pid); +} + +static inline int ss_is_pid_array_empty(spl_netconn_t * sh) +{ + return nsfw_pidinfo_empty(&sh->recycle.pid_info); +} + +spl_netconn_t *ss_malloc_conn(mring_handle pool, spl_netconn_type_t type); +spl_netconn_t *ss_malloc_conn_app(mring_handle pool, spl_netconn_type_t type); +void ss_free_conn(spl_netconn_t * conn); +void ss_reset_conn(spl_netconn_t * conn); + +typedef void (*ss_close_conn_fun) (void *close_data, u32 delay_sec); +int ss_recycle_conn(void *close_data, ss_close_conn_fun close_conn); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h new file mode 100644 index 0000000..cac3dcb --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h @@ -0,0 +1,42 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_TCP_OPT_H__ +#define __STACKX_TCP_OPT_H__ + +#include "spl_opt.h" + +/* TCP Options flags */ +#define TF_ACK_DELAY ((u32_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u32_t)0x02U) /* Immediate ACK. */ +#define TF_WINDOWSCALING ((u32_t)0x40U) /* Window scaling option enabled */ +#define TF_INFR ((u32_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u32_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u32_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u32_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u32_t)0x100U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u32_t)0x80U) + +/* TCP segment Options flags */ +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_OPTS_WS (u8_t)0x08U /* Include window scaling option. */ + +#define STACKX_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + \ + (flags & TF_SEG_OPTS_WS ? 4 : 0) +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c new file mode 100644 index 0000000..e7694ae --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c @@ -0,0 +1,62 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackxopts.h" +#include "nstack_log.h" +#include "stackx_tx_box.h" +#include "nsfw_mt_config.h" + +#define MZ_STACKX_RING_NAME "VppTCP_Ring" +#define MZ_STACKX_PRIORITY_RING_NAME "VppTCP_Priority%u_Ring" + +/* + * Given the stackx ring name template above, get the queue name + */ +const char *get_stackx_ring_name() +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char rbuffer[sizeof(MZ_STACKX_RING_NAME) + 16]; + + int retVal = + spl_snprintf(rbuffer, sizeof(rbuffer) - 1, MZ_STACKX_RING_NAME); + + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return rbuffer; +} + +const char *get_stackx_priority_ring_name(unsigned priority) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char prbuffer[sizeof(MZ_STACKX_PRIORITY_RING_NAME) + 32]; + + int retVal = spl_snprintf(prbuffer, sizeof(prbuffer) - 1, + MZ_STACKX_PRIORITY_RING_NAME, priority); + + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return prbuffer; +} diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h new file mode 100644 index 0000000..611ecfe --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h @@ -0,0 +1,39 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_TX_BOX_H +#define STACKX_TX_BOX_H +#include "sys/types.h" +#include "nsfw_mem_api.h" +#include "stackx_common.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +const char *get_stackx_ring_name(); +const char *get_stackx_priority_ring_name(unsigned priority); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackx_types.h b/stacks/lwip_stack/lwip_src/common/stackx_types.h new file mode 100644 index 0000000..6c78a20 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackx_types.h @@ -0,0 +1,68 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_TYPES_H +#define STACKX_TYPES_H + +#include +#include +#include +#include +#include +#include +#if 1 +#ifndef STACKX_MAX_S16_NUM +#define STACKX_MAX_S16_NUM ((s16_t)0x7fff) +#endif + +#ifndef STACKX_MAX_U16_NUM +#define STACKX_MAX_U16_NUM ((u16_t)0xFfff) +#endif + +#ifndef STACKX_MAX_U32_NUM +#define STACKX_MAX_U32_NUM ((u32_t)0xffffffff) +#endif + +#ifndef STACKX_MAX_S32_NUM +#define STACKX_MAX_S32_NUM ((s32_t)0x7fffffff) +#endif + +#ifndef STACKX_MAX_U64_NUM +#define STACKX_MAX_U64_NUM ((u64_t)0xffffffffffffffff) +#endif + +#ifndef STACKX_MAX_S64_NUM +#define STACKX_MAX_S64_NUM ((s64_t)0x7fffffffffffffff) +#endif +#endif + +#if 1 +typedef uint64_t u64_t; +typedef int64_t s64_t; + +typedef uint32_t u32_t; +typedef int32_t s32_t; + +typedef uint16_t u16_t; +typedef int16_t s16_t; + +typedef uint8_t u8_t; +typedef int8_t s8_t; + +typedef uintptr_t mem_ptr_t; +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/common/stackxopts.h b/stacks/lwip_stack/lwip_src/common/stackxopts.h new file mode 100644 index 0000000..6c95499 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/common/stackxopts.h @@ -0,0 +1,53 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_OPTS_H +#define STACKX_OPTS_H + +struct memory_statics +{ + char name[120]; + long size; +}; + +extern u32 g_type; +extern struct memory_statics memory_used_size[80]; + +#define DPDK_MEMORY_COUNT(memory, len)\ +{\ + if (g_type < MAX_MEMORY_USED_SIZE)\ + {\ + const char * ptr_memory = memory;\ + if (ptr_memory && EOK != strcpy_s(memory_used_size[g_type].name, sizeof(memory_used_size[g_type].name), ptr_memory))\ + {\ + NSPOL_LOGERR("STRCPY_S failed.");\ + }\ + memory_used_size[g_type].size =(long) len;\ + g_type++;\ + }\ +} + +#define SPL_MAX_UDP_MSG_LEN (0xFFFF -28) +#define RECV_MAX_POOL 4 +#define MAX_TRY_GET_MEMORY_TIMES 4 +#define MAX_MEMORY_USED_SIZE 80 +#define SPL_IP_HLEN 20 +#define SPL_TCP_HLEN 20 +#define SPL_TCP_MAX_OPTION_LEN 40 +#define SPL_FRAME_MTU 1500 +#define SPL_TCP_SEND_MAX_SEG_PER_MSG 5 + +#endif diff --git a/stacks/lwip_stack/lwip_src/core/global_tick.c b/stacks/lwip_stack/lwip_src/core/global_tick.c new file mode 100644 index 0000000..5e09218 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/global_tick.c @@ -0,0 +1,48 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_api.h" +#include "nstack_share_res.h" +#include "nstack_securec.h" + +extern nstack_tick_info_t g_nstack_timer_tick; + +int init_stackx_global_tick(void) +{ + nsfw_mem_zone mzone; + + if (strcpy_s + (mzone.stname.aname, NSFW_MEM_NAME_LENGTH, + NSTACK_GLOBAL_TICK_SHM) != 0) + { + NSPOL_LOGERR("STRCPY_S fail"); + return -1; + } + + mzone.stname.entype = NSFW_SHMEM; + mzone.isocket_id = -1; + mzone.lenth = sizeof(uint64_t); + mzone.ireserv = 0; + + g_nstack_timer_tick.tick_ptr = (u64 *) nsfw_mem_zone_create(&mzone); + if (NULL == g_nstack_timer_tick.tick_ptr) + { + NSPOL_LOGERR("Failed to create global timer tick memory"); + return -1; + } + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/core/spl_pbuf.c b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c new file mode 100644 index 0000000..dea577f --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c @@ -0,0 +1,605 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" + +#include "spl_def.h" +#include "spl_pbuf.h" +#include "stackx_pbuf.h" + +#include "stackx_spl_share.h" +#include "spl_api.h" + +#include "nsfw_maintain_api.h" +#include "netif/sc_dpdk.h" +#include + +#include +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_instance.h" + +#include "sys.h" +#include "mem.h" +#include "memp.h" +//#include "sockets.h" +//#include +#include +#include +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct spl_pbuf)) +u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +u16_t g_offSetArry[SPL_PBUF_MAX_LAYER] = + { PBUF_TRANSPORT_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + SPL_PBUF_UDP_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN, + SPL_PBUF_LINK_HLEN, + 0 +}; + +inline struct spl_pbuf *spl_pbuf_alloc_hugepage(spl_pbuf_layer layer, + u16_t length, + spl_pbuf_type Type, + u16_t proc_id, void *net_conn) +{ + struct spl_pbuf *p; + u16_t offset; + u16_t count = 0; + spl_netconn_t *conn = (spl_netconn_t *) net_conn; + + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, + "spl_pbuf_alloc_hugepage]length=%" U16_F, length); + + /* determine header offset */ + if (likely(layer < SPL_PBUF_MAX_LAYER)) + { + offset = g_offSetArry[layer]; + } + else + { + NSPOL_LOGERR("spl_pbuf_alloc_hugepage: bad pbuf layer"); + return NULL; + } + + if (unlikely(length < offset || Type != SPL_PBUF_HUGE)) + { + NSPOL_LOGERR("input is invalid!]length=%u, Type = %d", length, Type); + return NULL; + } + + p = spl_mbuf_malloc(length, SPL_PBUF_HUGE, &count); + + if (p == NULL) + { + /* last_log_prt_time and unprint_log_count indeed have multi-thread issue, + * but their values don't have precision requirement. No risk. */ + NS_LOG_CTRL(LOG_CTRL_HUGEPAGE_ALLOC_FAIL, STACKPOOL, "NSLWIP", + NSLOG_ERR, + "pbuf_alloc_huge: Could not allocate PBUF for SPL_PBUF_HUGE"); + + return NULL; + } + + if (conn) + { + p->conn_a = ADDR_LTOSH(conn); + } + else + { + p->conn_a = 0; + } + + p->tot_len -= offset; + p->len -= offset; + p->next_a = 0; + + p->payload_a = p->payload_a + offset; + + p->proto_type = SPL_PBUF_PROTO_NONE; + + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_alloc]length=%" U16_F ",p=%p", length, (void *) p); + return p; +} + +inline int spl_pbuf_internal_copy(struct spl_pbuf *dst, struct spl_pbuf *src) +{ + u32_t dst_len = dst->len; + u32_t src_len = src->len; + u32_t dst_pos = 0; + u32_t src_pos = 0; + while (dst != NULL && src != NULL) + { + if (dst_len > src_len) + { + if (NULL == + common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos, + PTR_SHTOL(char *, src->payload_a) + src_pos, + src_len)) + { + NSPOL_LOGERR("rte_memcpy error"); + return -1; + } + + dst_len -= src_len; + dst_pos += src_len; + src = ADDR_SHTOL(src->next_a); + src_len = src != NULL ? src->len : 0; + src_pos = 0; + } + else if (dst_len < src_len) + { + if (NULL == + common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos, + PTR_SHTOL(char *, src->payload_a) + src_pos, + dst_len)) + { + NSPOL_LOGERR("rte_memcpy error"); + return -1; + } + + src_len -= dst_len; + src_pos += dst_len; + dst = ADDR_SHTOL(dst->next_a); + dst_len = dst != NULL ? dst->len : 0; + dst_pos = 0; + } + else + { + if (NULL == + common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos, + PTR_SHTOL(char *, src->payload_a) + src_pos, + dst_len)) + { + NSPOL_LOGERR("rte_memcpy error"); + return -1; + } + + src = ADDR_SHTOL(src->next_a); + src_len = src != NULL ? src->len : 0; + src_pos = 0; + dst = ADDR_SHTOL(dst->next_a); + dst_len = dst != NULL ? dst->len : 0; + dst_pos = 0; + } + } + return 0; +} + +void spl_pbuf_realloc(struct spl_pbuf *p, u32_t new_len) +{ + if (NULL != p && p->type == SPL_PBUF_HUGE) + { + p->tot_len = new_len; + p->len = new_len; + return; + } +} + +void spl_pbuf_free(struct spl_pbuf *p) +{ + struct spl_pbuf *q; + u8_t count = 0; + + NSPOL_LOGINF(PBUF_DEBUG, "Freeing PBF %p", p); + + if (unlikely(p == NULL || p->type != SPL_PBUF_HUGE)) + { + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_LEVEL_SERIOUS, + "input param illegal]p=%p, type=%d", p, + p ? p->type : -1); + return; + } + + (void) count; + + /* de-allocate all consecutive pbufs from the head of the chain that + * obtain a zero reference count after decrementing*/ + do + { + /* remember next pbuf in chain for next iteration */ + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, + "spl_pbuf_free: deallocating]buf=%p", (void *) p); + q = (struct spl_pbuf *) ADDR_SHTOL(p->next_a); + if (res_free(&p->res_chk)) + { + //NSPOL_LOGERR("res_free failed]p=%p", p); + } + + count++; + { + pbuf_set_recycle_flg(p, MBUF_UNUSED); /* release buf hold by app on abnormal exit */ + spl_mbuf_free((char *) p - sizeof(struct common_mem_mbuf)); + p->res_chk.u8Reserve |= PBUF_FREE_FLAG; + } + + /* proceed to next pbuf */ + p = q; + } + while (p != NULL); + + /* return number of de-allocated pbufs */ + return; +} + +void spl_pbuf_cat(struct spl_pbuf *h, struct spl_pbuf *t) +{ + struct spl_pbuf *p; + + if (h == NULL || t == NULL) + { + NSPOL_LOGERR("pbuf_cat: h=NULL||t=NULL!!"); + return; + } + + for (p = h; p->next_a != 0; p = PTR_SHTOL(struct spl_pbuf *, p->next_a)) + { + /* add total length of second chain to all totals of first chain */ + p->tot_len += t->tot_len; + } + + if (0 != p->next_a) + { + NSPOL_LOGERR + ("pbuf_cat: p is not the last pbuf of the first chain, p->next_a != 0"); + return; + } + + /* add total length of second chain to last pbuf total of first chain */ + p->tot_len += t->tot_len; + + /* chain last pbuf of head (p) with first of tail (t) */ + p->next_a = (uint64_t) ADDR_LTOSH_EXT(t); + + /* p->next now references t, but the caller will drop its reference to t, + * so netto there is no change to the reference count of t. + */ +} + +err_t spl_pbuf_copy(struct spl_pbuf * p_to, struct spl_pbuf * p_from) +{ + u32_t offset_to = 0; + u32_t offset_from = 0; + u32_t len = 0; + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, "pbuf_copy]p_to=%p,p_from=%p", + (void *) p_to, (void *) p_from); + + if (! + ((p_to != NULL) && (p_from != NULL) + && (p_to->tot_len >= p_from->tot_len))) + { + NSPOL_LOGERR("pbuf_copy: target not big enough to hold source"); + return ERR_ARG; + } + + do + { + if (p_to == NULL) + { + NSPOL_LOGERR("pbuf_copy: target pbuf not exist: p_to == NULL!!"); + return ERR_ARG; + } + + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) + { + + len = p_from->len - offset_from; + } + else + { + + len = p_to->len - offset_to; + } + + if (EOK != + memmove_s((u8_t *) ADDR_SHTOL(p_to->payload_a) + offset_to, len, + (u8_t *) ADDR_SHTOL(p_from->payload_a) + offset_from, + len)) + { + NSPOL_LOGERR("MEMMOVE_S failed"); + return ERR_MEM; + } + + offset_to += len; + offset_from += len; + if (offset_to > p_to->len) + { + NSPOL_LOGERR + ("pbuf_copy: target offset not match: offset_to > p_to->len."); + return ERR_VAL; + } + if (offset_to == p_to->len) + { + offset_to = 0; + p_to = (struct spl_pbuf *) ADDR_SHTOL(p_to->next_a); + } + + if (offset_from >= p_from->len) + { + /* on to next p_from (if any) */ + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_copy: source offset not match: offset_from >= p_from->len"); + offset_from = 0; + p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) + { + if ((p_from->next_a != 0)) + { + NSPOL_LOGERR("pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) + { + /* don't copy more than one packet! */ + if ((p_to->next_a != 0)) + { + NSPOL_LOGERR("pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + } + while (p_from); + + NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, + "pbuf_copy: end of chain reached."); + return ERR_OK; +} + +err_t +splpbuf_to_pbuf_transport_copy(struct pbuf * p_to, struct spl_pbuf * p_from) +{ + if (EOK != memmove_s((u8_t *) p_to->payload, + p_to->len, (u8_t *) ADDR_SHTOL(p_from->payload_a), + p_from->len)) + { + NSPOL_LOGERR("MEMMOVE_S failed"); + return ERR_MEM; + } + + return ERR_OK; +} + +err_t splpbuf_to_pbuf_copy(struct pbuf * p_to, struct spl_pbuf * p_from) +{ + u32_t offset_to = 0; + u32_t offset_from = 0; + u32_t len = 0; + + NSPOL_LOGINF(NETIF_DEBUG, "splpbuf_to_pbuf_copy"); + + if (! + ((p_to != NULL) && (p_from != NULL) + && (p_to->tot_len >= p_from->tot_len))) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target not big enough to hold source"); + return ERR_ARG; + } + NSPOL_LOGINF(PBUF_DEBUG, + "splpbuf_to_pbuf_copy]p_to=%p [type %d tot_len %d], p_from=%p [type %d tot_len %d]", + (void *) p_to, p_to->type, p_to->tot_len, (void *) p_from, + p_from->type, p_from->tot_len); + do + { + NSPOL_LOGINF(NETIF_DEBUG, "copying...."); + if (p_to == NULL) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target not big enough to hold source p_to len [%d] p_from len [%d]", + p_to->tot_len, p_from->tot_len); + return ERR_ARG; + } + + if ((p_to->len - offset_to) >= (p_from->len - offset_from)) + { + + len = p_from->len - offset_from; + } + else + { + + len = p_to->len - offset_to; + } + + if (EOK != memmove_s((u8_t *) p_to->payload + offset_to, + len, + (u8_t *) ADDR_SHTOL(p_from->payload_a) + + offset_from, len)) + { + NSPOL_LOGERR("MEMMOVE_S failed"); + return ERR_MEM; + } + + offset_to += len; + offset_from += len; + if (offset_to > p_to->len) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy: target offset not match: offset_to > p_to->len."); + return ERR_VAL; + } + if (offset_to == p_to->len) + { + offset_to = 0; + p_to = p_to->next; + + NSPOL_LOGINF(NETIF_DEBUG, + "splpbuf_to_pbuf_copy: p_to next %p", p_to); + } + + if (offset_from >= p_from->len) + { + /* on to next p_from (if any) */ + NSPOL_LOGINF(NETIF_DEBUG, + "splpbuf_to_pbuf_copy: source offset not match: offset_from >= p_from->len"); + offset_from = 0; + p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a); + NSPOL_LOGINF(NETIF_DEBUG, + "splpbuf_to_pbuf_copy: pfrom next %p", p_from); + } + + if ((p_from != NULL) && (p_from->len == p_from->tot_len)) + { + if ((p_from->next_a != 0)) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + + if ((p_to != NULL) && (p_to->len == p_to->tot_len)) + { + /* don't copy more than one packet! */ + if ((p_to->next != NULL)) + { + NSPOL_LOGERR + ("splpbuf_to_pbuf_copy() does not allow packet queues!"); + return ERR_VAL; + } + } + } + while (p_from); + + NSPOL_LOGDBG(NETIF_DEBUG, "splpbuf_to_pbuf_copy: end of chain reached."); + return ERR_OK; +} + +err_t pbuf_to_splpbuf_copy(struct spl_pbuf * p_to, struct pbuf * p_from) +{ + int offset = 0; + void *data = NULL; + + do + { + data = (u8_t *) (p_to->payload_a) + offset; + memcpy(data, (u8_t *) p_from->payload, p_from->len); + offset = offset + p_from->len; + if (offset >= 2048) + { + NSPOL_LOGERR("More thank 2K size"); + return ERR_MEM; + } + p_from = p_from->next; + } + while (p_from != NULL); + + return ERR_OK; +} + +struct pbuf *spl_convert_spl_pbuf_to_pbuf(struct spl_pbuf *p_from) +{ + struct pbuf *p_to = NULL; + + p_to = pbuf_alloc(PBUF_RAW, p_from->tot_len, PBUF_POOL); + if (p_to) + { + splpbuf_to_pbuf_copy(p_to, p_from); + } + return p_to; +} + +spl_pbuf_layer get_pbuf_layer_from_pbuf_payload(struct pbuf * buf) +{ + + struct eth_hdr *ethhdr; + spl_pbuf_layer layer = SPL_PBUF_TRANSPORT; + u16_t type; + + if (buf->len <= SIZEOF_ETH_HDR) + { + NSPOL_LOGINF(PBUF_DEBUG, + "get_pbuf_layer_from_payload failed. length is wrong"); + return layer; + } + ethhdr = (struct eth_hdr *) buf->payload; + type = spl_htons(ethhdr->type); + + NSPOL_LOGINF(PBUF_DEBUG, "packet type %x", type); + + switch (type) + { + case ETHTYPE_IP: + layer = SPL_PBUF_IP; + break; + case ETHTYPE_ARP: + layer = SPL_PBUF_LINK; + break; + default: + layer = SPL_PBUF_TRANSPORT; + break; + } + + return layer; +} + +void print_pbuf_payload_info(struct pbuf *buf, bool send) +{ + + struct eth_hdr *ethhdr; + u16_t type; + + if (buf->len <= SIZEOF_ETH_HDR) + { + NSPOL_LOGINF(PBUF_DEBUG, + "get_pbuf_layer_from_payload failed. length is wrong"); + return; + } + ethhdr = (struct eth_hdr *) buf->payload; + type = spl_htons(ethhdr->type); + + if (send) + { + NSPOL_LOGINF(PBUF_DEBUG, "send packet start type %x len %d *****", + type, buf->len); + } + else + { + NSPOL_LOGINF(PBUF_DEBUG, + "receive packet start type %x len %d ########", type, + buf->len); + } + + switch (type) + { + case ETHTYPE_IP: + NSPOL_LOGINF(TCPIP_DEBUG, "ip packet len %d tot len %d type %x", + buf->len, buf->tot_len, type); + struct ip_hdr *ip = + (struct ip_hdr *) ((char *) buf->payload + SIZEOF_ETH_HDR); + NSPOL_LOGINF(PBUF_DEBUG, "ip packet src %x dest %x proto %d", + ip->src, ip->dest, ip->_proto); + break; + case ETHTYPE_ARP: + NSPOL_LOGINF(TCPIP_DEBUG, "arp packet len %d tot len %d type %x", + buf->len, buf->tot_len, type); + break; + default: + NSPOL_LOGINF(TCPIP_DEBUG, + "other packet len %d tot len %d type %x", buf->len, + buf->tot_len, type); + break; + } + return; +} diff --git a/stacks/lwip_stack/lwip_src/core/spl_timers.c b/stacks/lwip_stack/lwip_src/core/spl_timers.c new file mode 100644 index 0000000..5e8e5d9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/spl_timers.c @@ -0,0 +1,599 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "opt.h" +#include "nsfw_mem_api.h" +#include "def.h" +#include "sc_dpdk.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nstack_share_res.h" + +#include +#include +#include +#include +#include "nsfw_ps_api.h" +#include "spl_timers.h" +#include "common_mem_api.h" + +extern sys_thread_t g_timerThread_id; + +/*Since the range of the dpdk read TSC value is u64_t, it changes*/ + +#ifndef typecheck +#define typecheck(type, x) \ +({ type __dummy; \ + typeof(x)__dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ + }) +#endif + +#ifndef time_after_eq +#define time_after_eq(a, b) \ +(typecheck(unsigned long, a) \ + && typecheck(unsigned long, b) \ + && ((long)(a) - (long)(b) >= 0)) +#endif + +#define MIN_TIME_PICE 50 +#define MICRO_PER_SECOND 1000 +#define NANO_PER_MICROSECOND 1000000 +#define NANO_PER_SECOND 1000000000 + +#define PTIMER_MSG_BUFFER_SIZE 4096 + +#define PTIMER_STATE_INACTIVE 0x00 +#define PTIMER_STATE_ENQUEUED 0x01 +#define gettid() syscall(__NR_gettid) + +#define TIMER_CONTEXT_NAME "TIMER_CONTEXT_NAME" + +static timer_t lazy_tim; +static timer_t lazy_tim_retry; +static struct ptimer_base ptimer; +static sys_sem_t ptimer_lock; + +extern void recycle_tmr(struct ptimer_node *tmo); + +extern nstack_tick_info_t g_nstack_timer_tick; + +/* + *************************** + * rb_tree wrapper function* + *************************** + */ +NSTACK_STATIC void +remove_ptimer(struct ptimer_node *tmo, struct ptimer_base *base) +{ + if (tmo == NULL) + { + NSPOL_LOGERR("input parameter tmo is null"); + return; + } + if (!(tmo->state & PTIMER_STATE_ENQUEUED)) + { + NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "the timer state is: PTIMER_STATE_INACTIVE, no need to remove!"); + return; + } + + if (base->first == &tmo->node) + { + base->first = rb_next(&tmo->node); + } + + rb_erase(&tmo->node, &base->active); + + tmo->state = PTIMER_STATE_INACTIVE; +} + +NSTACK_STATIC struct ptimer_node *search_ptimer(struct ptimer_msg *msg) +{ + if (msg == NULL) + { + NSPOL_LOGERR("input parameter msg is null"); + return NULL; + } + if (msg->node) + { + return msg->node; + } + + return NULL; + +} + +err_t del_ptimer(struct ptimer_msg * msg) +{ + struct ptimer_node *tmo; + + tmo = search_ptimer(msg); + if (tmo) + { + remove_ptimer(tmo, &ptimer); + NSPOL_LOGDBG(TIMERS_DEBUG, "del]thread=%u,ptimer_node=%p", tmo->index, + tmo); + return ERR_OK; + } + + NSPOL_LOGERR("ptime_node not found!!"); + return ERR_VAL; +} + +/* + * Ptimer inserted into rb_tree + * @param node: the ptimer node pointer + * @param base: the ptimer root_base pointer + */ +NSTACK_STATIC void +enqueue_ptimer(struct ptimer_node *tmo, struct ptimer_base *base) +{ + struct rb_node **linknode; + struct rb_node *parent = NULL; + struct ptimer_node *entry; + int leftmost = 1; + if (tmo == NULL || base == NULL) + { + NSPOL_LOGERR("input parameter is null"); + return; + } + + if ((tmo->state & PTIMER_STATE_ENQUEUED)) + { + NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "the timer state is: PTIMER_STATE_ENQUEUED"); + return; + } + + linknode = &base->active.rb_node; + while (*linknode) + { + parent = *linknode; + entry = rb_entry(parent, struct ptimer_node, node); + //XXX: do by the equal case is all of price of the large case + if (time_after_eq(entry->abs_nsec, tmo->abs_nsec)) + { + linknode = &(*linknode)->rb_left; + } + else + { + linknode = &(*linknode)->rb_right; + leftmost = 0; + } + } + + /* + * Insert the timer to the rb_tree and check whether it + * replaces the first pending timer + */ + if (leftmost) + { + base->first = &tmo->node; + } + + rb_link_node(&tmo->node, parent, linknode); + rb_insert_color(&tmo->node, &base->active); + NSPOL_LOGDBG(TIMERS_DEBUG, "enqueue]thread=%u,ptimer_node=%p", tmo->index, + tmo); + tmo->state |= PTIMER_STATE_ENQUEUED; +} + +void launch_tmr(timer_t * tim, u64_t nsec) +{ + struct itimerspec vtim; + + vtim.it_value.tv_sec = (nsec) / NANO_PER_SECOND; + vtim.it_value.tv_nsec = (nsec) % NANO_PER_SECOND; + vtim.it_interval.tv_sec = 0; + vtim.it_interval.tv_nsec = 0; + + if (timer_settime(*tim, 0, &vtim, NULL) < 0) + { + NSPOL_LOGERR("add_ptimer:timer_settime failed"); + } + +} + +/* + * add ptimer to rb_tree + * @param tmo: the ptimer node pointer + */ +void add_ptimer(struct ptimer_node *tmo) +{ + if (tmo == NULL) + { + NSPOL_LOGERR("input parameter is null"); + return; + } + enqueue_ptimer(tmo, &ptimer); + + if (ptimer.first == &tmo->node) + { + launch_tmr(&lazy_tim, tmo->info.msec * NANO_PER_MICROSECOND); + } +} + +#if 1 +/* + * cond signal ,send a ptimer message + * @param type: the message type + * @param handler: timeout handler + * @param node: the ptimer node pointer + */ +void +regedit_ptimer(enum msg_type Type, sys_timeout_handler handler, + struct ptimer_node *node) +{ + (void) handler; + (void) pthread_mutex_lock(&ptimer.lock); + if (ptimer.tail == NULL) + { + (void) pthread_mutex_unlock(&ptimer.lock); + NSPOL_LOGERR("ptimer.tail is null"); + free(node); + node = NULL; + return; + } + ptimer.tail->msg_type = Type; + ptimer.tail->node = node; + ptimer.tail = ptimer.tail->next; + if (ptimer.head == ptimer.tail) + { + (void) pthread_mutex_unlock(&ptimer.lock); + NSPOL_LOGERR("ptimer.head equal to ptimer.tail"); + return; + } + + (void) pthread_kill(g_timerThread_id, SIGRTMIN + 2); + + (void) pthread_mutex_unlock(&ptimer.lock); + return; +} +#endif +/* + * deal with the timeout signal + * + */ +void deal_timeout_sig(void) +{ + struct ptimer_node *tmo; + struct timespec now; + unsigned long abs_nsec; + err_t err; + int retval; + if (ptimer.first == NULL) + { + return; + } + tmo = rb_entry(ptimer.first, struct ptimer_node, node); + retval = clock_gettime(CLOCK_MONOTONIC, &now); + if (0 != retval) + { + NSPOL_LOGERR("clock_gettime failed]retval=%d,errno=%d", retval, + errno); + } + abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec; + + // deal with all timeout point + while (time_after_eq(abs_nsec, tmo->abs_nsec)) + { + remove_ptimer(tmo, &ptimer); + + if (tmo->info.flags & PTIMER_ONESHOT) + { + } + else + { + //re-entry periodic ptimer + tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec + + tmo->info.msec * NANO_PER_MICROSECOND; + add_ptimer(tmo); + } + + //send timeout message + NSPOL_LOGDBG(INTERRUPT_DEBUG, + "ptimer happened to thread_index]index=%u", tmo->index); + if ((err = ltt_apimsg(tmo->info._phandle, (void *) tmo))) + { + NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING, + "send timeout message failed!]errno=%d", err); + } + + if (ptimer.first == NULL) + { + NSPOL_LOGERR("deal_timeout_sig: ptimer.first == NULL!!"); + return; + } + tmo = rb_entry(ptimer.first, struct ptimer_node, node); + } + + if (tmo->abs_nsec <= abs_nsec) + { + NSPOL_LOGERR("tmo->abs_nsec is smaller than abs_nsec"); + return; + } + + NSPOL_LOGDBG(TIMERS_DEBUG, "TIMERSIGNAL : Launch timer for]time=%ul", + tmo->abs_nsec - abs_nsec); + launch_tmr(&lazy_tim, tmo->abs_nsec - abs_nsec); //timer interupted eveny 50ms instand by tmo->abs_nsec +} + +/* + * timeout signal handle function + * @param v: unused argument + */ +/*ptimer is already protected and used*/ + +NSTACK_STATIC void timeout_sigaction(int sig) +{ + (void) sig; + if (!sys_arch_sem_trywait(&ptimer_lock)) + { + launch_tmr(&lazy_tim_retry, + (MIN_TIME_PICE / 5) * NANO_PER_MICROSECOND); + return; + } + + deal_timeout_sig(); + + sys_sem_signal(&ptimer_lock); + + return; +} + +/* + * initialize the ptimer buffer and timing mechanism + */ +err_t init_ptimer(void) +{ + int i, retval; + struct sigevent timer_event; + struct sigevent timer_event1; + struct ptimer_msg *ptr; + + if (pthread_mutex_init(&ptimer.lock, NULL)) + { + NSPOL_LOGERR("pthread_mutex_init failed"); + return ERR_MEM; + } + /*codex fix */ + if (ERR_MEM == sys_sem_new(&ptimer_lock, 1)) + { + NSPOL_LOGERR("init_ptimer: sys_sem_new failure"); + return ERR_MEM; + } + + ptimer.active.rb_node = NULL; + ptimer.first = NULL; + + ptr = + (struct ptimer_msg *) malloc(PTIMER_MSG_BUFFER_SIZE * + sizeof(struct ptimer_msg)); + if (!ptr) + { + NSPOL_LOGERR("init_ptimer: malloc ptimer buffer failed!"); + return ERR_MEM; + } + + int ret = + memset_s(ptr, (PTIMER_MSG_BUFFER_SIZE * sizeof(struct ptimer_msg)), + 0, (PTIMER_MSG_BUFFER_SIZE * sizeof(struct ptimer_msg))); + if (EOK != ret) + { + free(ptr); + NSPOL_LOGERR("init_ptimer: MEMSET_S ptimer buffer failed]ret=%d", + ret); + return ERR_MEM; + } + + for (i = 0; i < PTIMER_MSG_BUFFER_SIZE - 1; i++) + { + ptr[i].next = &ptr[(i + 1)]; + ptr[(i + 1)].prev = &ptr[i]; + } + + ptr[i].next = &ptr[0]; + ptr[0].prev = &ptr[i]; + ptimer.head = ptimer.tail = &ptr[0]; + retval = + memset_s(&timer_event, sizeof(struct sigevent), 0, + sizeof(struct sigevent)); + if (EOK != retval) + { + free(ptr); + ptr = NULL; + NSPOL_LOGERR("MEMSET_S failed]ret=%d", retval); + return ERR_VAL; + } + timer_event.sigev_notify = SIGEV_SIGNAL; + timer_event.sigev_signo = SIGRTMIN; + timer_event.sigev_value.sival_ptr = (void *) &lazy_tim; + timer_event1 = timer_event; + timer_event1.sigev_value.sival_ptr = (void *) &lazy_tim_retry; + + if (timer_create(CLOCK_MONOTONIC, &timer_event, &lazy_tim) < 0) + { + free(ptr); + ptr = NULL; + NSPOL_LOGERR("ptimer_init: timer_create failed!"); + return ERR_VAL; + } + + if (timer_create(CLOCK_MONOTONIC, &timer_event1, &lazy_tim_retry) < 0) + { + free(ptr); + ptr = NULL; + NSPOL_LOGERR("ptimer_init: timer_create failed!"); + return ERR_VAL; + } + + return ERR_OK; +} + +NSTACK_STATIC err_t process_timeout_msg(struct ptimer_msg * msg) +{ + struct ptimer_node *tmo = msg->node; + struct timespec now; + + switch (msg->msg_type) + { + case SYS_PTIMEROUT_MSG: + if (tmo) + { + int retval = clock_gettime(CLOCK_MONOTONIC, &now); + if (0 != retval) + { + NSPOL_LOGERR("clock_gettime failed]retval=%d,errno=%d", + retval, errno); + } + tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec + + tmo->info.msec * NANO_PER_MICROSECOND; + add_ptimer(tmo); + } + else + { + NSPOL_LOGERR("process_timeout_msg: rb_node is NULL!"); + return ERR_MEM; + } + + break; + case SYS_UNPTIMEROUT_MSG: + if (del_ptimer(msg) != ERR_OK) + { + NSPOL_LOGERR + ("process_timeout_msg: can not find the timeout event(oops)!"); + } + + break; + default: + NSPOL_LOGERR + ("process_timeout_msg: oops! lwip timeout_thread receive unacquainted message!"); + break; + } + + return ERR_OK; +} + +void ptimer_thread(void *arg) +{ + LWIP_UNUSED_ARG(arg); + int sig, ret = -1; + sigset_t waitset; + sigset_t oset; + struct ptimer_msg *msg; + + if (0 != sigemptyset(&waitset)) + { + NSTCP_LOGERR("sigemptyset function call error"); + return; + } + + if (0 != sigaddset(&waitset, SIGRTMIN)) + { + NSTCP_LOGERR("sigaddset function call error"); + return; + } + + if (0 != sigaddset(&waitset, SIGRTMIN + 2)) + { + NSTCP_LOGERR("sigaddset function call error"); + return; + } + + (void) pthread_sigmask(SIG_BLOCK, &waitset, &oset); + + (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + NSPOL_LOGDBG(TIMERS_DEBUG, "ptimer: init done !"); + + if (!g_nstack_timer_tick.tick_ptr) + { + NSTCP_LOGERR("g_nstack_timer_tick not inited"); + return; + } + (void) gettimeofday(&g_nstack_timer_tick.ref_time, NULL); + g_nstack_timer_tick.interval = 100; + *g_nstack_timer_tick.tick_ptr = 0; + g_nstack_timer_tick.ref_tick = 0; + while (1) + { + ret = sigwait(&waitset, &sig); + (void) nsfw_thread_chk(); // will only return TRUE, no need to check return value + if (ret != -1) + { + /* for timer expirt handle */ + if (SIGRTMIN == sig) + { + timeout_sigaction(sig); + continue; + } + } + else + { + continue; + } + + while (1) + { + (void) pthread_mutex_lock(&ptimer.lock); + if (ptimer.head == ptimer.tail) + { + (void) pthread_mutex_unlock(&ptimer.lock); + break; + } + + msg = ptimer.head; + ptimer.head = ptimer.head->next; + (void) pthread_mutex_unlock(&ptimer.lock); + + sys_arch_sem_wait(&ptimer_lock, 0); + + if (process_timeout_msg(msg) != ERR_OK) + { + NSPOL_LOGERR("oops: ptimer_thread panic!"); + } + + sys_sem_signal(&ptimer_lock); + } + } +} + +void timeout_phandler(void *act, void *arg) +{ + struct ptimer_node *tmo = arg; + if (act == NULL) + { + NSPOL_LOGERR("input parameter arg is null"); + return; + } + + NSPOL_LOGINF(TIMERS_DEBUG, "Timer expire @timeout_phandler Handle %p", + tmo->info._phandle); + if (tmo->info.flags & PTIMER_ONESHOT) + { + sys_timeout_handler handle = act; + handle(tmo->info.ctx); + return; + } + else + { + NSPOL_LOGINF(TIMERS_DEBUG, + "Timer expire error @timeout_phandler Handle %p", + tmo->info._phandle); + } +} diff --git a/stacks/lwip_stack/lwip_src/core/unmatch_version.c b/stacks/lwip_stack/lwip_src/core/unmatch_version.c new file mode 100644 index 0000000..e215a85 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/core/unmatch_version.c @@ -0,0 +1,59 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_api.h" +#include "nstack_share_res.h" +#include "nstack_securec.h" + +char *g_nstack_ver_info = NULL; + +int init_unmatch_version(void) +{ + int ret; + nsfw_mem_zone mzone; + + ret = + strcpy_s(mzone.stname.aname, NSFW_MEM_NAME_LENGTH, + NSTACK_VERSION_SHM); + if (EOK != ret) + { + NSPOL_LOGERR("STRCPY_S fail]ret=%d", ret); + return -1; + } + mzone.stname.entype = NSFW_SHMEM; + mzone.isocket_id = -1; + mzone.lenth = + NSTACK_VERSION_LEN + MAX_UNMATCH_VER_CNT * sizeof(unmatch_ver_info_t); + mzone.ireserv = 0; + + char *version = (char *) nsfw_mem_zone_create(&mzone); + if (NULL == version) + { + NSPOL_LOGERR("Failed to create unmatch_version memory"); + return -1; + } + + ret = strcpy_s(version, NSTACK_VERSION_LEN, NSTACK_VERSION); + if (EOK != ret) + { + NSPOL_LOGERR("STRCPY_S NSTACK_VERSION fail]ret=%d", ret); + return -1; + } + + g_nstack_ver_info = version; + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h new file mode 100644 index 0000000..3323bd1 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h @@ -0,0 +1,64 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSTACK_CONFIG_COMMON_H_ +#define _NSTACK_CONFIG_COMMON_H_ + +#include "ip_module_api.h" + +#define MAX_IP_MODULE_BUFF_SIZE 1024*1024 + +/* ip module config types */ +#define IP_MODULE_TYPE_IP "ip" +#define IP_MODULE_TYPE_NETWORK "network" +#define IP_MODULE_TYPE_PORT "port" +#define IP_MODULE_TYPE_SETLOG "setlog" +#define IP_MODULE_TYPE_SNAPSHOT "snapshot" +#define IP_MODULE_TYPE_SETTRACE "settrace" + +#define TCP_MODULE_TYPE_SET_OOS_LEN "ooslen" + +#define IP_MODULE_NAME "./nStackCtrl: " +#define IP_MODULE_INVALID_ARGUMENT_S "invalid argument -- \"%s\"\n" +#define IP_MODULE_MORE_OPTION "need more options -- " +#define IP_MODULE_LESS_OPTION "no need option -- " + +/* Error codes */ +#define IP_MODULE_OK 0 +#define IP_MODULE_DATA_ERROR 1 +#define IP_MODULE_DATA_NOT_EXIST 2 + +struct config_param +{ + int action; + char type[IP_MODULE_LENGTH_256]; + char name[IP_MODULE_LENGTH_256]; + char value[IP_MODULE_LENGTH_64]; + char container_id[IP_MODULE_LENGTH_256]; + int error; + + char error_desc[NSCRTL_ERRBUF_LEN]; + + u64 traceid; +}; + +struct config_data +{ + struct config_param param; + char json_buff[MAX_IP_MODULE_BUFF_SIZE - sizeof(struct config_param)]; +}; + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h new file mode 100644 index 0000000..d17bbb2 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h @@ -0,0 +1,26 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _CONFIGURATION_READER_H +#define _CONFIGURATION_READER_H +#include +#include "config_common.h" + +struct config_data *get_config_data(); +int get_str_value(const char *arg); +int setlog_level_value(const char *param, const char *value); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h new file mode 100644 index 0000000..fc76dfd --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h @@ -0,0 +1,39 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _CONTAINER_IP_H +#define _CONTAINER_IP_H +#include "ip_module_api.h" +#include "json.h" + +struct ip_action_param +{ + char container_id[IP_MODULE_LENGTH_256]; + char port_name[IP_MODULE_LENGTH_256]; +}; + +void free_container(struct container_ip *container, bool_t only_free); +struct container_port *parse_port_obj(struct json_object *port_obj); +struct container_ip *parse_container_ip_json(char *param); +int add_container(struct container_ip *container); +struct container_ip *get_container_by_container_id(char *container_id); + +int del_port(char *container_id, char *port_name); +struct container_port *get_port(char *container_id, char *port_name); +struct container_port *get_port_from_container(struct container_port *port); +int getIpCfgAll(char *jsonBuf, size_t size); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h new file mode 100644 index 0000000..2c9b662 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h @@ -0,0 +1,223 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _IP_MODULE_API_H_ +#define _IP_MODULE_API_H_ +#include "types.h" + +typedef int bool_t; +#define IP_MODULE_TRUE 1 +#define IP_MODULE_FALSE 0 +#define IP_MODULE_LENGTH_32 32 +#define IP_MODULE_LENGTH_64 64 +#define IP_MODULE_LENGTH_256 256 +#define IP_MODULE_LENGTH_1024 1024 +#define IP_MODULE_SUBNET_MASK_LEN IP_MODULE_LENGTH_32 +#define IP_MODULE_MAX_NAME_LEN IP_MODULE_LENGTH_256 +#define IP_MODULE_PORT_JSON_LEN (2048 * 2) +#define IP_MODULE_NETWORK_JSON_LEN (2048 * 2) +#define MAX_NETWORK_COUNT IP_MODULE_LENGTH_64 +#define MAX_NETWORK_IP_COUNT IP_MODULE_LENGTH_1024 +#define MAX_NETWORK_NUM (MAX_NETWORK_COUNT * 2) +COMPAT_PROTECT_RETURN(MAX_NETWORK_NUM, 128); +#define MAX_PORT_NUM (MAX_NETWORK_IP_COUNT * 2) +COMPAT_PROTECT_RETURN(MAX_PORT_NUM, 2048); +#define NSCRTL_ERRBUF_LEN IP_MODULE_LENGTH_256 + +#define INVALID_EXPIRE_TIME 0x7FFFFFFF +#define NSTACLCTRL_MAX_TRY_TIMES 60 + +/*sockaddr_un.sun_path is an array of 108 bytes*/ +#define IP_MODULE_MAX_PATH_LEN 108 + +typedef enum enumADERRCODE +{ + NSCRTL_OK = 0, + NSCRTL_ERR, + NSCRTL_RD_NOT_EXIST, + NSCRTL_RD_EXIST = 3, + NSCRTL_INPUT_ERR, + NSCRTL_STATUS_ERR, + NSCRTL_NETWORK_COUNT_EXCEED, + NSCRTL_IP_COUNT_EXCEED, + NSCRTL_FREE_ALL_PORT, //when all ports in container were deleted, need to free container. + + NSCRTL_MAX_ERR = 127 +} NSCRTL_ERR_CODE; + +#define NSOPR_SET_ERRINFO(_errno, fmt, ...) \ + {\ + struct config_data* cf_data = get_config_data(); \ + if (cf_data)\ + {\ + size_t len_error_desc = strlen(cf_data->param.error_desc); \ + cf_data->param.error = _errno; \ + if ((_errno != NSCRTL_OK) && (len_error_desc < NSCRTL_ERRBUF_LEN))\ + {\ + if (-1 == (snprintf_s(cf_data->param.error_desc + len_error_desc, \ + NSCRTL_ERRBUF_LEN - len_error_desc, NSCRTL_ERRBUF_LEN - len_error_desc - 1, fmt, ## __VA_ARGS__)))\ + {\ + NSOPR_LOGERR("SNPRINTF_S failed]"); \ + } \ + } \ + } \ + } \ + +struct ref_nic +{ + struct ref_nic *next; + char nic_name[IP_MODULE_MAX_NAME_LEN]; +}; + +struct phy_net +{ + struct ref_nic *header; + char bond_name[IP_MODULE_MAX_NAME_LEN]; + int bond_mode; +}; + +struct container_port_ip_cidr +{ + struct container_port_ip_cidr *next; + unsigned int ip; + unsigned int mask_len; +}; + +struct container_multicast_id +{ + struct container_multicast_id *next; + unsigned int ip; +}; + +typedef struct +{ + char port_json[IP_MODULE_PORT_JSON_LEN]; +} port_buffer; + +struct container_port +{ + struct container_port *next; + struct container_port_ip_cidr *ip_cidr_list; + struct container_multicast_id *multicast_list; + char port_name[IP_MODULE_MAX_NAME_LEN]; + port_buffer *buffer; +}; + +#define get_port_json(obj) obj->buffer->port_json + +struct container_ip +{ + struct container_ip *next; + struct container_port *ports_list; + char container_id[IP_MODULE_MAX_NAME_LEN]; +}; + +struct container_list +{ + struct container_ip *header; +}; + +struct ip_subnet +{ + struct ip_subnet *next; + unsigned int subnet; + unsigned int mask_len; +}; + +typedef struct +{ + char network_json[IP_MODULE_NETWORK_JSON_LEN]; +} network_buffer; + +struct network_configuration +{ + struct network_configuration *next; + struct phy_net *phy_net; + struct ip_subnet *ip_subnet; + char network_name[IP_MODULE_MAX_NAME_LEN]; + char type_name[IP_MODULE_MAX_NAME_LEN]; + char nic_type_name[IP_MODULE_MAX_NAME_LEN]; + network_buffer *buffer; +}; + +#define get_network_json(obj) obj->buffer->network_json + +struct network_list +{ + struct network_configuration *header; +}; + +void ip_subnet_print(struct ip_subnet *subnet); +bool_t is_in_same_network(unsigned int src_ip, unsigned int dst_ip); +bool_t is_ip_match_netif(unsigned int ip, char *netif_name); +bool_t is_ip_exist(unsigned int ip); +struct network_configuration *get_network_list(); +inline struct network_configuration *get_network_by_ip_with_tree(unsigned int + ip); + +/* "type" option */ +typedef enum +{ + IP_MODULE_NETWORK, + IP_MODULE_IP, + IP_MODULE_NETWORK_ALL, + IP_MODULE_IP_ALL, + IP_MODULE_ALL, +} ip_module_type; + +/* "action" option */ +typedef enum +{ + IP_MODULE_OPERATE_NULL, + IP_MODULE_OPERATE_ADD, + IP_MODULE_OPERATE_DEL, + IP_MODULE_OPERATE_QUERY, + IP_MODULE_OPERATE_SET, + IP_MODULE_GET_VERSION, + IP_MODULE_QUERY_NET, + IP_MODULE_MAX, //new type should be added before IP_MODULE_MAX + IP_MODULE_BOTTOM = 0xFFFFFFFF +} ip_module_operate_type; + +typedef int (*post_to_fn) (void *arg, ip_module_type type, + ip_module_operate_type operate_type); +typedef int (*add_netif_ip_fn) (char *netif_name, unsigned int ip, + unsigned int mask); +typedef int (*del_netif_ip_fn) (char *netif_name, unsigned int ip); + +typedef struct +{ + post_to_fn post_to; + add_netif_ip_fn add_netif_ip; + del_netif_ip_fn del_netif_ip; +} output_api; + +void regist_output_api(output_api * api); +output_api *get_output_api(); +int init_configuration_reader(); +int process_post(void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int process_configuration(void *arg, ip_module_type type, + ip_module_operate_type operate_type); + +port_buffer *malloc_port_buffer(); +void free_port_buffer(port_buffer * buffer); +network_buffer *malloc_network_buffer(); +void free_network_buffer(network_buffer * buffer); +int get_network_json_data(); +int get_ip_json_data(); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/network.h b/stacks/lwip_stack/lwip_src/include/ip_module/network.h new file mode 100644 index 0000000..f19682b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/network.h @@ -0,0 +1,36 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NETWORK_H +#define _NETWORK_H +#include "ip_module_api.h" + +void free_network_configuration(struct network_configuration *network, + bool_t only_free); +struct network_configuration *parse_network_obj(struct json_object + *network_obj); +struct network_configuration *parse_network_json(char *param, + struct network_configuration + *network_list); +int add_network_configuration(struct network_configuration + *network_configuration); +struct network_configuration *get_network_by_name(char *name); +struct network_configuration *get_network_by_nic_name(char *name); +int del_network_by_name(char *name); +int get_network_all(char *jsonBuf, size_t size); +int nic_already_init(const char *nic_name); + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h new file mode 100644 index 0000000..24d5d22 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h @@ -0,0 +1,77 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __TRP_RB_TREE_H__ +#define __TRP_RB_TREE_H__ + +typedef void *trp_key_t; +typedef void *trp_data_t; + +#define RB_RED 0 +#define RB_BLACK 1 + +typedef int (*key_compare) (trp_key_t left, trp_key_t right); // return > 0 left > right, return 0 left = right, return < 0 left < right + +typedef struct trp_rb_node +{ + struct trp_rb_node *rb_parent; + struct trp_rb_node *rb_right; + struct trp_rb_node *rb_left; + key_compare key_compare_fn; + trp_key_t key; + trp_data_t data; + unsigned int color; +} trp_rb_node_t; + +typedef struct trp_rb_root +{ + struct trp_rb_node *rb_node; +} trp_rb_root_t; + +int trp_rb_insert(trp_key_t, trp_data_t, trp_rb_root_t *, key_compare); +int trp_rb_insert_allow_same_key(trp_key_t, trp_data_t, trp_rb_root_t *, + key_compare); +void trp_rb_erase(trp_key_t, trp_rb_root_t *, key_compare key_compare_fn); +void trp_rb_erase_with_data(trp_key_t key, trp_data_t data, + trp_rb_root_t * root, int count, + key_compare key_compare_fn); + +static inline trp_rb_node_t *trp_rb_search(trp_key_t key, + trp_rb_root_t * root, + key_compare key_compare_fn) +{ + trp_rb_node_t *node = root->rb_node; + int ret; + while (node) + { + ret = key_compare_fn(node->key, key); + if (0 < ret) + { + node = node->rb_left; + } + else if (0 > ret) + { + node = node->rb_right; + } + else + { + return node; + } + } + + return NULL; +} +#endif diff --git a/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h new file mode 100644 index 0000000..ae5c31f --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h @@ -0,0 +1,162 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "spl_opt.h" +#include "spl_def.h" +#include "ip_module_api.h" +#include "stackx_ip_addr.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +/* Forward declaration to not include netif.h */ +struct netif; +#if BYTE_ORDER == BIG_ENDIAN + +/** Set an IPaddress given by the four byte-parts */ +#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else + +/** Set an IPaddress given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif + +/** memcpy-like copying of IPaddresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) MEMCPY_S(dest, sizeof(ip_addr_t), src, sizeof(ip_addr_t)) +#endif + +/** Copy IPaddress - faster than spl_ip_addr_set: no NULL check */ +#define spl_ip_addr_copy(dest, src) ((dest).addr = (src).addr) + +/** Safely copy one IPaddress to another (src may be NULL) */ +#define spl_ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) + +/** Safely copy one IPaddress to another and change byte order + * from host- to network-order. */ +#define spl_ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + htonl((src)->addr))) + +/** Get the network address by combining host address with netmask */ +#define spl_ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IPaddress 1 + * @arg addr2 IPaddress 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define spl_ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) + +/* && ((dest)->addr & tmp->netmask.addr) == (tmp->ip_addr.addr & tmp->netmask.addr) */ +/* add "netif = netif->root; \"*/ +#define ip_net_netif_cmp( dest, netif) ({ \ + netif = netif->root; \ + struct netif* tmp = netif; \ + int find = 0; \ + while(tmp) \ + { \ + if (is_in_same_network((dest)->addr, tmp->ip_addr.addr)) \ + { \ + netif->ip_addr.addr = tmp->ip_addr.addr; \ + netif->netmask.addr = tmp->netmask.addr; \ + find = 1; \ + break; \ + } \ + if (netif->is_out) \ + { \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +/* Check if netif match dest , if not , find one and swap */ +/* add "netif = netif->root; \"*/ + +#define ip_addr_netif_cmp_and_swap( dest, pnetif) ({ \ + pnetif = pnetif->root; \ + struct netif* tmp = pnetif; \ + int find = 0; \ + while(tmp) \ + { \ + if ((dest)->addr == tmp->ip_addr.addr) \ + { \ + pnetif->ip_addr.addr = tmp->ip_addr.addr; \ + pnetif->netmask.addr = tmp->netmask.addr; \ + find = 1; \ + break; \ + } \ + if (pnetif->is_out) \ + { \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +#define ip_addr_netif_cmp( dest, pnetif) ({ \ + pnetif = pnetif->root; \ + struct netif* tmp = pnetif; \ + int find = 0; \ + while(tmp) \ + { \ + if ((dest)->addr == tmp->ip_addr.addr) \ + { \ + find = 1; \ + break; \ + } \ + tmp = tmp->vnext; \ + } \ + (!!find); \ + }) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/common.h b/stacks/lwip_stack/lwip_src/include/netif/common.h new file mode 100644 index 0000000..131a27d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/common.h @@ -0,0 +1,227 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ +#include /* for size_t */ +#include "stackx_common.h" +#include "netif.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +//yyq + +/* define common names for structures shared between server and client */ + +#define MP_STACKX_INSTANCE_POLL_NAME "VppTCP_instance_poll" +#define MP_STACKX_PORT_ZONE "VppTCP_stackx_port_zone" +#define MP_STACKX_PORT_INFO "VppTCP_stackx_port_info" +#define MP_MEMPOLL_RX_NAME "VppTCP_MBUF_%u_%u_RX" +#define MP_MEMPOLL_RXMSG_NAME "VppTCP_MSG_%u_%u_RX" +#define MP_MEMPOLL_TX_NAME "VppTCP_MBUF_TX" +#define MP_MEMPOLL_SEG_NAME "VppTCP_MBUF_SEG" +#define MP_STACKX_MSG_NAME "VppTCP_msg" +#define MP_STACKX_RING_NAME "VppTCP_%u_ring" +#define MP_STACKX_LRING_NAME "VppTCP_%u_lring" + +#define MP_STACKX_BIT_SET_NAME "%s_bit_set" + +#define MP_STACKX_SOCKET_FREE_LIST_NAME "VppTCP_socket_list" + +#define MP_NETIF_LIST_NAME "VppTCP_Netif_list" + +/* + move sharemem create from App to nstackMain +advice rename app_tx_mbuf to VppTCP_APP_TXBUF_POOL +*/ +#define MP_STACKX_APP_TXBUF_POOL "app_tx_mbuf" + +#define MP_MEMPOLL_TCP_BUFF_NAME "VppTCP_MBUF_%u_TCP_BUFF" + +extern int spl_snprintf(char *buffer, int buflen, const char *format, ...); + +/*According to the number of network cards, the establishment of recv lring, + *each separate, each proc_id each NIC queue independent lring + */ +static inline const char *get_mempoll_rx_name(unsigned proc_id, + unsigned nic_id) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) + * the id may reach 65535, need add more space*/ + static char buffer[sizeof(MP_MEMPOLL_RX_NAME) + 32]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_MEMPOLL_RX_NAME, proc_id, nic_id); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_rxmsg_name(unsigned proc_id, + unsigned nic_id) +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) + * the id may reach 65535, need add more space*/ + static char buffer[sizeof(MP_MEMPOLL_RXMSG_NAME) + 32]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_MEMPOLL_RXMSG_NAME, proc_id, nic_id); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_ring_name(unsigned proc_id) +{ + static char buffer[sizeof(MP_STACKX_RING_NAME) + 16]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_STACKX_RING_NAME, + proc_id); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_lring_name(unsigned proc_id) +{ + static char buffer[sizeof(MP_STACKX_LRING_NAME) + 16]; + + int retVal = + spl_snprintf(buffer, sizeof(buffer) - 1, MP_STACKX_LRING_NAME, + proc_id); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_msg_name() +{ + static char buffer[sizeof(MP_STACKX_MSG_NAME) + 16]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_STACKX_MSG_NAME); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_tx_name() +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char buffer[sizeof(MP_MEMPOLL_TX_NAME) + 16]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_MEMPOLL_TX_NAME); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_mempoll_seg_name() +{ + /* buffer for return value. Size calculated by %u being replaced + * by maximum 3 digits (plus an extra byte for safety) */ + static char buffer[sizeof(MP_MEMPOLL_SEG_NAME) + 16]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, MP_MEMPOLL_SEG_NAME); //???????????buffer?? + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_memStatusBitSet_name(const char *name, + unsigned int num) +{ + static char buffer[64]; + + int retVal = + spl_snprintf(buffer, sizeof(buffer) - 1, MP_STACKX_BIT_SET_NAME "%d", + name, num); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_memNameWithProc(const char *name) +{ + static char buffer[64]; + + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, "%s", name); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +static inline const char *get_memInstancePoll_name(unsigned int type) +{ + static char buffer[sizeof(MP_STACKX_INSTANCE_POLL_NAME) + 32]; + int retVal = spl_snprintf(buffer, sizeof(buffer) - 1, "%s" "%d", + MP_STACKX_INSTANCE_POLL_NAME, type); + if (-1 == retVal) + { + NSPOL_LOGERR("spl_snprintf failed]"); + return NULL; + } + + return buffer; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h new file mode 100644 index 0000000..4934ac3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h @@ -0,0 +1,103 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _KNI_PROC_H_ +#define _KNI_PROC_H_ +#include +#include +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define KNI_MAX_KTHREAD 32 + +/* the kni is runned on the lcore from below on */ +#define DEFAULT_KNI_LCORE_BASE 24 + +/* Structure of kni para */ +struct disp_kni_para +{ + u8_t queue_id; + u8_t port_id; +}; + +/* + * Structure of port parameters + */ +struct kni_port_params +{ + uint8_t port_id; /* Port ID */ + unsigned lcore_rx; /* lcore ID for RX */ + unsigned lcore_tx; /* lcore ID for TX */ + uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */ + uint32_t nb_kni; /* Number of KNI devices to be created */ + unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */ + struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */ + struct rte_mempool *kni_pktmbuf_pool; + u8_t ip_reconfigured; +} __rte_cache_aligned; + +/* Structure type for storing kni interface specific stats */ +struct kni_interface_stats +{ + /* number of pkts received from NIC, and sent to KNI */ + uint64_t rx_packets; + + /* number of pkts received from NIC, but failed to send to KNI */ + uint64_t rx_dropped; + + /* number of pkts received from KNI, and sent to NIC */ + uint64_t tx_packets; + + /* number of pkts received from KNI, but failed to send to NIC */ + uint64_t tx_dropped; +}; + +/* External interface for initilizing KNI subsystem */ +int kni_proc_init(enum rte_proc_type_t proc_type, int proc_id, u32_t pmask, + struct kni_port_params **kni_para); + +int kni_proc_init_secondary(int proc_id, int port_id); +/* External interface for destroy KNI subsystem */ +void kni_proc_free(void); + +/* External interface for kni tx thread entry */ +void kni_tx_thread_cycle(void *arg); + +int kni_config_net(void); +void kni_handler_eth_operate_request(int port); + +/* External interface for commiting packet to kni device */ +void kni_dispatch_to_kernel(uint8_t port_id, + struct rte_mbuf *pkts_burst[], uint8_t nb_rx); + +/* the lcore kni tx/rx thread run on */ +unsigned kni_get_tx_lcore(uint8_t port_id); +unsigned kni_get_rx_lcore(uint8_t port_id); + +void init_kni(void); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /*#ifndef _KNI_PROC_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h new file mode 100644 index 0000000..3eeddd9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h @@ -0,0 +1,79 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SC_DPDK_H_ +#define SC_DPDK_H_ + +#include +#include + +#include "lwip/etharp.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSTACK_CONFIG_SHM "nstack_config" + +#define MBUF_DATA_SIZE 2048 +#define MBUF_SIZE (MBUF_DATA_SIZE + sizeof(struct common_mem_mbuf) + COMMON_PKTMBUF_HEADROOM) + +extern int g_nstack_bind_cpu; + +inline uint16_t spl_mbuf_refcnt_update(void *mbuf, int16_t value); +struct stack_proc_content *get_stack_proc_content(); + +inline int spl_msg_malloc(data_com_msg ** p_msg_entry); +#define spl_msg_free(p_msg_entry) msg_free(p_msg_entry) +struct spl_pbuf *spl_mbuf_malloc(uint16_t len, spl_pbuf_type type, + u16_t * count); + +inline void spl_mbuf_free(void *mbuf); + +inline int spl_set_lcore_id(unsigned dest_lcore_id); + +static inline unsigned spl_get_lcore_id() +{ + unsigned core_id = 0; + +#if (DPDK_MODULE != 1) +#ifdef HAL_LIB +#else + core_id = rte_lcore_id(); +#endif + if (core_id >= MAX_THREAD_NUM) + { + core_id = 0; + } +#endif + + return core_id; +} + +int set_share_config(); + +int init_instance(); + +void printmeminfo(); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* SERVER_DPDK_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h new file mode 100644 index 0000000..402aba4 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h @@ -0,0 +1,149 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SHAREDMEMORY_H_ +#define SHAREDMEMORY_H_ +#include "stackxopts.h" +#include +#include +//#include "stackx/raw.h" +#include "tcp.h" +#include "udp.h" +//#include "stackx/ip.h" +#include "spl_err.h" +#include "list.h" +#include "arch/queue.h" +#include "spl_opt.h" +#include "stackx/spl_ip_addr.h" + +#include "stackx/spl_api.h" +#include +#include "common_mem_api.h" +//#include "stackx/memp.h" +#include "stackx_instance.h" + +#include "nsfw_hal_api.h" +#ifdef HAL_LIB +#else +#include "rte_ring.h" +#endif + +/** Description for a task waiting in select */ +struct stackx_select_cb +{ + /** Pointer to the next waiting task */ + union + { + struct stackx_select_cb *next; + PTR_ALIGN_TYPE next_a; + }; + + /** Pointer to the previous waiting task */ + union + { + struct stackx_select_cb *prev; + PTR_ALIGN_TYPE prev_a; + }; + + /** semaphore to wake up a task waiting for select */ + //sys_sem_t sem; + union + { + sys_sem_t_v1 sem; + PTR_ALIGN_TYPE sem_a; + }; + + /** readset passed to select */ + fd_set readset; + + /** writeset passed to select */ + fd_set writeset; + + /** unimplemented: exceptset passed to select */ + fd_set exceptset; + + /** don't signal the same semaphore twice: set to 1 when signalled */ + volatile int sem_signalled; + + uint8_t pad_64bit[4]; +}; +/** From epoll.h: Definition of struct stackx_sock and stackx_select_cb ---------End*/ + +enum tcp_run_type +{ + TCP_MUTIPL_INSTANCE = 0, + TCP_MASTER_WORKER, + TCP_DISTRIBUTOR_WORKER, + TCP_RUN_TO_COMPETE, + TCP_PROC_TYPE_END +}; + +enum proc_run_type +{ + PROC_MAIN_RUN_TYPE = 0, + PROC_BACKUP_RUN_TYPE, + PROC_RUN_TYPE_END +}; + +struct linux_port_info +{ + char if_name[HAL_MAX_NIC_NAME_LEN]; + char if_type[HAL_MAX_NIC_NAME_LEN]; + char ip_addr_linux[18]; //uint32_t ip_addr_linux; + char mask_linux[18]; //uint32_t mask_linux; + char bcast_linux[18]; //uint32_t bcast_linux; + char mac_addr[20]; //struct ether_addr mac_addr; + hal_hdl_t hdl; +}; + +struct stackx_port_info +{ + struct stackx_port_info *next_use_port; + struct linux_port_info linux_ip; +}; + +struct stackx_port_zone +{ + unsigned int port_num; + unsigned int bonded_port_num; + struct stackx_port_info *stackx_one_port; +}; + +struct select_cb_entry +{ + struct stackx_select_cb select_cb; + + union + { + sem_t semForSelect; + ALIGN_TYPE pad_64bit[4]; + }; + + union + { + struct select_cb_entry *pre_empty_entry; + PTR_ALIGN_TYPE pre_empty_entry_a; + }; + + union + { + struct select_cb_entry *next_empty_entry; + PTR_ALIGN_TYPE next_empty_entry_a; + }; + +}; + +#endif /* SHAREDMEMORY_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h new file mode 100644 index 0000000..fe59be4 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h @@ -0,0 +1,112 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SPL_HAL_H_ +#define SPL_HAL_H_ + +#include "nsfw_hal_api.h" +#include "netif.h" +#include "nsfw_maintain_api.h" +#include "stackx_spl_share.h" +#include "stackx_pbuf_comm.h" +#include "netifapi.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +int spl_hal_init(int argc, char *argv[]); +int spl_hal_port_init(); + +int spl_hal_stats_display(struct netif *pnetif, char *str, u32_t len, + char *json, u32_t json_len); + +err_t spl_hal_output(struct netif *netif, struct pbuf *buf); +void spl_hal_input(struct netif *netif, struct spl_pbuf **buf); + +inline u16_t spl_hal_recv(struct netif *netif, u8_t id); + +int spl_hal_tx_ip_cksum_enable(); +int spl_hal_tx_udp_cksum_enable(); +int spl_hal_tx_tcp_cksum_enable(); + +u32 spl_hal_is_nic_exist(const char *name); + +int spl_hal_is_bond_netif(struct netif *pnetif); + +static inline void spl_do_dump(struct spl_pbuf *p, u16 direction) +{ + struct spl_pbuf *q = p; + while (q) + { + ntcpdump(q->payload, q->len, direction); + q = q->next; + } +} + +/* information of bond*/ +#define MAX_BOND_PORT_NUM 4 + +/* information of one bond port */ +struct bond_set +{ + char bond_port_name[HAL_MAX_NIC_NAME_LEN]; + char slave_ports[HAL_MAX_SLAVES_PER_BOND][HAL_MAX_NIC_NAME_LEN]; + u8_t slave_port_cnt; +}; + +#define NETIF_ETH_ADDR_LEN 6 + +/* information of all bond ports */ +struct bond_ports_info +{ + u8_t cnt; + struct bond_set ports[MAX_BOND_PORT_NUM]; +}; + +struct ether_addr +{ + u8_t addr_bytes[NETIF_ETH_ADDR_LEN]; + +}; + +struct netif *get_netif_by_ip(unsigned int ip); +struct netif *netif_check_broadcast_addr(spl_ip_addr_t * addr); +struct netifExt *getNetifExt(u16_t id); +int netifExt_add(struct netif *netif); + +int add_netif_ip(char *netif_name, unsigned int ip, unsigned int mask); +int del_netif_ip(char *netif_name, unsigned int ip); + +err_t spl_netifapi_netif_add(struct netif *pnetif, + spl_ip_addr_t * ipaddr, + spl_ip_addr_t * netmask, + spl_ip_addr_t * gw, + void *state, + netif_init_fn init, + netif_input_fn input, netifapi_void_fn voidfunc); +struct netif *find_netif_by_if_name(char *if_name); +void ethernetif_packets_input(struct netif *pstnetif); +err_t ethernetif_init(struct netif *pnetif); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif /* SPL_HAL_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h new file mode 100644 index 0000000..a424dd0 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h @@ -0,0 +1,90 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __internal_msg_h__ +#define __internal_msg_h__ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#include "nsfw_msg.h" +#include "netif.h" +#include "lwip/netifapi.h" +#include "ip_module_api.h" + +enum netif_msg_type +{ + NETIF_DO_ADD, + NETIF_MSG_API_MAX = MAX_MINOR_TYPE +}; + +/* NETIF_DO_ADD */ +typedef struct msg_add_netif_T +{ + void (*function) (struct msg_add_netif_T * m); + struct netif *netif; + spl_ip_addr_t *ipaddr; + spl_ip_addr_t *netmask; + spl_ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + netifapi_void_fn voidfunc; + /* no need to extend member */ +} msg_add_netif; + +typedef struct +{ + ip_module_type type; + ip_module_operate_type operate_type; + void *arg; +} msg_ip_module; + +typedef struct msg_internal_callback_T +{ + void (*function) (void *ctx); + void *ctx; +} msg_internal_callback; + +enum timer_msg_type +{ + TIMER_MSG_TIMEOUT, + TIMER_MSG_CLEAR, + TIMER_MSG_MAX = MAX_MINOR_TYPE +}; + +typedef struct msg_timer_T +{ + void *act; + void *arg; +} msg_timer; + +enum mt_msg_type +{ + MT_MSG_VER_MGR, + MT_MSG_MAX = MAX_MINOR_TYPE +}; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __internal_msg_h__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h new file mode 100644 index 0000000..0dbfd3e --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h @@ -0,0 +1,276 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __SPL_API_H__ +#define __SPL_API_H__ + +#include "opt.h" +#include "common_mem_base_type.h" +#include /* for size_t */ +#include "arch/queue.h" +#include "arch/sys_arch.h" +#include "arch/atomic_32.h" +#include "stackx_common_opt.h" +#include "stackx_spl_share.h" + +/* From lwip */ +#include "api.h" +#include "sys.h" +#include "sys_arch.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_WAIT_TIMEOUT 0x7FFFFFFF + +/* Throughout this file, IPaddresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for struct netconn.flags (u8_t) */ + +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01 + +/** Should this netconn avoid blocking? */ +#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02 + +/** Was the last connect action a non-blocking one? */ +#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 + +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08 + +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +// #define NETCONN_FLAG_CHECK_WRITESPACE 0x10 + +enum stackx_model +{ + SOCKET_STACKX = 0, + CALLBACK_STACKX +}; + +enum callback_type +{ + API_ACCEPT_EVENT = 0xF0, + API_RECV_EVENT, + API_SEND_EVENT, + API_CLOSE_EVENT +}; +#if 1 +/** Use to inform the callback function about changes */ +enum spl_netconn_evt +{ + SPL_NETCONN_EVT_RCVPLUS, + SPL_NETCONN_EVT_RCVMINUS, + SPL_NETCONN_EVT_SENDPLUS, + SPL_NETCONN_EVT_SENDMINUS, + SPL_NETCONN_EVT_ERROR, + SPL_NETCONN_EVT_HUP, + SPL_NETCONN_EVT_RDHUP, + SPL_NETCONN_EVT_AGAIN, + SPL_NETCONN_EVT_ACCEPT +}; +#endif +enum +{ + INET_ECN_NOT_ECT = 0, + INET_ECN_ECT_1 = 1, + INET_ECN_ECT_0 = 2, + INET_ECN_CE = 3, + INET_ECN_MASK = 3, +}; + +#define SPL_NETCONNTYPE_GROUP(t) (t & 0xF0) +#define SPL_NETCONNTYPE_DATAGRAM(t) (t & 0xE0) + +/* forward-declare some structs to avoid to include their headers */ +typedef struct common_pcb +{ + enum stackx_model model; + + int socket; + + /** type of the netconn (TCP, UDP or RAW) */ + enum spl_netconn_type type; + + /* share memory between sbr and stackx */ + spl_netconn_t *conn; + + u16 bind_thread_index; + u8 close_progress; + u8 recv_ring_not_empty; + + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. + */ + data_com_msg *current_msg; + + msg_write_buf *msg_head; + msg_write_buf *msg_tail; + + size_t write_offset; + + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; + + /* timeout to wait for send buffer writtable */ + int send_timeout; + + int sk_rcvlowat; + + //DFX stat for connection packet + /* dfx_conn_t dfx; */ + + /*store the hostpid info for release */ + uint32_t hostpid; + u8_t l4_tick; /* if is odd number, use l4 ring first */ + u8_t dataSentFlag; + + nsfw_res res_chk; +} common_pcb; + +/** A callback prototype to inform about events for a netconn */ +//typedef void (*netconn_callback)(struct spl_netconn *, enum netconn_evt, u16_t len); + +/* Though these callback pointers are not set and referenced in nStack Core, still +the padding is required since the structure will be used in netconn and it needs +padding across 32-bit and 64-bit architecture */ +typedef struct +{ + union + { + int (*accept_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE accept_event_a; + }; + + union + { + int (*recv_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE recv_event_a; + }; + union + { + int (*send_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE send_event_a; + }; + union + { + int (*close_event) (struct spl_netconn * conn); + PTR_ALIGN_TYPE close_event_a; + }; +} callback_funcation; + +union ring_addr_u +{ + void *ring_addr; + PTR_ALIGN_TYPE ring_addr_a; +}; + +struct mem_manage +{ + volatile uint32_t current_read; + volatile uint32_t current_write; + union ring_addr_u ring_addr[RECV_MAX_POOL]; + union ring_addr_u l4_ring; /* recv ring for l4 */ + //void *ring_addr[RECV_MAX_POOL]; +}; + +/* Pbuf free should be done in network stack */ +struct spl_netconn_recvbuf_recoder +{ + struct spl_pbuf *head; + struct spl_pbuf *tail; + int totalLen; +}; + +/** Register an Network connection event */ +void spl_event_callback(spl_netconn_t * conn, enum spl_netconn_evt evt, + int postFlag); + +#define SPL_API_EVENT(c, e, p) spl_event_callback(c, e, p) + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define SPL_NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ + } while (0); + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define spl_netconn_set_nonblocking(conn, val) do { if (val) { \ + (conn)->flags |= SPL_NETCONN_FLAG_NON_BLOCKING; \ + } else { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING; }} while (0) + +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define spl_netconn_is_nonblocking(conn) (((conn)->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define spl_netconn_set_noautorecved(conn, val) do { if (val) { \ + (conn)->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED; \ + } else { \ + (conn)->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED; }} while (0) + +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define spl_netconn_get_noautorecved(conn) (((conn)->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +/** Set the receive timeout in milliseconds */ +#define spl_netconn_set_recvtimeout(cpcb, timeout) ((cpcb)->recv_timeout = (timeout)) + +/** Get the receive timeout in milliseconds */ +#define spl_netconn_get_recvtimeout(cpcb) ((cpcb)->recv_timeout) + +/** Set the send timeout in milliseconds */ +#define spl_netconn_set_sendtimeout(cpcb, timeout) ((cpcb)->send_timeout = (timeout)) + +/** Get the send timeout in milliseconds */ +#define spl_netconn_get_sendtimeout(cpcb) ((cpcb)->send_timeout) + +#define spl_netconn_set_sendbufsize(conn, sendbufsize) ((conn)->send_bufsize = (sendbufsize)) + +/* "man 7 socket" information + SO_SNDBUF + Sets or _gets the maximum socket send buffer in bytes. The kernel doubles + this value (to allow space for bookkeeping overhead) when it is set using + setsockopt(2), and this doubled value is returned by getsockopt(2). +*/ +#define spl_netconn_get_sendbufsize(conn) (2 *((conn)->send_bufsize)) + +#define spl_netconn_set_reclowbufsize(cpcb, recvlowbufsize) ((cpcb)->sk_rcvlowat = ((recvlowbufsize) > 0) ? recvlowbufsize : 1) +#define spl_netconn_get_reclowbufsize(cpcb) ((cpcb)->sk_rcvlowat) + +extern int spl_post_msg(u16 mod, u16 maj, u16 min, u16 op, char *data, + u16 data_len, u32 src_pid); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_API_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h new file mode 100644 index 0000000..1db02fd --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h @@ -0,0 +1,128 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include +#include +#include + +#include "nsfw_msg.h" +#include "spl_opt.h" +#include "spl_ip_addr.h" +#include "spl_err.h" +#include "spl_api.h" +//#include "sockets.h" +#include "stackx_spl_share.h" +#include "stackx_spl_msg.h" + +/* From lwip */ +#include "tcp.h" +#include "udp.h" +#include "sys.h" + +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +struct callback_fn +{ + tcp_sent_fn sent_fn; + tcp_recv_fn recv_fn; + tcp_connected_fn connected_fn; + tcp_poll_fn poll_fn; + tcp_err_fn err_fn; + tcp_err_fn close_fn; + tcp_accept_fn accept_fn; +}; + +#ifdef HAL_LIB +#else +typedef enum _mbuf_recyle_flg +{ + MBUF_UNUSED = 0, + MBUF_HLD_BY_APP = 1, + MBUF_HLD_BY_SPL = 2, +} mbuf_recycle_flg; +#endif + +err_t sp_enqueue(struct common_pcb *cpcb, void *p); +err_t accept_dequeue(spl_netconn_t * lconn, void **new_buf, + u32_t timeout /*miliseconds */ ); +err_t accept_enqueue(spl_netconn_t * conn, void *p); +void free_conn_by_spl(spl_netconn_t * conn); +void unlink_pcb(struct common_pcb *cpcb); +void do_try_delconn(void *close_data, u32 delay_sec); +void do_delconn(struct common_pcb *cpcb, msg_delete_netconn * msg); +void do_bind(struct common_pcb *cpcb, msg_bind * msg); +void do_pbuf_free(struct spl_pbuf *buf); +void do_connect(struct common_pcb *cpcb, msg_connect * msg); +void do_listen(struct common_pcb *cpcb, msg_listen * msg); +void do_send(struct common_pcb *cpcb, msg_send_buf * msg); +void do_recv(struct common_pcb *cpcb, msg_recv_buf * msg); +void do_write(struct common_pcb *cpcb, msg_write_buf * msg); +void do_getaddr(struct common_pcb *cpcb, msg_getaddrname * msg); +void do_close(struct common_pcb *cpcb, msg_close * msg); +void do_getsockopt_internal(struct common_pcb *cpcb, + msg_setgetsockopt * smsg); +void do_setsockopt_internal(struct common_pcb *cpcb, + msg_setgetsockopt * smsg); +void do_getsockname(struct common_pcb *cpcb, msg_getaddrname * amsg); +int netconn_drain(enum spl_netconn_type t, spl_netconn_t * conn); +int spl_pcb_new(msg_new_netconn * m); +void do_app_touch(msg_app_touch * smsg); +int do_close_finished(struct common_pcb *cpcb, u8_t close_finished, + u8_t shut, err_t err, int OpShutDown); +err_t do_writemore(struct spl_netconn *conn); +err_t do_close_internal(struct common_pcb *cpcb, int OpShutDown); + +u8 get_shut_op(data_com_msg * m); +int ks_to_stk_opt(int opt); +void update_tcp_state(spl_netconn_t * conn, enum tcp_state state); + +err_t spl_poll_tcp(void *arg, struct tcp_pcb *pcb); +err_t spl_recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); +err_t spl_sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len); +void spl_err_tcp(void *arg, err_t err); +err_t spl_tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, + err_t err); +err_t spl_do_connected(void *arg, struct tcp_pcb *pcb, err_t err); +err_t spl_accept_function(void *arg, struct tcp_pcb *newpcb, err_t err); + +struct common_pcb *alloc_common_pcb(); +void free_common_pcb(struct common_pcb *cpcb); +int common_pcb_init(struct common_pcb *cpcb); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h new file mode 100644 index 0000000..a0188be --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h @@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_ERR_H__ +#define __STACKX_ERR_H__ + +#include "spl_opt.h" +#include "lwip/arch.h" +#include "stackx_err.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef s8_t err_t; + +/* Definitions for error constants. */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h new file mode 100644 index 0000000..c543c84 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h @@ -0,0 +1,30 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _SPL_INSTANCE_H_ +#define _SPL_INSTANCE_H_ +#include "nsfw_msg_api.h" +#include "stackx_instance.h" + +extern stackx_instance *p_def_stack_instance; + +int spl_process(data_com_msg * m); + +void add_disp_netif(struct netif *netif); +void do_update_pcbstate(); +void init_stackx_lwip(); + +#endif /* _SPL_INSTANCE_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h new file mode 100644 index 0000000..e9abd9c --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h @@ -0,0 +1,52 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "spl_opt.h" +#include "spl_pbuf.h" +#include "spl_ip_addr.h" +#include "common_mem_base_type.h" +//#include "common_mem_pal.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_netbuf.h" +#include +#include +#include +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** This spl_netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 + +/** This spl_netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +void spl_netbuf_delete(struct spl_netbuf *buf); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h new file mode 100644 index 0000000..b270b13 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h @@ -0,0 +1,174 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_PBUF_H__ +#define __STACKX_PBUF_H__ + +#include "cc.h" + +#include "common_mem_base_type.h" +#include "stackx_pbuf_comm.h" +#include "common_mem_mbuf.h" + +#ifdef HAL_LIB +#else +#include "common_pal_bitwide_adjust.h" +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +/** indicates this pbuf is loop buf .*/ +#define PBUF_FLAG_LOOPBUF 0x08U + +#define PBUF_SET_LOOP_FLAG(buf) ((buf)->flags |= PBUF_FLAG_LOOPBUF) +#define PBUF_IS_LOOP_BUF(buf) ((buf)->flags & PBUF_FLAG_LOOPBUF) + +/*Add 1 parameter, the last one, indicating which dpdk_malloc + *should be allocated from the pool; non-PBUF_ALLOC type regardless of this parameter*/ +struct spl_pbuf *spl_pbuf_alloc_hugepage(spl_pbuf_layer l, u16_t length, + spl_pbuf_type type, + u16_t thread_index, void *net_conn); +struct pbuf *spl_convert_spl_pbuf_to_pbuf(struct spl_pbuf *p_from); +err_t +splpbuf_to_pbuf_transport_copy(struct pbuf *p_to, struct spl_pbuf *p_from); + +err_t pbuf_to_splpbuf_copy(struct spl_pbuf *p_to, struct pbuf *p_from); +err_t splpbuf_to_pbuf_copy(struct pbuf *p_to, struct spl_pbuf *p_from); +spl_pbuf_layer get_pbuf_layer_from_pbuf_payload(struct pbuf *buf); +void print_pbuf_payload_info(struct pbuf *buf, bool send); + +static inline u8_t +spl_pbuf_header(struct spl_pbuf *p, s16_t header_size_increment) +{ + u8_t pbuf_ret; + /* header max len is tcp len+ ip len: 0xf*4+PBUF_IP_HLEN */ + if (unlikely + (((header_size_increment) < 0 && (-(header_size_increment)) > p->len) + || (header_size_increment > 0 + && (header_size_increment) >= (0xf * 4 + SPL_PBUF_IP_HLEN)))) + { + pbuf_ret = 1; + } + else + { + p->payload_a = p->payload_a - (header_size_increment); + p->len += (header_size_increment); + p->tot_len += (header_size_increment); + pbuf_ret = 0; + } + return pbuf_ret; +} + +void spl_pbuf_realloc(struct spl_pbuf *p, u32_t size); + +void spl_pbuf_cat(struct spl_pbuf *head, struct spl_pbuf *tail); +void spl_pbuf_free(struct spl_pbuf *p); + +#define pbuf_free_safe(x)\ +{\ + spl_pbuf_free((x));\ + (x) = NULL;\ +} + +/** + * Count number of pbufs in a chain + * + * @param p first pbuf of chain + * @return the number of pbufs in a chain + */ +static inline u16_t spl_pbuf_clen(struct spl_pbuf *p) +{ + u16_t len = 0; + while (p != NULL) + { + ++len; + p = (struct spl_pbuf *) ADDR_SHTOL(p->next_a); + } + return len; +} + +static inline u16_t mbuf_count(struct spl_pbuf *p) +{ + u16_t count = 0; + struct spl_pbuf *buf = p; + struct common_mem_mbuf *mbuf; + while (buf) + { + mbuf = + (struct common_mem_mbuf *) ((char *) buf - + sizeof(struct common_mem_mbuf)); + while (mbuf) + { + count++; +#ifdef HAL_LIB +#else + mbuf = mbuf->next; +#endif + } + buf = (struct spl_pbuf *) ADDR_SHTOL(buf->next_a); //buf->next; + } + return count; +} + +static inline u16_t mbuf_count_in_one_pbuf(struct spl_pbuf *p) +{ + + u16_t cnt = 0; + struct common_mem_mbuf *mbuf; + if (NULL == p) + { + NSPOL_LOGERR("Invalid param : p(null) !"); + return 0; + } + + mbuf = + (struct common_mem_mbuf *) ((char *) p - + sizeof(struct common_mem_mbuf)); + + /* no need to check mbuf itself */ +#ifdef HAL_LIB +#else + if (!mbuf->next) +#endif + return 1; + + while (mbuf) + { + ++cnt; +#ifdef HAL_LIB +#else + mbuf = mbuf->next; +#endif + } + + return cnt; +} + +inline int pbuf_internal_copy(struct spl_pbuf *dst, struct spl_pbuf *src); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_PBUF_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h new file mode 100644 index 0000000..fa385a5 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h @@ -0,0 +1,33 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _SPL_SBR_H_ +#define _SPL_SBR_H_ +#include "nsfw_msg_api.h" +#include "tcp.h" +#include "udp.h" +//#include "stackx/raw.h" +#define COMM_PRIVATE_PTR(m) \ + ((m->param.receiver) ? ((struct common_pcb *)m->param.comm_receiver) : 0) +#define TCP_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(struct tcp_pcb **)m->param.receiver) : 0) +#define UDP_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(struct udp_pcb **)m->param.receiver) : 0) +/*#define RAW_PRIVATE_PTR(m) \ + ((m->param.receiver) ? (*(void *)m->param.receiver) : 0) */ + +int spl_sbr_process(data_com_msg * m); +#endif /* _SPL_SBR_H_ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h new file mode 100644 index 0000000..f6ed9d9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h @@ -0,0 +1,252 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_SOCKETS_H__ +#define __STACKX_SOCKETS_H__ + +#include +#include /* for size_t */ +#include "arch/sys_arch.h" +#include "sys/socket.h" +#include +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef socklen_t +#define socklen_t u32_t +#endif + +#define SET_STACKP_ERRNO(err) (errno = (err)) //thread-local errno + +#ifndef set_errno +#define set_errno(err) SET_STACKP_ERRNO(err) +#endif + +#define sock_set_errno(sk, e) do { \ + (sk)->err = (e); \ + if ((sk)->err != 0) \ + set_errno((sk)->err); \ + } while (0) + +#ifndef __BITS_SOCKET_H +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info storing */ +#define SO_REUSEADDR 0x0002 +#endif + +#define SO_DONTROUTE 5 //0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 6 //0x0020 /* permit to send and to receive broad cast messages*/ +#define SO_KEEPALIVE 9 //0x0008 gaussdb /* keep connections alive */ +#define SO_OOBINLINE 10 //0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_LINGER 13 //0x0080 /* linger on close if data present */ +#define SO_REUSEPORT 15 /* Unimplemented: allow local address & port reuse */ +#define SO_ACCEPTCONN 30 //0x0002 /* socket has had listen() */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_TYPE 3 /* get socket type */ +#define SO_ERROR 4 +#define SO_SNDBUF 7 /* send buffer size */ +#define SO_RCVBUF 8 /* receive buffer size */ +#define SO_NO_CHECK 11 /* don't create UDP checksum */ +#define SO_RCVLOWAT 18 /* receive low-water mark */ +#define SO_SNDLOWAT 19 /* send low-water mark */ +#define SO_RCVTIMEO 20 /* receive timeout */ +#define SO_SNDTIMEO 21 /* Unimplemented: send timeout */ + +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 1 //0xfff + +#ifndef __BITS_SOCKET_H + +#define AF_UNSPEC 0 +#define PF_UNSPEC AF_UNSPEC +#define AF_INET 2 +#define PF_INET AF_INET + +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +#define IPPROTO_IP 0 + +#define MSG_PEEK 0x02 +#define MSG_WAITALL 0x100 +#define MSG_OOB 0x01 +#define MSG_DONTWAIT 0x40 +#define MSG_MORE 0x8000 +#endif + +#define IP_TOS 1 +#define IP_TTL 2 + +#define RCV_WND 0x21 +#define RCV_ANN_WND 0x22 +#define INIT_CWND 0x23 +#define THRESHOLD_FACTOR 0x24 +#define TMR_INTERVAL 0x25 + +/* + * Options and types for UDP multicast traffic handling + */ +#ifndef __BITS_SOCKET_H +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 +#endif + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_LOWCOST 0x02 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_MINCOST IPTOS_LOWCOST +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_ROUTINE 0x00 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) + +#if !defined (FIONREAD) || !defined (FIONBIO) +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */ + +#define _IO(x, y) (((x) << 8) | (y) |IOC_VOID ) + +#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) + +#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) +#endif + +/*unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) +#define SIOCGHIWAT _IOR('s', 1, unsigned long) +#define SIOCSLOWAT _IOW('s', 2, unsigned long) +#define SIOCGLOWAT _IOR('s', 3, unsigned long) +#ifndef __BITS_SOCKET_H +#define SIOCATMARK _IOR('s', 7, unsigned long) +#endif +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 0X800 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY O_NONBLOCK /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0x80000 /* set close_on_exec */ +#endif +#ifndef __BITS_SOCKET_H +#define SOCK_CLOEXEC O_CLOEXEC +#endif +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif +#ifndef SHUT_RD +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 +#endif + +struct pollfd +{ + + int fd; /* file descriptor */ + short events; /* wait event */ + short revents; /* actual event happened */ +}; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_SOCKETS_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h new file mode 100644 index 0000000..331255b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_TCPIP_H__ +#define __STACKX_TCPIP_H__ + +#include "spl_opt.h" +#include "stackx/spl_ip_addr.h" +#include "tcp.h" + +#define USEAGE_LOW 60 +#define USEAGE_HIGHT 80 +#define USEAGE_INVALID 0xFF + +/*** Put into stackx_instance ********* + +************************************/ +#include "stackx/spl_api_msg.h" +#include "netifapi.h" +#include "stackx/spl_pbuf.h" +#include "stackx/spl_api.h" +#include "sys.h" +#include "netif.h" +#include "ip_module_api.h" +#include "internal_msg.h" +#include "pbuf.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** Function prototype for send timeout message */ +err_t ltt_apimsg(sys_timeout_handler h, void *arg); + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn) (void *arg); + +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn) (void *ctx); + +int init_by_main_thread(); +int init_by_tcpip_thread(); +err_t spl_tcpip_input(struct pbuf *p, struct netif *inp); + +int post_ip_module_msg(void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int process_ip_module_msg(void *arg, ip_module_type type, + ip_module_operate_type operate_type); +int init_new_network_configuration(); + +#if STACKX_NETIF_API +err_t tcpip_netif_add(msg_add_netif * tmp); +#endif /* STACKX_NETIF_API */ + +err_t ltt_clearTmrmsg(void *pcb, void *arg); + +sys_mbox_t get_primary_box(); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_TCPIP_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h new file mode 100644 index 0000000..078846b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h @@ -0,0 +1,108 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __SPL_TIMERS_H__ +#define __SPL_TIMERS_H__ + +#include "opt.h" +#include "common_mem_base_type.h" + +typedef void (*sys_timeout_handler) (void *arg); + +#include "rb_tree.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ + +/* + * ************************************************************************* + * PTIMER defined 2013/3/15 + * ************************************************************************* + */ +#define PTIMER_DEFAULT 0x00 /* periodic mode */ +#define PTIMER_ONESHOT 0x01 +#define PTIMER_USER_DEF 0x02 + +enum msg_type +{ + SYS_PTIMEROUT_MSG, + SYS_UNPTIMEROUT_MSG, +}; + +struct msg_context +{ + unsigned long msec; + union + { + sys_timeout_handler handle; + } action; +#define _act_category action.act_category +#define _phandle action.handle + u32_t flags; /* oneshot|user_def|... */ + void *ctx; /* pcb ptr */ +}; + +struct ptimer_node +{ + struct rb_node node; + unsigned long abs_nsec; + struct msg_context info; + unsigned long state; + u16_t index; /* store a lwip thread message box id */ +}; + +struct ptimer_msg +{ + enum msg_type msg_type; + struct ptimer_node *node; + struct ptimer_msg *next, *prev; +}; + +struct ptimer_base +{ + struct rb_root active; + struct rb_node *first; /* point the recently timeout */ + pthread_mutex_t lock; + pthread_cond_t cond; + struct ptimer_msg *head, *tail; +}; + +/* + * ***************************************************** + * ptimer E-N-D + * ***************************************************** + */ +void ptimer_thread(void *arg); +void timeout_phandler(void *act, void *arg); +void regedit_ptimer(enum msg_type type, sys_timeout_handler handler, + struct ptimer_node *node); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __LWIP_TIMERS_H__ */ diff --git a/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h new file mode 100644 index 0000000..3f24756 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h @@ -0,0 +1,91 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_INSTANCE_H__ +#define __STACKX_INSTANCE_H__ + +#include "stackx/spl_tcpip.h" +#include "netif.h" +#include "lwip/ip4_frag.h" +#include "stackx/spl_pbuf.h" +#include "arch/sys_arch.h" +#include "arch/queue.h" +#include "stackx_tx_box.h" +#include "nsfw_msg.h" +#include "stackx_app_res.h" +#include "ip_module_api.h" +#include "tcp.h" +#include "udp.h" + +#define PKT_BURST 32 + +#define TASK_BURST 16 + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_NETBUFS 1024*2 //define for C10M + +#define TOTAL_MSG_QUEUE_NUM (MSG_PRIO_QUEUE_NUM+1) /* three priority queue and one primary queue */ + +struct stackx_stat +{ + struct rti_queue primary_stat; //primary box stat + u64_t extend_member_bit; +}; + +struct stackx_stack +{ + struct queue primary_mbox; + struct queue priority_mbox[MSG_PRIO_QUEUE_NUM]; //0-highest; 1-medium; 2-lowest + //stackx_apis stackx_api; +}; + +struct disp_netif_list +{ + struct disp_netif_list *next; + struct netif *netif; +}; + +typedef struct stackx_instance +{ + uint16_t rss_queue_id; + + mpool_handle mp_tx; + //mring_handle mp_seg; + mring_handle cpcb_seg; + mring_handle lmsg_pool; + + struct stackx_stack lstack; + struct stackx_stat lstat; //point to p_stackx_table->lstat[i]; + + /** + * Header of the input packet currently being processed. + */ + /* global variables */ + struct disp_netif_list *netif_list; +} stackx_instance; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* __STACKX_INSTANCE_H__ */ diff --git a/stacks/lwip_stack/lwip_src/instance/spl_instance.c b/stacks/lwip_stack/lwip_src/instance/spl_instance.c new file mode 100644 index 0000000..7e9fe1b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/instance/spl_instance.c @@ -0,0 +1,47 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_msg_api.h" +#include "nsfw_init_api.h" +#include "stackx/spl_sbr.h" +#include "stackx/stackx_instance.h" + +stackx_instance *p_def_stack_instance = NULL; + +/** + * process message from other module, but the MT module message will be delayed + * to handle in the end of the loop to avoid to lose the message dequeued out. + * + * @param m the data_com_msg to handle + */ +int spl_process(data_com_msg * m) +{ + return call_msg_fun(m); +} + +void add_disp_netif(struct netif *netif) +{ + struct disp_netif_list *item = malloc(sizeof(struct disp_netif_list)); + if (!item) + { + NSPOL_LOGERR("malloc failed"); + return; + } + + item->netif = netif; + item->next = p_def_stack_instance->netif_list; + p_def_stack_instance->netif_list = item; +} diff --git a/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c b/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c new file mode 100644 index 0000000..46bdc08 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c @@ -0,0 +1,1039 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "configuration_reader.h" +#include "container_ip.h" +#include "network.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "json.h" +#include "spl_tcpip.h" + +#include "types.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_maintain_api.h" + +NSTACK_STATIC struct config_data g_ip_module_buff; +NSTACK_STATIC struct config_data *g_config_data; +NSTACK_STATIC char ip_module_unix_socket[IP_MODULE_MAX_PATH_LEN + 1]; +NSTACK_STATIC char ip_module_unix_socket_dir_path[IP_MODULE_MAX_PATH_LEN + 1]; +//static unsigned long int g_thread_id = 0; + +#define MAX_CONNECTION_NUMBER 5 +#define TCP_OOS_LEN_MAX 250 + +NSTACK_STATIC int read_configuration(); +NSTACK_STATIC int unix_socket_listen(const char *servername); +NSTACK_STATIC int process_query(); + +/***************************************************************************** +* Prototype : is_digit_str +* Description : check if a string contains only digit +* Input : char *input +* Output : 1 for yes, 0 for no +* Return Value : int +* Calls : +* Called By : get_main_pid +* +*****************************************************************************/ +NSTACK_STATIC int is_digit_str(char *input) +{ + if (NULL == input || '\0' == input[0]) + { + return 0; + } + + while (*input) + { + if (*input > '9' || *input < '0') + { + return 0; + } + input++; + } + + return 1; +} + +/***************************************************************************** +* Prototype : process_query +* Description : ./nStackCtrl -a query +* Input : none +* Output : none +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int process_query() +{ + int retval; + + if (0 == g_config_data->param.type[0]) + { + return process_post(NULL, IP_MODULE_ALL, IP_MODULE_OPERATE_QUERY); + } + + /*name & p are freed inside process_post */ + if (0 == strcmp(g_config_data->param.type, IP_MODULE_TYPE_PORT)) + { + struct ip_action_param *p = malloc(sizeof(struct ip_action_param)); + if (p == NULL) + { + NSOPR_LOGERR("name allocation failed!"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "mem alloc error!"); + return -1; + } + + retval = + memset_s(p, sizeof(struct ip_action_param), 0, + sizeof(struct ip_action_param)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "MEMSET_S error!"); + free(p); + return -1; + } + + retval = + strcpy_s(p->container_id, sizeof(p->container_id), + g_config_data->param.container_id); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(p); + return -1; + } + + retval = + strcpy_s(p->port_name, sizeof(p->port_name), + g_config_data->param.name); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(p); + return -1; + } + + return process_post((void *) p, IP_MODULE_IP, + IP_MODULE_OPERATE_QUERY); + } + else if (0 == strcmp(g_config_data->param.type, IP_MODULE_TYPE_NETWORK)) + { + if (0 == g_config_data->param.name[0]) + { + return process_post(NULL, IP_MODULE_NETWORK_ALL, + IP_MODULE_OPERATE_QUERY); + } + else + { + char *name = malloc(sizeof(g_config_data->param.name)); + if (NULL == name) + { + NSOPR_LOGERR("name allocation failed!"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "mem alloc error!"); + return -1; + } + + retval = + memset_s(name, sizeof(g_config_data->param.name), 0, + sizeof(g_config_data->param.name)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "MEMSET_S error!"); + free(name); + return -1; + } + + retval = + strcpy_s(name, sizeof(g_config_data->param.name), + g_config_data->param.name); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(name); + return -1; + } + + return process_post((void *) name, IP_MODULE_NETWORK, + IP_MODULE_OPERATE_QUERY); + } + } + else if (0 == strcmp(g_config_data->param.type, IP_MODULE_TYPE_IP)) + { + if (0 == g_config_data->param.name[0]) + { + return process_post(NULL, IP_MODULE_IP_ALL, + IP_MODULE_OPERATE_QUERY); + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + } + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + } + + return -1; +} + +int read_ipmoduleoperatesetnet_configuration() +{ + if (strcmp(g_config_data->param.type, IP_MODULE_TYPE_SETLOG) == 0) + { + if (NSCRTL_OK == + setlog_level_value(g_config_data->param.name, + g_config_data->param.value)) + { + NSOPR_LOGDBG("set log level ok!"); + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + } + } + else if (strcmp(g_config_data->param.type, TCP_MODULE_TYPE_SET_OOS_LEN) == + 0) + { + if (is_digit_str(g_config_data->param.value) == 0) + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, + "Invalid value:value must be digital and smaller than %u]value=\"%s\"", + TCP_OOS_LEN_MAX, g_config_data->param.value); + return 0; + } + + unsigned int value_len = strlen(g_config_data->param.value); + if ((value_len >= 2) && (g_config_data->param.value[0] == '0')) + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, + "Invalid value:value cannot start with 0"); + return 0; + } + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + } + + return 0; +} + +/***************************************************************************** +* Prototype : read_version +* Description : Query Version by nStackCtrl +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int read_version() +{ + int retVal; + json_object *version = json_object_new_object(); + + if (NULL == version) + { + NSOPR_SET_ERRINFO(NSCRTL_ERR, "internal error for version=NULL!"); + return NSCRTL_ERR; + } + + json_object_object_add(version, "moudle", + json_object_new_string(NSTACK_GETVER_MODULE)); + json_object_object_add(version, "version", + json_object_new_string(NSTACK_GETVER_VERSION)); + json_object_object_add(version, "buildtime", + json_object_new_string(NSTACK_GETVER_BUILDTIME)); + + json_object *version_array = json_object_new_array(); + if (NULL == version_array) + { + json_object_put(version); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "internal error for version_array=NULL!"); + return NSCRTL_ERR; + } + + retVal = json_object_array_add(version_array, version); + + if (0 != retVal) + { + json_object_put(version_array); + json_object_put(version); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "internal error for json_object_array_add failed!"); + return NSCRTL_ERR; + } + + const char *str = json_object_to_json_string(version_array); + + if (NULL == str) + { + json_object_put(version_array); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "internal error for str=NULL!"); + return NSCRTL_ERR; + } + + size_t str_len = strlen(str); + if (str_len >= sizeof(get_config_data()->json_buff)) + { + json_object_put(version_array); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "internal error!"); + return NSCRTL_ERR; + } + + retVal = + strncpy_s(get_config_data()->json_buff, + sizeof(get_config_data()->json_buff), str, str_len); + if (EOK != retVal) + { + json_object_put(version_array); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRNCPY_S error!"); + return NSCRTL_ERR; + } + + json_object_put(version_array); + return NSCRTL_OK; +} + +void reset_config_data(void) +{ + int retval = memset_s(g_config_data, sizeof(struct config_data), 0, + sizeof(struct config_data)); + if (EOK != retval) + { + printf("MEMSET_S failed]retval=%d.\n", retval); + exit(1); + } +} + +int get_network_json_data() +{ + strcpy_s(g_config_data->param.type, sizeof(g_config_data->param.type), + "network"); + g_config_data->param.action = IP_MODULE_OPERATE_ADD; + + char *tmp_config_path; + tmp_config_path = realpath("./network_data_tonStack.json", NULL); + if (!tmp_config_path) + { + NSTCP_LOGINF("Warning! It use the second search path ../configure"); + tmp_config_path = + realpath("../configure/network_data_tonStack.json", NULL); + } + + if (!tmp_config_path) + { + return 1; + } + + int fp = open(tmp_config_path, O_RDONLY); + if (-1 == fp) + { + free(tmp_config_path); + NSTCP_LOGINF("network file open failed.\n"); + exit(1); + } + free(tmp_config_path); + + int nread = read(fp, g_config_data->json_buff, + sizeof(g_config_data->json_buff) - 1); + if (nread <= 0) + { + close(fp); + NSTCP_LOGINF("read failed %d.\n", nread); + exit(1); + } + + /* though MEMSET_S is done above, MEMSET_S can be removed */ + g_config_data->json_buff[nread] = '\0'; + close(fp); + + struct network_configuration *network = NULL; + struct network_configuration *tmp = NULL; + + /* input shouldnot be same with return */ + network = parse_network_json(g_config_data->json_buff, NULL); + if (!network) + { + NSTCP_LOGINF("Invalid network data!"); + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "Invalid network data!"); + return -1; + } + + /* run process_post for each network, not only the head node */ + while (network) + { + tmp = network; + network = network->next; + int retval = + add_network_configuration((struct network_configuration *) tmp); + + /* When network exceeds max number, just log warning at operation.log */ + if (retval == NSCRTL_NETWORK_COUNT_EXCEED) + { + NSTCP_LOGINF + ("Warning!! Network count exceed max allowed number]max=%d", + MAX_NETWORK_COUNT); + } + else + { + + NSTCP_LOGINF("add_network_configuration %d", retval); + NSOPR_SET_ERRINFO(retval, "add_network_configuration return %d", + retval); + } + + if (!retval) + { + /*init DPDK eth */ + if ((retval = init_new_network_configuration()) != ERR_OK) + { + NSTCP_LOGINF("process_configuration failed! %d", retval); + free_network_configuration((struct network_configuration *) + tmp, IP_MODULE_TRUE); + NSOPR_SET_ERRINFO(retval, + "init_new_network_configuration return %d", + retval); + return -1; + } + } + } + NSTCP_LOGINF("Get_network_json_data done!"); + + return 0; +} + +int get_ip_json_data() +{ + NSTCP_LOGINF("get_ip_json_data start!"); + + strcpy_s(g_config_data->param.type, sizeof(g_config_data->param.type), + "ip"); + g_config_data->param.action = IP_MODULE_OPERATE_ADD; + + char *tmp_config_path; + tmp_config_path = realpath("./ip_data.json", NULL); + if (!tmp_config_path) + { + NSTCP_LOGINF("Warning! It use the second search path ../configure"); + tmp_config_path = realpath("../configure/ip_data.json", NULL); + } + + if (!tmp_config_path) + { + return 1; + } + + int fp = open(tmp_config_path, O_RDONLY); + if (-1 == fp) + { + free(tmp_config_path); + NSTCP_LOGINF("network file open failed\n"); + exit(1); + } + free(tmp_config_path); + + int nread = read(fp, g_config_data->json_buff, + sizeof(g_config_data->json_buff) - 1); + if (nread <= 0) + { + close(fp); + NSTCP_LOGINF("read failed %d.\n", nread); + exit(1); + } + + /* though MEMSET_S is done above, MEMSET_S can be removed */ + g_config_data->json_buff[nread] = '\0'; + close(fp); + + struct container_ip *container = + parse_container_ip_json(g_config_data->json_buff); + if (container) + { + int retval = add_container(container); + + NSTCP_LOGINF("add_container %d", retval); + NSOPR_SET_ERRINFO(retval, "add_container return %d", retval); + } + else + { + NSTCP_LOGINF("Invalid IP config data!"); + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "Invalid IP config data!"); + return -1; + } + NSTCP_LOGINF("get_ip_json_data done!"); + + return 0; +} + +int read_ipmoduleoperateadd_configuration() +{ + struct network_configuration *tmp = NULL; + if (strcmp(g_config_data->param.type, IP_MODULE_TYPE_IP) == 0) + { + struct container_ip *container = + parse_container_ip_json(g_config_data->json_buff); + if (container) + { + return process_post((void *) container, IP_MODULE_IP, + IP_MODULE_OPERATE_ADD); + } + else + { + NSOPR_LOGERR("Invalid IP config data!"); + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "Invalid IP config data!"); + return -1; + } + } + else if (strcmp(g_config_data->param.type, IP_MODULE_TYPE_NETWORK) == 0) + { + struct network_configuration *network = NULL; + + //Read network.json + + /* input shouldnot be same with return */ + network = parse_network_json(g_config_data->json_buff, NULL); + if (!network) + { + NSOPR_LOGERR("Invalid network data!"); + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "Invalid network data!"); + return -1; + } + + /* run process_post for each network, not only the head node */ + while (network) + { + tmp = network; + network = network->next; + int ret = process_post((void *) tmp, IP_MODULE_NETWORK, + IP_MODULE_OPERATE_ADD); + if (ret == -1) + { + NSOPR_LOGERR("process_configuration failed!"); + return -1; + } + } + return 0; + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + return -1; + } +} + +int read_ipmoduleoperatedel_configuration() +{ + int retval; + + if (strcmp(g_config_data->param.type, IP_MODULE_TYPE_IP) == 0) + { + struct ip_action_param *p = malloc(sizeof(struct ip_action_param)); + if (NULL == p) + { + NSOPR_LOGERR("ip_action_param allocation failed!"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "mem alloc error!"); + return -1; + } + + retval = + memset_s(p, sizeof(struct ip_action_param), 0, + sizeof(struct ip_action_param)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "MEMSET_S error!"); + free(p); + return -1; + } + + retval = + strcpy_s(p->container_id, sizeof(p->container_id), + g_config_data->param.container_id); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(p); + return -1; + } + + retval = + strcpy_s(p->port_name, sizeof(p->port_name), + g_config_data->param.name); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(p); + return -1; + } + + return process_post((void *) p, IP_MODULE_IP, IP_MODULE_OPERATE_DEL); + } + else if (strcmp(g_config_data->param.type, IP_MODULE_TYPE_NETWORK) == 0) + { + char *name = malloc(sizeof(g_config_data->param.name)); + if (name == NULL) + { + NSOPR_LOGERR("name allocation failed!"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "mem alloc error!"); + return -1; + } + + retval = + memset_s(name, sizeof(g_config_data->param.name), 0, + sizeof(g_config_data->param.name)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "MEMSET_S error!"); + free(name); + return -1; + } + + retval = + strcpy_s(name, sizeof(g_config_data->param.name), + g_config_data->param.name); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, "STRCPY_S error!"); + free(name); + return -1; + } + + return process_post((void *) name, IP_MODULE_NETWORK, + IP_MODULE_OPERATE_DEL); + } + else + { + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + return -1; + } +} + +NSTACK_STATIC int read_configuration() +{ + int retval = -1; + //u64 traceid = 0; + + /* initialise default memory */ + g_config_data->param.error = NSCRTL_OK; + + /* Make sure error_desc is inited to null string */ + g_config_data->param.error_desc[0] = '\0'; + + //traceid = g_config_data->param.traceid; + + NSOPR_LOGINF + ("g_config_data]type=%s,name=%s,value=%s,container_id=%s,action=%d,Json_buf=%s, traceid=%llu", + g_config_data->param.type, g_config_data->param.name, + g_config_data->param.value, g_config_data->param.container_id, + g_config_data->param.action, g_config_data->json_buff, + g_config_data->param.traceid); + + retval = + memset_s(g_config_data->param.error_desc, + sizeof(g_config_data->param.error_desc), 0, + sizeof(g_config_data->param.error_desc)); + if (0 != retval) + { + NSOPR_SET_ERRINFO(NSCRTL_ERR, "ERR:internal error, MEMSET_S failed]"); + return -1; + } + + switch (g_config_data->param.action) + { + case IP_MODULE_OPERATE_DEL: + { + retval = read_ipmoduleoperatedel_configuration(); + break; + } + case IP_MODULE_OPERATE_QUERY: + { + retval = process_query(); + break; + } + case IP_MODULE_OPERATE_ADD: + { + retval = read_ipmoduleoperateadd_configuration(); + break; + } + case IP_MODULE_OPERATE_SET: + retval = read_ipmoduleoperatesetnet_configuration(); + break; + case IP_MODULE_GET_VERSION: + { + retval = read_version(); + break; + } + + default: + { + retval = -1; //here, must set retval to -1 + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "input error!"); + break; + } + } + + return retval; +} + +NSTACK_STATIC int unix_socket_listen(const char *servername) +{ + int fd, retval; + unsigned int len; + struct stat st; + struct sockaddr_un un; + + if (stat(ip_module_unix_socket_dir_path, &st) == 0) + { + NSOPR_LOGDBG(" /directory is present"); + } + else + { + NSOPR_LOGERR(" /var/run/nStack/ directory is not present "); + return (-1); + } + + if ((fd = nsfw_base_socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + return -1; + } + + retval = unlink(servername); /* in case it already exists */ + if (0 != retval) + { + NSOPR_LOGWAR("unlink failed]retval=%d,errno=%d", retval, errno); + } + + retval = memset_s(&un, sizeof(un), 0, sizeof(un)); + if (EOK != retval) + { + (void) nsfw_base_close(fd); + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + return -1; + } + + un.sun_family = AF_UNIX; + retval = strcpy_s(un.sun_path, sizeof(un.sun_path), servername); + if (EOK != retval) + { + (void) nsfw_base_close(fd); + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + return -1; + } + + len = + (unsigned int) (offsetof(struct sockaddr_un, sun_path) + + strlen(servername)); + + if (nsfw_base_bind(fd, (struct sockaddr *) &un, len) < 0) + { + (void) nsfw_base_close(fd); + return -1; + } + else + { + if (nsfw_base_listen(fd, MAX_CONNECTION_NUMBER) < 0) + { + (void) nsfw_base_close(fd); + return -1; + } + else + { + return fd; + } + } +} + +/***************************************************************************** +* Prototype : read_fn +* Description : process new ip module msg +* Input : i32 fd +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +void read_fn(i32 fd) +{ + ssize_t size; + ssize_t offset = 0; + size_t left = MAX_IP_MODULE_BUFF_SIZE; + while (left > 0) + { + size = nsfw_base_recv(fd, (char *) g_config_data + offset, left, 0); + if (size > 0) + { + offset += size; + left -= (size_t) size; + } + else + { + NSOPR_LOGERR("Error when recieving]errno=%d,err_string=%s", errno, + strerror(errno)); + break; + } + } + + if (left != 0) + { + (void) nsfw_base_close(fd); + return; + } + + (void) read_configuration(); // if it returns -1, the err desc info will be wrote to g_config_data, so no need to check return value. + + offset = 0; + left = MAX_IP_MODULE_BUFF_SIZE; + while (left > 0) + { + size = + nsfw_base_send(fd, (char *) g_config_data + offset, left, + MSG_NOSIGNAL); + + if (size > 0) + { + offset += size; + left -= (size_t) size; + } + else + { + NSOPR_LOGERR("Error when Sending data]errno=%d", errno); + break; + } + } + + (void) nsfw_base_close(fd); + return; +} + +/***************************************************************************** +* Prototype : ip_module_new_msg +* Description : recv new config message +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int ip_module_new_msg(i32 epfd, i32 fd, u32 events) +{ + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + nsfw_mgr_unreg_sock_fun(fd); + (void) nsfw_base_close(fd); + return TRUE; + } + + nsfw_mgr_unreg_sock_fun(fd); + read_fn(fd); + return TRUE; +} + +int init_ip_module_unix_socket_path() +{ + const char *directory = "/var/log/nStack"; + const char *home_dir = getenv("HOME"); + + if (getuid() != 0 && home_dir != NULL) + directory = home_dir; + + if (strcpy_s + (ip_module_unix_socket_dir_path, IP_MODULE_MAX_PATH_LEN, + directory) < 0) + { + NSOPR_LOGERR("STRCPY_S fail]"); + return -1; + } + + if (strcat_s + (ip_module_unix_socket_dir_path, IP_MODULE_MAX_PATH_LEN, + "/ip_module") < 0) + { + NSOPR_LOGERR("STRCAT_S fail]"); + return -1; + } + + if (strcpy_s + (ip_module_unix_socket, IP_MODULE_MAX_PATH_LEN, + ip_module_unix_socket_dir_path) < 0) + { + NSOPR_LOGERR("STRCPY_S fail]"); + return -1; + } + + if (strcat_s + (ip_module_unix_socket, IP_MODULE_MAX_PATH_LEN, + "/ip_module_unix_sock") < 0) + { + NSOPR_LOGERR("STRCAT_S fail]"); + return -1; + } + + NSOPR_LOGINF("ip_module_unix_socket=%s", ip_module_unix_socket); + NSOPR_LOGINF("ip_module_unix_socket_dir_path=%s", + ip_module_unix_socket_dir_path); + return 0; +} + +/***************************************************************************** +* Prototype : ip_module_new_connection +* Description : recv new connect for network config +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int ip_module_new_connection(i32 epfd, i32 fd, u32 events) +{ + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close(fd); + NSFW_LOGINF("listen disconnect!]epfd=%d,listen=%d,event=0x%x", epfd, + fd, events); + nsfw_mgr_unreg_sock_fun(fd); + + if (init_ip_module_unix_socket_path() < 0) + { + NSFW_LOGERR + ("Error when init path]epfd=%d,listen_fd=%d,event=0x%x", epfd, + fd, events); + return FALSE; + } + + i32 listen_fd = unix_socket_listen(ip_module_unix_socket); + if (listen_fd < 0) + { + NSFW_LOGERR + ("get listen_fd faied!]epfd=%d,listen_fd=%d,event=0x%x", epfd, + fd, events); + return FALSE; + } + + if (FALSE == + nsfw_mgr_reg_sock_fun(listen_fd, ip_module_new_connection)) + { + (void) nsfw_base_close(listen_fd); + return FALSE; + } + return TRUE; + } + + struct sockaddr in_addr; + socklen_t in_len; + int infd; + in_len = sizeof in_addr; + + while (1) + { + infd = nsfw_base_accept(fd, &in_addr, &in_len); + if (infd == -1) + { + break; + } + + if (FALSE == nsfw_mgr_reg_sock_fun(infd, ip_module_new_msg)) + { + NSFW_LOGINF("accept new fd but reg failed]new_mgr_fd=%d", infd); + return FALSE; + } + NSFW_LOGINF("accept new fd]new_mgr_fd=%d", infd); + } + + return TRUE; +} + +int init_configuration_reader() +{ + int error_number = 0; + INITPOL_LOGINF("CONFIGURATION", "init_configuration_reader", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + g_config_data = &g_ip_module_buff; + + if (init_ip_module_unix_socket_path() < 0) + { + INITPOL_LOGERR("CONFIGURATION", "init_configuration_reader", + "Error when init path", LOG_INVALID_VALUE, + MODULE_INIT_FAIL); + return -1; + } + + i32 listen_fd = unix_socket_listen(ip_module_unix_socket); + if (listen_fd < 0) + { + error_number = errno; + INITPOL_LOGERR("CONFIGURATION", "init_configuration_reader", + "when listening ip_module_unix_socket", error_number, + MODULE_INIT_FAIL); + return -1; + } + + NSOPR_LOGINF("start mgr_com module!]listern_fd=%d", listen_fd); + + if (FALSE == nsfw_mgr_reg_sock_fun(listen_fd, ip_module_new_connection)) + { + (void) nsfw_base_close(listen_fd); + NSOPR_LOGERR("nsfw_mgr_reg_sock_fun failed]listen_fd=%d", listen_fd); + return -1; + } + + INITPOL_LOGINF("CONFIGURATION", "init_configuration_reader", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + return 0; +} + +struct config_data *get_config_data() +{ + return g_config_data; +} diff --git a/stacks/lwip_stack/lwip_src/ip_module/container_ip.c b/stacks/lwip_stack/lwip_src/ip_module/container_ip.c new file mode 100644 index 0000000..1cbcfb3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/ip_module/container_ip.c @@ -0,0 +1,1117 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "lwip/inet.h" +#include "trp_rb_tree.h" +#include "container_ip.h" +#include "network.h" +#include "netif.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "config_common.h" +#include "igmp.h" +#include "spl_def.h" +#include "stackx_ip_addr.h" +#include "nsfw_hal_api.h" +#include "spl_hal.h" + +struct container_list g_container_list = { 0 }; +static trp_rb_root_t g_container_ip_root = { 0 }; //only handled in tcpip thread, no need protect it with a lock +static trp_rb_root_t g_container_multicast_root = { 0 }; //only handled in tcpip thread, no need protect it with a lock + +static void free_container_port(struct container_port *port, + bool_t only_free); + +/*unsigned int value is typecasted into void * pointer and passed as argument to +this function. so the value can never be > 0xFFFFFFFF. so can suppress the warning*/ + +static int ip_compare(trp_key_t left, trp_key_t right) +{ + //return (int)((unsigned long)left - (unsigned long)right); + + if (left > right) + { + return 1; + } + else if (left < right) + { + return -1; + } + else + { + return 0; + } +} + +NSTACK_STATIC bool_t is_container_ok(struct container_ip * container) +{ + if (!container->ports_list) + { + return 0; + } + + return 1; +} + +NSTACK_STATIC void +add_port(struct container_ip *container, struct container_port *port) +{ + if (port->ip_cidr_list) + { + port->next = container->ports_list; + container->ports_list = port; + } + else + { + free_container_port(port, IP_MODULE_TRUE); + } +} + +static void +add_ip_cidr(struct container_port *port, + struct container_port_ip_cidr *ip_cidr) +{ + if (!ip_cidr) + { + return; + } + + ip_cidr->next = port->ip_cidr_list; + port->ip_cidr_list = ip_cidr; + return; +} + +NSTACK_STATIC void +add_multilcast_ip(struct container_port *port, + struct container_multicast_id *muticastIP) +{ + if (!muticastIP) + { + return; + } + + muticastIP->next = port->multicast_list; + port->multicast_list = muticastIP; + return; +} + +NSTACK_STATIC void +free_container_port_ip_cidr(struct container_port_ip_cidr *ip_cidr, + bool_t only_free) +{ + output_api *api = get_output_api(); + struct container_port_ip_cidr *ip_cidr_tmp = NULL; + + while (ip_cidr) + { + ip_cidr_tmp = ip_cidr; + ip_cidr = ip_cidr_tmp->next; + if (!only_free) + { + if (api->del_netif_ip) + { + struct network_configuration *network = + get_network_by_ip_with_tree(ip_cidr_tmp->ip); + if (network) + { + if (network->phy_net->bond_name[0] != 0) + { + (void) api->del_netif_ip(network->phy_net->bond_name, ip_cidr_tmp->ip); //fails only when netif_name not exist, no side effect so don't check return value. + } + else + { + (void) api->del_netif_ip(network->phy_net-> + header->nic_name, + ip_cidr_tmp->ip); + } + } + else + { + NSOPR_LOGERR("can't find network by]IP=%u", + ip_cidr_tmp->ip); + } + } + + trp_rb_erase((void *) (u64_t) ip_cidr_tmp->ip, + &g_container_ip_root, ip_compare); + } + + free(ip_cidr_tmp); + ip_cidr_tmp = NULL; + } +} + +static void +free_container_multicast(struct container_multicast_id *multicast, + bool_t only_free) +{ + struct container_multicast_id *tmp = NULL; + + while (multicast) + { + tmp = multicast; + multicast = multicast->next; + if (!only_free) + { + trp_rb_erase((void *) (u64_t) tmp->ip, + &g_container_multicast_root, ip_compare); + } + + free(tmp); + tmp = NULL; + } +} + +static void free_container_port(struct container_port *port, bool_t only_free) +{ + struct container_port *port_tmp = NULL; + struct container_port *port_curr = port; + + while (port_curr) + { + port_tmp = port_curr; + port_curr = port_tmp->next; + + free_container_multicast(port_tmp->multicast_list, only_free); + free_container_port_ip_cidr(port_tmp->ip_cidr_list, only_free); + + if (port_tmp->buffer) + { + free_port_buffer(port_tmp->buffer); + port_tmp->buffer = NULL; + } + + free(port_tmp); + port_tmp = NULL; + } +} + +void free_container(struct container_ip *container, bool_t only_free) +{ + struct container_ip *container_tmp = NULL; + struct container_ip *container_curr = container; + + while (container_curr) + { + container_tmp = container_curr; + container_curr = container_tmp->next; + if (container_tmp->ports_list) + { + free_container_port(container_tmp->ports_list, only_free); + } + + free(container_tmp); + container_tmp = NULL; + } +} + +struct container_port *parse_port_obj(struct json_object *port_obj) +{ + int retval; + struct json_object *port_name_obj = NULL; + struct json_object *ip_cidr_list_obj = NULL; + struct json_object *mcIDObj = NULL; + + if (!port_obj) + { + NSOPR_LOGERR("port_obj is null"); + return NULL; + } + + struct container_port *port = malloc(sizeof(struct container_port)); + if (!port) + { + NSOPR_LOGERR("malloc failed"); + return NULL; + } + + retval = + memset_s(port, sizeof(struct container_port), 0, + sizeof(struct container_port)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + free(port); + return NULL; + } + + json_object_object_get_ex(port_obj, "port_name", &port_name_obj); + if (port_name_obj) + { + const char *port_name = json_object_get_string(port_name_obj); + if ((NULL == port_name) + || (strlen(port_name) >= IP_MODULE_MAX_NAME_LEN)) + { + NSOPR_LOGERR("port name is not ok"); + goto RETURN_ERROR; + } + + retval = + strcpy_s(port->port_name, sizeof(port->port_name), port_name); + + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + } + + json_object_object_get_ex(port_obj, "ip_cidr", &ip_cidr_list_obj); + if (ip_cidr_list_obj) + { + int j; + int ip_cidr_num = json_object_array_length(ip_cidr_list_obj); + for (j = 0; j < ip_cidr_num; ++j) + { + struct json_object *ip_cidr_obj = + json_object_array_get_idx(ip_cidr_list_obj, j); + if (ip_cidr_obj) + { + char tmp[IP_MODULE_LENGTH_32] = { 0 }; + struct container_port_ip_cidr *port_ip_cidr = + malloc(sizeof(struct container_port_ip_cidr)); + if (NULL == port_ip_cidr) + { + NSOPR_LOGERR("malloc failed"); + goto RETURN_ERROR; + } + + retval = + memset_s(port_ip_cidr, + sizeof(struct container_port_ip_cidr), 0, + sizeof(struct container_port_ip_cidr)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + const char *ip_cidr = json_object_get_string(ip_cidr_obj); + if ((NULL == ip_cidr) || (ip_cidr[0] == 0)) + { + NSOPR_LOGERR("ip_cidr is not ok"); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + const char *sub = strstr(ip_cidr, "/"); + if ((NULL == sub) + || (sizeof(tmp) - 1 < (unsigned int) (sub - ip_cidr)) + || (strlen(sub) > sizeof(tmp) - 1)) + { + NSOPR_LOGERR + ("Error : Ipaddress notation must be in ip cidr notation!"); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + retval = + strncpy_s(tmp, sizeof(tmp), ip_cidr, + (size_t) (sub - ip_cidr)); + if (EOK != retval) + { + NSOPR_LOGERR("STRNCPY_S failed]ret=%d", retval); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + struct in_addr addr; + int iRet; + retval = memset_s(&addr, sizeof(addr), 0, sizeof(addr)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + iRet = spl_inet_aton(tmp, &addr); + if (0 == iRet) + { + NSOPR_LOGERR("spl_inet_aton failed"); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + port_ip_cidr->ip = addr.s_addr; + iRet = atoi(sub + 1); + if ((iRet <= 0) || (iRet > IP_MODULE_LENGTH_32)) + { + NSOPR_LOGERR("IP mask length is not correct"); + free(port_ip_cidr); + port_ip_cidr = NULL; + goto RETURN_ERROR; + } + + port_ip_cidr->mask_len = (unsigned int) iRet; + add_ip_cidr(port, port_ip_cidr); + } + } + } + + json_object_object_get_ex(port_obj, "multicast_id", &mcIDObj); + if (mcIDObj) + { + int j; + int arrLen = json_object_array_length(mcIDObj); + if (0 == arrLen) + { + NSOPR_LOGERR("arrLen is 0"); + goto RETURN_ERROR; + } + + for (j = 0; j < arrLen; ++j) + { + struct json_object *elemObj = + json_object_array_get_idx(mcIDObj, j); + + if (elemObj) + { + struct json_object *tObj = NULL; + const char *tStr; + int ret; + struct in_addr addr; + + struct container_multicast_id *mcID = + malloc(sizeof(struct container_multicast_id)); + if (NULL == mcID) + { + NSOPR_LOGERR("Can't alloc container multicast id"); + goto RETURN_ERROR; + } + + json_object_object_get_ex(elemObj, "group_ip", &tObj); + if (NULL == tObj) + { + NSOPR_LOGERR("No group_IP"); + free(mcID); + mcID = NULL; + goto RETURN_ERROR; + } + + tStr = json_object_get_string(tObj); + if (NULL == tStr) + { + NSOPR_LOGERR("Get Multiple cast group IP Failed"); + free(mcID); + mcID = NULL; + goto RETURN_ERROR; + } + + ret = spl_inet_aton(tStr, &addr); + if (0 == ret) + { + NSOPR_LOGERR("Parse group IP Failed"); + free(mcID); + mcID = NULL; + goto RETURN_ERROR; + } + + mcID->ip = addr.s_addr; + add_multilcast_ip(port, mcID); + } + } + } + + const char *port_json = json_object_get_string(port_obj); + if ((NULL == port_json) || (0 == strlen(port_json))) + { + NSOPR_LOGERR("json_object_get_string failed"); + goto RETURN_ERROR; + } + + port->buffer = malloc_port_buffer(); + if (!port->buffer) + { + goto RETURN_ERROR; + } + + retval = + strcpy_s(get_port_json(port), IP_MODULE_PORT_JSON_LEN, port_json); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + + return port; + RETURN_ERROR: + free_container_port(port, IP_MODULE_TRUE); + return NULL; +} + +struct container_ip *parse_container_ip_json(char *param) +{ + int retval; + struct json_object *obj = json_tokener_parse(param); + struct json_object *container_id_obj = NULL; + struct json_object *ports_list_obj = NULL; + + if (!obj) + { + return NULL; + } + + struct container_ip *container = malloc(sizeof(struct container_ip)); + if (container == NULL) + { + json_object_put(obj); + return NULL; + } + + retval = + memset_s(container, sizeof(struct container_ip), 0, + sizeof(struct container_ip)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + + json_object_object_get_ex(obj, "containerID", &container_id_obj); + if (container_id_obj) + { + const char *container_id = json_object_get_string(container_id_obj); + if ((container_id == NULL) || (container_id[0] == 0) + || (strlen(container_id) >= IP_MODULE_MAX_NAME_LEN)) + { + goto RETURN_ERROR; + } + + retval = + memset_s(container->container_id, sizeof(container->container_id), + 0, sizeof(container->container_id)); + if (EOK != retval) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + + retval = + strcpy_s(container->container_id, sizeof(container->container_id), + container_id); + + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + } + else + { + /* this mandatory parameter */ + NSOPR_LOGWAR("json_object_object_get_ex containerID failed"); + } + + json_object_object_get_ex(obj, "ports_list", &ports_list_obj); + if (ports_list_obj) + { + int i; + int port_num = json_object_array_length(ports_list_obj); + + if (port_num == 0) + { + /* this mandatory parameter */ + goto RETURN_ERROR; + } + + for (i = 0; i < port_num; i++) + { + struct json_object *port_obj = + json_object_array_get_idx(ports_list_obj, i); + struct container_port *port = parse_port_obj(port_obj); + if (!port) + { + goto RETURN_ERROR; + } + + add_port(container, port); + } + } + else + { + /* mandatory parameter */ + goto RETURN_ERROR; + } + + /* Check if this function is required, or needs more check inside this function, + as some of them are alraedy validated + */ + if (!is_container_ok(container)) + { + goto RETURN_ERROR; + } + + json_object_put(obj); + return container; + + RETURN_ERROR: + json_object_put(obj); + free_container(container, IP_MODULE_TRUE); + return NULL; +} + +bool_t is_ip_match_netif(unsigned int ip, char *netif_name) +{ + if (!netif_name) + { + return 0; + } + + if (trp_rb_search((void *) (u64_t) ip, &g_container_ip_root, ip_compare)) + { + struct network_configuration *network = + get_network_by_ip_with_tree(ip); + if (network && network->phy_net && network->phy_net->header) + { + if (0 == + strncmp(netif_name, network->phy_net->header->nic_name, + HAL_MAX_NIC_NAME_LEN)) + { + return 1; + } + } + } + + return 0; +} + +inline bool_t is_ip_exist(unsigned int ip) +{ + if (trp_rb_search((void *) (u64_t) ip, &g_container_ip_root, ip_compare)) + { + return 1; + } + + return 0; +} + +int validate_addcontainerconfig(struct container_ip *container) +{ + struct container_port *port; + struct container_ip *old = + get_container_by_container_id(container->container_id); + struct container_port *tmp = container->ports_list; + + if (old) + { + struct container_port *last = NULL; + + while (tmp) + { + if (get_port(container->container_id, tmp->port_name)) + { + NSOPR_LOGERR("port=%s already exists!", tmp->port_name); + return NSCRTL_RD_EXIST; + } + + last = tmp; + tmp = tmp->next; + } + + (void) last; + } + + /* check if port_name duplicates in one json configuration */ + tmp = container->ports_list; + while (tmp) + { + if (get_port_from_container(tmp)) + { + NSOPR_LOGERR("port=%s duplicates!", tmp->port_name); + return NSCRTL_RD_EXIST; + } + + tmp = tmp->next; + } + + bool_t is_nstack_dpdk_port; + struct container_port **ref = &container->ports_list; + while ((port = *ref)) + { + is_nstack_dpdk_port = 1; + struct container_port_ip_cidr *ip_cidr = port->ip_cidr_list; + while (ip_cidr) + { + struct network_configuration *network = + get_network_by_ip_with_tree(ip_cidr->ip); + if (network && (0 == strcmp(network->type_name, "nstack-dpdk"))) + { + struct netif *pnetif; + if (get_netif_by_ip(ip_cidr->ip)) + { + NSOPR_LOGERR("ip exists]IP=0x%08x", ip_cidr->ip); + return NSCRTL_RD_EXIST; + } + + if (network->phy_net->bond_name[0] != 0) + { + pnetif = + find_netif_by_if_name(network->phy_net->bond_name); + } + else + { + pnetif = + find_netif_by_if_name(network->phy_net-> + header->nic_name); + } + + if (!pnetif) + { + NSOPR_LOGERR("can't find netif, network json:%s", + get_network_json(network)); + return NSCRTL_ERR; + } + + if (0 == port->port_name[0]) + { + NSOPR_LOGINF + ("ip=0x%08x is in nstack dpdk network, but port_name is null, json:%s", + ip_cidr->ip, get_port_json(port)); + is_nstack_dpdk_port = 0; + break; + } + } + else + { + NSOPR_LOGINF("port %s is not in nstack dpdk network, json:%s", + port->port_name, get_port_json(port)); + is_nstack_dpdk_port = 0; + break; + } + + ip_cidr = ip_cidr->next; + } + + /* only use nstack dpdk port */ + if (is_nstack_dpdk_port) + { + ref = &port->next; + } + else + { + *ref = port->next; + port->next = NULL; + free_container_port(port, IP_MODULE_TRUE); + } + } + + return (!container->ports_list) ? NSCRTL_FREE_ALL_PORT : NSCRTL_OK; +} + +/* get the num of IPs in a container , which in a certain subnet */ +extern struct network_list g_network_list; +extern inline int is_in_subnet(unsigned int ip, struct ip_subnet *subnet); +NSTACK_STATIC inline int get_network_ip_count + (struct container_ip *container, struct ip_subnet *subnet) +{ + int ip_count = 0; + struct container_port *port_list = NULL; + struct container_ip *ci = container; + + while (ci) + { + port_list = ci->ports_list; + while (port_list) + { + struct container_port_ip_cidr *ip_list = port_list->ip_cidr_list; + while (ip_list) + { + if (!is_in_subnet(ip_list->ip, subnet)) + { + ip_count++; + } + + ip_list = ip_list->next; + } + + port_list = port_list->next; + } + + ci = ci->next; + } + + return ip_count; +} + +int check_ip_count(struct container_ip *container) +{ + int cur_count = 0; + int new_count = 0; + + if (NULL == container) + { + return 1; + } + + struct network_configuration *network = g_network_list.header; + while (network) + { + cur_count = + get_network_ip_count(g_container_list.header, network->ip_subnet); + new_count = get_network_ip_count(container, network->ip_subnet); + + if ((cur_count > MAX_NETWORK_IP_COUNT) + || (new_count > MAX_NETWORK_IP_COUNT) + || (cur_count + new_count > MAX_NETWORK_IP_COUNT)) + { + NSOPR_LOGERR + ("reach ip addr max count]network=%s, max=%d, current=%d, new=%d.", + network->network_name, MAX_NETWORK_IP_COUNT, cur_count, + new_count); + return 0; + } + + network = network->next; + } + + return 1; +} + +int +match_groupaddr(struct container_multicast_id *multi_list, + spl_ip_addr_t * groupaddr) +{ + struct container_multicast_id *group_info = multi_list; + + while (group_info) + { + if (group_info->ip == groupaddr->addr) + { + return 1; + } + + group_info = group_info->next; + } + + return 0; +} + +int add_container(struct container_ip *container) +{ + int retVal = 0; + + /* need to check if any of the netif operation failed, then we should return fail */ + retVal = validate_addcontainerconfig(container); + if (retVal != NSCRTL_OK) + { + free_container(container, IP_MODULE_TRUE); + return (NSCRTL_FREE_ALL_PORT == retVal) ? NSCRTL_OK : retVal; + } + + /* control max network and ipaddress count */ + if (!check_ip_count(container)) + { + free_container(container, IP_MODULE_TRUE); + return NSCRTL_IP_COUNT_EXCEED; + } + + struct container_port *last = NULL; + struct container_ip *old = + get_container_by_container_id(container->container_id); + if (old) + { + struct container_port *tmp = container->ports_list; + while (tmp) + { + /* here we don't need to check "if tmp->port_name == NULL", as validate_addcontainerconfig() has done this. */ + if (get_port(container->container_id, tmp->port_name)) + { + free_container(container, IP_MODULE_TRUE); + NSOPR_LOGERR("port exist!"); + return NSCRTL_RD_EXIST; + } + + last = tmp; + tmp = tmp->next; + } + } + else + { + container->next = g_container_list.header; + g_container_list.header = container; + } + + output_api *api = get_output_api(); + struct container_port *port = container->ports_list; + while (port) + { + struct container_port_ip_cidr *ip_cidr = port->ip_cidr_list; + while (ip_cidr) + { + if (api->add_netif_ip) + { + struct network_configuration *network = + get_network_by_ip_with_tree(ip_cidr->ip); + if (network) + { + unsigned int mask = ~0; + mask = + (mask << + (IP_MODULE_SUBNET_MASK_LEN - ip_cidr->mask_len)); + mask = spl_htonl(mask); + if (network->phy_net->bond_name[0] != 0) + { + (void) api->add_netif_ip(network->phy_net->bond_name, ip_cidr->ip, mask); //no need to check return value, validate_addcontainerconfig() has been checked parameters. + } + else + { + (void) api->add_netif_ip(network->phy_net-> + header->nic_name, + ip_cidr->ip, mask); + } + } + else + { + NSOPR_LOGERR("can't find network by]IP=%u,port_name=%s", + ip_cidr->ip, port->port_name); + } + } + + retVal = + trp_rb_insert((void *) (u64_t) ip_cidr->ip, (void *) port, + &g_container_ip_root, ip_compare); + + if (0 != retVal) + { + NSOPR_LOGERR("trp_rb_insert failed]ip_cidr->ip=%u", + ip_cidr->ip); + } + + ip_cidr = ip_cidr->next; + } + port = port->next; + } + + if (old) + { + if (last) + { + last->next = old->ports_list; + old->ports_list = container->ports_list; + } + + container->ports_list = NULL; + free_container(container, IP_MODULE_FALSE); + } + + return NSCRTL_OK; +} + +struct container_ip *get_container_by_container_id(char *container_id) +{ + if (NULL == container_id) + { + NSOPR_LOGERR("Param input container ID is NULL"); + return NULL; + } + + struct container_ip *container = g_container_list.header; + while (container) + { + if (0 == strcmp(container->container_id, container_id)) + { + return container; + } + + container = container->next; + } + + return NULL; +} + +/***************************************************************************** +* Prototype : getIpCfgAll +* Description : Get All ip configurations +* Input : char * +* size_t +* Output : char * patern:[***,***,***] +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int getIpCfgAll(char *jsonBuf, size_t size) +{ + int retval; + + if (NULL == jsonBuf) + { + return NSCRTL_ERR; + } + + if (size < 2) + { + NSOPR_LOGERR("get all ip cfg error, buffer is not enough."); + return NSCRTL_STATUS_ERR; + } + + char bfirstData = 1; + *jsonBuf = '['; + jsonBuf = jsonBuf + 1; + + /*need another two char to keep [and ] */ + size_t len = size - 2; + size_t strsize = 0; + struct container_port *port = NULL; + struct container_ip *container = g_container_list.header; + while (container) + { + port = container->ports_list; + while (port) + { + if (NULL == port->buffer) + { + port = port->next; + continue; + } + + strsize = strlen(get_port_json(port)) + 1; + + /*always reserve 1 char */ + if ((strsize > 0) && (strsize < len)) + { + if (bfirstData) + { + bfirstData = 0; + } + else + { + *jsonBuf = ','; + jsonBuf = jsonBuf + 1; + len = len - 1; + } + + retval = strcpy_s(jsonBuf, len, get_port_json(port)); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retval); + return NSCRTL_ERR; + } + + len = len - strlen(get_port_json(port)); + jsonBuf = jsonBuf + strlen(get_port_json(port)); + } + else + { + NSOPR_LOGERR("get all ip cfg error, buffer is not enough."); + return NSCRTL_STATUS_ERR; + } + + port = port->next; + } + + container = container->next; + } + + *jsonBuf = ']'; + return 0; +} + +int del_port(char *container_id, char *port_name) +{ + struct container_port *port = NULL; + struct container_port **ref = NULL; + struct container_ip *container = NULL; + struct container_ip **container_ref = &g_container_list.header; + + while ((container = *container_ref)) + { + NSOPR_LOGDBG("container->container_id=%s,container_id=%p", + container->container_id, container_id); + if (strcmp(container->container_id, container_id) == 0) + { + ref = &container->ports_list; + while ((port = *ref)) + { + if (strcmp(port_name, port->port_name) == 0) + { + *ref = port->next; + port->next = NULL; + free_container_port(port, IP_MODULE_FALSE); + return 0; + } + + ref = &port->next; + } + + break; + } + + container_ref = &container->next; + } + + return NSCRTL_RD_NOT_EXIST; +} + +struct container_port *get_port(char *container_id, char *port_name) +{ + struct container_port *port = NULL; + struct container_ip *container = g_container_list.header; + + while (container) + { + if (strcmp(container->container_id, container_id) == 0) + { + port = container->ports_list; + while (port) + { + if (strcmp(port_name, port->port_name) == 0) + { + return port; + } + + port = port->next; + } + } + + container = container->next; + } + + return NULL; +} + +struct container_port *get_port_from_container(struct container_port *port) +{ + char *port_name = port->port_name; + struct container_port *tmp = port->next; + + while (tmp) + { + if (strcmp(port_name, tmp->port_name) == 0) + { + return tmp; + } + + tmp = tmp->next; + } + + return NULL; +} diff --git a/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c b/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c new file mode 100644 index 0000000..d7ba054 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c @@ -0,0 +1,356 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "inet.h" +#include "spl_ip_addr.h" +#include "ip_module_api.h" +#include "container_ip.h" +#include "network.h" +#include "config_common.h" +#include "configuration_reader.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +#include "stackx_common.h" +#include "spl_tcpip.h" + +static output_api g_output_api = { 0 }; + +void regist_output_api(output_api * api) +{ + if (NULL == api) + { + NSOPR_LOGERR("error!!!param api==NULL]"); + return; + } + + g_output_api = *api; +} + +output_api *get_output_api() +{ + return &g_output_api; +} + +int +process_post(void *arg, ip_module_type Type, + ip_module_operate_type operate_type) +{ + /* only when add network, in other words: + only when (IP_MODULE_NETWORK == Type) && (IP_MODULE_OPERATE_ADD == operate_type), + process_configuration() is called in read_fn thread itself. + other cases, will post_to tcpip_thread to handle them. + + tips: when add network, it need to post msg(add netif) to tcpip thread and wait a sem, + but after the msg is handled by tcpip thread, the sem could be post. + so adding netword is handled in read_fn thread, can't be moved to tcpip thread. + + But we should know, many global and static variables maybe not safe(netif,sc_dpdk etc.), + because they can be visited by multi-thread. */ + if ((IP_MODULE_NETWORK == Type) + && (IP_MODULE_OPERATE_ADD == operate_type)) + { + return process_configuration(arg, Type, operate_type); + } + + if (g_output_api.post_to) + { + int retval = g_output_api.post_to(arg, Type, operate_type); + if ((post_ip_module_msg == g_output_api.post_to) && (retval != ERR_OK) + && (arg != NULL)) + { + if ((IP_MODULE_IP == Type) + && (IP_MODULE_OPERATE_ADD == operate_type)) + { + free_container((struct container_ip *) arg, IP_MODULE_TRUE); + } + else + { + free(arg); + } + + arg = NULL; + NSOPR_LOGERR("post failed]ret=%d", retval); + NSOPR_SET_ERRINFO(NSCRTL_INPUT_ERR, "process_post failed!"); + } + + return retval; + } + else + { + NSOPR_LOGERR("g_output_api.post_to==NULL"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "ERR:internal error, g_output_api.post_to==NULL]"); + return -1; + } +} + +/* arg can be NULL, no need check */ +int +process_configuration(void *arg, ip_module_type Type, + ip_module_operate_type operate_type) +{ + NSOPR_LOGINF("precoess begin]arg=%p,action=%d,type=%d", arg, operate_type, + Type); + int retval = 0; + + switch (Type) + { + case IP_MODULE_NETWORK: + switch (operate_type) + { + case IP_MODULE_OPERATE_ADD: + retval = + add_network_configuration((struct + network_configuration *) + arg); + + /* When network exceeds max number, just log warning at operation.log */ + if (retval == NSCRTL_NETWORK_COUNT_EXCEED) + { + NSOPR_LOGWAR + ("Warning!! Network count exceed max allowed number]max=%d", + MAX_NETWORK_COUNT); + } + else + { + NSOPR_SET_ERRINFO(retval, + "add_network_configuration return %d", + retval); + } + + if (!retval) + { + /*init DPDK eth */ + if ((retval = + init_new_network_configuration()) != ERR_OK) + { + free_network_configuration((struct + network_configuration + *) arg, + IP_MODULE_TRUE); + NSOPR_SET_ERRINFO(retval, + "init_new_network_configuration return %d", + retval); + } + } + break; + case IP_MODULE_OPERATE_DEL: + { + retval = del_network_by_name((char *) arg); + NSOPR_SET_ERRINFO(retval, + "del_network_by_name return %d", + retval); + free(arg); + arg = NULL; + } + break; + case IP_MODULE_OPERATE_QUERY: + { + struct network_configuration *network = + get_network_by_name((char *) arg); + if (!network) + { + retval = NSCRTL_RD_NOT_EXIST; + NSOPR_SET_ERRINFO(retval, + "get_network_by_name return %d", + retval); + } + else + { + if (strlen(get_network_json(network)) > + sizeof(get_config_data()->json_buff) - 1) + { + NSOPR_LOGERR + ("length of network->network_json too big]len=%u", + strlen(get_network_json(network))); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "ERR:internal error, buf is not enough]"); + retval = NSCRTL_ERR; + } + + retval = + strcpy_s(get_config_data()->json_buff, + sizeof(get_config_data()->json_buff), + get_network_json(network)); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", + retval); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "ERR:internal error, STRCPY_S failed]ret=%d", + retval); + retval = NSCRTL_ERR; + } + + } + + free(arg); + arg = NULL; + } + break; + default: + break; + } + + break; + case IP_MODULE_IP: + switch (operate_type) + { + case IP_MODULE_OPERATE_ADD: + retval = add_container((struct container_ip *) arg); + NSOPR_SET_ERRINFO(retval, "add_container return %d", + retval); + break; + case IP_MODULE_OPERATE_DEL: + { + struct ip_action_param *p = + (struct ip_action_param *) arg; + retval = del_port(p->container_id, p->port_name); + NSOPR_SET_ERRINFO(retval, "del_port return %d", + retval); + free(arg); + arg = NULL; + } + break; + case IP_MODULE_OPERATE_QUERY: + { + struct ip_action_param *p = + (struct ip_action_param *) arg; + struct container_port *port = + get_port(p->container_id, p->port_name); + if (!port) + { + retval = NSCRTL_RD_NOT_EXIST; + NSOPR_SET_ERRINFO(retval, "get_port return %d", + retval); + } + else + { + if (strlen(get_port_json(port)) > + sizeof(get_config_data()->json_buff) - 1) + { + NSOPR_LOGERR + ("length of network->network_json too big]len=%u", + strlen(get_port_json(port))); + retval = NSCRTL_ERR; + } + + retval = + strcpy_s(get_config_data()->json_buff, + sizeof(get_config_data()->json_buff), + get_port_json(port)); + if (EOK != retval) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", + retval); + retval = NSCRTL_ERR; + } + + } + + free(arg); + arg = NULL; + } + break; + default: + break; + } + + break; + case IP_MODULE_NETWORK_ALL: + if (operate_type == IP_MODULE_OPERATE_QUERY) + { + retval = + get_network_all(get_config_data()->json_buff, + sizeof(get_config_data()->json_buff)); + NSOPR_SET_ERRINFO(retval, "get_network_all return %d", + retval); + } + + break; + + case IP_MODULE_IP_ALL: + if (operate_type == IP_MODULE_OPERATE_QUERY) + { + retval = + getIpCfgAll(get_config_data()->json_buff, + sizeof(get_config_data()->json_buff)); + NSOPR_SET_ERRINFO(retval, "getIpCfgAll return %d", retval); + } + + break; + + case IP_MODULE_ALL: + if (operate_type == IP_MODULE_OPERATE_QUERY) + { + NSOPR_LOGERR + ("---------- IP_MODULE_ALL query is not implemented --------------"); + NSOPR_SET_ERRINFO(NSCRTL_ERR, + "ERR:This query interface is not implemented. ErrCode:%d", + NSCRTL_ERR); + } + + break; + + default: + break; + } + + NSOPR_LOGINF("process finished]result=%d", retval); + + return retval; +} + +void ip_subnet_print(struct ip_subnet *subnet) +{ + spl_ip_addr_t ipAddr; + + if (subnet == NULL) + { + return; + } + + ipAddr.addr = spl_htonl(subnet->subnet); + NSPOL_LOGINF(IP_DEBUG, "]\t Subnet=%s/%u", spl_inet_ntoa(ipAddr), + subnet->mask_len); +} + +port_buffer *malloc_port_buffer() +{ + port_buffer *buffer = malloc(sizeof(port_buffer)); + return buffer; +} + +void free_port_buffer(port_buffer * buffer) +{ + free(buffer); +} + +network_buffer *malloc_network_buffer() +{ + network_buffer *buffer = malloc(sizeof(network_buffer)); + return buffer; +} + +void free_network_buffer(network_buffer * buffer) +{ + free(buffer); +} diff --git a/stacks/lwip_stack/lwip_src/ip_module/network.c b/stacks/lwip_stack/lwip_src/ip_module/network.c new file mode 100644 index 0000000..d34c6a9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/ip_module/network.c @@ -0,0 +1,1093 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include "json.h" +#include "trp_rb_tree.h" +#include "network.h" +#include "nstack_log.h" +#include "config_common.h" +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +#include "sharedmemory.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "inet.h" + +struct network_list g_network_list = { 0 }; + +extern struct stackx_port_zone *p_stackx_port_zone; +extern u32 spl_hal_is_nic_exist(const char *name); + +static bool_t is_phy_net_ok(struct phy_net *pst_phy_net) +{ + if (!pst_phy_net || !pst_phy_net->header) + { + NSOPR_LOGERR("phy_net is not ok"); + return 0; + } + + return 1; +} + +static bool_t +is_network_configuration_ok(struct network_configuration *network) +{ + while (network) + { + if (!is_phy_net_ok(network->phy_net)) + { + return 0; + } + + network = network->next; + } + + return 1; +} + +static void +add_ref_nic(struct phy_net *pst_phy_net, struct ref_nic *pst_ref_nic) +{ + pst_ref_nic->next = pst_phy_net->header; + pst_phy_net->header = pst_ref_nic; +} + +static void free_ref_nic(struct ref_nic *pst_ref_nic) +{ + struct ref_nic *nic = pst_ref_nic; + struct ref_nic *tmp = NULL; + + while (nic) + { + tmp = nic; + nic = tmp->next; + free(tmp); + } +} + +static void free_phy_net(struct phy_net *pst_phy_net) +{ + if (pst_phy_net) + { + free_ref_nic(pst_phy_net->header); + free(pst_phy_net); + } +} + +static void free_ip_subnet(struct ip_subnet *subnet, bool_t only_free) +{ + struct ip_subnet *tmp = NULL; + + while (subnet) + { + tmp = subnet; + subnet = subnet->next; + free(tmp); + } +} + +void +free_network_configuration(struct network_configuration *network, + bool_t only_free) +{ + if (network) + { + free_ip_subnet(network->ip_subnet, only_free); + free_phy_net(network->phy_net); + + if (network->buffer) + { + free_network_buffer(network->buffer); + network->buffer = NULL; + } + + free(network); + } +} + +inline int is_in_subnet(unsigned int ip, struct ip_subnet *subnet) +{ + unsigned int mask = ~0; + unsigned int seg_ip, seg; + + mask = mask << (IP_MODULE_SUBNET_MASK_LEN - subnet->mask_len); + + seg_ip = ip & mask; + seg = subnet->subnet & mask; + + return seg_ip != seg ? 1 : 0; +} + +inline struct network_configuration *get_network_by_ip_with_tree(unsigned int + ip) +{ + unsigned int h_ip = spl_ntohl(ip); + struct network_configuration *p = g_network_list.header; + + while (p) + { + if (!is_in_subnet(h_ip, p->ip_subnet)) + { + return p; + } + + p = p->next; + } + + return NULL; +} + +struct network_configuration *get_network_by_name(char *name) +{ + struct network_configuration *network = g_network_list.header; + + while (network) + { + if (strcasecmp(name, network->network_name) == 0) + { + return network; + } + + network = network->next; + } + + return NULL; +} + +struct network_configuration *get_network_by_nic_name(char *name) +{ + if (NULL == name) + { + return NULL; + } + + struct ref_nic *refnic = NULL; + struct phy_net *phynet = NULL; + struct network_configuration *network = g_network_list.header; + while (network) + { + phynet = network->phy_net; + if (phynet) + { + if ((phynet->bond_mode != -1) + && strcmp(name, phynet->bond_name) == 0) + { + return network; + } + + refnic = phynet->header; + while (refnic) + { + if (strcmp(name, refnic->nic_name) == 0) + { + return network; + } + + refnic = refnic->next; + } + } + + network = network->next; + } + + return NULL; +} + +struct network_configuration *get_network_by_name_from_json(struct + network_configuration + *network) +{ + char *name = network->network_name; + struct network_configuration *tmp = network->next; + + while (tmp) + { + if (strcasecmp(name, tmp->network_name) == 0) + { + return tmp; + } + + tmp = tmp->next; + } + + return NULL; +} + +NSTACK_STATIC inline int get_network_count() +{ + int count = 0; + struct network_configuration *network = g_network_list.header; + + while (network) + { + count++; + network = network->next; + } + + return count; +} + +int get_network_all(char *jsonBuf, size_t size) +{ + if (NULL == jsonBuf) + { + return NSCRTL_ERR; + } + + if (size < 2) + { + NSOPR_LOGERR("get all ip cfg error, buffer is not enough."); + return NSCRTL_STATUS_ERR; + } + + int retVal; + char bfirstData = 1; + *jsonBuf = '['; + jsonBuf = jsonBuf + 1; + + size_t len = size - 2; // strlen("[]") + size_t strsize = 0; + struct network_configuration *network = g_network_list.header; + while (network) + { + if (NULL == network->buffer) + { + network = network->next; + continue; + } + + if (bfirstData) + { + bfirstData = 0; + } + else + { + *jsonBuf = ','; + jsonBuf = jsonBuf + 1; + len = len - 1; + } + + strsize = strlen(get_network_json(network)) + 1; + if ((strsize > 0) && (strsize < len)) + { + retVal = strcpy_s(jsonBuf, len, get_network_json(network)); + if (EOK != retVal) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal); + return NSCRTL_STATUS_ERR; + } + + len = len - strlen(get_network_json(network)); + jsonBuf = jsonBuf + strlen(get_network_json(network)); + } + else + { + NSOPR_LOGERR("get all network cfg error, buffer is not enough."); + return NSCRTL_STATUS_ERR; + } + + network = network->next; + } + + *jsonBuf = ']'; + return 0; +} + +int nic_already_bind(const char *nic_name) +{ + struct ref_nic *pnic = NULL; + struct network_configuration *pnetwork = g_network_list.header; + + while (pnetwork) + { + pnic = pnetwork->phy_net->header; + while (pnic) + { + if (0 == strcmp(pnic->nic_name, nic_name)) + { + return 1; + } + + pnic = pnic->next; + } + + pnetwork = pnetwork->next; + } + + return 0; +} + +int nic_already_init(const char *nic_name) +{ + unsigned int i; + + for (i = 0; i < p_stackx_port_zone->port_num; i++) + { + if (0 == + strcmp(p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name, + nic_name)) + { + return 1; + } + } + + return 0; +} + +extern struct stackx_port_info *head_used_port_list; +int +bonded_nic_already_bind(struct network_configuration *pnetwork, + const char *nic_name) +{ + struct stackx_port_info *p_port_list = head_used_port_list; + + while (p_port_list) + { + if (0 == strcmp(p_port_list->linux_ip.if_name, nic_name)) + { + return 1; + } + + p_port_list = p_port_list->next_use_port; + } + + struct ref_nic *pnic = NULL; + + while (pnetwork) + { + if (pnetwork->phy_net->bond_mode == -1) + { + pnic = pnetwork->phy_net->header; + if (0 == strcmp(pnic->nic_name, nic_name)) + { + return 1; + } + } + + pnetwork = pnetwork->next; + } + + return 0; +} + +extern struct bond_ports_info bond_ports_array; +int +nic_already_bond(struct network_configuration *pnetwork, const char *nic_name) +{ + u8_t i, j; + struct bond_set *s; + + for (i = 0; i < bond_ports_array.cnt; i++) + { + s = &bond_ports_array.ports[i]; + for (j = 0; j < s->slave_port_cnt; j++) + { + if (strcmp(s->slave_ports[j], nic_name) == 0) + { + return 1; + } + } + } + + struct ref_nic *pnic = NULL; + + while (pnetwork) + { + if (pnetwork->phy_net->bond_mode != -1) + { + pnic = pnetwork->phy_net->header; + while (pnic) + { + if (0 == strcmp(pnic->nic_name, nic_name)) + { + return 1; + } + + pnic = pnic->next; + } + } + + pnetwork = pnetwork->next; + } + + return 0; +} + +/* add network to list in descending sort */ +void add_network_to_list(struct network_configuration *network) +{ + struct network_configuration *curr = g_network_list.header; + struct network_configuration *prev = NULL; + + network->next = NULL; + + while (curr) + { + if (network->ip_subnet->mask_len >= curr->ip_subnet->mask_len) + { + break; + } + + prev = curr; + curr = curr->next; + } + + if (NULL == prev) + { + network->next = curr; + g_network_list.header = network; + } + else + { + network->next = prev->next; + prev->next = network; + } +} + +int +add_network_configuration(struct network_configuration + *pst_network_configuration) +{ + struct network_configuration *tmp = pst_network_configuration; + struct ref_nic *pheader; + + if (tmp) + { + if (get_network_by_name(tmp->network_name) + || get_network_by_name_from_json(tmp)) + { + NSOPR_LOGERR("network exists or duplicates]network_name=%s", + tmp->network_name); + free_network_configuration(pst_network_configuration, + IP_MODULE_TRUE); + return NSCRTL_RD_EXIST; + } + + if (strcasecmp("nstack-dpdk", tmp->type_name) != 0) + { + NSOPR_LOGWAR("illegal network type]type_name=%s", tmp->type_name); + } + + /* control max network and ipaddress count */ + if (get_network_count() >= MAX_NETWORK_COUNT) + { + NSOPR_LOGERR("network reach]max_count=%d", MAX_NETWORK_COUNT); + free_network_configuration(pst_network_configuration, + IP_MODULE_TRUE); + return NSCRTL_NETWORK_COUNT_EXCEED; + } + + /* If nic is not existed or not initiated, return error */ + pheader = tmp->phy_net->header; + while (pheader) + { + if (!spl_hal_is_nic_exist(pheader->nic_name) + && !nic_already_init(pheader->nic_name) + && strncmp(tmp->nic_type_name, "vhost", strlen("vhost"))) + { + NSOPR_LOGERR("Invalid configuration %s not exist Error! ", + pheader->nic_name); + free_network_configuration(pst_network_configuration, + IP_MODULE_TRUE); + return NSCRTL_RD_NOT_EXIST; + } + + pheader = pheader->next; + } + + /* if a bonded nic has been inited in a non-bond network, return error */ + if (tmp->phy_net->bond_mode != -1) + { + pheader = tmp->phy_net->header; + while (pheader) + { + if (bonded_nic_already_bind + (pst_network_configuration, pheader->nic_name)) + { + NSOPR_LOGERR("Invalid configuration %s already bind! ", + pheader->nic_name); + free_network_configuration(pst_network_configuration, + IP_MODULE_TRUE); + return NSCRTL_INPUT_ERR; + } + + pheader = pheader->next; + } + } + + /* if a non-bond nic has been inited in a bonded network, return error */ + if (tmp->phy_net->bond_mode == -1) + { + pheader = tmp->phy_net->header; + while (pheader) + { + if (nic_already_bond + (pst_network_configuration, pheader->nic_name)) + { + NSOPR_LOGERR("Invalid configuration %s already bind! ", + pheader->nic_name); + free_network_configuration(pst_network_configuration, + IP_MODULE_TRUE); + return NSCRTL_INPUT_ERR; + } + + pheader = pheader->next; + } + } + } + else + { + NSOPR_LOGERR("Invalid network configuration!"); + return NSCRTL_INPUT_ERR; + } + + /*looping through each node has move to read_ipmoduleoperateadd_configuration */ + ip_subnet_print(tmp->ip_subnet); + add_network_to_list(tmp); + + return NSCRTL_OK; +} + +struct network_configuration *parse_network_obj(struct json_object + *network_obj) +{ + int retVal; + struct network_configuration *pst_network_configuration = NULL; + struct json_object *network_name_obj = NULL, *args_obj = NULL, *phy_obj = + NULL, *type_name_obj = NULL; + struct json_object *ref_nic_list_obj = NULL, *bond_mode_obj = + NULL, *bond_name_obj = NULL, *ipam_obj = NULL; + struct json_object *subnet_obj = NULL, *nic_type_obj = NULL; + + if (!network_obj) + { + NSOPR_LOGERR("network_obj is null"); + goto RETURN_ERROR; + } + + pst_network_configuration = malloc(sizeof(struct network_configuration)); + if (NULL == pst_network_configuration) + { + NSOPR_LOGERR("malloc failed"); + goto RETURN_ERROR; + } + + retVal = + memset_s(pst_network_configuration, + sizeof(struct network_configuration), 0, + sizeof(struct network_configuration)); + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal); + goto RETURN_ERROR; + } + + json_object_object_get_ex(network_obj, "name", &network_name_obj); + if (network_name_obj) + { + const char *network_name = json_object_get_string(network_name_obj); + if ((NULL == network_name) || (network_name[0] == 0) + || (strlen(network_name) >= IP_MODULE_MAX_NAME_LEN)) + { + NSOPR_LOGERR("network_name is not ok"); + goto RETURN_ERROR; + } + + retVal = + strcpy_s(pst_network_configuration->network_name, + sizeof(pst_network_configuration->network_name), + network_name); + + if (EOK != retVal) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGERR("name is not ok"); + goto RETURN_ERROR; + } + + json_object_object_get_ex(network_obj, "type", &type_name_obj); + if (type_name_obj) + { + const char *type_name = json_object_get_string(type_name_obj); + if ((NULL == type_name) || (type_name[0] == 0) + || (strlen(type_name) >= IP_MODULE_MAX_NAME_LEN)) + { + NSOPR_LOGERR("type parse error"); + goto RETURN_ERROR; + } + + retVal = + strcpy_s(pst_network_configuration->type_name, + sizeof(pst_network_configuration->type_name), type_name); + + if (EOK != retVal) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d", retVal); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGERR("type is not ok"); + goto RETURN_ERROR; + } + + json_object_object_get_ex(network_obj, "args", &args_obj); + if (args_obj) + { + json_object_object_get_ex(args_obj, "phynet", &phy_obj); + if (phy_obj) + { + struct phy_net *pst_phy_net = malloc(sizeof(struct phy_net)); + if (NULL == pst_phy_net) + { + NSOPR_LOGERR("malloc failed"); + goto RETURN_ERROR; + } + + retVal = + memset_s(pst_phy_net, sizeof(struct phy_net), 0, + sizeof(struct phy_net)); + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d", retVal); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + json_object_object_get_ex(phy_obj, "nic_type", &nic_type_obj); /*lint !e534 no need to check return value */ + if (nic_type_obj) + { + const char *nic_type_name = + json_object_get_string(nic_type_obj); + if (strcmp(nic_type_name, "pci") != 0 + && strcmp(nic_type_name, "vhost") != 0) + { + NSOPR_LOGERR("unsupported nic_type]nic_type=%s", + nic_type_name); + goto RETURN_ERROR; + } + + retVal = + strcpy_s(pst_network_configuration->nic_type_name, + sizeof(pst_network_configuration->nic_type_name), + nic_type_name); + if (EOK != retVal) + { + NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGINF + ("nic_type not specified, use default type]defaul nic_type=pci"); + retVal = + strcpy_s(pst_network_configuration->nic_type_name, + sizeof(pst_network_configuration->nic_type_name), + "pci"); + if (EOK != retVal) + { + NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal); + goto RETURN_ERROR; + } + } + + json_object_object_get_ex(phy_obj, "ref_nic", &ref_nic_list_obj); + if (ref_nic_list_obj) + { + int j; + int ref_nic_num = json_object_array_length(ref_nic_list_obj); + if (0 == ref_nic_num) + { + NSOPR_LOGERR("ref_nic is empty"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + for (j = ref_nic_num - 1; j >= 0; j--) + { + struct json_object *ref_nic_obj = + json_object_array_get_idx(ref_nic_list_obj, j); + if (ref_nic_obj) + { + const char *nic_name = + json_object_get_string(ref_nic_obj); + if ((NULL == nic_name) || (nic_name[0] == 0) + || (strlen(nic_name) >= HAL_MAX_NIC_NAME_LEN)) + { + NSOPR_LOGERR("nic_name is not ok"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + struct ref_nic *pst_ref_nic = + malloc(sizeof(struct ref_nic)); + if (NULL == pst_ref_nic) + { + NSOPR_LOGERR("malloc failed"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + retVal = + memset_s(pst_ref_nic, sizeof(struct ref_nic), 0, + sizeof(struct ref_nic)); + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal); + free(pst_ref_nic); + pst_ref_nic = NULL; + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + retVal = + strcpy_s(pst_ref_nic->nic_name, + sizeof(pst_ref_nic->nic_name), nic_name); + + if (EOK != retVal) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal); + free(pst_ref_nic); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + add_ref_nic(pst_phy_net, pst_ref_nic); + } + } + } + else + { + NSOPR_LOGERR("ref_nic is not ok"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + json_object_object_get_ex(phy_obj, "bond_mode", &bond_mode_obj); + if (bond_mode_obj) + { + pst_phy_net->bond_mode = json_object_get_int(bond_mode_obj); + if (pst_phy_net->bond_mode != -1) + { + json_object_object_get_ex(phy_obj, "bond_name", + &bond_name_obj); + if (bond_name_obj) + { + const char *bond_name = + json_object_get_string(bond_name_obj); + if ((NULL == bond_name) + || (strlen(bond_name) >= IP_MODULE_MAX_NAME_LEN)) + { + NSOPR_LOGERR("bond_name is not ok"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + retVal = + memset_s(pst_phy_net->bond_name, + sizeof(pst_phy_net->bond_name), 0, + sizeof(pst_phy_net->bond_name)); + + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + + retVal = + strncpy_s(pst_phy_net->bond_name, + sizeof(pst_phy_net->bond_name), + bond_name, strlen(bond_name)); + + if (EOK != retVal) + { + NSOPR_LOGERR("STRNCPY_S failed]retVal=%d", + retVal); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGERR("bond_name is not ok"); + free_phy_net(pst_phy_net); + goto RETURN_ERROR; + } + } + } + else + { + pst_phy_net->bond_mode = -1; + } + + pst_network_configuration->phy_net = pst_phy_net; + } + else + { + NSOPR_LOGERR("phy_net is not ok"); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGERR("args is not ok"); + goto RETURN_ERROR; + } + + json_object_object_get_ex(network_obj, "ipam", &ipam_obj); + if (ipam_obj) + { + json_object_object_get_ex(ipam_obj, "subnet", &subnet_obj); + if (subnet_obj) + { + int iRet; + char tmp[IP_MODULE_LENGTH_32] = { 0 }; + const char *subnet = json_object_get_string(subnet_obj); + struct in_addr addr; + + retVal = memset_s(&addr, sizeof(addr), 0, sizeof(addr)); + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal); + goto RETURN_ERROR; + } + + if ((NULL == subnet) || (subnet[0] == 0) + || (strlen(subnet) > IP_MODULE_LENGTH_32)) + { + NSOPR_LOGERR("subnet is not ok"); + goto RETURN_ERROR; + } + + const char *sub = strstr(subnet, "/"); + if ((NULL == sub) + || (sizeof(tmp) - 1 <= (unsigned int) (sub - subnet)) + || (strlen(sub) >= sizeof(tmp) - 1)) + { + NSOPR_LOGERR("subnet is not ok"); + goto RETURN_ERROR; + } + + iRet = + strncpy_s(tmp, sizeof(tmp), subnet, (size_t) (sub - subnet)); + if (EOK != iRet) + { + NSOPR_LOGERR("STRNCPY_S failed]ret=%d", iRet); + goto RETURN_ERROR; + } + + iRet = spl_inet_aton(tmp, &addr); + if (0 == iRet) + { + NSOPR_LOGERR("subnet is not ok"); + goto RETURN_ERROR; + } + + pst_network_configuration->ip_subnet = + (struct ip_subnet *) malloc(sizeof(struct ip_subnet)); + if (!pst_network_configuration->ip_subnet) + { + NSOPR_LOGERR("malloc failed"); + goto RETURN_ERROR; + } + + retVal = + memset_s(pst_network_configuration->ip_subnet, + sizeof(struct ip_subnet), 0, + sizeof(struct ip_subnet)); + if (EOK != retVal) + { + NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal); + goto RETURN_ERROR; + } + + pst_network_configuration->ip_subnet->next = NULL; + pst_network_configuration->ip_subnet->subnet = + spl_ntohl(addr.s_addr); + + iRet = atoi(sub + 1); + if ((iRet < 0) || (iRet > IP_MODULE_LENGTH_32)) + { + NSOPR_LOGERR("mask is not ok"); + goto RETURN_ERROR; + } + + pst_network_configuration->ip_subnet->mask_len = + (unsigned int) iRet; + } + else + { + NSOPR_LOGERR("subnet is not ok"); + goto RETURN_ERROR; + } + } + else + { + NSOPR_LOGERR("ipam is not ok"); + goto RETURN_ERROR; + } + + const char *network_json = json_object_get_string(network_obj); + if ((NULL == network_json) || (network_json[0] == 0)) + { + NSOPR_LOGERR("json_object_get_string failed"); + goto RETURN_ERROR; + } + + pst_network_configuration->buffer = malloc_network_buffer(); + if (!pst_network_configuration->buffer) + { + NSOPR_LOGERR("malloc_network_buffer failed"); + goto RETURN_ERROR; + } + + retVal = + strcpy_s(get_network_json(pst_network_configuration), + IP_MODULE_NETWORK_JSON_LEN, network_json); + if (EOK != retVal) + { + NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal); + goto RETURN_ERROR; + } + + return pst_network_configuration; + + RETURN_ERROR: + if (pst_network_configuration) + { + free_network_configuration(pst_network_configuration, IP_MODULE_TRUE); + pst_network_configuration = NULL; + } + + return NULL; +} + +struct network_configuration *parse_network_json(char *param, + struct network_configuration + *pnetwork_list) +{ + struct json_object *obj = json_tokener_parse(param); + struct network_configuration *pst_network_configuration = NULL; + + if (!obj) + { + NSOPR_LOGERR("parse error"); + return NULL; + } + + int network_num = json_object_array_length(obj); + if (0 == network_num) + { + json_object_put(obj); + return NULL; + } + + int i; + for (i = 0; i < network_num; i++) + { + struct json_object *network_obj = json_object_array_get_idx(obj, i); + if (network_obj) + { + pst_network_configuration = parse_network_obj(network_obj); + if (!pst_network_configuration) + { + NSOPR_LOGERR("parse_network_obj error"); + goto RETURN_ERROR; + } + + pst_network_configuration->next = pnetwork_list; + pnetwork_list = pst_network_configuration; + pst_network_configuration = NULL; + } + else + { + NSOPR_LOGERR("network_obj is NULL"); + goto RETURN_ERROR; + } + } + + if (pnetwork_list) + { + if (!is_network_configuration_ok(pnetwork_list)) + { + NSOPR_LOGERR("network_configuration is not ok"); + goto RETURN_ERROR; + } + } + + json_object_put(obj); + return pnetwork_list; + + RETURN_ERROR: + free_network_configuration(pnetwork_list, IP_MODULE_TRUE); + json_object_put(obj); + return NULL; +} + +int del_network_by_name(char *name) +{ + struct network_configuration *network = NULL; + struct network_configuration **ref = &g_network_list.header; + + while ((network = *ref)) + { + if (strcasecmp(name, network->network_name) == 0) + { + *ref = network->next; + network->next = NULL; + + free_network_configuration(network, IP_MODULE_FALSE); + return 0; + } + + ref = &network->next; + } + + return NSCRTL_RD_NOT_EXIST; +} + +int is_in_same_network(unsigned int src_ip, unsigned int dst_ip) +{ + if (src_ip == dst_ip) + { + return 1; + } + + struct network_configuration *src = get_network_by_ip_with_tree(src_ip); + struct network_configuration *dst = get_network_by_ip_with_tree(dst_ip); + if (src && (src == dst)) + { + return 1; + } + + return 0; +} + +struct network_configuration *get_network_list() +{ + return g_network_list.header; +} diff --git a/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c b/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c new file mode 100644 index 0000000..4f129d4 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c @@ -0,0 +1,563 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include "trp_rb_tree.h" + +NSTACK_STATIC void +__rb_rotate_left(struct trp_rb_node *X, struct trp_rb_root *root) +{ + /************************** + * rotate Node X to left * + **************************/ + + struct trp_rb_node *Y = X->rb_right; + + /* estblish X->Right link */ + X->rb_right = Y->rb_left; + if (Y->rb_left != NULL) + Y->rb_left->rb_parent = X; + + /* estblish Y->Parent link */ + Y->rb_parent = X->rb_parent; + if (X->rb_parent) + { + if (X == X->rb_parent->rb_left) + X->rb_parent->rb_left = Y; + else + X->rb_parent->rb_right = Y; + } + else + { + root->rb_node = Y; + } + + /* link X and Y */ + Y->rb_left = X; + X->rb_parent = Y; + + return; +} + +NSTACK_STATIC void +__rb_rotate_right(struct trp_rb_node *X, struct trp_rb_root *root) +{ + /**************************** + * rotate Node X to right * + ****************************/ + + struct trp_rb_node *Y = X->rb_left; + + /* estblish X->Left link */ + X->rb_left = Y->rb_right; + if (Y->rb_right != NULL) + Y->rb_right->rb_parent = X; + + /* estblish Y->Parent link */ + Y->rb_parent = X->rb_parent; + if (X->rb_parent) + { + if (X == X->rb_parent->rb_right) + X->rb_parent->rb_right = Y; + else + X->rb_parent->rb_left = Y; + } + else + { + root->rb_node = Y; + } + + /* link X and Y */ + Y->rb_right = X; + X->rb_parent = Y; + + return; +} + +/* X, Y are for application */ +NSTACK_STATIC void +__rb_erase_color(struct trp_rb_node *X, struct trp_rb_node *Parent, + struct trp_rb_root *root) +{ + /************************************* + * maintain red-black tree balance * + * after deleting node X * + *************************************/ + + while (X != root->rb_node && (!X || X->color == RB_BLACK)) + { + + if (Parent == NULL) + { + break; + } + + if (X == Parent->rb_left) + { + struct trp_rb_node *W = Parent->rb_right; + if (W->color == RB_RED) + { + W->color = RB_BLACK; + Parent->color = RB_RED; /* Parent != NIL? */ + __rb_rotate_left(Parent, root); + W = Parent->rb_right; + } + + if ((!W->rb_left || W->rb_left->color == RB_BLACK) + && (!W->rb_right || W->rb_right->color == RB_BLACK)) + { + W->color = RB_RED; + X = Parent; + Parent = X->rb_parent; + } + else + { + if (!W->rb_right || W->rb_right->color == RB_BLACK) + { + if (W->rb_left != NULL) + W->rb_left->color = RB_BLACK; + W->color = RB_RED; + __rb_rotate_right(W, root); + W = Parent->rb_right; + } + + W->color = Parent->color; + Parent->color = RB_BLACK; + if (W->rb_right->color != RB_BLACK) + { + W->rb_right->color = RB_BLACK; + } + __rb_rotate_left(Parent, root); + X = root->rb_node; + break; + } + } + else + { + + struct trp_rb_node *W = Parent->rb_left; + if (W->color == RB_RED) + { + W->color = RB_BLACK; + Parent->color = RB_RED; /* Parent != NIL? */ + __rb_rotate_right(Parent, root); + W = Parent->rb_left; + } + + if ((!W->rb_left || (W->rb_left->color == RB_BLACK)) + && (!W->rb_right || (W->rb_right->color == RB_BLACK))) + { + W->color = RB_RED; + X = Parent; + Parent = X->rb_parent; + } + else + { + if (!W->rb_left || (W->rb_left->color == RB_BLACK)) + { + if (W->rb_right != NULL) + W->rb_right->color = RB_BLACK; + W->color = RB_RED; + __rb_rotate_left(W, root); + W = Parent->rb_left; + } + + W->color = Parent->color; + Parent->color = RB_BLACK; + if (W->rb_left->color != RB_BLACK) + { + W->rb_left->color = RB_BLACK; + } + __rb_rotate_right(Parent, root); + X = root->rb_node; + break; + } + } + } + + if (X) + { + X->color = RB_BLACK; + } + + return; +} + +static void rb_insert_color(struct trp_rb_node *X, struct trp_rb_root *root) +{ + /************************************* + * maintain red-black tree balance * + * after inserting node X * + *************************************/ + + /* check red-black properties */ + while (X != root->rb_node && X->rb_parent->color == RB_RED) + { + /* we have a violation */ + if (X->rb_parent == X->rb_parent->rb_parent->rb_left) + { + struct trp_rb_node *Y = X->rb_parent->rb_parent->rb_right; + if (Y && Y->color == RB_RED) + { + + /* uncle is red */ + X->rb_parent->color = RB_BLACK; + Y->color = RB_BLACK; + X->rb_parent->rb_parent->color = RB_RED; + X = X->rb_parent->rb_parent; + } + else + { + + /* uncle is black */ + if (X == X->rb_parent->rb_right) + { + /* make X a left child */ + X = X->rb_parent; + __rb_rotate_left(X, root); + } + + /* recolor and rotate */ + X->rb_parent->color = RB_BLACK; + X->rb_parent->rb_parent->color = RB_RED; + __rb_rotate_right(X->rb_parent->rb_parent, root); + } + } + else + { + + /* miror image of above code */ + struct trp_rb_node *Y = X->rb_parent->rb_parent->rb_left; + if (Y && (Y->color == RB_RED)) + { + + /* uncle is red */ + X->rb_parent->color = RB_BLACK; + Y->color = RB_BLACK; + X->rb_parent->rb_parent->color = RB_RED; + X = X->rb_parent->rb_parent; + } + else + { + + /* uncle is black */ + if (X == X->rb_parent->rb_left) + { + X = X->rb_parent; + __rb_rotate_right(X, root); + } + X->rb_parent->color = RB_BLACK; + X->rb_parent->rb_parent->color = RB_RED; + __rb_rotate_left(X->rb_parent->rb_parent, root); + } + } + } + + root->rb_node->color = RB_BLACK; + + return; +} + +static void rb_erase(struct trp_rb_node *node, struct trp_rb_root *root) +{ + struct trp_rb_node *child, *parent; + unsigned int color; + + if (!node->rb_left) + { + child = node->rb_right; + } + else if (!node->rb_right) + { + child = node->rb_left; + } + else + { + struct trp_rb_node *old = node, *left; + + node = node->rb_right; + while ((left = node->rb_left) != NULL) + { + node = left; + } + + if (old->rb_parent) + { + if (old->rb_parent->rb_left == old) + { + old->rb_parent->rb_left = node; + } + else + { + old->rb_parent->rb_right = node; + } + } + else + { + root->rb_node = node; + } + + child = node->rb_right; + parent = node->rb_parent; + color = node->color; + + if (parent == old) + { + parent = node; + } + else + { + if (child) + { + child->rb_parent = parent; + } + + parent->rb_left = child; + + node->rb_right = old->rb_right; + old->rb_right->rb_parent = node; + } + + node->color = old->color; + node->rb_parent = old->rb_parent; + node->rb_left = old->rb_left; + old->rb_left->rb_parent = node; + + if (color == RB_BLACK) + { + __rb_erase_color(child, parent, root); + } + + return; + + } + + parent = node->rb_parent; + color = node->color; + + if (child) + { + child->rb_parent = parent; + } + + if (parent) + { + if (parent->rb_left == node) + { + parent->rb_left = child; + } + else + { + parent->rb_right = child; + } + } + else + { + root->rb_node = child; + } + + if (color == RB_BLACK) + { + __rb_erase_color(child, parent, root); + } + + return; +} + +NSTACK_STATIC trp_rb_node_t *rb_new_node(trp_key_t key, trp_data_t data, + trp_rb_node_t * parent + /*, key_compare key_compare_fn */ ) +{ + trp_rb_node_t *node = (trp_rb_node_t *) malloc(sizeof(trp_rb_node_t)); + if (!node) + { + return NULL; + } + node->key = key; + node->data = data; + node->rb_parent = parent; + node->rb_left = node->rb_right = NULL; + node->color = RB_RED; + /*node->key_compare_fn = key_compare_fn; */ + return node; +} + +int +trp_rb_insert(trp_key_t key, trp_data_t data, trp_rb_root_t * root, + key_compare key_compare_fn) +{ + trp_rb_node_t *node = root->rb_node, *parent = NULL; + int ret = 0; /* CID 24640 */ + while (node) + { + parent = node; + ret = key_compare_fn(node->key, key); + if (0 < ret) + { + node = node->rb_left; + } + else if (0 > ret) + { + node = node->rb_right; + } + else + { + return -1; + } + } + + node = rb_new_node(key, data, parent /*, key_compare_fn */ ); + if (!node) + { + return -1; + } + + if (parent) + { + if (ret > 0) + { + parent->rb_left = node; + } + else + { + parent->rb_right = node; + } + } + else + { + root->rb_node = node; + } + + rb_insert_color(node, root); + return 0; +} + +int +trp_rb_insert_allow_same_key(trp_key_t key, trp_data_t data, + trp_rb_root_t * root, key_compare key_compare_fn) +{ + trp_rb_node_t *node = root->rb_node, *parent = NULL; + int ret = 0; /*CID 24638 */ + while (node) + { + parent = node; + ret = key_compare_fn(node->key, key); + if (0 < ret) + { + node = node->rb_left; + } + else + { + node = node->rb_right; + } + } + + node = rb_new_node(key, data, parent /*, key_compare_fn */ ); + if (!node) + { + return -1; + } + + if (parent) + { + if (ret > 0) + { + parent->rb_left = node; + } + else + { + parent->rb_right = node; + } + } + else + { + root->rb_node = node; + } + + rb_insert_color(node, root); + return 0; +} + +NSTACK_STATIC trp_rb_node_t *trp_rb_search_inorder(trp_key_t key, + trp_data_t data, + trp_rb_node_t * node, + int *count, + key_compare key_compare_fn) +{ + if (!node) + { + return NULL; + } + + int ret = key_compare_fn(node->key, key);; + if (0 == ret && data == node->data) + { + return node; + } + + if ((NULL == count) || (0 >= --(*count))) + { + return NULL; + } + + trp_rb_node_t *ret_node = + trp_rb_search_inorder(key, data, node->rb_left, count, + key_compare_fn); + if (ret_node) + { + return ret_node; + } + + ret_node = + trp_rb_search_inorder(key, data, node->rb_right, count, + key_compare_fn); + return ret_node; +} + +void +trp_rb_erase_with_data(trp_key_t key, trp_data_t data, trp_rb_root_t * root, + int count, key_compare key_compare_fn) +{ + trp_rb_node_t *node; + /* recursion operation need depth protect */ + if (! + (node = + trp_rb_search_inorder(key, data, root->rb_node, &count, + key_compare_fn))) + { + return; + } + + rb_erase(node, root); + free(node); + node = NULL; +} + +void +trp_rb_erase(trp_key_t key, trp_rb_root_t * root, key_compare key_compare_fn) +{ + trp_rb_node_t *node; + if (!(node = trp_rb_search(key, root, key_compare_fn))) + { + return; + } + + rb_erase(node, root); + free(node); + node = NULL; +} diff --git a/stacks/lwip_stack/lwip_src/maintain/spl_mt_config.c b/stacks/lwip_stack/lwip_src/maintain/spl_mt_config.c new file mode 100644 index 0000000..35872b1 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/maintain/spl_mt_config.c @@ -0,0 +1,778 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include "types.h" +#include "nsfw_mt_config.h" +#include +#include +#include "nstack_log.h" +#include "nstack_securec.h" +#include "json.h" +#include "nsfw_init_api.h" +#include "nsfw_mgr_com_api.h" + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ + +// can be read from config file +extern u32 g_base_cfg_items[MAX_BASE_CFG]; + +// calculated according to base config +extern u32 g_custom_cfg_items[MAX_CUSTOM_CFG]; + +// note: if seg number greater than 16, such buffer should use malloc +// or it will be exceed 2K +//struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM]; + +NSTACK_STATIC int g_cfg_item_count[CFG_SEG_MAX] = { 0 }; + +NSTACK_STATIC char *g_cfg_seg_name[CFG_SEG_MAX]; + +#define set_cfg_info(tag, item, min, max, def) { \ + g_cfg_item_info[tag][item].min_value = (min); \ + g_cfg_item_info[tag][item].max_value = (max); \ + g_cfg_item_info[tag][item].default_value = (def);\ + g_cfg_item_info[tag][item].value = (def);\ +} + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +/* nStackCtrl cannot get the env path info, no start by shell script, need get + the path info ,and legal check , add a input parameter proc_type*/ + +NSTACK_STATIC int get_ctrl_dir_info(char *current_path, unsigned path_len) +{ + char ctrl_dir[MAX_FILE_NAME_LEN] = { 0 }; + int count = 0; + unsigned int dir_len = 0; + + //nStackCtrl cannot get the path from the env, so need get from current pwd. + count = readlink("/proc/self/exe", ctrl_dir, MAX_FILE_NAME_LEN); + if ((count < 0) || (count >= MAX_FILE_NAME_LEN)) + { + save_pre_init_log(NSLOG_ERR, + "readlink get nStackCtrl path failed, write nothing!"); + return -1; + } + ctrl_dir[count] = '\0'; + + dir_len = strlen(ctrl_dir); + if ((dir_len > strlen("nStackCtrl")) && (dir_len < MAX_FILE_NAME_LEN)) + { + ctrl_dir[dir_len - strlen("nStackCtrl")] = '\0'; + } + else + { + save_pre_init_log(NSLOG_ERR, + "path strlen is illegal, write nothing!"); + return -1; + } + + if (NULL == strstr(ctrl_dir, "bin")) + { + /* Exit before nstack_log_init, use printf */ + printf + ("the nStackServer content change, plz keep same with nStack release, exit!\n"); +#ifdef FOR_NSTACK_UT + return -1; +#else + exit(1); +#endif + } + if (EOK != + strncat_s(ctrl_dir, sizeof(ctrl_dir), "/../configure", + strlen("/../configure"))) + { + save_pre_init_log(NSLOG_ERR, "STRNCAT_S failed, current_dir = %s", + ctrl_dir); + return -1; + } + + if (-1 == + snprintf_s(current_path, path_len, path_len - 1, "%s", ctrl_dir)) + { + save_pre_init_log(NSLOG_ERR, + "SNPRINTF_S path name failed, ctrl_dir %s.", + ctrl_dir); + return -1; + } + + return 0; + +} + +NSTACK_STATIC int get_cfg_buf(u32 proc_type, char *cfg_buf, unsigned buf_size) +{ + char current_dir[MAX_FILE_NAME_LEN] = { 0 }; + char cfg_file_name[MAX_FILE_NAME_LEN] = { 0 }; + char *cfg_resolved_path = NULL; + char *cfg_path = NULL; + FILE *fp = NULL; + int cfg_buf_len = 0; + + cfg_path = getenv(CFG_PATH); + if ((NULL == cfg_path) && (NSFW_PROC_CTRL == proc_type)) + { + if (-1 == get_ctrl_dir_info(current_dir, sizeof(current_dir))) + { + save_pre_init_log(NSLOG_ERR, "get_ctrl_dir_info failed."); + return -1; + } + cfg_path = current_dir; + } + else if ((NULL == cfg_path) && (NSFW_PROC_CTRL != proc_type)) + { + save_pre_init_log(NSLOG_ERR, + "main or master process get nstack config path failed, will use default config!"); + return -1; + } + + if (-1 == + sprintf_s(cfg_file_name, sizeof(cfg_file_name), "%s/%s", cfg_path, + CFG_FILE_NAME)) + { + save_pre_init_log(NSLOG_ERR, + "format config file name failed, path %s, name %s.", + cfg_path, CFG_FILE_NAME); + return -1; + } + + cfg_resolved_path = realpath(cfg_file_name, NULL); + if (NULL == cfg_resolved_path) + { + save_pre_init_log(NSLOG_ERR, "config file path invalid, cfg name %s.", + cfg_file_name); + return -1; + } + + fp = fopen(cfg_resolved_path, "r"); + if (NULL == fp) + { + free(cfg_resolved_path); + save_pre_init_log(NSLOG_ERR, "config file path invalid, cfg name %s.", + cfg_file_name); + return -1; + } + + free(cfg_resolved_path); + // read config file to json buffer + cfg_buf_len = fread(cfg_buf, 1, buf_size, fp); + + fclose(fp); + + return cfg_buf_len; +} + +NSTACK_STATIC inline int +get_value_from_json_obj(struct json_object *obj, struct cfg_item_info *pitem) +{ + switch (pitem->type) + { + case CFG_ITEM_TYPE_INT: + pitem->value = json_object_get_int(obj); + break; + case CFG_ITEM_TYPE_STRING: + pitem->pvalue = (char *) json_object_get_string(obj); + break; + default: + // print log here? + return -1; + } + return 0; +} + +NSTACK_STATIC inline void get_cfg_item(struct json_object *obj, int seg_index) +{ + struct json_object *cfg_seg_obj = NULL; + struct json_object *cfg_seg = NULL; + struct json_object *cfg_item_obj[MAX_CFG_ITEM] = { 0 }; + int i = 0; + int cfg_num = 0; + + (void) json_object_object_get_ex(obj, g_cfg_seg_name[seg_index], + &cfg_seg_obj); + if (NULL == cfg_seg_obj) + { + save_pre_init_log(NSLOG_ERR, "get config segment obj failed, seg:%s.", + g_cfg_seg_name[seg_index]); + return; + } + + cfg_num = json_object_array_length(cfg_seg_obj); + if (cfg_num < 1) + { + save_pre_init_log(NSLOG_ERR, + "config segment count invalid, config segment %s, count %d.", + g_cfg_seg_name[seg_index], cfg_num); + return; + } + + // each config segment just has 1 array element + cfg_seg = + (struct json_object *) json_object_array_get_idx(cfg_seg_obj, 0); + if (NULL == cfg_seg) + { + save_pre_init_log(NSLOG_ERR, "no config item in seg %s.", + g_cfg_seg_name[seg_index]); + return; + } + + for (; i < g_cfg_item_count[seg_index]; i++) + { + (void) json_object_object_get_ex(cfg_seg, + g_cfg_item_info[seg_index][i].name, + &cfg_item_obj[i]); + + if (NULL == cfg_item_obj[i]) + { + save_pre_init_log(NSLOG_ERR, + "get config item failed, config item %s.", + g_cfg_item_info[seg_index][i].name); + return; + } + + // note: should specify the config item type if not only int item exist + if (get_value_from_json_obj + (cfg_item_obj[i], &g_cfg_item_info[seg_index][i]) != 0) + { + return; + } + } + + return; +} + +NSTACK_STATIC inline void parse_cfg(char *cfg_buf) +{ + if (NULL == cfg_buf) + { + return; + } + + struct json_object *obj = + (struct json_object *) json_tokener_parse(cfg_buf); + int i = 0; + + for (; i < CFG_SEG_MAX; i++) + { + if (0 == g_cfg_item_count[i]) + { + continue; + } + + get_cfg_item(obj, i); + } +} + +NSTACK_STATIC inline int is_valid(int value, int min_value, int max_value) +{ + if ((value < min_value) || (value > max_value)) + { + return 0; + } + + return 1; +} + +NSTACK_STATIC inline void check_cfg_item_int(struct cfg_item_info *pitem) +{ + if (!is_valid(pitem->value, pitem->min_value, pitem->max_value)) + { + pitem->value = pitem->default_value; + } +} + +NSTACK_STATIC inline void check_cfg_item_string(struct cfg_item_info *pitem) +{ + if ((NULL == pitem->pvalue) + || ((pitem->pvalue) && (0 == pitem->pvalue[0]))) + { + pitem->pvalue = pitem->default_str; + } +} + +NSTACK_STATIC inline void check_cfg_item(struct cfg_item_info *pitem) +{ + switch (pitem->type) + { + case CFG_ITEM_TYPE_INT: + check_cfg_item_int(pitem); + if (pitem->custom_check) + pitem->custom_check(pitem); + break; + case CFG_ITEM_TYPE_STRING: + check_cfg_item_string(pitem); + if (pitem->custom_check) + pitem->custom_check(pitem); + break; + default: + break; + } +} + +NSTACK_STATIC inline void check_cfg() +{ + int i = 0; + int j = 0; + for (i = 0; i < CFG_SEG_MAX; i++) + { + for (j = 0; j < g_cfg_item_count[i]; j++) + { + check_cfg_item(&g_cfg_item_info[i][j]); + } + } +} + +NSTACK_STATIC inline void +print_item_info(char *seg_name, struct cfg_item_info *pitem) +{ + switch (pitem->type) + { + case CFG_ITEM_TYPE_INT: + save_pre_init_log(NSLOG_INF, + "config read seg:%s, name:%s, value:%d.", + seg_name, pitem->name, pitem->value); + break; + case CFG_ITEM_TYPE_STRING: + save_pre_init_log(NSLOG_INF, + "config read seg:%s, name:%s, pvalue:%s.", + seg_name, pitem->name, pitem->pvalue); + break; + default: + break; + } +} + +NSTACK_STATIC inline void print_config_item_info() +{ + int i = 0; + int j = 0; + for (; i < CFG_SEG_MAX; i++) + { + for (j = 0; j < g_cfg_item_count[i]; j++) + { + print_item_info(g_cfg_seg_name[i], &g_cfg_item_info[i][j]); + } + } +} + +void check_socket_config(void *pitem) +{ + struct cfg_item_info *item = (struct cfg_item_info *) pitem; + if (item->value > 0 && !(item->value & (item->value - 1))) + return; + save_pre_init_log(NSLOG_WAR, + "warning: config socket_num (%u) is not 2^n, will use the default value:%u", + item->value, item->default_value); + item->value = item->default_value; +} + +/* thread schedule mode and thread priority should be matched */ +void check_thread_config(void *pitem) +{ + struct cfg_item_info *pri_cfg = (struct cfg_item_info *) pitem; + struct cfg_item_info *policy_cfg = + &g_cfg_item_info[CFG_SEG_PRI][CFG_ITEM_THREAD_PRI_POLICY]; + + int max_pri = sched_get_priority_max(policy_cfg->value); + int min_pri = sched_get_priority_min(policy_cfg->value); + if ((pri_cfg->value > max_pri) || (pri_cfg->value < min_pri)) + { + save_pre_init_log(NSLOG_INF, + "detect invalid thread priority configuration, use default value] policy=%d, pri=%d, def policy=%d, def pri=%d", + policy_cfg->value, pri_cfg->value, + policy_cfg->default_value, pri_cfg->default_value); + + policy_cfg->value = policy_cfg->default_value; + pri_cfg->value = pri_cfg->default_value; + } +} + +#define SET_CFG_ITEM(seg, item, field, value) g_cfg_item_info[seg][item].field = (value) +#define SET_THREAD_CFG_ITEM(item, field, value) SET_CFG_ITEM(CFG_SEG_PRI, item, field, value) + +NSTACK_STATIC void init_main_def_config_items() +{ + /* base config */ + g_cfg_seg_name[CFG_SEG_BASE] = "cfg_seg_socket"; + /* element count of cfg_seg_socket in nStackConfig.json */ + g_cfg_item_count[CFG_SEG_BASE] = 3; + /* -- socket number */ + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_SOCKET_NUM].name = + "socket_num"; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_SOCKET_NUM].type = + CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_SOCKET_NUM].custom_check = + check_socket_config; + set_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_SOCKET_NUM, MIN_SOCKET_NUM, + MAX_SOCKET_NUM, DEF_SOCKET_NUM); + /* -- arp stale time */ + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_ARP_STALE_TIME].name = + "arp_stale_time"; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_ARP_STALE_TIME].type = + CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_ARP_STALE_TIME].custom_check = + NULL; + set_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_ARP_STALE_TIME, + MIN_ARP_STACLE_TIME, MAX_ARP_STACLE_TIME, + DEF_ARP_STACLE_TIME); + /* -- arp braodcast retransmission times */ + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_ARP_BC_RETRANS_NUM].name = + "arp_bc_retrans_num"; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_ARP_BC_RETRANS_NUM].type = + CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_BASE] + [CFG_ITEM_BASE_ARP_BC_RETRANS_NUM].custom_check = NULL; + set_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_ARP_BC_RETRANS_NUM, + MIN_ARP_BC_RETRANS_NUM, MAX_ARP_BC_RETRANS_NUM, + DEF_ARP_BC_RETRANS_NUM); + + /* support thread priority configuration */ + g_cfg_seg_name[CFG_SEG_PRI] = "cfg_seg_thread_pri"; + g_cfg_item_count[CFG_SEG_PRI] = CFG_ITEM_THREAD_PRI_MAX; + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_POLICY, name, "sched_policy"); + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_POLICY, type, CFG_ITEM_TYPE_INT); + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_POLICY, custom_check, NULL); + set_cfg_info(CFG_SEG_PRI, CFG_ITEM_THREAD_PRI_POLICY, 0, 2, 0); + + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_PRI, name, "thread_pri"); + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_PRI, type, CFG_ITEM_TYPE_INT); + SET_THREAD_CFG_ITEM(CFG_ITEM_THREAD_PRI_PRI, custom_check, + check_thread_config); + set_cfg_info(CFG_SEG_PRI, CFG_ITEM_THREAD_PRI_PRI, 0, 99, 0); + + /* remove unsed operation config set */ + /* log config */ + g_cfg_seg_name[CFG_SEG_LOG] = "cfg_seg_log"; + g_cfg_item_count[CFG_SEG_LOG] = 2; + g_cfg_item_info[CFG_SEG_LOG][0].name = "run_log_size"; + g_cfg_item_info[CFG_SEG_LOG][0].type = CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_LOG][0].custom_check = NULL; + g_cfg_item_info[CFG_SEG_LOG][1].name = "run_log_count"; + g_cfg_item_info[CFG_SEG_LOG][1].type = CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_LOG][1].custom_check = NULL; + set_cfg_info(CFG_SEG_LOG, 0, 10, 100, 50); + set_cfg_info(CFG_SEG_LOG, 1, 2, 20, 10); + + /* path config */ + /* set the path string and default str */ + g_cfg_seg_name[CFG_SEG_PATH] = "cfg_seg_path"; + g_cfg_item_count[CFG_SEG_PATH] = 1; + g_cfg_item_info[CFG_SEG_PATH][0].name = "stackx_log_path"; + g_cfg_item_info[CFG_SEG_PATH][0].type = CFG_ITEM_TYPE_STRING; + g_cfg_item_info[CFG_SEG_PATH][0].default_str = NSTACK_LOG_NAME; + g_cfg_item_info[CFG_SEG_PATH][0].custom_check = NULL; + + /* stackpool max ring size */ + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_SPL_MAX_RING_SIZE].name = + "spl_max_ring_size"; + g_cfg_item_info[CFG_SEG_BASE][CFG_ITEM_BASE_SPL_MAX_RING_SIZE].type = + CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_BASE] + [CFG_ITEM_BASE_SPL_MAX_RING_SIZE].custom_check = NULL; + set_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_SPL_MAX_RING_SIZE, 128, 16384, + 1024); +} + +/* master and ctrl both use the function to reduce the redundancy, +* as the parameter and operation all same. +*/ +NSTACK_STATIC void init_master_def_config_items() +{ + int i = 0; + for (; i < CFG_SEG_MAX; i++) + { + if (i != CFG_SEG_LOG) + { + g_cfg_item_count[i] = 0; + } + } + + g_cfg_seg_name[CFG_SEG_LOG] = "cfg_seg_log"; + g_cfg_item_count[CFG_SEG_LOG] = 2; + g_cfg_item_info[CFG_SEG_LOG][0].name = "mon_log_size"; + g_cfg_item_info[CFG_SEG_LOG][0].type = CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_LOG][0].custom_check = NULL; + g_cfg_item_info[CFG_SEG_LOG][1].name = "mon_log_count"; + g_cfg_item_info[CFG_SEG_LOG][1].type = CFG_ITEM_TYPE_INT; + g_cfg_item_info[CFG_SEG_LOG][1].custom_check = NULL; + + set_cfg_info(CFG_SEG_LOG, 0, 2, 20, 10); + set_cfg_info(CFG_SEG_LOG, 1, 2, 20, 10); + + g_cfg_seg_name[CFG_SEG_PATH] = "cfg_seg_path"; + g_cfg_item_count[CFG_SEG_PATH] = 1; + g_cfg_item_info[CFG_SEG_PATH][0].name = "master_log_path"; + g_cfg_item_info[CFG_SEG_PATH][0].type = CFG_ITEM_TYPE_STRING; + g_cfg_item_info[CFG_SEG_PATH][0].default_str = NSTACK_LOG_NAME; + g_cfg_item_info[CFG_SEG_PATH][0].custom_check = NULL; +} + +NSTACK_STATIC void read_init_config(u32 proc_type) +{ + int cfg_buf_len = 0; + char cfg_json_buf[CFG_BUFFER_LEN] = { 0 }; + + cfg_buf_len = get_cfg_buf(proc_type, cfg_json_buf, sizeof(cfg_json_buf)); + if (cfg_buf_len < 0) + { + save_pre_init_log(NSLOG_WAR, + "warning:file not exist, use default config."); + return; + } + else + { + /* parse json buffer */ + parse_cfg(cfg_json_buf); + } + save_pre_init_log(NSLOG_INF, "read configuration finished."); +} + +/* =========== set config items ========= */ +NSTACK_STATIC inline void set_base_config() +{ + g_base_cfg_items[CFG_BASE_RING_SIZE] = DEF_RING_BASE_SIZE; + g_base_cfg_items[CFG_BASE_HAL_PORT_NUM] = DEF_HAL_PORT_NUM; + + g_base_cfg_items[CFG_BASE_SOCKET_NUM] = + (u32) get_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_SOCKET_NUM); + g_base_cfg_items[CFG_BASE_ARP_STALE_TIME] = + (u32) get_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_ARP_STALE_TIME); + g_base_cfg_items[CFG_BASE_ARP_BC_RETRANS_NUM] = + (u32) get_cfg_info(CFG_SEG_BASE, CFG_ITEM_BASE_ARP_BC_RETRANS_NUM); +} + +NSTACK_STATIC void init_base_config(cfg_module_param * param) +{ + /* initial default config */ + /* omc_ctrl single log file should be 10M */ + if (param->proc_type == NSFW_PROC_CTRL) + { + init_master_def_config_items(); + } + else + { + init_main_def_config_items(); + } + + /* read base config from file */ + read_init_config(param->proc_type); + /* check config and reset value */ + check_cfg(); + + /* print config info */ + print_config_item_info(); + + set_base_config(); +} + +NSTACK_STATIC void init_stackx_config() +{ + u32 socket_num_per_thread = CUR_CFG_SOCKET_NUM; + u32 factor = socket_num_per_thread / SOCKET_NUM_PER_THREAD; + + if (factor == 0 || socket_num_per_thread % SOCKET_NUM_PER_THREAD > 0) + { + factor += 1; + } + + save_pre_init_log(NSLOG_INF, "socket num:%d, factor:%d", + CUR_CFG_SOCKET_NUM, factor); + + /* MBUF config */ + set_custom_cfg_item(CFG_MBUF_DATA_SIZE, DEF_MBUF_DATA_SIZE); + set_custom_cfg_item(CFG_TX_MBUF_NUM, DEF_TX_MBUF_POOL_SIZE); + set_custom_cfg_item(CFG_RX_MBUF_NUM, DEF_RX_MBUF_POOL_SIZE); + set_custom_cfg_item(CFG_MP_TCPSEG_NUM, DEF_MEMP_NUM_TCP_SEG); /* tcp segment number */ + set_custom_cfg_item(CFG_MP_MSG_NUM, DEF_TX_MSG_POOL_SIZE); /* msg number */ + + /* ring config */ + set_custom_cfg_item(CFG_HAL_RX_RING_SIZE, DEF_HAL_RX_RING_SIZE); /* netif ring size not changed */ + set_custom_cfg_item(CFG_HAL_TX_RING_SIZE, DEF_HAL_TX_RING_SIZE); /* netif ring size not changed */ + set_custom_cfg_item(CFG_MBOX_RING_SIZE, DEF_MBOX_RING_SIZE); + set_custom_cfg_item(CFG_SPL_MAX_ACCEPT_RING_SIZE, DEF_SPL_MAX_RING_SIZE); /* stackx ring size */ + + /* pcb config */ + set_custom_cfg_item(CFG_TCP_PCB_NUM, DEF_TCP_PCB_NUM * factor); + set_custom_cfg_item(CFG_UDP_PCB_NUM, DEF_UDP_PCB_NUM * factor); + set_custom_cfg_item(CFG_RAW_PCB_NUM, DEF_RAW_PCB_NUM * factor); + set_custom_cfg_item(CFG_ARP_QUEUE_NUM, + CUR_CFG_SOCKET_NUM > + DEF_SOCKET_NUM ? LARGE_ARP_QUEUE_NUM : + DEF_ARP_QUEUE_NUM); +} + +void print_final_config_para() +{ + save_pre_init_log(NSLOG_INF, "socket_num :%u", + get_base_cfg(CFG_BASE_SOCKET_NUM)); + save_pre_init_log(NSLOG_INF, "base_ring_size :%u", + get_base_cfg(CFG_BASE_RING_SIZE)); + save_pre_init_log(NSLOG_INF, "hal_port_num :%u", + get_base_cfg(CFG_BASE_HAL_PORT_NUM)); + save_pre_init_log(NSLOG_INF, "arp_stale_num :%u", + get_base_cfg(CFG_BASE_ARP_STALE_TIME)); + save_pre_init_log(NSLOG_INF, "arp_bc_retrans_num :%u", + get_base_cfg(CFG_BASE_ARP_BC_RETRANS_NUM)); + + save_pre_init_log(NSLOG_INF, "mbuf_data_size :%u", + get_custom_cfg(CFG_MBUF_DATA_SIZE)); + save_pre_init_log(NSLOG_INF, "tx_mbuf_num :%u", + get_custom_cfg(CFG_TX_MBUF_NUM)); + save_pre_init_log(NSLOG_INF, "rx_mbuf_num :%u", + get_custom_cfg(CFG_RX_MBUF_NUM)); + save_pre_init_log(NSLOG_INF, "tcp_seg_mp_num :%u", + get_custom_cfg(CFG_MP_TCPSEG_NUM)); + save_pre_init_log(NSLOG_INF, "msg_mp_num :%u", + get_custom_cfg(CFG_MP_MSG_NUM)); + save_pre_init_log(NSLOG_INF, "hal_tx_ring_size :%u", + get_custom_cfg(CFG_HAL_TX_RING_SIZE)); + save_pre_init_log(NSLOG_INF, "hal_rx_ring_size :%u", + get_custom_cfg(CFG_HAL_RX_RING_SIZE)); + save_pre_init_log(NSLOG_INF, "mbox_ring_size :%u", + get_custom_cfg(CFG_MBOX_RING_SIZE)); + save_pre_init_log(NSLOG_INF, "spl_ring_size :%u", + get_custom_cfg(CFG_SPL_MAX_ACCEPT_RING_SIZE)); + save_pre_init_log(NSLOG_INF, "tcp_pcb_num :%u", + get_custom_cfg(CFG_TCP_PCB_NUM)); + save_pre_init_log(NSLOG_INF, "udp_pcb_num :%u", + get_custom_cfg(CFG_UDP_PCB_NUM)); + save_pre_init_log(NSLOG_INF, "raw_pcb_num :%u", + get_custom_cfg(CFG_RAW_PCB_NUM)); +} + +NSTACK_STATIC void init_module_cfg_default() +{ + init_stackx_config(); + + print_final_config_para(); +} + +NSTACK_STATIC void init_main_log_cfg_para() +{ + struct log_init_para log_para; + log_para.run_log_size = g_cfg_item_info[CFG_SEG_LOG][0].value; + log_para.run_log_count = g_cfg_item_info[CFG_SEG_LOG][1].value; + + /* log path valid check */ + if (0 == access(g_cfg_item_info[CFG_SEG_PATH][0].pvalue, W_OK)) + { + log_para.run_log_path = g_cfg_item_info[CFG_SEG_PATH][0].pvalue; + } + else + { + log_para.run_log_path = g_cfg_item_info[CFG_SEG_PATH][0].default_str; + } + + set_log_init_para(&log_para); +} + +/* nStackCtrl is the diff process with main, cannot use main process info, + need get the configure info respectively */ +/* omc_ctrl single log file should be 10M */ +NSTACK_STATIC void init_ctrl_log_cfg_para() +{ + struct log_init_para log_para; + log_para.mon_log_size = g_cfg_item_info[CFG_SEG_LOG][0].value; + log_para.mon_log_count = g_cfg_item_info[CFG_SEG_LOG][1].value; + + /* log path valid check */ + if (0 == access(g_cfg_item_info[CFG_SEG_PATH][0].pvalue, W_OK)) + { + log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].pvalue; + } + else + { + log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].default_str; + } + + set_log_init_para(&log_para); +} + +/*===========config init for nstack main=============*/ + +NSTACK_STATIC void init_module_cfg_nstackmain() +{ + /* init config data */ + init_module_cfg_default(); + + /* init log para */ + init_main_log_cfg_para(); +} + +/*===========config init for nstack ctrl=============*/ + +/* nStackCtrl is the diff process with main, + cannot use main process info, need get the configure info respectively */ + +NSTACK_STATIC void init_module_cfg_nstackctrl() +{ + init_ctrl_log_cfg_para(); +} + +/*===========init config module=============*/ +void config_module_init(cfg_module_param * param) +{ + save_pre_init_log(NSLOG_INF, "config module init begin] proc type=%d", + param->proc_type); + + init_base_config(param); + + switch (param->proc_type) + { + case NSFW_PROC_MAIN: + init_module_cfg_nstackmain(); + break; + + case NSFW_PROC_CTRL: + init_module_cfg_nstackctrl(); + break; + + default: + init_module_cfg_default(); + break; + } + + save_pre_init_log(NSLOG_INF, "config module init end."); +} + +int set_share_cfg_to_mem(void *mem) +{ + if (EOK != + memcpy_s(mem, sizeof(g_base_cfg_items), g_base_cfg_items, + sizeof(g_base_cfg_items))) + { + return -1; + } + + char *custom_cfg_mem = (char *) mem + sizeof(g_base_cfg_items); + + if (EOK != + memcpy_s(custom_cfg_mem, sizeof(g_custom_cfg_items), + g_custom_cfg_items, sizeof(g_custom_cfg_items))) + { + return -1; + } + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c b/stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c new file mode 100644 index 0000000..b45ba33 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c @@ -0,0 +1,392 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +#include +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init_api.h" +#include "common_mem_mbuf.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" + +#include "nsfw_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_ring_data.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +nsfw_res_mgr_item_cfg g_all_res_can[NSFW_MAX_RES_SCAN_COUNT]; + +#define NSFW_RES_SCAN_TVLAUE_DEF 60 +#define NSFW_RES_SCAN_TVLAUE (g_scan_cfg.scan_tvalue) + +typedef struct _nsfw_res_scan_init_cfg +{ + nsfw_timer_info *scan_timer; + u16 scan_tvalue; +} nsfw_res_scan_init_cfg; +nsfw_res_scan_init_cfg g_scan_cfg; + +static inline u32 spl_get_alloc_count(u32 head, u32 tail) +{ + if (head >= tail) + { + return head - tail; + } + + return head + (0xFFFFFFFF - tail); +} + +int spl_res_sp_item_chk(void *data, void *argv) +{ + nsfw_res_mgr_item_cfg *res_scn_item = (nsfw_res_mgr_item_cfg *) argv; + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + char *elm = (char *) data; + + if (NULL == scn_cfg || NULL == elm) + { + return FALSE; + } + + nsfw_res *res_item = NULL; + res_item = (nsfw_res *) (elm + scn_cfg->res_mem_offset); + if (0 == res_item->chk_count) + { + res_item->data = res_scn_item->cons_head; + } + res_item->chk_count++; + + if (res_item->chk_count < scn_cfg->force_free_chk_num) + { + return FALSE; + } + + if (res_scn_item->free_percent > scn_cfg->force_free_percent) + { + return FALSE; + } + + if (scn_cfg->total_num * scn_cfg->alloc_speed_factor > + spl_get_alloc_count(res_scn_item->cons_head, res_item->data)) + { + return FALSE; + } + + if (NULL == scn_cfg->free_fun) + { + return FALSE; + } + + if (TRUE == scn_cfg->free_fun((void *) elm)) + { + res_scn_item->force_count++; + } + + res_item->chk_count = 0; + return TRUE; +} + +int spl_res_flash_data(nsfw_res_mgr_item_cfg * res_scn_item) +{ + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + + u32 cur_head = 0; + u32 cur_tail = 0; + u32 elm_num = 0; + u32 free_count = 0; + + switch (scn_cfg->type) + { + case NSFW_RES_SCAN_MBUF: + { + struct common_mem_ring *ring = + (struct common_mem_ring *) scn_cfg->mgr_ring; + struct common_mem_mempool *mp = + (struct common_mem_mempool *) scn_cfg->data; + if (NULL == ring) + { + ring = mp->pool_data; + if (NULL == ring) + return FALSE; + } + cur_head = ring->prod.head; + cur_tail = ring->cons.head; + elm_num = mp->size; + } + break; + case NSFW_RES_SCAN_SPOOL: + { + struct nsfw_mem_ring *mem_ring = + (struct nsfw_mem_ring *) scn_cfg->mgr_ring; + if (NULL == mem_ring) + { + mem_ring = (struct nsfw_mem_ring *) scn_cfg->data; + if (NULL == mem_ring) + return FALSE; + } + + cur_head = mem_ring->prod.head; + cur_tail = mem_ring->cons.tail; + elm_num = mem_ring->size; + } + break; + case NSFW_RES_SCAN_ARRAY: + { + struct nsfw_mem_ring *mem_ring = + (struct nsfw_mem_ring *) scn_cfg->mgr_ring; + if (NULL == mem_ring) + { + return FALSE; + } + + cur_head = mem_ring->prod.head; + cur_tail = mem_ring->cons.tail; + elm_num = scn_cfg->total_num; + } + break; + default: + return FALSE; + } + + free_count = spl_get_alloc_count(cur_head, cur_tail); + + res_scn_item->cons_head = cur_head; + res_scn_item->prod_head = cur_tail; + if (0 != elm_num) + { + res_scn_item->free_percent = free_count * 100 / elm_num; + } + else + { + res_scn_item->free_percent = 100; + } + + scn_cfg->total_num = elm_num; + return TRUE; +} + +void spl_res_scan_mem(nsfw_res_mgr_item_cfg * res_scn_item) +{ + if (NULL == res_scn_item) + { + return; + } + + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + if (NULL == scn_cfg->data) + { + return; + } + + u32 start = res_scn_item->last_scn_idx; + u32 end = start + scn_cfg->num_per_cyc; + int res_chk_number = 0; + if (NSFW_RES_SCAN_SPOOL == scn_cfg->type) + { + res_chk_number = + nsfw_mem_sp_iterator(scn_cfg->data, start, end, + spl_res_sp_item_chk, (void *) res_scn_item); + } + else + { + res_chk_number = + nsfw_mem_mbuf_iterator(scn_cfg->data, start, end, + spl_res_sp_item_chk, + (void *) res_scn_item); + } + + if (0 == res_chk_number) + { + res_scn_item->last_scn_idx = 0; + start = res_scn_item->last_scn_idx; + end = start + scn_cfg->num_per_cyc; + if (NSFW_RES_SCAN_SPOOL == scn_cfg->type) + { + res_chk_number = + nsfw_mem_sp_iterator(scn_cfg->data, start, end, + spl_res_sp_item_chk, + (void *) res_scn_item); + } + else + { + res_chk_number = + nsfw_mem_mbuf_iterator(scn_cfg->data, start, end, + spl_res_sp_item_chk, + (void *) res_scn_item); + } + } + + if (res_chk_number + start < end) + { + res_scn_item->last_scn_idx = 0; + } + else + { + res_scn_item->last_scn_idx += res_chk_number; + } + + return; +} + +void spl_res_scan_array(nsfw_res_mgr_item_cfg * res_scn_item) +{ + if (NULL == res_scn_item) + { + return; + } + + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + if (NULL == scn_cfg->data) + { + return; + } + + u32 i; + char *elm = + (char *) scn_cfg->data + + (res_scn_item->last_scn_idx * scn_cfg->elm_size); + for (i = res_scn_item->last_scn_idx; i < scn_cfg->total_num; i++) + { + if (i >= res_scn_item->last_scn_idx + scn_cfg->num_per_cyc) + { + break; + } + + if (TRUE == spl_res_sp_item_chk(elm, (void *) res_scn_item)) + { + NSFW_LOGINF("force free item]data=%p,cfg=%p", elm, res_scn_item); + } + + elm += scn_cfg->elm_size; + } + + if (i >= scn_cfg->total_num) + { + res_scn_item->last_scn_idx = 0; + } + else + { + res_scn_item->last_scn_idx = i; + } + + return; +} + +void spl_res_scan_proc(nsfw_res_mgr_item_cfg * res_scn_item) +{ + (void) spl_res_flash_data(res_scn_item); + switch (res_scn_item->scn_cfg.type) + { + case NSFW_RES_SCAN_ARRAY: + spl_res_scan_array(res_scn_item); + break; + case NSFW_RES_SCAN_SPOOL: + case NSFW_RES_SCAN_MBUF: + spl_res_scan_mem(res_scn_item); + break; + default: + break; + } +} + +int spl_res_scan_all(u32 timer_type, void *data) +{ + NSFW_LOGDBG("scan start!"); + struct timespec time_left = { NSFW_RES_SCAN_TVLAUE, 0 }; + g_scan_cfg.scan_timer = + nsfw_timer_reg_timer(0, NULL, spl_res_scan_all, time_left); + + if (g_hbt_switch) + { + return TRUE; + } + + int i; + for (i = 0; i < NSFW_MAX_RES_SCAN_COUNT; i++) + { + /*last fun */ + if (NULL == g_all_res_can[i].scn_cfg.data) + { + break; + } + + spl_res_scan_proc(&g_all_res_can[i]); + } + + return TRUE; +} + +static int spl_resmgr_module_init(void *param); +static int spl_resmgr_module_init(void *param) +{ + u8 proc_type = (u8) ((long long) param); + NSFW_LOGINF("res mgr module init]type=%u", proc_type); + g_scan_cfg.scan_tvalue = NSFW_RES_SCAN_TVLAUE_DEF; + switch (proc_type) + { + case NSFW_PROC_MAIN: + { + struct timespec time_left = { NSFW_RES_SCAN_TVLAUE, 0 }; + g_scan_cfg.scan_timer = + nsfw_timer_reg_timer(0, NULL, spl_res_scan_all, + time_left); + return 0; + } + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME(SPL_RES_MGR_MODULE) +NSFW_MODULE_PRIORITY(99) +NSFW_MODULE_INIT(spl_resmgr_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/stacks/lwip_stack/lwip_src/netif/ethernetif.c b/stacks/lwip_stack/lwip_src/netif/ethernetif.c new file mode 100644 index 0000000..d135e83 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/ethernetif.c @@ -0,0 +1,164 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" + +#include "spl_def.h" +#include "mem.h" +#include "stackx/spl_pbuf.h" +//#include +//#include "sockets.h" +#include + +#include "stackx_spl_share.h" +#include "stackx/spl_api.h" +#include "lwip/etharp.h" + +#include +#include "sc_dpdk.h" + +#include "cpuid.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "nsfw_hal_api.h" + +#include "sys.h" + +#define IFNAME0 'e' +#define IFNAME1 'n' + +struct ethernetif +{ + struct eth_addr *ethaddr; + +}; + +#if (DPDK_MODULE != 1) +NSTACK_STATIC void low_level_init(struct netif *pnetif) +{ + struct ether_addr eth_addr; + + struct netifExt *pnetifExt = NULL; + NSPOL_LOGINF(NETIF_DEBUG, "low_level_init \n"); + + pnetifExt = getNetifExt(pnetif->num); + if (NULL == pnetifExt) + return; + + hal_get_macaddr(pnetifExt->hdl, ð_addr); + NSPOL_LOGINF(SC_DPDK_INFO, + "low_level_init: Port %s, MAC : %02X:%02X:%02X:%02X:%02X:%02X", + pnetifExt->if_name, eth_addr.addr_bytes[0], + eth_addr.addr_bytes[1], eth_addr.addr_bytes[2], + eth_addr.addr_bytes[3], eth_addr.addr_bytes[4], + eth_addr.addr_bytes[5]); + + pnetif->hwaddr_len = 6; + pnetif->hwaddr[0] = eth_addr.addr_bytes[0]; //0x00; + pnetif->hwaddr[1] = eth_addr.addr_bytes[1]; //0x1b; + pnetif->hwaddr[2] = eth_addr.addr_bytes[2]; //0x21; + pnetif->hwaddr[3] = eth_addr.addr_bytes[3]; //0x6b; + pnetif->hwaddr[4] = eth_addr.addr_bytes[4]; //0x24; + pnetif->hwaddr[5] = eth_addr.addr_bytes[5]; //0x40; + pnetif->mtu = SPL_FRAME_MTU; + + /* don't set SPL_NETIF_FLAG_ETHARP if this device is not an ethernet one */ + pnetif->flags = + NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + pnetif->flags |= NETIF_FLAG_IGMP; + +} +#endif + +#if (DPDK_MODULE != 1) + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to spl_netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if privatedata couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif * pnetif) +{ + struct ethernetif *eth_netif; + + if (NULL == pnetif) + { + NSPOL_LOGERR("netif=NULL"); + return ERR_VAL; + } + NSPOL_LOGINF(NETIF_DEBUG, "ethernetif_init \n"); + + eth_netif = (struct ethernetif *) malloc(sizeof(struct ethernetif)); + if (eth_netif == NULL) + { + NSPOL_LOGERR("ethernetif_init: out of memory"); + return ERR_MEM; + } + + pnetif->state = eth_netif; + pnetif->name[0] = IFNAME0; + pnetif->name[1] = IFNAME1; + + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + pnetif->output = etharp_output; + pnetif->linkoutput = spl_hal_output; + + eth_netif->ethaddr = (struct eth_addr *) &(pnetif->hwaddr[0]); + + // Add extra netif information here + if (0 != netifExt_add(pnetif)) + { + return ERR_VAL; + } + + /* initialize the hardware */ + low_level_init(pnetif); + NSPOL_LOGINF(NETIF_DEBUG, + "ethernetif_init complete ifname [%c][%c][%d] \n", + pnetif->name[0], pnetif->name[1], pnetif->num); + + return ERR_OK; +} + +void ethernetif_packets_input(struct netif *pstnetif) +{ + struct spl_pbuf *p = NULL; + spl_hal_input(pstnetif, &p); + + /* no packet could be read, silently ignore this */ + if (p != NULL + && pstnetif->input(spl_convert_spl_pbuf_to_pbuf(p), + pstnetif) != ERR_OK) + { + NSPOL_LOGERR("netif->input failed]p=%p, netif=%p", p, pstnetif); + } + + /* Free the spl pbuf */ + spl_pbuf_free(p); +} +#endif +//#endif /* 0 */ diff --git a/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c new file mode 100644 index 0000000..a1497b6 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c @@ -0,0 +1,563 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "sc_dpdk.h" +#include "common_mem_mbuf.h" +#include "netif/common.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_msg_api.h" +#include "nsfw_maintain_api.h" +#include "nsfw_recycle_api.h" +#include "stackx_app_res.h" +#include "stackx_pbuf.h" +#ifdef SYS_MEM_RES_STAT +#include "memp.h" +#endif +#include "spl_instance.h" +#ifdef HAL_LIB +#else +#include "rte_memzone.h" +#endif +#include "nsfw_shmem_mng.h" + +#define SPL_MEM_MODULE "spl_mem_module" + +#define TMR_TICK_LENGTH TCP_TMR_INTERVAL /* define the tick length */ + +u32_t uStackArgIndex = 0; +int stackx_core_mask = 40; + +int g_nstack_bind_cpu = 0; +int g_tcpip_thread_sleep_time = 0; + +extern int sbr_create_tx_pool(); +extern int stackx_stat_zone_create(); + +#define GLOBAL_STACK_CORE_ARG "-c" +#define GLOBAL_STACK_CORE_BINE "-bind_cpu" + +u32 g_type; +struct memory_statics memory_used_size[80]; + +void printmeminfo() +{ + unsigned int i = 0; + long size = 0; + + NSPOL_LOGDBG(SC_DPDK_INFO, + "*************************************************************"); + for (i = 0; i < g_type; i++) + { + NSPOL_LOGDBG(SC_DPDK_INFO, "%s : %ld", memory_used_size[i].name, + memory_used_size[i].size); + size += memory_used_size[i].size; + } + + size += (g_type * sizeof(struct common_mem_memzone)); + NSPOL_LOGDBG(SC_DPDK_INFO, "total size %ld", size); + NSPOL_LOGDBG(SC_DPDK_INFO, + "*************************************************************"); +} + +void print_call_stack() +{ +} + +/* Parse the argument given in the command line of the application */ +void smp_parse_stack_args(int argc, char **argv) +{ + int i = 0; + + const unsigned int global_core_length = 2; //GLOBAL_STACK_CORE_ARG "-c" string length is 2 + + for (i = uStackArgIndex + 1; i < argc; i++) + { + if ((i + 1) < argc) + { + if (strncmp(argv[i], "-sleep", 6) == 0) //compare "-sleep" string, length is 6 + { + g_tcpip_thread_sleep_time = atoi(argv[++i]); + NSPOL_LOGDBG(SC_DPDK_INFO, "g_tcpip_thread_sleep_time=%d", + g_tcpip_thread_sleep_time); + continue; + } + + if (strncmp(argv[i], GLOBAL_STACK_CORE_ARG, global_core_length) == + 0) + { + stackx_core_mask = atoi(argv[++i]); + if (stackx_core_mask < 1) + { + NSPOL_LOGDBG(SC_DPDK_INFO, + "Invalid Args:core_mask can't be less than 1,input value is:%s", + argv[i]); + } + + continue; + } + + if (strncmp + (argv[i], GLOBAL_STACK_CORE_BINE, + sizeof(GLOBAL_STACK_CORE_BINE)) == 0) + { + if (argv[++i]) + { + g_nstack_bind_cpu = atoi(argv[i]); + } + + if (g_nstack_bind_cpu < 0) + { + g_nstack_bind_cpu = 0; + } + + continue; + } + } + else + { + NSPOL_LOGDBG(SC_DPDK_INFO, "Invalid args:%s miss value ", argv[i]); //now ,only support this format ,others maybe supported in future + } + } + + return; +} + +mpool_handle create_tx_mbuf_pool() +{ + mpool_handle mbf_pool_handle = NULL; + + nsfw_mem_mbfpool mbuf_pool; + + mbuf_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf(mbuf_pool.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + get_mempoll_tx_name()); + if (retval < 0) + { + NSPOL_LOGERR("spl_snprintf failed"); + return NULL; + } + + mbuf_pool.usnum = TX_MBUF_POOL_SIZE - 1; + mbuf_pool.uscash_size = 0; + mbuf_pool.uspriv_size = 0; + mbuf_pool.usdata_room = TX_MBUF_MAX_LEN; + mbuf_pool.isocket_id = SOCKET_ID_ANY; + mbuf_pool.enmptype = NSFW_MRING_SPSC; + mbf_pool_handle = nsfw_mem_mbfmp_create(&mbuf_pool); + if (NULL == mbf_pool_handle) + { + NSPOL_LOGERR("create_tx_mbuf_pool failed]name=%s, num=%u, room=%u", + mbuf_pool.stname.aname, mbuf_pool.usnum, + mbuf_pool.usdata_room); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "tx_mempool_malloc=%p, num=%u, room=%u, total_mem=%d", + mbf_pool_handle, TX_MBUF_POOL_SIZE, mbuf_pool.usdata_room, + nsfw_mem_get_len(mbf_pool_handle, NSFW_MEM_MBUF)); + DPDK_MEMORY_COUNT((get_mempoll_tx_name()), + nsfw_mem_get_len(mbf_pool_handle, NSFW_MEM_MBUF)); + MEM_STAT(SPL_MEM_MODULE, "spl_mbuf_pool", NSFW_SHMEM, + nsfw_mem_get_len(mbf_pool_handle, NSFW_MEM_MBUF)); + + return mbf_pool_handle; +} + +mring_handle create_segment_pool() +{ + nsfw_mem_sppool seg_pool; + seg_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf(seg_pool.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + get_mempoll_seg_name()); + if (retval < 0) + { + NSPOL_LOGERR("spl_snprintf failed"); + return NULL; + } + + seg_pool.usnum = 16; + seg_pool.useltsize = sizeof(struct common_pcb); + seg_pool.isocket_id = SOCKET_ID_ANY; + seg_pool.enmptype = NSFW_MRING_SPSC; + + mring_handle seg_mp_handle = nsfw_mem_sp_create(&seg_pool); + if (NULL == seg_mp_handle) + { + NSPOL_LOGERR + ("create_segment_pool common failed]name=%s, num=%u, size=%u", + seg_pool.stname.aname, MEMP_NUM_TCP_SEG, seg_pool.useltsize); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "common seg_mempool_malloc=%p, num=%u, size=%u, total_mem=%d", + seg_mp_handle, MEMP_NUM_TCP_SEG, seg_pool.useltsize, + nsfw_mem_get_len(seg_mp_handle, NSFW_MEM_SPOOL)); + DPDK_MEMORY_COUNT((get_mempoll_seg_name()), + nsfw_mem_get_len(seg_mp_handle, NSFW_MEM_SPOOL)); + MEM_STAT(SPL_MEM_MODULE, "spl_seg_pool", NSFW_SHMEM, + nsfw_mem_get_len(seg_mp_handle, NSFW_MEM_SPOOL)); + return seg_mp_handle; +} + +mring_handle create_msg_pool() +{ + nsfw_mem_sppool msg_pool; + msg_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf(msg_pool.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + get_mempoll_msg_name()); + if (retval < 0) + { + NSPOL_LOGERR("spl_snprintf fail"); + return NULL; + } + + msg_pool.usnum = TX_MSG_POOL_SIZE; + msg_pool.useltsize = sizeof(data_com_msg); + msg_pool.isocket_id = SOCKET_ID_ANY; + msg_pool.enmptype = NSFW_MRING_MPMC; + mring_handle msg_mp_handle = nsfw_mem_sp_create(&msg_pool); + + if (NULL == msg_mp_handle) + { + NSPOL_LOGERR("create_msg_pool failed]name=%s, num=%u, size=%u", + msg_pool.stname.aname, TX_MSG_POOL_SIZE, + msg_pool.useltsize); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "msg_pool_malloc=%p, num=%u, size=%u, total_mem=%d", + msg_mp_handle, TX_MSG_POOL_SIZE, msg_pool.useltsize, + nsfw_mem_get_len(msg_mp_handle, NSFW_MEM_SPOOL)); + DPDK_MEMORY_COUNT((get_mempoll_msg_name()), + nsfw_mem_get_len(msg_mp_handle, NSFW_MEM_SPOOL)); + MEM_STAT(SPL_MEM_MODULE, "spl_msg_pool", NSFW_SHMEM, + nsfw_mem_get_len(msg_mp_handle, NSFW_MEM_SPOOL)); + return msg_mp_handle; +} + +mring_handle create_primary_box() +{ + nsfw_mem_mring mbox_pool; + mbox_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf(mbox_pool.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + get_stackx_ring_name()); + if (retval < 0) + { + NSPOL_LOGERR("spl_snprintf failed"); + return NULL; + } + + mbox_pool.usnum = MBOX_RING_SIZE - 1; + mbox_pool.isocket_id = SOCKET_ID_ANY; + mbox_pool.enmptype = NSFW_MRING_MPSC; + mring_handle mbox_handle = nsfw_mem_ring_create(&mbox_pool); + if (NULL == mbox_handle) + { + NSPOL_LOGERR("create_primary_mbox failed]name=%s, num=%u", + mbox_pool.stname.aname, mbox_pool.usnum + 1); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "primary_mbox_malloc=%p, num=%u, total_mem=%d", + mbox_handle, MBOX_RING_SIZE, + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + DPDK_MEMORY_COUNT((get_stackx_ring_name()), + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + MEM_STAT(SPL_MEM_MODULE, "primary_mbox_ring", NSFW_SHMEM, + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + return mbox_handle; +} + +mring_handle create_priority_box(u32 prio) +{ + nsfw_mem_mring mbox_pool; + mbox_pool.stname.entype = NSFW_SHMEM; + int retval = + spl_snprintf(mbox_pool.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + get_stackx_priority_ring_name(prio)); + if (retval < 0) + { + NSPOL_LOGERR("spl_snprintf failed"); + return NULL; + } + + mbox_pool.usnum = MBOX_RING_SIZE - 1; + mbox_pool.isocket_id = SOCKET_ID_ANY; + mbox_pool.enmptype = NSFW_MRING_MPSC; + mring_handle mbox_handle = nsfw_mem_ring_create(&mbox_pool); + if (NULL == mbox_handle) + { + NSPOL_LOGERR("Create priority mbox fail]name=%s, num=%u", + mbox_pool.stname.aname, mbox_pool.usnum + 1); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "prio=%u, mbox=%p, num=%u, total_mem=%d", prio, + mbox_handle, MBOX_RING_SIZE, + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + DPDK_MEMORY_COUNT((get_stackx_priority_ring_name(prio)), + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + MEM_STAT(SPL_MEM_MODULE, mbox_pool.stname.aname, NSFW_SHMEM, + (nsfw_mem_get_len(mbox_handle, NSFW_MEM_RING))); + return mbox_handle; + +} + +int init_instance() +{ + int ret; + p_def_stack_instance = + (stackx_instance *) malloc(sizeof(stackx_instance)); + if (NULL == p_def_stack_instance) + { + NSPOL_LOGERR("malloc failed"); + return -1; + } + + ret = memset_s(p_def_stack_instance, sizeof(stackx_instance), 0, + sizeof(stackx_instance)); + if (EOK != ret) + { + NSPOL_LOGERR("MEMSET_S failed]ret=%d", ret); + return -1; + } + + p_def_stack_instance->rss_queue_id = 0; + p_def_stack_instance->netif_list = NULL; + p_def_stack_instance->mp_tx = create_tx_mbuf_pool(); + if (!p_def_stack_instance->mp_tx) + { + return -1; + } + + (void) spl_reg_res_tx_mgr(p_def_stack_instance->mp_tx); // will only return 0, no need to check return value + + /* Modified above code to hold common_pcb */ + p_def_stack_instance->cpcb_seg = create_segment_pool(); + if (!p_def_stack_instance->cpcb_seg) + { + return -1; + } + + p_def_stack_instance->lmsg_pool = create_msg_pool(); + if (!p_def_stack_instance->lmsg_pool) + { + return -1; + } + + mring_handle mbox_array[SPL_MSG_BOX_NUM] = { NULL }; + p_def_stack_instance->lstack.primary_mbox.llring = create_primary_box(); + if (!p_def_stack_instance->lstack.primary_mbox.llring) + { + return -1; + } + mbox_array[0] = p_def_stack_instance->lstack.primary_mbox.llring; + + u32 m = 0; + while (m < MSG_PRIO_QUEUE_NUM) + { + p_def_stack_instance->lstack.priority_mbox[m].llring = + create_priority_box(m); + if (!p_def_stack_instance->lstack.priority_mbox[m].llring) + { + return -1; + } + mbox_array[m + 1] = + p_def_stack_instance->lstack.priority_mbox[m].llring; + m++; + } + + (void) spl_add_mbox(mbox_array, SPL_MSG_BOX_NUM); + + g_nsfw_rti_primary_stat = &p_def_stack_instance->lstat.primary_stat; //save to g_nsfw_rti_primary_stat(this is a SH addr) + return 0; +} + +void spl_free_msgs_in_box(mring_handle r) +{ + i32 count = 0, i = 0; + + void **msgs = NULL; + data_com_msg *m = NULL; + + while ((count = nsfw_mem_ring_dequeuev(r, msgs, 32)) > 0) + { + /* drop all of them */ + if (msgs == NULL) + break; + + for (i = 0; i < count; i++) + { + m = (data_com_msg *) msgs[i]; + if (m->param.op_type == MSG_ASYN_POST) + ASYNC_MSG_FREE(m); + else + SYNC_MSG_ACK(m); + } + } +} + +inline int spl_msg_malloc(data_com_msg ** p_msg_entry) +{ + mring_handle msg_pool = NULL; + int rslt; + stackx_instance *instance = p_def_stack_instance; + msg_pool = instance->lmsg_pool; + if (!msg_pool) + { + NSPOL_LOGERR("msg_pool is NULL"); + return -1; + } + + rslt = nsfw_mem_ring_dequeue(msg_pool, (void **) p_msg_entry); + if ((rslt == 0) || (*p_msg_entry == NULL)) + { + NSPOL_LOGERR("failed to get msg from ring"); + return -1; + } + + res_alloc(&(*p_msg_entry)->param.res_chk); + + (*p_msg_entry)->param.msg_from = msg_pool; + (*p_msg_entry)->param.err = ERR_OK; + return 0; +} + +struct spl_pbuf *spl_mbuf_malloc(uint16_t len, spl_pbuf_type Type, + u16_t * count) +{ + struct common_mem_mbuf *mbuf = NULL; + struct common_mem_mbuf *mbuf_first = NULL; + struct common_mem_mbuf *mbuf_tail = NULL; + struct spl_pbuf *buf = NULL; + struct spl_pbuf *first = NULL; + struct spl_pbuf *tail = NULL; + + mpool_handle mp = NULL; + + mp = p_def_stack_instance->mp_tx; + if (mp == NULL) + { + return NULL; /*if mp is NULL when init app will Inform */ + } + + while (len > 0) + { + mbuf = (struct common_mem_mbuf *) nsfw_shmem_mbfalloc(mp); + if (unlikely(mbuf == NULL)) + { + if (mbuf_first != NULL) + { + if (res_free + (& + (((struct spl_pbuf *) ((char *) mbuf_first + + sizeof(struct + common_mem_mbuf)))->res_chk))) + { + NSPOL_LOGERR("res_free failed"); + } + spl_mbuf_free(mbuf_first); + } + + return NULL; + } + + uint16_t alloc = TX_MBUF_MAX_LEN; + if (len < TX_MBUF_MAX_LEN) + { + alloc = len; + } + + (*count)++; + mbuf->data_len = alloc; + mbuf->next = NULL; + buf = + (struct spl_pbuf *) ((char *) mbuf + + sizeof(struct common_mem_mbuf)); + res_alloc(&buf->res_chk); + + buf->next_a = 0; + buf->payload_a = ADDR_LTOSH_EXT(common_pktmbuf_mtod(mbuf, void *)); + buf->tot_len = len; + buf->len = alloc; + buf->type = Type; + buf->flags = 0; + + buf->freeNext = NULL; + + buf->conn_a = 0; + + if (first == NULL) + { + first = buf; + mbuf_first = mbuf; + tail = buf; + mbuf_tail = mbuf; + mbuf_first->nb_segs = 1; + mbuf_first->pkt_len = alloc; + } + else + { + /* Already there is a check for the return value of rtp_pktmbuf_alloc, + hence not an issue */ + + tail->next_a = ADDR_LTOSH_EXT(buf); + tail = buf; +#ifdef HAL_LIB +#else + mbuf_tail->next = mbuf; +#endif + mbuf_tail = mbuf; + + mbuf_first->pkt_len = (mbuf_first->pkt_len + mbuf->data_len); + mbuf_first->nb_segs++; + + } + + len -= alloc; + } + + return first; +} + +/* + * Ring distribution function: protocol stack once a packet processing, so there is no use of bulk package + * @param buf pbuf means * @param packet_inport the packet from which the port to enter, for the configuration table with the ip comparison + * @ Protocol stack add location: ip.c-> ip_input () -> (if (netif == NULL) branch) + * @ Return value: 0 for the send into * 0 for the transmission failed: send the original failure 1, + * err = -20 did not match to the client, err = -1Ring full, overflow, will release the package +*/ + +inline void spl_mbuf_free(void *mbuf) +{ + (void) nsfw_shmem_mbffree((mbuf_handle) mbuf); +} + +inline uint16_t spl_mbuf_refcnt_update(void *mbuf, int16_t value) +{ + common_mbuf_refcnt_set((struct common_mem_mbuf *) mbuf, + common_mbuf_refcnt_read((struct common_mem_mbuf *) + mbuf) + value); + return 1; +} diff --git a/stacks/lwip_stack/lwip_src/netif/spl_hal.c b/stacks/lwip_stack/lwip_src/netif/spl_hal.c new file mode 100644 index 0000000..71d5c06 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/netif/spl_hal.c @@ -0,0 +1,1755 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "sys_arch.h" +#include "netif.h" +#include "spl_sockets.h" +//#include + +#include "stackx_spl_share.h" +#include "stackx_pbuf.h" +#include "spl_api.h" +#include "sharedmemory.h" +//#include "nettool.h" +#include "lwip/etharp.h" +#include "ip_module_api.h" +#include "sc_dpdk.h" +#include "nstack_log.h" +#include "common.h" +#include "nstack_securec.h" +//#include "ip.h" +#include "configuration_reader.h" +#include "spl_hal.h" +#include "nsfw_maintain_api.h" +#include "stackx_common.h" +#include "spl_instance.h" +#include +#include "prot/tcp.h" +#include "nsfw_shmem_mng.h" + +extern u32_t g_mbuf_size[MAX_THREAD_NUM]; +extern u32_t uStackArgIndex; +extern void smp_parse_stack_args(int argc, char **argv); +extern void spl_do_dump(struct spl_pbuf *p, u16 direction); + +#define SPL_HAL_SEND_TRY 100000 + +#define SPL_HAL_MODULE "SPL_HAL_MODULE" +extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER]; + +/* structure to store the rx and tx packets. Put two per cache line as ports + * used in pairs */ +struct port_stats +{ + unsigned rx; + unsigned tx; + unsigned drop; + u64_t rx_size; + u64_t tx_size; + u64_t recv_last_cycles; + u64_t send_last_cycles; +} __attribute__ ((aligned(COMMON_CACHE_LINE_SIZE / 2))); + +struct port_capa +{ + u32_t tx_ipv4_cksum_offload; + u32_t tx_udp_cksum_offload; + u32_t tx_tcp_cksum_offload; +}; + +struct rx_pkts +{ + u16_t num; + u16_t index; + struct common_mem_mbuf *pkts[PKT_BURST]; +}; + +struct tx_pkts +{ + u16_t num; + struct common_mem_mbuf *pkts[PKT_BURST]; +}; + +struct port_pkts +{ + struct rx_pkts rx; + struct tx_pkts tx; +}; + +struct psd_header +{ + u32_t src_addr; /* IPaddress of source host. */ + u32_t dst_addr; /* IPaddress of destination host(s). */ + u8_t zero; /* zero. */ + u8_t proto; /* L4 protocol type. */ + u16_t len; /* L4 length. */ +} __attribute__ ((__packed__)); + +NSTACK_STATIC unsigned num_ports_NIC = 0; +NSTACK_STATIC unsigned num_ports_NIC_start = 0; + +struct stackx_port_info *head_used_port_list; +struct stackx_port_zone *p_stackx_port_zone = NULL; + +struct bond_ports_info bond_ports_array = {.cnt = 0 }; + +static u8_t bond_ports_array_cnt_start = 0; + +static struct port_capa spl_hal_capa = { 0 }; + +static struct port_pkts spl_hal_pkts[HAL_MAX_NIC_NUM]; + +NSTACK_STATIC inline u16_t get_ipv4_16b_sum(u16_t * ptr16, u32_t nr) +{ + u32_t sum = 0; + + while (nr > 1) + { + sum += *ptr16; + nr -= sizeof(u16_t); + ptr16++; + + if (sum > UINT16_MAX) + { + sum -= UINT16_MAX; + } + } + + /* If length is in odd bytes */ + if (nr) + { + sum += *((u8_t *) ptr16); + } + + sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff); + sum &= 0x0ffff; + return (u16_t) sum; +} + +NSTACK_STATIC inline u16_t get_ipv4_bswap16(u16_t x) +{ + return (u16_t) (((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8)); +} + +NSTACK_STATIC inline u16_t +get_ipv4_psd_sum(struct ip_hdr * iphdr, u64_t ol_flags) +{ + struct psd_header psd_hdr; + + psd_hdr.src_addr = iphdr->src.addr; + psd_hdr.dst_addr = iphdr->dest.addr; + psd_hdr.zero = 0; + psd_hdr.proto = iphdr->_proto; + + if (ol_flags & PKT_TX_TCP_SEG) + { + psd_hdr.len = 0; + } + else + { + psd_hdr.len = get_ipv4_bswap16((get_ipv4_bswap16(iphdr->_len) + - sizeof(struct ip_hdr))); + } + + return get_ipv4_16b_sum((u16_t *) & psd_hdr, sizeof(struct psd_header)); +} + +/* should be called after head_used_port_list is initialized */ +NSTACK_STATIC hal_hdl_t get_port_hdl_by_name(const char *name) +{ + unsigned int i = 0; + struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port; + + while (i < p_stackx_port_zone->port_num) + { + if (!strncasecmp(p->linux_ip.if_name, name, strlen(name))) + { + return p->linux_ip.hdl; + } + + p = &p_stackx_port_zone->stackx_one_port[++i]; + } + + NSPOL_LOGERR("failed to find port id]name=%s", name); + return hal_get_invalid_hdl(); +} + +NSTACK_STATIC struct stackx_port_info *get_port_info_by_name(const char *name) +{ + struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port; + unsigned int i = 0; + + while (i < p_stackx_port_zone->port_num) + { + if (!strncasecmp(p->linux_ip.if_name, name, strlen(name))) + { + return p; + } + + p = &p_stackx_port_zone->stackx_one_port[++i]; + } + + return NULL; +} + +NSTACK_STATIC int del_port_in_port_list(const char *name) +{ + struct stackx_port_info *inf = head_used_port_list; + struct stackx_port_info *prev = NULL; + + while (inf) + { + if (!strncasecmp(inf->linux_ip.if_name, name, strlen(name))) + { + if (prev != NULL) + { + prev->next_use_port = inf->next_use_port; + } + else + { + head_used_port_list = inf->next_use_port; + } + + break; + } + + prev = inf; + inf = inf->next_use_port; + } + + return 0; +} + +extern void create_netif(struct stackx_port_info *p_port_info); + +NSTACK_STATIC int add_port_in_port_list(struct stackx_port_info *p) +{ + char *name; + struct stackx_port_info *inf = head_used_port_list; + struct stackx_port_info *prev = NULL; + + name = p->linux_ip.if_name; + + while (inf) + { + if (!strncasecmp(inf->linux_ip.if_name, name, strlen(name))) + { + NSPOL_LOGERR("ERROR: add an existing port!"); + return -1; + } + + prev = inf; + inf = inf->next_use_port; + } + + if (prev == NULL) + { + head_used_port_list = p; + } + else + { + prev->next_use_port = p; + } + + p->next_use_port = NULL; + create_netif(p); + return 0; +} + +/* Queries the link status of a port and prints it to screen */ +NSTACK_STATIC void report_port_link_status(struct stackx_port_info *p) +{ + /* get link status */ + u32 status; + + status = hal_link_status(p->linux_ip.hdl); + + if (status) + { + NSPOL_LOGINF(SC_DPDK_INFO, "Port=%s: Link Up", p->linux_ip.if_name); + } + else + { + NSPOL_LOGINF(SC_DPDK_INFO, "Port=%s: Link Down", p->linux_ip.if_name); + } +} + +int spl_hal_ether_etoa(const unsigned char *e, int e_len, char *a, int a_len) +{ + char *c = a; + int i; + int retVal; + + if (!e || !a || e_len < 0) + return -1; + + if (e_len > NETIF_ETH_ADDR_LEN) + e_len = NETIF_ETH_ADDR_LEN; + + if (a_len < e_len * 3) + return -1; + + for (i = 0; i < e_len; i++) + { + if (i) + { + *c++ = ':'; + } + retVal = sprintf_s(c, a_len - (c - a), "%02x", e[i] & 0xff); + if (-1 == retVal) + { + NSPOL_LOGERR("SPRINTF_S failed]ret=%d.", retVal); + return -1; + } + c = c + retVal; + } + + return 0; +} + +NSTACK_STATIC inline void +spl_hal_buf_convert(struct common_mem_mbuf *mbuf, struct spl_pbuf **buf) +{ + struct common_mem_mbuf *before = NULL; + struct spl_pbuf *last = NULL; + struct spl_pbuf *first = NULL; + struct spl_pbuf *tmp = NULL; + + while (mbuf != NULL) + { + //dpdk 2.1 + tmp = + (struct spl_pbuf *) ((char *) mbuf + + sizeof(struct common_mem_mbuf)); + res_alloc(&tmp->res_chk); + tmp->payload = common_pktmbuf_mtod(mbuf, void *); + tmp->tot_len = mbuf->pkt_len; + tmp->len = mbuf->data_len; + tmp->type = SPL_PBUF_HUGE; + tmp->proto_type = SPL_PBUF_PROTO_NONE; + tmp->next = NULL; + tmp->flags = 0; + + if (first == NULL) + { + first = tmp; + last = first; + } + else + { + /* Always the "if(first == NULL)" code segment is executed and then + "else" segment code is executed, so the "last" variable is not + NULL always when "else" case is executed */ + last->next = tmp; + last = tmp; + } + + before = mbuf; + mbuf = mbuf->next; + + before->next = NULL; + } + + *buf = first; +} + +NSTACK_STATIC int spl_hal_port_zone_init() +{ + int retVal; + nsfw_mem_zone create_port_zone; + nsfw_mem_zone create_port_info; + struct stackx_port_info *mz_port_info; + INITPOL_LOGINF("HAL", "spl_hal_port_zone_init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + + if ((CUR_CFG_HAL_PORT_NUM < 1) + || (SIZE_MAX / sizeof(struct stackx_port_info) < + CUR_CFG_HAL_PORT_NUM)) + { + NSPOL_LOGERR("malloc parameter incorrect]max_linux_port=%u", + CUR_CFG_HAL_PORT_NUM); + return -1; + } + + if (spl_snprintf + (create_port_zone.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + MP_STACKX_PORT_ZONE) < 0) + { + NSPOL_LOGERR("spl_snprintf fail"); + + return -1; + } + + create_port_zone.stname.entype = NSFW_SHMEM; + create_port_zone.isocket_id = SOCKET_ID_ANY; + create_port_zone.lenth = sizeof(struct stackx_port_zone); + create_port_zone.ireserv = 0; + p_stackx_port_zone = + (struct stackx_port_zone *) nsfw_mem_zone_create(&create_port_zone); + + if (NULL == p_stackx_port_zone) + { + INITPOL_LOGERR("HAL", "spl_hal_port_zone_init", + "Cannot create memory zone for MP_STACKX_PORT_ZONE information", + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + common_exit(EXIT_FAILURE, + "Cannot create memory zone for MP_STACKX_PORT_ZONE information"); + } + + retVal = + memset_s(p_stackx_port_zone, sizeof(struct stackx_port_zone), 0, + sizeof(struct stackx_port_zone)); + + if (EOK != retVal) + { + INITPOL_LOGERR("HAL", "spl_hal_port_zone_init", + "MEMSET_S return fail", retVal, MODULE_INIT_FAIL); + nsfw_mem_zone_release(&create_port_zone.stname); + return -1; + } + + if (spl_snprintf + (create_port_info.stname.aname, NSFW_MEM_NAME_LENTH - 1, "%s", + MP_STACKX_PORT_INFO) < 0) + { + NSPOL_LOGERR("VSNPRINTF_S fail"); + return -1; + } + + create_port_info.stname.entype = NSFW_SHMEM; + create_port_info.isocket_id = SOCKET_ID_ANY; + create_port_info.lenth = + CUR_CFG_HAL_PORT_NUM * sizeof(struct stackx_port_info); + create_port_info.ireserv = 0; + mz_port_info = + (struct stackx_port_info *) nsfw_mem_zone_create(&create_port_info); + + if (NULL == mz_port_info) + { + INITPOL_LOGERR("HAL", "spl_hal_port_zone_init", + "Cannot create memory zone for MP_STACKX_PORT_INFO information", + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + common_exit(EXIT_FAILURE, + "Cannot create memory zone for MP_STACKX_PORT_INFO information"); + } + + retVal = + memset_s(mz_port_info, create_port_info.length, 0, + create_port_info.lenth); + + if (EOK != retVal) + { + INITPOL_LOGERR("HAL", "spl_hal_port_zone_init", + "MEMSET_S return fail", retVal, MODULE_INIT_FAIL); + nsfw_mem_zone_release(&create_port_info.stname); + nsfw_mem_zone_release(&create_port_zone.stname); + return -1; + } + + MEM_STAT(SPL_HAL_MODULE, create_port_zone.stname.aname, NSFW_SHMEM, + create_port_info.lenth); + + p_stackx_port_zone->stackx_one_port = mz_port_info; + + INITPOL_LOGINF("HAL", "spl_hal_port_zone_init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + return 0; +} + +int spl_hal_init(int argc, char *argv[]) +{ + int retval = -1; + int idx_init; + + NSPOL_LOGINF(SC_DPDK_INFO, "spl_hal_init start"); + + /* Get nstack args */ + smp_parse_stack_args(argc, argv); + + if (0 == uStackArgIndex) + { + NSPOL_LOGERR("uStackArgIndex is 0, can lead to long loop]"); + return retval; + } + + /* Init DPDK */ + argc = uStackArgIndex--; + INITPOL_LOGINF("HAL", "hal_init_global", NULL_STRING, LOG_INVALID_VALUE, + MODULE_INIT_START); + + for (idx_init = 0; idx_init < argc; idx_init++) + { + NSPOL_LOGINF(SC_DPDK_INFO, + "hal_init_global]idx_init=%d,argv[idx_init]=%s", + idx_init, argv[idx_init]); + } + + retval = hal_init_global(argc, argv); + + if (0 != retval) + { + NSPOL_LOGERR("call hal_init_global fail]retval = %d", retval); + return -1; + } + + retval = hal_init_local(); + + if (0 != retval) + { + NSPOL_LOGERR("call hal_init_local fail]retval = %d", retval); + return -1; + } + + retval = spl_hal_port_zone_init(); + if (0 != retval) + { + NSPOL_LOGERR("call hal_init_local fail]retval = %d", retval); + return -1; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "Finished Process Init"); + + return 0; + +} + +static inline int spl_hal_rx_mbuf_free(void *data, void *arg) +{ + struct spl_pbuf *tmp = NULL; + struct common_mem_mbuf *mbuf = (struct common_mem_mbuf *) data; + (void) arg; + + tmp = + (struct spl_pbuf *) ((char *) mbuf + sizeof(struct common_mem_mbuf)); + if (tmp->res_chk.alloc_flag == TRUE) + return 1; + + if (common_mbuf_refcnt_read(mbuf) == 0) + return 1; + + NSPOL_LOGDBG(SC_DPDK_INFO, "rx_pool init in fault case: free mbuf=%p", + mbuf); + spl_mbuf_free(mbuf); + return 0; +} + +struct common_mem_mempool *spl_hal_rx_pool_create(int nic_id, int queue_id, + int start_type) +{ + int retval; + struct common_mem_mempool *mp; + nsfw_mem_mbfpool create_mbuf_pool; + nsfw_mem_name lookup_mbuf_pool; + struct common_mem_ring *ring; + + if (start_type == 1) + { + create_mbuf_pool.stname.entype = NSFW_SHMEM; + create_mbuf_pool.uscash_size = 0; + create_mbuf_pool.uspriv_size = 0; + create_mbuf_pool.isocket_id = SOCKET_ID_ANY; + create_mbuf_pool.enmptype = NSFW_MRING_SPSC; + + retval = + spl_snprintf(create_mbuf_pool.stname.aname, + NSFW_MEM_NAME_LENTH - 1, "%s", + get_mempoll_rx_name(queue_id, nic_id)); + + if (-1 == retval) + { + NSPOL_LOGERR("spl_snprintf fail"); + return NULL; + } + + create_mbuf_pool.usnum = RX_MBUF_POOL_SIZE - 1; + /*performance, rx buf cap is special, ((size - HEADROOM) >> 10) <<10, see ixgbe_dev_rx_init; + if want cap size == TX_MBUF_MAX_LEN, must let data_root=TX_MBUF_MAX_LEN+COMMON_PKTMBUF_HEADROOM and + TX_MBUF_MAX_LEN must N*1024; + */ + create_mbuf_pool.usdata_room = + TX_MBUF_MAX_LEN + COMMON_PKTMBUF_HEADROOM; + + NSPOL_LOGDBG(SC_DPDK_INFO, "hal_rx_pool.usnum=%u, usdata_room=%u", + create_mbuf_pool.usnum, create_mbuf_pool.usdata_room); + + mp = (struct common_mem_mempool *) + nsfw_mem_mbfmp_create(&create_mbuf_pool); + + if (mp == NULL) + { + NSPOL_LOGERR("nsfw_mem_mbfmp_create fail"); + return NULL; + } + + MEM_STAT(SPL_HAL_MODULE, create_mbuf_pool.stname.aname, NSFW_SHMEM, + nsfw_mem_get_len(mp, NSFW_MEM_MBUF)); + NSPOL_LOGDBG(SC_DPDK_INFO, "create:thread=%d,nic_id=%d,mp=%p,size=%d", + queue_id, nic_id, mp, nsfw_mem_get_len(mp, + NSFW_MEM_MBUF)); + + char rx_msg_arr_name[NSFW_MEM_NAME_LENTH]; + data_com_msg *rx_msg_array = NULL; + retval = spl_snprintf(rx_msg_arr_name, NSFW_MEM_NAME_LENTH, "%s", + get_mempoll_rxmsg_name(queue_id, nic_id)); + + if (-1 != retval) + { + rx_msg_array = (data_com_msg *) sbr_create_mzone(rx_msg_arr_name, + (size_t) + sizeof + (data_com_msg) * + RX_MBUF_POOL_SIZE); + } + + if (!rx_msg_array) + { + NSSBR_LOGERR + ("Create rx_msg_array zone fail]name=%s, num=%u, size=%zu", + rx_msg_arr_name, RX_MBUF_POOL_SIZE, + (size_t) sizeof(data_com_msg) * RX_MBUF_POOL_SIZE); + } + else + { + /*bind msg to pbuf */ + MEM_STAT(SPL_HAL_MODULE, rx_msg_arr_name, NSFW_SHMEM, + (size_t) sizeof(data_com_msg) * RX_MBUF_POOL_SIZE); + NSSBR_LOGINF + ("Create rx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%zu", + rx_msg_arr_name, rx_msg_array, RX_MBUF_POOL_SIZE, + sizeof(data_com_msg) * RX_MBUF_POOL_SIZE); + + struct common_mem_mbuf *mbuf = NULL; + struct spl_pbuf *buf = NULL; + u32 loop = 0; + + for (; loop < RX_MBUF_POOL_SIZE; loop++) + { + mbuf = nsfw_shmem_mbfalloc(mp); + + if (!mbuf) + { + /* alloc failed , still can work, no prebind success just not so faster */ + NSSBR_LOGERR + ("nsfw_mem_mbf_alloc failed,this can not happen"); + break; + } + + buf = + (struct spl_pbuf *) ((char *) mbuf + + sizeof(struct common_mem_mbuf)); + sys_sem_init(&rx_msg_array[loop].param.op_completed); + rx_msg_array[loop].param.msg_from = NULL; + buf->msg = (void *) &rx_msg_array[loop]; + (void) res_free(&buf->res_chk); //no need to check return value, as it will do free operation depends on alloc_flag + + if (nsfw_shmem_mbffree(mbuf) < 0) + { + /* free failed , still can work, no prebind work just not so faster */ + NSSBR_LOGERR + ("nsfw_mem_mbf_free failed,this can not happen"); + break; + } + } + + } + + } + else + { + retval = + spl_snprintf(lookup_mbuf_pool.aname, NSFW_MEM_NAME_LENTH - 1, + "%s", get_mempoll_rx_name(queue_id, nic_id)); + + if (-1 == retval) + { + NSPOL_LOGERR("spl_snprintf fail"); + return NULL; + } + + lookup_mbuf_pool.entype = NSFW_SHMEM; + lookup_mbuf_pool.enowner = NSFW_PROC_MAIN; + mp = (struct common_mem_mempool *) + nsfw_mem_mbfmp_lookup(&lookup_mbuf_pool); + + if (mp == NULL) + { + NSPOL_LOGERR("nsfw_mem_mbfmp_lookup fail, name=%s, try to create", + lookup_mbuf_pool.aname); + return spl_hal_rx_pool_create(nic_id, queue_id, 1); + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "lookup:thread=%d,nic_id=%d,mp=%p,size=%d", + queue_id, nic_id, mp, nsfw_mem_get_len(mp, + NSFW_MEM_MBUF)); + + /*We have to recycle RX mbufs hold by DPDK when fault recovering of upgrading nstack */ + if (start_type == 3 || start_type == 2) + { + ring = (struct common_mem_ring *) (mp->pool_data); + NSPOL_LOGINF(SC_DPDK_INFO, + "BEFORE clear rx_mpool]prod.head=%u, prod.tail=%u, " + "cons.head=%u, cons.tail=%u", ring->prod.head, + ring->prod.tail, ring->cons.head, ring->cons.tail); + + if (nsfw_mem_mbuf_iterator(mp, 0, mp->size, + spl_hal_rx_mbuf_free, NULL) < 0) + { + NSPOL_LOGERR("nsfw_mem_mbuf_iterator return fail"); + return NULL; + } + + NSPOL_LOGINF(SC_DPDK_INFO, + "AFTER clear rx_mpool]prod.head=%u, prod.tail=%u, " + "cons.head=%u, cons.tail=%u", ring->prod.head, + ring->prod.tail, ring->cons.head, ring->cons.tail); + } + + } + + return mp; + +} + +int spl_hal_bond_config(struct network_configuration *network) +{ + struct phy_net *phynet = network->phy_net; + struct ref_nic *phead = phynet->header; + static u8_t bond_index = 0; /* for auto-generating bond_name */ + unsigned int check_bond = 0, check_name; + int retVal; + u8_t j, k, idx = 0; + + /* get bond info from network configuration */ + if (phynet->bond_mode != -1 && bond_ports_array.cnt < MAX_BOND_PORT_NUM) + { + struct ref_nic *phead_bond = phead; + char *name = phynet->bond_name; + struct bond_set *s = &bond_ports_array.ports[bond_ports_array.cnt]; + + while (phead_bond != NULL) + { + /* check slave name, repeated slave nic cannot be added to bond set. */ + check_name = 0; + + for (j = 0; j < idx; j++) + { + if (strcmp(s->slave_ports[j], phead_bond->nic_name) == 0) + { + check_name = 1; + break; + } + } + + if (check_name) + { + break; + } + + /* if this nic has been added to a bond_set, ignore it */ + check_bond = 0; + + for (k = 0; k < bond_ports_array.cnt && !check_bond; k++) + { + for (j = 0; + j < bond_ports_array.ports[k].slave_port_cnt + && !check_bond; j++) + { + if (strcmp + (bond_ports_array.ports[k].slave_ports[j], + phead_bond->nic_name) == 0) + { + check_bond = 1; + + if (name[0] == 0) + { + retVal = + strncpy_s(name, IP_MODULE_MAX_NAME_LEN, + bond_ports_array. + ports[k].bond_port_name, + strlen(bond_ports_array. + ports[k].bond_port_name)); + if (EOK != retVal) + { + NSPOL_LOGERR("STRNCPY_S failed]ret=%d.", + retVal); + return -1; + } + } + + if (strcmp + (name, + bond_ports_array.ports[k].bond_port_name) != 0) + { + NSOPR_SET_ERRINFO(-1, "%s init failed!\n", name); + NSPOL_LOGERR + ("%s init failed! %s in both %s and %s", name, + phead_bond->nic_name, name, + bond_ports_array.ports[k].bond_port_name); + return -1; + } + } + } + } + + if (check_bond == 1) + { + break; + } + + /* copy slave ports name to bond array */ + retVal = + strncpy_s(s->slave_ports[idx], HAL_MAX_NIC_NAME_LEN, + phead_bond->nic_name, strlen(phead_bond->nic_name)); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRNCPY_S failed]ret=%d.", retVal); + return -1; + } + + idx++; + phead_bond = phead_bond->next; + + if (idx >= HAL_MAX_SLAVES_PER_BOND) + { + break; + } + } + + if (check_bond == 0) + { + if (name[0] == 0) + { + /* if bond_name is a empty string, generate a new bond name */ + retVal = + sprintf_s(name, HAL_MAX_NIC_NAME_LEN, "bond%u_auto", + bond_index++); + + if (-1 == retVal) + { + NSPOL_LOGERR("SPRINTF_S failed]ret=%d.", retVal); + return -1; + } + } + + /* copy bond_name to bond array */ + retVal = + strncpy_s(s->bond_port_name, HAL_MAX_NIC_NAME_LEN, name, + strlen(name)); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRNCPY_S failed]ret=%d.", retVal); + return -1; + } + + s->slave_port_cnt = idx; + bond_ports_array.cnt++; + NSPOL_LOGINF(SC_DPDK_INFO, + "bond_ports_array.cnt=%u,slave_port_cnt=%u", + bond_ports_array.cnt, s->slave_port_cnt); + } + } + + return 0; +} + +int spl_hal_port_config(unsigned int *port_num) +{ + int retVal; + unsigned int check; + struct phy_net *phynet; + + struct network_configuration *network = get_network_list(); + + if (!network) + { + NSPOL_LOGERR("fail to get_provider_node"); + return -1; + } + + unsigned int port_index = p_stackx_port_zone->port_num; + + while (network && (phynet = network->phy_net)) + { + struct ref_nic *phead = phynet->header; + NSPOL_LOGINF(SC_DPDK_INFO, "network=%p,network_name=%s", network, + network->network_name); + + if (spl_hal_bond_config(network) < 0) + { + NSPOL_LOGERR("spl_hal_bond_config fail."); + return -1; + } + + while (phead != NULL) + { + /* check if the NIC is inited */ + for (check = 0; check < port_index; ++check) + { + if (strcmp + (p_stackx_port_zone->stackx_one_port[check]. + linux_ip.if_name, phead->nic_name) == 0) + { + break; + } + } + + if (check != port_index) + { + phead = phead->next; + continue; + } + + /* check if the number of VF exceeds MAX_VF_NUM */ + if (port_index >= + MAX_VF_NUM + p_stackx_port_zone->bonded_port_num) + { + NSOPR_SET_ERRINFO(-1, "Support Only %d VF. %s init failed!\n", + MAX_VF_NUM, phead->nic_name); + NSPOL_LOGERR("Support Only %d VF. %s init failed!", + MAX_VF_NUM, phead->nic_name); + NSOPR_SET_ERRINFO(-1, "Add network %s failed!\n", + network->network_name); + break; + } + + if (strlen(phead->nic_name) >= + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name) - 1 + || strlen(phead->nic_name) <= 3) + { + NSPOL_LOGERR("Invalid configuration"); + return -1; + } + + retVal = + strcpy_s(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name, + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name), + phead->nic_name); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "if_name %s", + p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_name); + + retVal = + strcpy_s(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_type, + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_type), + network->nic_type_name); + if (EOK != retVal) + { + NSPOL_LOGERR("strcpy_s failed]ret=%d.", retVal); + return -1; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "if_type %s", + p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.if_type); + + retVal = + strcpy_s(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.ip_addr_linux, + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + ip_addr_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + retVal = + strcpy_s(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.mask_linux, + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + mask_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + retVal = + strcpy_s(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip.bcast_linux, + sizeof(p_stackx_port_zone-> + stackx_one_port[port_index].linux_ip. + bcast_linux), "0.0.0.0"); + + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d.", retVal); + return -1; + } + + ++port_index; + NSPOL_LOGINF(SC_DPDK_INFO, "port_index=%u", port_index); + + if (CUR_CFG_HAL_PORT_NUM <= port_index + bond_ports_array.cnt) + { + // TODO: Invalid configuration received, return immediately + NSPOL_LOGERR + ("Insufficient nStack configuration when compared to configuration from network.json"); + return -1; + } + + /* [TA33636] [2017-04-11] Do not need provider.json */ + if (phynet->bond_mode == -1 /*&& strncmp(network->network_name, "provider", 8) != 0 */ + ) + { + break; + } + else + { + phead = phead->next; + } + } + + network = network->next; + } + + *port_num = port_index; + + return ERR_OK; +} + +void spl_hal_capa_init() +{ + u32_t ipv4_cksum_offload = 1; + u32_t udp_cksum_offload = 1; + u32_t tcp_cksum_offload = 1; + struct hal_netif_hw_feature info = { 0 }; + struct stackx_port_info *p_port_info = head_used_port_list; + + while (p_port_info) + { + hal_get_capability(p_port_info->linux_ip.hdl, &info); + + if (info.tx_csum_ip == 0) + { + ipv4_cksum_offload = 0; + + NSPOL_LOGDBG(SC_DPDK_INFO, + "Port %s TX_OFFLOAD_IPV4_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + if (info.tx_csum_udp == 0) + { + udp_cksum_offload = 0; + + NSPOL_LOGDBG(SC_DPDK_INFO, "Port %s TX_OFFLOAD_UDP_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + if (info.tx_csum_tcp == 0) + { + tcp_cksum_offload = 0; + + NSPOL_LOGDBG(SC_DPDK_INFO, "Port %s TX_OFFLOAD_TCP_CKSUM Disable", + p_port_info->linux_ip.if_name); + } + + p_port_info = p_port_info->next_use_port; + } + + spl_hal_capa.tx_ipv4_cksum_offload = ipv4_cksum_offload; + spl_hal_capa.tx_udp_cksum_offload = udp_cksum_offload; + spl_hal_capa.tx_tcp_cksum_offload = tcp_cksum_offload; + + NSPOL_LOGINF(SC_DPDK_INFO, + "ipv4_cksum_offload(%u),udp_cksum_offload(%u),tcp_cksum_offload(%u)", + ipv4_cksum_offload, udp_cksum_offload, tcp_cksum_offload); + +} + +NSTACK_STATIC void +spl_hal_bond_info_init(hal_hdl_t hdl, struct bond_set *s, + struct stackx_port_info *p) +{ +#define MAX_MAC_STR_LEN 20 + char mac_string[MAX_MAC_STR_LEN]; + int retVal; + struct ether_addr addr; + + p->linux_ip.hdl = hdl; + + struct stackx_port_info *slave_port; + slave_port = get_port_info_by_name(s->slave_ports[0]); + + if (slave_port == NULL) + { + NSPOL_LOGERR("get_port_info_by_name failed]bond_port_name=%s", + s->bond_port_name); + return; + } + + /* check the lenght of bond_port_name */ + retVal = + strcpy_s(p->linux_ip.if_name, sizeof(p->linux_ip.if_name), + s->bond_port_name); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return; + } + + hal_get_macaddr(hdl, &addr); + retVal = + spl_hal_ether_etoa(addr.addr_bytes, sizeof(addr.addr_bytes), + mac_string, sizeof(mac_string)); + if (retVal < 0) + { + NSPOL_LOGERR("spl_hal_ether_etoa failed]ret=%d", retVal); + return; + } + + retVal = + strcpy_s(p->linux_ip.mac_addr, sizeof(p->linux_ip.mac_addr), + mac_string); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + strcpy_s(p->linux_ip.ip_addr_linux, sizeof(p->linux_ip.ip_addr_linux), + slave_port->linux_ip.ip_addr_linux); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + strcpy_s(p->linux_ip.mask_linux, sizeof(p->linux_ip.mask_linux), + slave_port->linux_ip.mask_linux); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return; + } + + retVal = + strcpy_s(p->linux_ip.bcast_linux, sizeof(p->linux_ip.bcast_linux), + slave_port->linux_ip.bcast_linux); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return; + } + + NSPOL_LOGINF(SC_DPDK_INFO, "===== the bond port info ======"); + NSPOL_LOGINF(SC_DPDK_INFO, "bond port name=%s", p->linux_ip.if_name); + NSPOL_LOGINF(SC_DPDK_INFO, "bond port mac=%s", p->linux_ip.mac_addr); + NSPOL_LOGINF(SC_DPDK_INFO, "bond port ip=%s", p->linux_ip.ip_addr_linux); + NSPOL_LOGINF(SC_DPDK_INFO, "bond port netmask=%s", + p->linux_ip.mask_linux); + NSPOL_LOGINF(SC_DPDK_INFO, "bond port broad_cast addr=%s", + p->linux_ip.bcast_linux); + +} + +NSTACK_STATIC int spl_hal_bond_start(void) +{ + u8_t i, j = 0; + struct stackx_port_info *bond_port = NULL; + hal_hdl_t hdl; + hal_hdl_t slave_hdl[HAL_MAX_SLAVES_PER_BOND]; + + NSPOL_LOGINF(SC_DPDK_INFO, "bond_ports_array.cnt=%u", + bond_ports_array.cnt); + + for (i = bond_ports_array_cnt_start; i < bond_ports_array.cnt; i++) + { + struct bond_set *s = &bond_ports_array.ports[i]; + NSPOL_LOGINF(SC_DPDK_INFO, "i=%u,bond_port_name=%s", i, + s->bond_port_name); + + u8_t slave_num = 0; + for (j = 0; j < s->slave_port_cnt; j++) + { + NSPOL_LOGINF(SC_DPDK_INFO, "s->slave_ports[%u]=%s", j, + s->slave_ports[j]); + hdl = get_port_hdl_by_name(s->slave_ports[j]); + + if (!hal_is_valid(hdl)) + { + continue; + } + + slave_hdl[slave_num++] = hdl; + + /* here we didn't release the port mem allocated in p_stackx_port_zone */ + del_port_in_port_list(s->slave_ports[j]); + } + + hdl = hal_bond(s->bond_port_name, slave_num, slave_hdl); + + if (!hal_is_valid(hdl)) + { + NSPOL_LOGERR("hal_bond fail: bond_name =%s", s->bond_port_name); + return -1; + } + + bond_port = + &p_stackx_port_zone-> + stackx_one_port[p_stackx_port_zone->port_num]; + num_ports_NIC++; + p_stackx_port_zone->port_num++; + p_stackx_port_zone->bonded_port_num++; + + spl_hal_bond_info_init(hdl, s, bond_port); + add_port_in_port_list(bond_port); + + } + + bond_ports_array_cnt_start = bond_ports_array.cnt; + return 0; +} + +/* + * Initialises a given port using global settings and with the rx buffers + * coming from the mbuf_pool passed as parameter + */ + +NSTACK_STATIC inline int +spl_hal_port_start(uint16_t nic_id, struct stackx_port_info *p_port_info, + u16_t num_queues) +{ + u16_t num_queues_request, q; + hal_hdl_t hdl; + struct common_mem_mempool *mp; + hal_netif_config_t conf; +#define MAX_MAC_STR_LEN 20 + char mac_string[MAX_MAC_STR_LEN]; + int retVal; + struct ether_addr addr; + + // change the queues number per configuration. + // even we only receive packets from one rx queue when dispatch mode is on, the tx queue + // shoule set to the queues number requested. + num_queues_request = num_queues; + if (num_queues_request > HAL_ETH_MAX_QUEUE_NUM) + { + NSPOL_LOGERR + ("no enougth queue num for thread!]num_queues_request=%u,MAX_QUEUE_NUM=%u", + num_queues_request, HAL_ETH_MAX_QUEUE_NUM); + return -1; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "# Initialising index=%s... ", + p_port_info->linux_ip.if_name); + /* used to have fflush,no use code ,remove it. */ + + conf.bit.hw_vlan_filter = 1; + conf.bit.hw_vlan_strip = 1; + + conf.rx.queue_num = num_queues_request; + conf.tx.queue_num = num_queues_request; + + for (q = 0; q < num_queues_request; q++) + { + mp = (struct common_mem_mempool *) spl_hal_rx_pool_create(nic_id, q, + 1); + + if (mp == NULL) + { + NSPOL_LOGERR + ("spl_hal_rx_pool_create fail]mp=NULL,nic_id=%u,if_name=%s", + nic_id, p_port_info->linux_ip.if_name); + return -1; + } + + (void) spl_reg_res_txrx_mgr((mpool_handle *) mp); // will only return 0, no need to check return value + conf.rx.ring_pool[q] = mp; + conf.rx.ring_size[q] = HAL_RX_RING_SIZE; + conf.tx.ring_size[q] = HAL_TX_RING_SIZE; + } + + hdl = + hal_create(p_port_info->linux_ip.if_name, + p_port_info->linux_ip.if_type, &conf); + + if (!hal_is_valid(hdl)) + { + NSPOL_LOGERR("hal_create fail]if_name =%s", + p_port_info->linux_ip.if_name); + return -1; + } + + p_port_info->linux_ip.hdl = hdl; + + /* add mac address */ + hal_get_macaddr(hdl, &addr); + retVal = + spl_hal_ether_etoa(addr.addr_bytes, sizeof(addr.addr_bytes), + mac_string, sizeof(mac_string)); + if (retVal < 0) + { + NSPOL_LOGERR("spl_hal_ether_etoa failed]ret=%d", retVal); + return -1; + } + + retVal = + strcpy_s(p_port_info->linux_ip.mac_addr, + sizeof(p_port_info->linux_ip.mac_addr), mac_string); + if (EOK != retVal) + { + NSPOL_LOGERR("STRCPY_S failed]ret=%d", retVal); + return -1; + } + + return 0; +} + +NSTACK_STATIC int spl_hal_port_setup() +{ + unsigned int i; + struct stackx_port_info *p_port_info = NULL; + + INITPOL_LOGINF("HAL", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + + for (i = num_ports_NIC_start; i < num_ports_NIC; i++) + { + p_port_info = &(p_stackx_port_zone->stackx_one_port[i]); + + if (spl_hal_port_start(i, p_port_info, (u16_t) 1) < 0) + { + NSPOL_LOGERR("Error initialising]nic_id=%u", i); + + INITPOL_LOGERR("HAL", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + + return -1; + } + else + { + report_port_link_status(p_port_info); + add_port_in_port_list(p_port_info); + } + } + + if (spl_hal_bond_start() < 0) + { + NSPOL_LOGERR("bond port init failed!"); + + INITPOL_LOGERR("HAL", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + + return -1; + } + + spl_hal_capa_init(); + + INITPOL_LOGINF("HAL", "spl_hal_port_setup", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + return 0; + +} + +int spl_hal_port_init() +{ + int retval; + unsigned int i, port_num = 0; + + int port_num_start = p_stackx_port_zone->port_num; + num_ports_NIC_start = num_ports_NIC; + + //Read network info + INITPOL_LOGINF("IP", "spl_hal_port_config", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + retval = spl_hal_port_config(&port_num); + + if (retval != ERR_OK) + { + INITPOL_LOGERR("IP", "spl_hal_port_config", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + return -1; + } + + p_stackx_port_zone->port_num = port_num; + + NSPOL_LOGINF(SC_DPDK_INFO, "port_num=%u", port_num); + INITPOL_LOGINF("IP", "spl_hal_port_config", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + if (port_num_start == p_stackx_port_zone->port_num) + { + NSPOL_LOGERR("No new NIC find."); + return 0; + } + + //Get ports num + for (i = port_num_start; i < p_stackx_port_zone->port_num; i++) + { + if (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name[0] != 0) + { + /* right now hard coded, */ + int eth_num = + atoi(p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name + + 3); + + num_ports_NIC++; + + NSPOL_LOGDBG(SC_DPDK_INFO, "port_mask=%d ,eth_name=%s", eth_num, + p_stackx_port_zone->stackx_one_port[i]. + linux_ip.if_name); + } + } + + if (num_ports_NIC > HAL_MAX_NIC_NUM) + { + NSPOL_LOGERR("just support one eth"); + common_exit(EXIT_FAILURE, "just surport one eth"); + } + + if (num_ports_NIC == num_ports_NIC_start) + { + NSPOL_LOGERR("No new NIC find."); + return 0; + } + + retval = spl_hal_port_setup(); + + if (retval == -1) + { + return -1; + } + + NSPOL_LOGDBG(SC_DPDK_INFO, "Finished Process Init."); + + return 1; +} + +inline NSTACK_STATIC void spl_hal_send(struct netif *pnetif) +{ + u16_t i, sent = 0; + struct netifExt *pnetifExt = NULL; + u16_t netif_id = pnetif->num; + u16_t tx_num = spl_hal_pkts[netif_id].tx.num; + struct common_mem_mbuf **tx_ptks = spl_hal_pkts[netif_id].tx.pkts; + + for (i = 0; i < tx_num; i++) + { + (void) + res_free(& + (((struct spl_pbuf *) (((char *) tx_ptks[i]) + + sizeof(struct + common_mem_mbuf)))->res_chk)); + } + + int _retry = 0; + + pnetifExt = getNetifExt(pnetif->num); + if (NULL == pnetifExt) + return; + + do + { + sent += + hal_send_packet(pnetifExt->hdl, 0, (void **) &(tx_ptks[sent]), + tx_num - sent); + _retry++; + + if (_retry > SPL_HAL_SEND_TRY) + { + NSPOL_LOGERR("send loop %d times but dpdk send data fail ", + SPL_HAL_SEND_TRY); + break; + } + } + while (unlikely(sent != tx_num)); + + if (unlikely(sent != tx_num)) + { + for (i = sent; i < tx_num; i++) + { + (void) nsfw_shmem_mbffree((mbuf_handle) (tx_ptks[i])); + } + } + for (i = 0; i < tx_num; i++) + { + /* set dpdk_send flag */ + ((struct spl_pbuf *) (((char *) tx_ptks[i]) + + sizeof(struct common_mem_mbuf)))-> + res_chk.u8Reserve |= DPDK_SEND_FLAG; + } + + spl_hal_pkts[netif_id].tx.num = 0; + +} + +inline u16_t spl_hal_recv(struct netif *pnetif, u8_t id) +{ + u16_t netif_id, rx_c = 0; + struct netifExt *pnetifExt = NULL; + + netif_id = pnetif->num; + + pnetifExt = getNetifExt(pnetif->num); + if (NULL == pnetifExt) + return 0; + + rx_c = + hal_recv_packet(pnetifExt->hdl, 0, + (void **) spl_hal_pkts[netif_id].rx.pkts, PKT_BURST); + + if (rx_c <= 0) + { + return 0; + } + + spl_hal_pkts[netif_id].rx.num = rx_c; + spl_hal_pkts[netif_id].rx.index = 0; + + return rx_c; +} + +/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/ +NSTACK_STATIC inline void +spl_hal_set_cksum(struct spl_pbuf *buf, struct common_mem_mbuf *mbuf) +{ + + //need to be careful, special when small packet oversize + if (buf->tot_len > mbuf->pkt_len) + { + NSPOL_LOGWAR(SC_DPDK_INFO, + "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u", + buf->len, mbuf->pkt_len); + mbuf->pkt_len = buf->len; + } + + if (!spl_hal_tx_ip_cksum_enable() || !spl_hal_tx_tcp_cksum_enable() + || !spl_hal_tx_udp_cksum_enable()) + { + struct tcp_hdr *t_hdr; + struct udp_hdr *u_hdr; + u16_t flag_offset; + u64_t ol_flags = (mbuf->ol_flags); //& (~PKT_TX_L4_MASK)); + + struct eth_hdr *ethhdr = (struct eth_hdr *) ((char *) buf->payload); + + if (ethhdr->type == 8) + { + struct ip_hdr *iphdr = + (struct ip_hdr *) ((char *) buf->payload + + sizeof(struct eth_hdr)); + + if (!spl_hal_tx_ip_cksum_enable()) + { + ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM; + iphdr->_chksum = 0; + } + + flag_offset = spl_ntohs(iphdr->_offset); + + /*ip frag, only the first packet has udp or tcp head */ + if (0 == (flag_offset & IP_OFFMASK)) + { + switch (iphdr->_proto) + { + case IPPROTO_TCP: + if (!spl_hal_tx_tcp_cksum_enable()) + { + t_hdr = + (struct tcp_hdr *) ((char *) buf->payload + + sizeof(struct eth_hdr) + + sizeof(struct ip_hdr)); + t_hdr->chksum = get_ipv4_psd_sum(iphdr, ol_flags); + ol_flags |= PKT_TX_TCP_CKSUM; + } + + break; + + case IPPROTO_UDP: + { + if ((mbuf->ol_flags & PKT_TX_UDP_CKSUM) == + PKT_TX_UDP_CKSUM) + { + u_hdr = (struct udp_hdr *) ((char *) buf->payload + sizeof(struct eth_hdr) + sizeof(struct ip_hdr)); //l2_len + l3_len); + u_hdr->chksum = + get_ipv4_psd_sum(iphdr, mbuf->ol_flags); + } + } + + break; + + default: + + break; + } + } + mbuf->l2_len = sizeof(struct eth_hdr); //l2_len; + mbuf->l3_len = sizeof(struct ip_hdr); + mbuf->ol_flags = ol_flags; + } + } +} + +/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/ +err_t spl_hal_output(struct netif *pnetif, struct pbuf *buf) +{ + u16_t netif_id, idx; + struct common_mem_mbuf *mbuf; + struct spl_pbuf *spbuf = NULL; + //spl_pbuf_layer layer = SPL_PBUF_TRANSPORT; + //u16_t offset; + + if (!p_def_stack_instance) + { + NSPOL_LOGERR("p_def_stack_instance is NULL"); + return -1; + } + + u16_t proc_id = spl_get_lcore_id(); + + NSPOL_LOGINF(SC_DPDK_INFO, "spl_hal_output. len %d totlen %d", buf->len, + buf->tot_len); + print_pbuf_payload_info(buf, true); + + if (buf->tot_len > DEF_MBUF_DATA_SIZE) + { + NSPOL_LOGINF(TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + + } + spbuf = spl_pbuf_alloc_hugepage(SPL_PBUF_RAW, + buf->tot_len, + SPL_PBUF_HUGE, proc_id, NULL); + + if (!spbuf) + { + NSPOL_LOGINF(TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!"); + return ERR_MEM; + } + + if (ERR_OK != pbuf_to_splpbuf_copy(spbuf, buf)) + { + NSPOL_LOGERR("pbuf to splpbuf copy failed"); + return -1; + } + + mbuf = + (struct common_mem_mbuf *) ((char *) spbuf - + sizeof(struct common_mem_mbuf)); + + if (spbuf->tot_len > mbuf->pkt_len) + { + NSPOL_LOGWAR(SC_DPDK_INFO, + "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u", + spbuf->len, mbuf->pkt_len); + mbuf->pkt_len = spbuf->len; + } + + spl_hal_set_cksum(spbuf, mbuf); + + netif_id = pnetif->num; + idx = spl_hal_pkts[netif_id].tx.num++; + spl_hal_pkts[netif_id].tx.pkts[idx] = mbuf; + spl_do_dump(spbuf, DUMP_SEND); + spl_hal_send(pnetif); + + return 0; +} + +void spl_hal_input(struct netif *pnetif, struct spl_pbuf **buf) +{ + u16_t netif_id; + + struct common_mem_mbuf *mbuf; + + netif_id = pnetif->num; + + if (likely + (spl_hal_pkts[netif_id].rx.num > spl_hal_pkts[netif_id].rx.index)) + { + mbuf = + spl_hal_pkts[netif_id].rx.pkts[spl_hal_pkts[netif_id].rx.index]; + spl_hal_pkts[netif_id].rx.index++; + spl_hal_buf_convert(mbuf, buf); + spl_do_dump(*buf, DUMP_RECV); + } + else + { + NSPOL_LOGERR + ("recv from spl_dev has a problem]pnetif=%p, num=%u, index=%u", + pnetif, spl_hal_pkts[netif_id].rx.num, + spl_hal_pkts[netif_id].rx.index); + *buf = NULL; + } + return; +} + +int spl_hal_tx_ip_cksum_enable() +{ + return !spl_hal_capa.tx_ipv4_cksum_offload; +} + +int spl_hal_tx_udp_cksum_enable() +{ + return !spl_hal_capa.tx_udp_cksum_offload; +} + +int spl_hal_tx_tcp_cksum_enable() +{ + return !spl_hal_capa.tx_tcp_cksum_offload; +} + +u32 spl_hal_is_nic_exist(const char *name) +{ + return hal_is_nic_exist(name); +} + +int spl_hal_is_bond_netif(struct netif *pnetif) +{ + int i; + struct bond_set *s; + struct netifExt *pnetifExt = NULL; + + pnetifExt = getNetifExt(pnetif->num); + if (NULL == pnetifExt) + return 0; + + for (i = 0; i < bond_ports_array.cnt; i++) + { + s = &bond_ports_array.ports[i]; + if (!strncmp + (pnetifExt->if_name, s->bond_port_name, HAL_MAX_NIC_NAME_LEN)) + { + return 1; + } + } + + return 0; +} diff --git a/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c b/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c new file mode 100644 index 0000000..00ba785 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c @@ -0,0 +1,666 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_spl_share.h" +#include "nsfw_recycle_api.h" +#include "nstack_log.h" +#include "nsfw_msg_api.h" +#include "stackx_socket.h" +#include "stackx_spl_msg.h" +#include "stackx_app_res.h" +#include "common.h" +#include "sc_dpdk.h" +#include "nsfw_mt_config.h" +#include "spl_instance.h" + +#define SS_DELAY_CLOSE_SEC 5 + +extern struct stackx_port_zone *p_stackx_port_zone; + +/***************************************************************************** +* Prototype : sbr_recycle_rx_mbuf +* Description : iterator and free rx mbufs with pid flags, when the app + with certain pid is no longer exist +* Input : void *data +* void *arg +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int sbr_recycle_rx_mbuf(void *data, void *arg) +{ + u32 *recycle_flg; + pid_t *pid = (pid_t *) arg; + struct common_mem_mbuf *m_buf = (struct common_mem_mbuf *) data; +#ifdef HAL_LIB +#else + recycle_flg = + (u32 *) ((char *) (m_buf->buf_addr) + RTE_PKTMBUF_HEADROOM - + sizeof(u32)); +#endif + if (m_buf->refcnt > 0 && *recycle_flg == *pid) + { + NSSBR_LOGDBG("free rx mbuf hold by app], mbuf=%p", m_buf); + *recycle_flg = MBUF_UNUSED; + spl_mbuf_free(m_buf); + } + return 0; +} + +/***************************************************************************** +* Prototype : sbr_recycle_rx_pool +* Description : recycle rx mbufs hold by app when app crahes +* Input : pid_t pid +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int sbr_recycle_rx_pool(pid_t pid) +{ + static struct common_mem_mempool *rx_pool[MAX_VF_NUM * + 2][MAX_THREAD_NUM] = { {0} }; + struct common_mem_mempool *mp; + nsfw_mem_name lookup_mbuf_pool; + u32 nic_id, queue_id = 0; + int retval; + struct common_mem_ring *ring; + + for (nic_id = 0; + nic_id < p_stackx_port_zone->port_num && nic_id < MAX_VF_NUM * 2; + nic_id++) + { + mp = rx_pool[nic_id][queue_id]; + if (mp == NULL) + { + retval = + spl_snprintf(lookup_mbuf_pool.aname, NSFW_MEM_NAME_LENTH - 1, + "%s", get_mempoll_rx_name(queue_id, nic_id)); + if (-1 == retval) + { + NSPOL_LOGERR("spl_snprintf fail"); + break; + } + + lookup_mbuf_pool.entype = NSFW_SHMEM; + lookup_mbuf_pool.enowner = NSFW_PROC_MAIN; + mp = (struct common_mem_mempool *) + nsfw_mem_mbfmp_lookup(&lookup_mbuf_pool); + if (mp == NULL) + break; + rx_pool[nic_id][queue_id] = mp; + } + if (nsfw_mem_mbuf_iterator + (mp, 0, mp->size, sbr_recycle_rx_mbuf, (void *) &pid) < 0) + { + NSSBR_LOGERR("nsfw_mem_mbuf_iterator return fail"); + return -1; + } + ring = (struct common_mem_ring *) (mp->pool_data); + NSSBR_LOGINF + ("after recycling rx pbuf hold by app]ring=%p,prod.head=%u,prod.tail=%u," + "cons.head=%u,cons.tail=%u.", ring, ring->prod.head, + ring->prod.tail, ring->cons.head, ring->cons.tail); + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_recycle_rx_pool +* Description : recycle stackx tx mbufs hold by app when app crahes +* Input : pid_t pid +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int sbr_recycle_tx_pool(pid_t pid) +{ + struct common_mem_mempool *mp; + struct common_mem_ring *ring; + + /* Try to free all the RX mbufs which are holded in stackx TX pool */ + mp = (struct common_mem_mempool *) p_def_stack_instance->mp_tx; + if (mp == NULL) + return -1; + + if (nsfw_mem_mbuf_iterator + (mp, 0, mp->size, sbr_recycle_rx_mbuf, (void *) &pid) < 0) + { + NSSBR_LOGERR("nsfw_mem_mbuf_iterator return fail"); + return -1; + } + ring = (struct common_mem_ring *) (mp->pool_data); + NSSBR_LOGINF + ("after recycling stackx tx pbuf hold by app]ring=%p,prod.head=%u,prod.tail=%u," + "cons.head=%u,cons.tail=%u.", ring, ring->prod.head, ring->prod.tail, + ring->cons.head, ring->cons.tail); + + return 0; +} + +/***************************************************************************** +* Prototype : ss_free_del_conn_msg +* Description : free msg +* Input : msg_delete_netconn *dmsg +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void ss_free_del_conn_msg(msg_delete_netconn * dmsg) +{ + data_com_msg *msg = (data_com_msg *) ((char *) dmsg - MAX_MSG_PARAM_SIZE); + + if (MSG_ASYN_POST == msg->param.op_type) /* should check type for linger */ + { + msg_free(msg); + } +} + +extern int nsep_recyle_ep(u32 pid); + +/***************************************************************************** +* Prototype : ss_recycle_done +* Description : recycle done,need recycle ep and rx pool +* Input : pid_t pid +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void ss_recycle_done(pid_t pid) +{ + spl_free_tx_pool(pid); + spl_recycle_msg_pool(pid); + (void) sbr_recycle_rx_pool(pid); + (void) sbr_recycle_tx_pool(pid); + (void) nsep_recyle_ep(pid); + (void) nsfw_recycle_obj_end(pid); +} + +/***************************************************************************** +* Prototype : ss_notify_omc +* Description : try to notify omc +* Input : spl_netconn_t** conn_array +* u32 conn_num +* u8 notify_omc +* pid_t pid +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_notify_omc(spl_netconn_t ** conn_array, u32 conn_num, u8 notify_omc, + pid_t pid) +{ + if (notify_omc) + { + u32 i; + for (i = 0; i < conn_num; ++i) + { + struct spl_netconn *conn = conn_array[i]; + if (ss_is_pid_exist(conn, pid)) + { + NSSBR_LOGINF("there are still conn at work]pid=%d", pid); + break; + } + + msg_delete_netconn *delay_msg = conn->recycle.delay_msg; + if (delay_msg && (delay_msg->pid == pid)) + { + delay_msg->notify_omc = notify_omc; + NSSBR_LOGINF("there are still conn at delay]pid=%d", pid); + break; + } + } + + if (conn_num == i) + { + NSSBR_LOGINF("recycle done,notify omc]pid=%d", pid); + ss_recycle_done(pid); + } + } +} + +extern void do_pbuf_free(struct spl_pbuf *buf); + +static void ss_recycle_fd_share(sbr_fd_share * fd_share) +{ + /* to free pbufs which are attached to sbr_fd_share */ + if (fd_share->recoder.head) + { + struct spl_pbuf *buf = fd_share->recoder.head; + fd_share->recoder.head = NULL; + fd_share->recoder.tail = NULL; + fd_share->recoder.totalLen = 0; + do_pbuf_free(buf); + } +} + +extern void nsep_recycle_epfd(void *epinfo, u32 pid); +extern void tcp_free_accept_ring(spl_netconn_t * conn); +extern void free_conn_by_spl(spl_netconn_t * conn); +extern void tcp_drop_conn(spl_netconn_t * conn); + +/***************************************************************************** +* Prototype : ss_close_conn_now +* Description : close netconn now +* Input : spl_netconn_t *conn +* msg_delete_netconn *dmsg +* pid_t pid +* ss_close_conn_fun close_conn +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_close_conn_now(spl_netconn_t * conn, msg_delete_netconn * dmsg, pid_t pid, + ss_close_conn_fun close_conn) +{ + spl_netconn_t **conn_array = conn->recycle.group->conn_array; + u32 conn_num = conn->recycle.group->conn_num; + u8 notify_omc = dmsg->notify_omc; + + close_conn(dmsg, 0); + + nsep_recycle_epfd(conn->epInfo, pid); + conn->epInfo = NULL; /*must be set to NULL */ + + u32 i; + if (conn->recycle.is_listen_conn) + { + /* drop the conn inside the accept ring */ + tcp_free_accept_ring(conn); + + /* app coredump and accept_from not changed, need recyle */ + for (i = 0; i < conn_num; ++i) + { + struct spl_netconn *accept_conn = conn_array[i]; + if ((accept_conn->recycle.accept_from == conn) + && ss_is_pid_array_empty(accept_conn)) + { + NSSBR_LOGINF + ("recycle lost conn]listen_conn=%p,listen_private_data=%p,accept_conn=%p,accept_private_data=%p,pid=%d", + conn, conn->private_data, accept_conn, + accept_conn->private_data, pid); + data_com_msg *msg = + (data_com_msg *) ((char *) dmsg - MAX_MSG_PARAM_SIZE); + msg->param.receiver = ss_get_recv_obj(accept_conn); + dmsg->buf = NULL; + dmsg->time_started = sys_now(); + dmsg->shut = 0; + dmsg->conn = accept_conn; + close_conn(dmsg, 0); + + nsep_recycle_epfd(accept_conn->epInfo, pid); + accept_conn->epInfo = NULL; /*must be set to NULL */ + + /* lost conn need drop first, can't just free conn */ + tcp_drop_conn(accept_conn); + } + } + } + + if (SS_DELAY_STOPPED == conn->recycle.delay_flag) + { + sbr_fd_share *fd_share = + (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE); + ss_recycle_fd_share(fd_share); + free_conn_by_spl(conn); + } + + ss_free_del_conn_msg(dmsg); + ss_notify_omc(conn_array, conn_num, notify_omc, pid); +} + +/***************************************************************************** +* Prototype : ss_close_conn_delay +* Description : delay to close conn +* Input : spl_netconn_t *conn +* pid_t pid +* msg_delete_netconn *dmsg +* ss_close_conn_fun close_conn +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_close_conn_delay(spl_netconn_t * conn, pid_t pid, + msg_delete_netconn * dmsg, ss_close_conn_fun close_conn) +{ + NSSBR_LOGINF + ("ref > 0 and pid array is empty, start delay closing conn]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + close_conn(dmsg, SS_DELAY_CLOSE_SEC); +} + +/***************************************************************************** +* Prototype : ss_process_delay_up +* Description : delay is up +* Input : spl_netconn_t *conn +* pid_t pid +* msg_delete_netconn *dmsg +* ss_close_conn_fun close_conn +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void +ss_process_delay_up(spl_netconn_t * conn, pid_t pid, + msg_delete_netconn * dmsg, ss_close_conn_fun close_conn) +{ + spl_netconn_t **conn_array = conn->recycle.group->conn_array; + u32 conn_num = conn->recycle.group->conn_num; + u8 notify_omc = dmsg->notify_omc; + + if (SS_DELAY_STARTED == conn->recycle.delay_flag) + { + if (ss_is_pid_array_empty(conn)) + { + NSSBR_LOGINF + ("delay time is up,close conn now]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + conn->recycle.delay_flag = SS_DELAY_STOPPED; + conn->recycle.delay_msg = NULL; + ss_close_conn_now(conn, dmsg, pid, close_conn); + return; + } + else + { + NSSBR_LOGINF + ("stop delay closing conn,conn still working]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + conn->recycle.delay_flag = SS_DELAY_STOPPED; + conn->recycle.delay_msg = NULL; + ss_free_del_conn_msg(dmsg); + ss_notify_omc(conn_array, conn_num, notify_omc, pid); + return; + } + } + else if (SS_DELAY_AGAIN == conn->recycle.delay_flag) + { + if (ss_is_pid_array_empty(conn)) + { + NSSBR_LOGINF + ("delay time is up,but need delay again]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + conn->recycle.delay_flag = SS_DELAY_STARTED; + ss_close_conn_delay(conn, pid, dmsg, close_conn); + return; + } + else + { + NSSBR_LOGINF + ("stop delay closing conn,conn still working]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + conn->recycle.delay_flag = SS_DELAY_STOPPED; + conn->recycle.delay_msg = NULL; + ss_free_del_conn_msg(dmsg); + ss_notify_omc(conn_array, conn_num, notify_omc, pid); + return; + } + } + else if (SS_DELAY_STOPPING == conn->recycle.delay_flag) + { + NSSBR_LOGINF + ("the conn has been closed,free conn]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + conn->recycle.delay_flag = SS_DELAY_STOPPED; + conn->recycle.delay_msg = NULL; + free_conn_by_spl(conn); + ss_free_del_conn_msg(dmsg); + ss_notify_omc(conn_array, conn_num, notify_omc, pid); + return; + } + else + { + NSSBR_LOGERR("this can not happen]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + } +} + +/***************************************************************************** +* Prototype : ss_recycle_conn +* Description : recycle conn +* Input : void *close_data +* ss_close_conn_fun close_conn +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int ss_recycle_conn(void *close_data, ss_close_conn_fun close_conn) +{ + msg_delete_netconn *dmsg = (msg_delete_netconn *) close_data; + spl_netconn_t *conn = dmsg->conn; + pid_t pid = dmsg->pid; + u8 notify_omc = dmsg->notify_omc; + struct spl_netconn **conn_array = conn->recycle.group->conn_array; + u32 conn_num = conn->recycle.group->conn_num; + + int ret = ss_del_pid(conn, pid); + if (0 == ret) + { + i32 ref = ss_dec_fork_ref(conn); + if (0 == ref) + { + if (conn->recycle.delay_flag != SS_DELAY_STOPPED) + { + conn->recycle.delay_flag = SS_DELAY_STOPPING; + NSSBR_LOGINF + ("stop delay closing conn,close conn now]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + } + else + { + NSSBR_LOGINF("close conn now]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + } + + ss_close_conn_now(conn, dmsg, pid, close_conn); + return 0; + } + else + { + if (ss_is_pid_array_empty(conn)) + { + if (SS_DELAY_STOPPED == conn->recycle.delay_flag) /* only start one delay */ + { + conn->recycle.delay_flag = SS_DELAY_STARTED; + conn->recycle.delay_msg = close_data; + ss_close_conn_delay(conn, pid, dmsg, close_conn); + return 0; + } + else if (SS_DELAY_STARTED == conn->recycle.delay_flag) + { + conn->recycle.delay_flag = SS_DELAY_AGAIN; + NSSBR_LOGINF + ("ref > 0 and pid array is empty, delay again]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + } + } + } + } + else + { + if (conn->recycle.delay_msg && (conn->recycle.delay_msg == close_data)) /* only the stater can process */ + { + ss_process_delay_up(conn, pid, dmsg, close_conn); + return 0; + } + } + + NSSBR_LOGINF("go to notify omc]conn=%p,pid=%d,private_data=%p", conn, pid, + conn->private_data); + ss_free_del_conn_msg(dmsg); + ss_notify_omc(conn_array, conn_num, notify_omc, pid); + return 0; +} + +/***************************************************************************** +* Prototype : sbr_handle_recycle_conn +* Description : post msg to spl +* Input : spl_netconn_t* conn +* pid_t pid +* u8 notify_omc +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_handle_recycle_conn(spl_netconn_t * conn, pid_t pid, u8 notify_omc) +{ + data_com_msg *m = msg_malloc(ss_get_msg_pool(conn)); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]conn=%p,pid=%d,private_data=%p", conn, + pid, conn->private_data); + return -1; + } + + NSSBR_LOGINF("recycle conn]conn=%p,pid=%d,private_data=%p", conn, pid, + conn->private_data); + + m->param.module_type = MSG_MODULE_SBR; + m->param.major_type = SPL_TCPIP_NEW_MSG_API; + m->param.minor_type = SPL_API_DO_DELCON; + m->param.err = 0; + m->param.op_type = MSG_ASYN_POST; + sys_sem_init(&m->param.op_completed); + m->param.receiver = ss_get_recv_obj(conn); + m->param.extend_member_bit = 0; + + msg_delete_netconn *p = (msg_delete_netconn *) m->buffer; + p->extend_member_bit = 0; + p->time_started = sys_now(); + p->shut = 0; + p->pid = pid; + p->conn = conn; + p->notify_omc = notify_omc; + p->msg_box_ref = SPL_MSG_BOX_NUM; + p->buf = NULL; + + /* to ensure that the last deal with SPL_API_DO_DELCON message */ + int i; + for (i = 0; i < SPL_MSG_BOX_NUM; ++i) + { + if (msg_post_with_lock_rel + (m, + ss_get_instance_msg_box(ss_get_bind_thread_index(conn), i)) < 0) + { + msg_free(m); + NSSBR_LOGERR("post msg failed]conn=%p,pid=%d,private_data=%p", + conn, pid, conn->private_data); + return -1; + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_recycle_fd_share +* Description : recycle sbr_fd_share +* Input : sbr_fd_share* fd_share +* pid_t pid +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_recycle_fd_share(sbr_fd_share * fd_share, pid_t pid) +{ + if (fd_share->common_lock.locked == pid) + { + common_spinlock_unlock(&fd_share->common_lock); + } + + if (fd_share->recv_lock.locked == pid) + { + common_spinlock_unlock(&fd_share->recv_lock); + } +} + +/***************************************************************************** +* Prototype : sbr_recycle_conn +* Description : recycle api,called by recycle module +* Input : u32 exit_pid +* void *pdata +* u16 rec_type +* Output : None +* Return Value : nsfw_rcc_stat +* Calls : +* Called By : +* +*****************************************************************************/ +nsfw_rcc_stat sbr_recycle_conn(u32 exit_pid, void *pdata, u16 rec_type) +{ + NSSBR_LOGINF("start recycle]pid=%d", exit_pid); + + if (0 == exit_pid) + { + NSSBR_LOGERR("pid is not ok]pid=%d", exit_pid); + return NSFW_RCC_CONTINUE; + } + + spl_netconn_t **conn_array = spl_get_conn_array(exit_pid); + if (!conn_array) + { + NSSBR_LOGERR("conn_array is NULL]pid=%d", exit_pid); + return NSFW_RCC_CONTINUE; + } + + u32 num = spl_get_conn_num(); + spl_netconn_t *conn; + sbr_fd_share *fd_share; + u32 i; + for (i = 0; i < num; ++i) + { + conn = conn_array[i]; + if (ss_is_pid_exist(conn, exit_pid)) + { + fd_share = (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE); + sbr_recycle_fd_share(fd_share, exit_pid); + sbr_handle_recycle_conn(conn, exit_pid, FALSE); + } + } + + sbr_handle_recycle_conn(conn_array[0], exit_pid, TRUE); + return NSFW_RCC_SUSPEND; +} + +REGIST_RECYCLE_OBJ_FUN(NSFW_REC_SBR_SOCKET, sbr_recycle_conn) diff --git a/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt new file mode 100644 index 0000000..8516ef3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt @@ -0,0 +1,75 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIE -pie -fPIC -m64 -mssse3 -std=gnu89") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium") + +SET(ADAPT_DIRECTORIES "${PROJECT_SOURCE_DIR}/src/adapt/") +#SET(DMM_API "${PROJECT_SOURCE_DIR}/src/nSocket/include/") + +ADD_DEFINITIONS(-D_GNU_SOURCE -D_FORTIFY_SOURCE=2) +ADD_DEFINITIONS(-DDPDK_MODULE=0) +if(WITH_HAL_LIB) +SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/include/rtp_config.h) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") + SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/src/mem/include/common_sys_config.h) + INCLUDE_DIRECTORIES( + ${PAL_H_DIRECTORIES} + ${ADAPT_DIRECTORIES} +# ${DMM_API} + ) +endif() +SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/compile_config.h) +#SET(MGR_COM ${PROJECT_SOURCE_DIR}/src/framework/ipc/mgr_com/mgr_com.h) +SET(MGR_COM ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/ipc/mgr_com/mgr_com.h) +ADD_DEFINITIONS(-include ${RTP_CONFIG}) +ADD_DEFINITIONS(-include ${COMPLE_CONFIG}) +ADD_DEFINITIONS(-include ${MGR_COM}) +if(WITH_SECUREC_LIB) +LINK_LIBRARIES(pthread rt securec) +else() +LINK_LIBRARIES(pthread rt) +endif() +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/json/json-c-0.12.1/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/glog/glog-0.3.5/src/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ +# ${ADAPT_DIRECTORIES} +# ${DMM_API} +) + +FILE(GLOB COMMON ../common/*.c) +FILE(GLOB SOCKET ./*.c) +ADD_LIBRARY(socket STATIC ${COMMON} ${SOCKET}) +ADD_DEPENDENCIES(socket JSON GLOG DPDK) +TARGET_INCLUDE_DIRECTORIES( + socket + PRIVATE + ../common/ + ./ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../src/mem/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../src/mem/nsfw_shmem/ + ${CMAKE_CURRENT_LIST_DIR}/../../src/sbr/ +) diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h new file mode 100644 index 0000000..e6d100d --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h @@ -0,0 +1,54 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_CONTAINER_CFG_H +#define STACKX_CONTAINER_CFG_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SBR_MAX_CFG_PATH_LEN 256 +#define SBR_MAX_CONTAINER_IP_NUM 1024 +#define SBR_MAX_CFG_FILE_SIZE (1 * 1024 * 1024) + +typedef struct +{ + u32 ip; + u32 mask_len; +} sbr_container_ip; + +typedef struct +{ + sbr_container_ip ip_array[SBR_MAX_CONTAINER_IP_NUM]; + u32 ip_num; +} sbr_container_ip_group; + +extern sbr_container_ip_group g_container_ip_group; + +int sbr_init_cfg(); +int sbr_get_src_ip(u32 dst_ip, u32 * src_ip); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c new file mode 100644 index 0000000..8c6ab46 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c @@ -0,0 +1,329 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include "stackx_cfg.h" +#include "json.h" +#include "nstack_log.h" +#include "spl_def.h" +#include "nstack_securec.h" +#include "stackx_ip_addr.h" + +sbr_container_ip_group g_container_ip_group; + +/***************************************************************************** +* Prototype : sbr_parse_container_ip_json +* Description : parse port json +* Input : char* param +* Output : None +* Return Value : static void +* Calls : +* Called By : +* +*****************************************************************************/ +static void sbr_parse_container_ip_json(char *param) +{ + int retval; + struct json_object *obj = json_tokener_parse(param); + struct json_object *container_id_obj = NULL; + struct json_object *ports_list_obj = NULL; + struct json_object *ip_cidr_list_obj = NULL; + + if (!obj) + { + NSSBR_LOGERR("json_tokener_parse failed"); + return; + } + + json_object_object_get_ex(obj, "containerID", &container_id_obj); + if (!container_id_obj) + { + NSSBR_LOGERR("can't get containerID"); + goto RETURN_ERROR; + } + + json_object_object_get_ex(obj, "ports_list", &ports_list_obj); + if (ports_list_obj) + { + int i; + int port_num = json_object_array_length(ports_list_obj); + + if (0 == port_num) + { + NSSBR_LOGERR("port num is 0"); + goto RETURN_ERROR; + } + + for (i = 0; i < port_num; i++) + { + struct json_object *port_obj = + json_object_array_get_idx(ports_list_obj, i); + json_object_object_get_ex(port_obj, "ip_cidr", &ip_cidr_list_obj); + if (ip_cidr_list_obj) + { + int j; + int ip_cidr_num = json_object_array_length(ip_cidr_list_obj); + for (j = 0; j < ip_cidr_num; ++j) + { + struct json_object *ip_cidr_obj = + json_object_array_get_idx(ip_cidr_list_obj, j); + if (ip_cidr_obj) + { + char tmp[32] = { 0 }; + const char *ip_cidr = + json_object_get_string(ip_cidr_obj); + if ((NULL == ip_cidr) || (ip_cidr[0] == 0)) + { + NSSBR_LOGERR("ip is empty"); + goto RETURN_ERROR; + } + + const char *sub = strstr(ip_cidr, "/"); + if ((NULL == sub) + || (sizeof(tmp) - 1 < + (unsigned int) (sub - ip_cidr)) + || (strlen(sub) > sizeof(tmp) - 1)) + { + NSSBR_LOGERR("ip format is not ok"); + goto RETURN_ERROR; + } + + retval = + strncpy_s(tmp, sizeof(tmp), ip_cidr, + (size_t) (sub - ip_cidr)); + if (EOK != retval) + { + NSSBR_LOGERR("STRNCPY_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + + struct in_addr addr; + retval = + memset_s(&addr, sizeof(addr), 0, sizeof(addr)); + if (EOK != retval) + { + NSSBR_LOGERR("MEMSET_S failed]ret=%d", retval); + goto RETURN_ERROR; + } + + retval = spl_inet_aton(tmp, &addr); + if (0 == retval) + { + NSSBR_LOGERR("spl_inet_aton failed]ret=%d", + retval); + goto RETURN_ERROR; + } + + g_container_ip_group. + ip_array[g_container_ip_group.ip_num].ip = + addr.s_addr; + int mask_len = atoi(sub + 1); + if ((mask_len <= 0) || (mask_len > 32)) + { + NSSBR_LOGERR("mask len is not ok"); + goto RETURN_ERROR; + } + + g_container_ip_group. + ip_array[g_container_ip_group.ip_num].mask_len = + (u32) mask_len; + g_container_ip_group.ip_num++; + + if (g_container_ip_group.ip_num >= + SBR_MAX_CONTAINER_IP_NUM) + { + NSSBR_LOGWAR("container ip num is full]ip_num=%u", + g_container_ip_group.ip_num); + goto RETURN_OK; + } + } + } + } + } + } + else + { + NSSBR_LOGERR("can't get ports_list"); + goto RETURN_ERROR; + } + + RETURN_OK: + json_object_put(obj); + NSSBR_LOGINF("container ip num is %u", g_container_ip_group.ip_num); + u32 idx; + for (idx = 0; idx < g_container_ip_group.ip_num; ++idx) + { + NSSBR_LOGDBG("container ip=0x%08x", + g_container_ip_group.ip_array[idx].ip); + } + return; + + RETURN_ERROR: + json_object_put(obj); + if (memset_s + (&g_container_ip_group, sizeof(sbr_container_ip_group), 0, + sizeof(sbr_container_ip_group)) != EOK) + { + NSSBR_LOGERR("MEMSET_S failed"); + } +} + +/***************************************************************************** +* Prototype : sbr_get_cfg_path +* Description : get cfg path +* Input : None +* Output : None +* Return Value : NSTACK_STATIC const char* +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC const char *sbr_get_cfg_path() +{ + static char cfg_file[SBR_MAX_CFG_PATH_LEN] = + "/canal/output/portinfo.json"; + return cfg_file; +} + +/***************************************************************************** +* Prototype : sbr_init_cfg +* Description : init cfg from file +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_init_cfg() +{ + int ret; + off_t file_len = 0; + off_t buff_len = 0; + char *buff = NULL; + const char *cfg_file = sbr_get_cfg_path(); /* no need check ret */ + + int fp = open(cfg_file, O_RDONLY); + + if (fp < 0) + { + NSSBR_LOGWAR("failed to open file]file name=%s", cfg_file); + goto RETURN_ERROR; + } + + file_len = lseek(fp, 0, SEEK_END); + if (file_len <= 0) + { + NSSBR_LOGWAR("failed to get file len]file name=%s", cfg_file); + goto RETURN_ERROR; + } + + if (file_len > SBR_MAX_CFG_FILE_SIZE) + { + NSSBR_LOGWAR + ("file len is too big]file len=%d, max len=%d, file name=%s", + file_len, SBR_MAX_CFG_FILE_SIZE, cfg_file); + goto RETURN_ERROR; + } + + ret = lseek(fp, 0, SEEK_SET); + if (ret < 0) + { + NSSBR_LOGWAR("seek to start failed]file name=%s", cfg_file); + goto RETURN_ERROR; + } + + buff_len = file_len + 1; + buff = (char *) malloc(buff_len); + if (!buff) + { + NSSBR_LOGWAR("malloc buff failed]buff_len=%d", buff_len); + goto RETURN_ERROR; + } + + ret = memset_s(buff, buff_len, 0, buff_len); + if (EOK != ret) + { + NSSBR_LOGWAR("MEMSET_S failed]ret=%d.", ret); + goto RETURN_ERROR; + } + + ret = read(fp, buff, buff_len - 1); + if (ret <= 0) + { + NSSBR_LOGWAR("read failed]ret=%d", ret); + goto RETURN_ERROR; + } + + sbr_parse_container_ip_json(buff); + close(fp); + free(buff); + return 0; + + RETURN_ERROR: + if (fp >= 0) + { + close(fp); + } + + if (buff) + { + free(buff); + } + + return -1; +} + +/***************************************************************************** +* Prototype : sbr_get_src_ip +* Description : get src ip from cfg +* Input : u32 dst_ip +* u32* src_ip +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_get_src_ip(u32 dst_ip, u32 * src_ip) +{ + if (!src_ip) + { + NSSBR_LOGERR("src_ip is NULL"); + return -1; + } + + u32 i; + for (i = 0; i < g_container_ip_group.ip_num; ++i) + { + unsigned int mask = ~0; + mask = (mask << (32 - g_container_ip_group.ip_array[i].mask_len)); + mask = htonl(mask); + if ((dst_ip & mask) == (g_container_ip_group.ip_array[i].ip & mask)) + { + *src_ip = g_container_ip_group.ip_array[i].ip; + NSSBR_LOGDBG("find src ip]container_ip=0x%08x,dest_ip=0x%08x", + *src_ip, dst_ip); + return 0; + } + } + + NSSBR_LOGDBG("can't find src ip]dest_ip=0x%08x", dst_ip); + return -1; +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c new file mode 100644 index 0000000..da62381 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c @@ -0,0 +1,143 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_epoll_api.h" +#include "stackx_spl_share.h" +#include "common_pal_bitwide_adjust.h" +#include "nstack_dmm_adpt.h" +#include "nstack_epoll_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* _cplusplus */ + +void epoll_triggle_event_from_api(sbr_socket_t * sock, int op) +{ + struct spl_netconn *conn = sbr_get_conn(sock); + void *epInfo = ADDR_SHTOL(conn->epInfo); + //NSPOL_LOGDBG(SOCKETS_DEBUG, "enter]fd=%d,op=%d", sock, op); + switch (op) + { + case EPOLL_API_OP_RECV: + break; + case EPOLL_API_OP_SEND: + if (conn->epoll_flag && epInfo) + { + NSTACK_EPOLL_EVENT_ADD(epInfo, EPOLLOUT, EVENT_INFORM_APP); + } + break; + case EPOLL_API_OP_STACK_RECV: + if (conn->epoll_flag && epInfo) + { + NSTACK_EPOLL_EVENT_ADD(epInfo, EPOLLIN, EVENT_INFORM_APP); + } + break; + default: + break; + } + return; +} + +/* + * This function will be registed to application + * The context will be in the application + */ +void *stackx_eventpoll_triggle(sbr_socket_t * sock, int triggle_ops, + void *pdata, void *event) +{ + struct spl_netconn *conn = sbr_get_conn(sock); + unsigned int events = 0; + if (!conn) + { + NSPOL_LOGINF(SOCKETS_DEBUG, "get socket failed]fd=%d", sock->fd); + return NULL; + } + + NSPOL_LOGINF(SOCKETS_DEBUG, + "]fd=%d,triggle_ops=%d conn=%p pdata=%p", sock->fd, + triggle_ops, conn, pdata); + /* + * sock->epoll_flag must be set before sock->rcvevent check. + * Consider this Scenario : 1) network stack has got one packet, but event_callback not called yet + * 2) Do epoll ctl add, then stackx triggle will check event, it will get 0 + * 3) network stack call event_callback , it will check epoll_flag + * So, if epoll_flag not set before sock->rcvent check, neither of network stack and stackx triggle + * will add this event to epoll. because : for network stack, event_callback check epoll_flag fail + * for stackx triggle, event check fail. + */ + if (nstack_ep_triggle_add == triggle_ops) + { + /*log info */ + conn->epInfo = pdata; + __sync_fetch_and_add(&conn->epoll_flag, 1); + } + + if ((!((conn->rcvevent == 0) && (sbr_get_fd_share(sock)->lastdata == 0) + && (sbr_get_fd_share(sock)->lastoffset == 0)))) + events |= EPOLLIN; + if (conn->sendevent) + events |= EPOLLOUT; + if (conn->errevent) + events |= conn->errevent; + + switch (triggle_ops) + { + case nstack_ep_triggle_add: + case nstack_ep_triggle_mod: + *(int *) event = events; + break; + case nstack_ep_triggle_del: + if (conn->epoll_flag > 0) + { + __sync_fetch_and_sub(&conn->epoll_flag, 1); + } + events = 0; + break; + default: + return NULL; + } + return conn; +} + +/* + * This function will be registed to application + * The context will be in the application + * RETURN VALUE : Event exists in current protocol + */ +int stackx_eventpoll_getEvt(sbr_socket_t * sock) +{ + struct spl_netconn *conn = sbr_get_conn(sock); + int tevent = 0; + if (!((conn->rcvevent == 0) && (sbr_get_fd_share(sock)->lastdata == 0) + && (sbr_get_fd_share(sock)->lastoffset == 0))) + { + tevent |= EPOLLIN; + } + + if (conn->sendevent) + { + tevent |= EPOLLOUT; + } + return tevent; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* _cplusplus */ diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h new file mode 100644 index 0000000..9bbd695 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h @@ -0,0 +1,46 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_EPOLL_API_H +#define STACKX_EPOLL_API_H +#include "stackx_socket.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef enum +{ + EPOLL_API_OP_RECV, + EPOLL_API_OP_SEND, + EPOLL_API_OP_STACK_RECV +} EPOLL_TRIGGLE_EVENT_API_OPS_T; + +extern void epoll_triggle_event_from_api(sbr_socket_t * sock, int op); +extern int stackx_eventpoll_getEvt(sbr_socket_t * sock); +extern void *stackx_eventpoll_triggle(sbr_socket_t * sock, + int triggle_ops, + void *pdata, void *event); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.c b/stacks/lwip_stack/lwip_src/socket/stackx_event.c new file mode 100644 index 0000000..3b3eb00 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.c @@ -0,0 +1,175 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_spl_share.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_event.h" + +#define FREE_FD_SET(readfd, writefd, exceptfd) {\ +if(readfd)\ +free(readfd);\ +if(writefd)\ +free(writefd);\ +if(exceptfd)\ +free(exceptfd);\ +} + +#define FREE_SELECT_BITS(read_set, write_set, err_set)\ +{\ + if((read_set)->fds_bits)\ + free((read_set)->fds_bits);\ + if((write_set)->fds_bits)\ + free((write_set)->fds_bits);\ + if((err_set)->fds_bits)\ + free((err_set)->fds_bits);\ +} + +NSTACK_STATIC inline int sbr_fd_copy(nstack_fd_set * psrc, + nstack_fd_set * pdst, u32 size) +{ + return memcpy_s(pdst->fds_bits, size, psrc->fds_bits, size); +} + +int +lwip_try_select(int fdsize, fd_set * fdread, fd_set * fdwrite, + fd_set * fderr, struct timeval *timeout) +{ + int i; + int nready = 0; + nstack_fd_set *read_out; + nstack_fd_set *write_out; + nstack_fd_set *err_out; + nstack_fd_set *readfd = (nstack_fd_set *) fdread; + nstack_fd_set *writefd = (nstack_fd_set *) fdwrite; + nstack_fd_set *exceptfd = (nstack_fd_set *) fderr; + sbr_socket_t *sock; + spl_netconn_t *conn; + + if ((fdsize >= NSTACK_SETSIZE) || (fdsize < 0)) + { + return 0; + } + read_out = malloc(sizeof(nstack_fd_set)); + write_out = malloc(sizeof(nstack_fd_set)); + err_out = malloc(sizeof(nstack_fd_set)); + if ((!read_out) || (!write_out) || (!err_out)) + { + NSPOL_LOGERR("malloc nstack_fd_set fail"); + FREE_FD_SET(read_out, write_out, err_out); + return -1; + } + + u32 fd_set_size = sizeof(unsigned char) * ((SBR_MAX_FD_NUM + 7) / 8); + read_out->fds_bits = (unsigned char *) malloc(fd_set_size); + write_out->fds_bits = (unsigned char *) malloc(fd_set_size); + err_out->fds_bits = (unsigned char *) malloc(fd_set_size); + if ((!read_out->fds_bits) || (!write_out->fds_bits) + || (!err_out->fds_bits)) + { + NSPOL_LOGERR("malloc nstack_fd_set fd_bits fail"); + nready = -1; + goto return_over; + } + + int ret = NSTACK_FD_ZERO(read_out, fd_set_size); + int ret1 = NSTACK_FD_ZERO(write_out, fd_set_size); + int ret2 = NSTACK_FD_ZERO(err_out, fd_set_size); + + if ((EOK != ret) || (EOK != ret1) || (EOK != ret2)) + { + NSPOL_LOGERR("NSTACK_FD_ZERO fail"); + nready = -1; + goto return_over; + } + + for (i = 0; i < fdsize; i++) + { + if (!((readfd && NSTACK_FD_ISSET(i, readfd)) + || (writefd && NSTACK_FD_ISSET(i, writefd)) + || (exceptfd && NSTACK_FD_ISSET(i, exceptfd)))) + { + continue; + } + sock = sbr_lookup_sk(i); + if (sock == NULL) + { + errno = EBADF; + nready = -1; + goto return_over; + } + conn = sbr_get_conn(sock); + if (!conn) + { + errno = EBADF; + nready = -1; + goto return_over; + } + if (readfd && NSTACK_FD_ISSET(i, readfd) && + ((sbr_get_fd_share(sock)->lastdata != NULL) + || (conn->rcvevent > 0))) + { + NSTACK_FD_SET(i, read_out); + nready++; + } + if (writefd && NSTACK_FD_ISSET(i, writefd) && (conn->sendevent != 0)) + { + NSTACK_FD_SET(i, write_out); + nready++; + } + if (exceptfd && NSTACK_FD_ISSET(i, exceptfd) && (conn->errevent != 0)) + { + NSTACK_FD_SET(i, write_out); + nready++; + } + } + + //TODO: need to handle fd_set and nstack_fd_set memory issue + if (readfd) + { + if (EOK != sbr_fd_copy(read_out, readfd, fd_set_size)) + { + NSPOL_LOGERR("NSTACK_FD_COPY fail"); + nready = -1; + goto return_over; + } + } + + if (writefd) + { + if (EOK != sbr_fd_copy(write_out, writefd, fd_set_size)) + { + NSPOL_LOGERR("NSTACK_FD_COPY fail"); + nready = -1; + goto return_over; + } + } + + if (exceptfd) + { + if (EOK != sbr_fd_copy(err_out, exceptfd, fd_set_size)) + { + NSPOL_LOGERR("NSTACK_FD_COPY fail"); + nready = -1; + goto return_over; + } + } + + return_over: + + FREE_SELECT_BITS(read_out, write_out, err_out); + FREE_FD_SET(read_out, write_out, err_out); + return nready; +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.h b/stacks/lwip_stack/lwip_src/socket/stackx_event.h new file mode 100644 index 0000000..6335fc2 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.h @@ -0,0 +1,46 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __STACKX_EVENT_H__ +#define __STACKX_EVENT_H__ + +#include +#include +#include +#include +#include "stackx_socket.h" +#include "nstack_securec.h" +#include "sbr_res_mgr.h" +#include "sbr_index_ring.h" +#define NSTACK_SETSIZE SBR_MAX_FD_NUM + +typedef struct +{ + unsigned char *fds_bits; //(NSTACK_SETSIZE + 7) / 8 +} __attribute__ ((packed)) nstack_fd_set; + +#define NSTACK_FD_SET(n, p) ((p)->fds_bits[(n)/8]|=1U<<((n)&0x07)) +#define NSTACK_FD_ISSET(n,p) (((p)->fds_bits[(n)/8]&(1U<<((n)&0x07)))?1:0) +#define NSTACK_FD_CLR(n,p) ((p)->fds_bits[(n)/8]&=~(1U<<((n)&0x07))) +#define NSTACK_FD_ZERO(p, mem_size) (memset_s((void *)(p->fds_bits), mem_size,0,mem_size)) +#define NSTACK_FD_OR(p1 ,p2) {\ + int i;\ + for(i = 0; i < (NSTACK_SETSIZE+7)/8; i++){\ + (p1)->fds_bits[i] |= (p2)->fds_bits[i];\ + }\ +} + +#endif /* __STACKX_EVENT_H__ */ diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_macro.h b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h new file mode 100644 index 0000000..96a0b91 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h @@ -0,0 +1,24 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_MACRO_H +#define STACKX_MACRO_H + +#ifndef SBR_USE_LOCK +#define SBR_USE_LOCK +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c new file mode 100644 index 0000000..38cf620 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c @@ -0,0 +1,766 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_msg_handler.h" +#include "stackx_spl_share.h" +#include "stackx_spl_msg.h" +#include "nsfw_msg_api.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_res_mgr.h" +#include "stackx_prot_com.h" +#include "nstack_securec.h" +//#include "stackx_dfx_api.h" + +#define SBR_MSG_MALLOC(sk) msg_malloc(ss_get_msg_pool(sbr_get_conn(sk))) +#define SBR_MSG_FREE(msg) msg_free(msg) + +#define SBR_MSG_POST(msg, ring) \ + do { \ + if (MSG_ASYN_POST == msg->param.op_type)\ + {\ + if (msg_post(msg, ring) < 0)\ + {\ + SBR_MSG_FREE(msg); \ + NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \ + msg->param.major_type, msg->param.minor_type, msg->param.op_type); \ + }\ + } \ + else \ + {\ + if (msg_post(msg, ring) < 0)\ + {\ + msg->param.err = ECONNABORTED; \ + NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \ + msg->param.major_type, msg->param.minor_type, msg->param.op_type); \ + }\ + } \ + } while (0) + +#define SBR_MSG_POST_RET(msg, ring, ret) \ + do { \ + if (MSG_ASYN_POST == msg->param.op_type)\ + {\ + if ((ret = msg_post(msg, ring)) < 0)\ + {\ + SBR_MSG_FREE(msg); \ + NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \ + msg->param.major_type, msg->param.minor_type, msg->param.op_type); \ + }\ + } \ + else \ + {\ + if ((ret = msg_post(msg, ring)) < 0)\ + {\ + msg->param.err = ECONNABORTED; \ + NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \ + msg->param.major_type, msg->param.minor_type, msg->param.op_type); \ + }\ + } \ + } while (0) + +NSTACK_STATIC inline void +_sbr_construct_msg(data_com_msg * m, u16 major_type, u16 minor_type, + u16 type, sbr_socket_t * sk) +{ + m->param.module_type = MSG_MODULE_SBR; + m->param.major_type = major_type; + m->param.minor_type = minor_type; + m->param.err = 0; + m->param.op_type = type; + sys_sem_init(&m->param.op_completed); + m->param.receiver = ss_get_recv_obj(sbr_get_conn(sk)); + m->param.comm_receiver = ss_get_comm_private_data(sbr_get_conn(sk)); + m->param.extend_member_bit = 0; +} + +#define sbr_construct_msg(m, major_type, minor_type, type, sk) { \ + _sbr_construct_msg(m, major_type, minor_type, type, sk); \ + NSSBR_LOGINF("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \ + } + +#define sbr_construct_msg_dbg(m, major_type, minor_type, type, sk) { \ + _sbr_construct_msg(m, major_type, minor_type, type, sk); \ + NSSBR_LOGDBG("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \ + } + +/***************************************************************************** +* Prototype : sbr_attach_msg +* Description : use buf's msg first +* Input : sbr_socket_t * sk +* struct pbuf* buf +* Output : None +* Return Value : static inline data_com_msg* +* Calls : +* Called By : +* +*****************************************************************************/ +static inline data_com_msg *sbr_attach_msg(sbr_socket_t * sk, + struct spl_pbuf *buf) +{ + data_com_msg *m = NULL; + if (!sk) + { + return m; + } + + if (buf && buf->msg) + { + m = (data_com_msg *) ADDR_SHTOL(buf->msg); + } + else + { + m = SBR_MSG_MALLOC(sk); + } + + return m; +} + +/***************************************************************************** +* Prototype : sbr_handle_socket +* Description : create socket +* Input : sbr_socket_t * sk +* netconn_type_t type +* u8 proto +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_handle_socket(sbr_socket_t * sk, spl_netconn_type_t type, u8 proto) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_NEWCONN, + MSG_SYN_POST, sk); + msg_new_netconn *p = (msg_new_netconn *) m->buffer; + p->conn = (spl_netconn_t *) ADDR_LTOSH(sbr_get_conn(sk)); + p->type = type; + p->proto = proto; + p->socket = sk->fd; + p->extend_member_bit = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + int err = sbr_spl_err_to_errno(m->param.err); + SBR_MSG_FREE(m); + if (err != 0) + { + NSSBR_LOGERR("handle socket failed]fd=%d,type=%d,proto=%u,err=%d", + sk->fd, type, proto, err); + sbr_set_sk_errno(sk, err); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_handle_bind +* Description : bind +* Input : sbr_socket_t * sk +* spl_ip_addr_t * addr +* u16 port +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_handle_bind(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_BIND, MSG_SYN_POST, + sk); + msg_bind *p = (msg_bind *) m->buffer; + p->ipaddr = *addr; + p->port = port; + p->extend_member_bit = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + int err = sbr_spl_err_to_errno(m->param.err); + SBR_MSG_FREE(m); + if (err != 0) + { + NSSBR_LOGERR("handle bind failed]fd=%d,err=%d", sk->fd, err); + sbr_set_sk_errno(sk, err); + return -1; + } + + return 0; +} + +int sbr_handle_listen(sbr_socket_t * sk, int backlog) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_LISTEN, + MSG_SYN_POST, sk); + msg_listen *p = (msg_listen *) m->buffer; + p->conn_pool = sbr_get_conn_pool(); + p->backlog = backlog; + p->extend_member_bit = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + int err = sbr_spl_err_to_errno(m->param.err); + SBR_MSG_FREE(m); + if (err != 0) + { + NSSBR_LOGERR("handle listen failed]fd=%d,err=%d", sk->fd, err); + sbr_set_sk_errno(sk, err); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_handle_connect +* Description : connect +* Input : sbr_socket_t * sk +* spl_ip_addr_t * addr +* u16 port +* spl_ip_addr_t* local_ip +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_handle_connect(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port, + spl_ip_addr_t * local_ip) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CONNECT, + MSG_SYN_POST, sk); + msg_connect *p = (msg_connect *) m->buffer; + p->local_ip = *local_ip; + p->ipaddr = *addr; + p->port = port; + p->extend_member_bit = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + int err = sbr_spl_err_to_errno(m->param.err); + SBR_MSG_FREE(m); + if (err != 0) + { + NSSBR_LOGERR("handle connect failed]fd=%d,err=%d", sk->fd, err); + sbr_set_sk_errno(sk, err); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_handle_get_name +* Description : get name +* Input : sbr_socket_t * sk +* struct sockaddr * name +* socklen_t * namelen +* u8 cmd +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_handle_get_name(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen, u8 cmd) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GETSOCK_NAME, + MSG_SYN_POST, sk); + msg_getaddrname *p = (msg_getaddrname *) m->buffer; + p->cmd = cmd; + p->extend_member_bit = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + int err = sbr_spl_err_to_errno(m->param.err); + if (err != 0) + { + NSSBR_LOGERR("handle get name failed]fd=%d,err=%d", sk->fd, err); + goto error; + } + else + { + if (*namelen > sizeof(p->sock_addr)) + { + *namelen = sizeof(p->sock_addr); + } + + int ret = memcpy_s(name, *namelen, &p->sock_addr, *namelen); + if (0 != ret) + { + NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret); + err = EINVAL; + goto error; + } + + *namelen = sizeof(p->sock_addr); + } + + SBR_MSG_FREE(m); + return 0; + + error: + sbr_set_sk_errno(sk, err); + SBR_MSG_FREE(m); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_handle_setsockopt +* Description : msg box will changed in IP_TOS +* Input : sbr_socket_t * sk +* int level +* int optname +* const void *optval +* socklen_t optlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_handle_setsockopt(sbr_socket_t * sk, int level, int optname, + const void *optval, socklen_t optlen) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SET_SOCK_OPT, + MSG_SYN_POST, sk); + msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer; + p->extend_member_bit = 0; + p->level = level; + p->optname = optname; + p->msg_box = NULL; /* init the value to avoid unexpected consequences */ + + if (optlen > sizeof(p->optval)) + { + optlen = sizeof(p->optval); + } + + p->optlen = optlen; + int err; + int ret = memcpy_s(&p->optval, sizeof(p->optval), optval, optlen); + if (0 != ret) + { + NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret); + err = EINVAL; + goto error; + } + + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + err = sbr_spl_err_to_errno(m->param.err); + if (err != 0) + { + NSSBR_LOGERR("handle setsockopt failed]fd=%d,err=%d", sk->fd, err); + goto error; + } + + if (IPPROTO_IP == level && IP_TOS == optname && p->msg_box) + { + ss_set_msg_box(sbr_get_conn(sk), + (mring_handle) ADDR_SHTOL(p->msg_box)); + } + + SBR_MSG_FREE(m); + return 0; + + error: + sbr_set_sk_errno(sk, err); + SBR_MSG_FREE(m); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_handle_getsockopt +* Description : get sockopt +* Input : sbr_socket_t * sk +* int level +* int optname +* void *optval +* socklen_t* optlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_handle_getsockopt(sbr_socket_t * sk, int level, int optname, + void *optval, socklen_t * optlen) +{ + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GET_SOCK_OPT, + MSG_SYN_POST, sk); + msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer; + p->extend_member_bit = 0; + p->level = level; + p->optname = optname; + + if (*optlen > sizeof(p->optval)) + { + *optlen = sizeof(p->optval); + } + + p->optlen = *optlen; + int err; + int ret = memcpy_s(&p->optval, sizeof(p->optval), optval, *optlen); + if (0 != ret) + { + NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret); + err = EINVAL; + goto error; + } + + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + + err = sbr_spl_err_to_errno(m->param.err); + if (err != 0) + { + NSSBR_LOGERR("handle getsockopt failed]fd=%d,err=%d", sk->fd, err); + goto error; + } + + ret = memcpy_s(optval, *optlen, &p->optval.int_optval, *optlen); + if (0 != ret) + { + NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret); + err = EINVAL; + goto error; + } + + SBR_MSG_FREE(m); + return 0; + + error: + sbr_set_sk_errno(sk, err); + SBR_MSG_FREE(m); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_handle_close +* Description : need care msg_box_ref,make sure to finalize this message +* Input : sbr_socket_t * sk +* u8 how +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_handle_close(sbr_socket_t * sk, u8 how) +{ + data_com_msg *m = sbr_attach_msg(sk, + (struct spl_pbuf *) + ADDR_SHTOL(sbr_get_fd_share + (sk)->recoder.head)); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_DELCON, + MSG_ASYN_POST, sk); + msg_delete_netconn *p = (msg_delete_netconn *) m->buffer; + p->extend_member_bit = 0; + p->buf = NULL; + p->time_started = sys_now(); + p->shut = how; + p->pid = get_sys_pid(); + p->conn = (spl_netconn_t *) ADDR_LTOSH(sbr_get_conn(sk)); + p->notify_omc = FALSE; + p->msg_box_ref = SPL_MSG_BOX_NUM; + + /* to ensure that the last deal with SPL_API_DO_DELCON message */ + int i; + for (i = 0; i < SPL_MSG_BOX_NUM; ++i) + { + SBR_MSG_POST(m, + ss_get_instance_msg_box(ss_get_bind_thread_index + (sbr_get_conn(sk)), i)); + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_handle_udp_send +* Description : udp send +* Input : sbr_socket_t * sk +* struct netbuf *buf +* spl_ip_addr_t* local_ip +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_handle_udp_send(sbr_socket_t * sk, struct spl_netbuf *buf, + spl_ip_addr_t * local_ip) +{ + data_com_msg *m = + sbr_attach_msg(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p)); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SEND, + MSG_ASYN_POST, sk); + msg_send_buf *p = (msg_send_buf *) m->buffer; + p->local_ip.addr = local_ip->addr; + int ret = memcpy_s(&p->addr, sizeof(spl_ip_addr_t), &buf->addr, + sizeof(spl_ip_addr_t)); + if (ret != 0) + { + NSSBR_LOGERR("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret); + sbr_set_sk_io_errno(sk, EINVAL); + SBR_MSG_FREE(m); + return -1; + } + + p->p = buf->p; + p->port = buf->port; + p->extend_member_bit = 0; + SBR_MSG_POST_RET(m, sbr_get_msg_box(sk), ret); + + if (0 == ret) + { + return 0; + } + else + { + NSSBR_LOGERR("post msg failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EAGAIN); + return -1; + } +} + +/***************************************************************************** +* Prototype : sbr_handle_free_recv_buf +* Description : free recv buf,can't free buf in app +* Input : sbr_socket_t * sk +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void sbr_handle_free_recv_buf(sbr_socket_t * sk) +{ + data_com_msg *m = sbr_attach_msg(sk, + (struct spl_pbuf *) + ADDR_SHTOL(sbr_get_fd_share + (sk)->recoder.head)); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + return; + } + + sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE, + MSG_ASYN_POST, sk); + msg_free_buf *p = (msg_free_buf *) m->buffer; + p->extend_member_bit = 0; + p->buf = sbr_get_fd_share(sk)->recoder.head; + sbr_get_fd_share(sk)->recoder.head = NULL; + sbr_get_fd_share(sk)->recoder.tail = NULL; + sbr_get_fd_share(sk)->recoder.totalLen = 0; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); +} + +void sbr_handle_free_send_buf(sbr_socket_t * sk, struct spl_pbuf *buf) +{ + if (buf != NULL) + { + data_com_msg *m = sbr_attach_msg(sk, buf); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + return; + } + + sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE, + MSG_ASYN_POST, sk); + msg_free_buf *p = (msg_free_buf *) m->buffer; + p->extend_member_bit = 0; + p->buf = (struct spl_pbuf *) ADDR_LTOSH(buf); + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + } +} + +/***************************************************************************** +* Prototype : sbr_handle_shutdown +* Description : shut down +* Input : sbr_socket_t * sk +* u8 how +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_handle_shutdown(sbr_socket_t * sk, u8 how) +{ + int err; + data_com_msg *m = SBR_MSG_MALLOC(sk); + + if (!m) + { + NSSBR_LOGERR("malloc msg failed]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CLOSE, + MSG_SYN_POST, sk); + msg_close *p = (msg_close *) m->buffer; + p->extend_member_bit = 0; + p->time_started = sys_now(); + p->shut = how; + SBR_MSG_POST(m, sbr_get_msg_box(sk)); + err = sbr_spl_err_to_errno(m->param.err); + SBR_MSG_FREE(m); + if (err != 0) + { + NSSBR_LOGERR("handle getsockopt failed]fd=%d,err=%d", sk->fd, err); + sbr_set_sk_errno(sk, err); + return -1; + } + + return 0; +} + +void sbr_handle_tcp_recv(sbr_socket_t * sk, u32 len, struct spl_pbuf *buf) +{ + data_com_msg *m = sbr_attach_msg(sk, buf); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + return; + } + + sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_RECV, + MSG_ASYN_POST, sk); + msg_recv_buf *p = (msg_recv_buf *) m->buffer; + p->extend_member_bit = 0; + p->len = len; + p->p = (struct spl_pbuf *) ADDR_LTOSH(buf); + SBR_MSG_POST(m, sbr_get_msg_box(sk)); +} + +int +sbr_handle_tcp_send(sbr_socket_t * sk, size_t size, struct spl_pbuf *buf, + u8 api_flag) +{ + int ret; + data_com_msg *m = sbr_attach_msg(sk, buf); + + if (!m) + { + NSSBR_LOGERR("attach msg failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, ENOMEM); + return -1; + } + + sbr_construct_msg_dbg(m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_WRITE, + MSG_ASYN_POST, sk); + msg_write_buf *p = (msg_write_buf *) m->buffer; + p->extend_member_bit = 0; + p->len = size; + p->p = (struct spl_pbuf *) ADDR_LTOSH(buf); + p->apiflags = api_flag; + SBR_MSG_POST_RET(m, sbr_get_msg_box(sk), ret); + + if (0 == ret) + { + return 0; + } + else + { + NSSBR_LOGERR("post msg failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EAGAIN); + return -1; + } +} + +/* need delete sbr_handle_app_touch */ +void sbr_handle_app_touch(void) +{ +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h new file mode 100644 index 0000000..a659650 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h @@ -0,0 +1,78 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_MSG_HANDLER_H +#define STACKX_MSG_HANDLER_H +#include "stackx_socket.h" +#include "stackx_ip_addr.h" +#include "stackx_netbuf.h" +#include "stackx_spl_share.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SBR_GET_SOCK_NAME 1 +#define SBR_GET_PEER_NAME 0 + +int sbr_handle_socket(sbr_socket_t * sk, spl_netconn_type_t type, u8 proto); + +int sbr_handle_bind(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port); + +int sbr_handle_listen(sbr_socket_t * sk, int backlog); + +int sbr_handle_connect(sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port, + spl_ip_addr_t * local_ip); + +int sbr_handle_get_name(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen, u8 cmd); + +int sbr_handle_setsockopt(sbr_socket_t * sk, int level, int optname, + const void *optval, socklen_t optlen); + +int sbr_handle_getsockopt(sbr_socket_t * sk, int level, int optname, + void *optval, socklen_t * optlen); + +int sbr_handle_close(sbr_socket_t * sk, u8 how); + +int sbr_handle_udp_send(sbr_socket_t * sk, struct spl_netbuf *buf, + spl_ip_addr_t * local_ip); + +void sbr_handle_free_recv_buf(sbr_socket_t * sk); + +void sbr_handle_free_send_buf(sbr_socket_t * sk, struct spl_pbuf *buf); + +int sbr_handle_shutdown(sbr_socket_t * sk, u8 how); + +void sbr_handle_tcp_recv(sbr_socket_t * sk, u32 len, struct spl_pbuf *buf); + +int sbr_handle_tcp_send(sbr_socket_t * sk, size_t size, struct spl_pbuf *buf, + u8 api_flag); + +int sbr_handle_custom_send(sbr_socket_t * sk, struct spl_pbuf *buf, + spl_ip_addr_t * src, spl_ip_addr_t * dst, u8 tos); + +int sbr_handle_custom_close(sbr_socket_t * sk, spl_ip_addr_t * addr); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c new file mode 100644 index 0000000..18588a1 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c @@ -0,0 +1,670 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include "stackx_msg_handler.h" +#include "stackx_prot_com.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_err.h" +#include "nstack_securec.h" +#include "nsfw_rti.h" +//#include "stackx_custom.h" + +#define FAST_SLEEP_TIME 10000 +#define FAST_RETRY_COUNT 100 +#define MAX_WAIT_TIMEOUT 0x7FFFFFFF + +/***************************************************************************** +* Prototype : sbr_getsockopt_sol_socket +* Description : get sol socket +* Input : sbr_socket_t * sk +* int optname +* void * optval +* socklen_t optlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_getsockopt_sol_socket(sbr_socket_t * sk, int optname, void *optval, + socklen_t optlen) +{ + int err = 0; + + switch (optname) + { + case SO_ERROR: + { + if (optlen < sizeof(int)) + { + return EINVAL; + } + + /* only overwrite ERR_OK or tempoary errors */ + err = sbr_get_sk_errno(sk); + + if ((0 == err) || (EINPROGRESS == err)) + { + err = + sbr_spl_err_to_errno(ss_get_last_errno + (sbr_get_conn(sk))); + sbr_set_sk_errno(sk, err); + } + else + { + sbr_set_sk_errno(sk, 0); + } + + *(int *) optval = sbr_get_sk_errno(sk); + + return 0; + } + case SO_BROADCAST: + case SO_KEEPALIVE: + case SO_RCVBUF: + case SO_SNDBUF: + case SO_REUSEADDR: + if (optlen < sizeof(int)) + { + err = EINVAL; + } + + break; + case SO_RCVTIMEO: + case SO_SNDTIMEO: + if (optlen < sizeof(struct timeval)) + { + err = EINVAL; + } + + break; + case SO_LINGER: + if (optlen < sizeof(struct linger)) + { + err = EINVAL; + } + + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +/***************************************************************************** +* Prototype : sbr_getsockopt_ipproto_ip +* Description : get ipproto ip +* Input : int optname +* void * optval +* socklen_t optlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_getsockopt_ipproto_ip(int optname, void *optval, socklen_t optlen) +{ + int err = 0; + + switch (optname) + { + case IP_TOS: + if (optlen < sizeof(u8)) + { + err = EINVAL; + } + + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +/***************************************************************************** +* Prototype : sbr_pick_timeout +* Description : pick time +* Input : const void * optval +* socklen_t optlen +* i32* timeout +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_pick_timeout(const void *optval, socklen_t optlen, i32 * timeout) +{ + if (optlen < sizeof(struct timeval)) + { + return EINVAL; + } + + struct timeval *time_val = (struct timeval *) optval; + if ((time_val->tv_usec < 0) || (time_val->tv_usec > USEC_TO_SEC)) + { + return EDOM; + } + else + { + if (time_val->tv_sec < 0) + { + *timeout = 0; + } + else + { + *timeout = MAX_WAIT_TIMEOUT; + if ((time_val->tv_sec != 0) || (time_val->tv_usec != 0)) + { + if (time_val->tv_sec < ((MAX_WAIT_TIMEOUT / 1000) - 1)) + { + *timeout = + time_val->tv_sec * 1000 + time_val->tv_usec / 1000; + } + } + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_setsockopt_sol_socket +* Description : set sol socket +* Input : sbr_socket_t * sk +* int optname +* const void * optval +* socklen_t optlen +* netconn_type_t type +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_setsockopt_sol_socket(sbr_socket_t * sk, int optname, const void *optval, + socklen_t optlen, spl_netconn_type_t type) +{ + int err = 0; + + switch (optname) + { + case SO_REUSEADDR: + case SO_BROADCAST: + case SO_KEEPALIVE: + case SO_RCVBUF: + case SO_SNDBUF: + if (optlen < sizeof(int)) + { + err = EINVAL; + } + + break; + case SO_RCVTIMEO: + err = + sbr_pick_timeout(optval, optlen, + &sbr_get_fd_share(sk)->recv_timeout); + break; + case SO_SNDTIMEO: + err = + sbr_pick_timeout(optval, optlen, + &sbr_get_fd_share(sk)->send_timeout); + break; + case SO_LINGER: + if (optlen < sizeof(struct linger)) + { + err = EINVAL; + } + + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +/***************************************************************************** +* Prototype : sbr_setsockopt_ipproto_ip +* Description : set ipproto ip +* Input : int optname +* const void * optval +* socklen_t optlen +* netconn_type_t type +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_setsockopt_ipproto_ip(int optname, const void *optval, socklen_t optlen, + spl_netconn_type_t type) +{ + int err = 0; + + switch (optname) + { + case IP_TOS: + if (optlen < sizeof(u8)) + { + err = EINVAL; + } + + break; + case IP_MULTICAST_TTL: + if (optlen < sizeof(u8)) + { + err = EINVAL; + break; + } + + if (type != SPL_NETCONN_UDP) + { + err = EAFNOSUPPORT; + break; + } + + break; + case IP_MULTICAST_IF: + if (optlen < sizeof(struct in_addr)) + { + err = EINVAL; + break; + } + + if (type != SPL_NETCONN_UDP) + { + err = EAFNOSUPPORT; + break; + } + + break; + case IP_MULTICAST_LOOP: + if (optlen < sizeof(u8)) + { + err = EINVAL; + break; + } + + if (type != SPL_NETCONN_UDP) + { + err = EAFNOSUPPORT; + break; + } + + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +/***************************************************************************** +* Prototype : sbr_dequeue_buf +* Description : dequeue buf +* Input : sbr_socket_t * sk +* void **buf +* i32 timeout +* u8 use_l4_ring +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_dequeue_buf(sbr_socket_t * sk, void **buf, i32 timeout) +{ + mring_handle ring = ss_get_recv_ring(sbr_get_conn(sk)); + + struct timespec start, end; + long timediff; + long timediff_sec; + long timeout_sec = (long) (timeout / 1000); + unsigned int retry_count = 0; + + if (timeout > 0) + { + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &start))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + } + + if (!ss_recv_ring_valid(sbr_get_conn(sk))) + { + NSSBR_LOGDBG("ring is invalid]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, ENOTCONN); + return -1; + } + + int dequeue_ret = 0; + pid_t pid = get_sys_pid(); + + while (1) + { + if (ss_is_shut_rd(sbr_get_conn(sk))) + { + NSSBR_LOGDBG("is shut rd]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + + dequeue_ret = nsfw_mem_ring_dequeue(ring, buf); + if (1 == dequeue_ret) + { + pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid); /*release buf hold by app on abnormal exit */ + return 0; + } + else if (0 == dequeue_ret) + { + /*If the peer reset connect, try to receive data only once */ + if (ss_can_not_recv(sbr_get_conn(sk))) + { + NS_LOG_CTRL(LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR", + NSLOG_WAR, "try to fetch one more time]fd=%d", + sk->fd); + /** + * l4_ring will not be processed here as can_not_recv flag is + * set by TCP only. + */ + if (1 == nsfw_mem_ring_dequeue(ring, buf)) + { + pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid); + return 0; + } + + sbr_set_sk_io_errno(sk, ENOTCONN); + return -1; + } + + int err = ss_get_last_errno(sbr_get_conn(sk)); + if (SPL_ERR_IS_FATAL(err) || err == ERR_TIMEOUT) /* have to handle ERR_TIMEOUT here, when TCP keepalive timeout. */ + { + NS_LOG_CTRL(LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR", + NSLOG_ERR, "connection fatal error!err=%d", err); + + /* l4_ring need to be handled in the future */ + if (1 == nsfw_mem_ring_dequeue(ring, buf)) + { + pbuf_set_recycle_flg((struct spl_pbuf *) *buf, pid); + return 0; + } + + sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err)); + return -1; + } + + if (0 > timeout) + { + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + return -1; + } + + if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns(0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns(0, sbr_get_fd_share(sk)->block_polling_time); + } + + if (timeout > 0) + { + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &end))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + timediff_sec = end.tv_sec - start.tv_sec; + if (timediff_sec >= timeout_sec) + { + timediff = end.tv_nsec > start.tv_nsec ? + (timediff_sec * 1000) + (end.tv_nsec - + start.tv_nsec) / + USEC_TO_SEC : (timediff_sec * 1000) - + ((start.tv_nsec - end.tv_nsec) / USEC_TO_SEC); + if (timediff > timeout) + { + NSSBR_LOGDBG("recv timeout]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + return -1; + } + } + } + } + else + { + NSSBR_LOGERR("dequeue failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + } +} + +int sbr_com_peak(sbr_socket_t * sk) +{ + NSSBR_LOGERR("not implement]fd=%d", sk->fd); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_com_try_lock_recv +* Description : try lock recv +* Input : sbr_socket_t * sk +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_com_try_lock_recv(sbr_socket_t * sk) +{ +#ifdef SBR_USE_LOCK + return common_spinlock_try_lock_with_pid(&sbr_get_fd_share(sk)->recv_lock, + get_sys_pid()); +#else + return 1; +#endif +} + +/***************************************************************************** +* Prototype : sbr_com_lock_common +* Description : lock common +* Input : sbr_socket_t * sk +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void sbr_com_lock_common(sbr_socket_t * sk) +{ +#ifdef SBR_USE_LOCK + while (!common_spinlock_try_lock_with_pid + (&sbr_get_fd_share(sk)->common_lock, get_sys_pid())) + { + sys_sleep_ns(0, 0); + } +#endif + +} + +void sbr_com_fork_parent(sbr_socket_t * sk, pid_t p) +{ + i32 ref = ss_inc_fork_ref(sbr_get_conn(sk)); + NSSBR_LOGINF + ("inc fork ref] fd=%d, p=%d, ref=%d, conn=%p, private_data=%p", + sk->fd, p, ref, sbr_get_conn(sk), sbr_get_conn(sk)->private_data); +} + +void sbr_com_fork_child(sbr_socket_t * sk, pid_t p, pid_t c) +{ + if (ss_add_pid(sbr_get_conn(sk), c) != 0) + { + NSSBR_LOGERR + ("add pid failed] fd=%d, p=%d, c=%d, ref=%d, conn=%p, private_data=%p", + sk->fd, p, c, ss_get_fork_ref(sbr_get_conn(sk)), + sbr_get_conn(sk), sbr_get_conn(sk)->private_data); + } + else + { + NSSBR_LOGINF + ("add pid ok] fd=%d, p=%d, c=%d, ref=%d, conn=%p, private_data=%p", + sk->fd, p, c, ss_get_fork_ref(sbr_get_conn(sk)), + sbr_get_conn(sk), sbr_get_conn(sk)->private_data); + } +} + +/***************************************************************************** +* Prototype : sbr_com_unlock_common +* Description : unlock common +* Input : sbr_socket_t * sk +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void sbr_com_unlock_common(sbr_socket_t * sk) +{ +#ifdef SBR_USE_LOCK + common_spinlock_unlock(&sbr_get_fd_share(sk)->common_lock); +#endif +} + +/***************************************************************************** +* Prototype : sbr_com_free_recv_buf +* Description : free recv buf,can't free buf in app +* Input : sbr_socket_t * sk +* struct spl_pbuf *p +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void sbr_com_free_recv_buf(sbr_socket_t * sk, struct spl_pbuf *p) +{ + struct spl_pbuf *p_orig = p; + if (p) + { + p->freeNext = NULL; + p = (struct spl_pbuf *) ADDR_LTOSH(p); + + if (sbr_get_fd_share(sk)->recoder.totalLen > 0) + { + ((struct spl_pbuf *) + ADDR_SHTOL(sbr_get_fd_share(sk)->recoder.tail))->freeNext = p; + sbr_get_fd_share(sk)->recoder.tail = p; + } + else + { + sbr_get_fd_share(sk)->recoder.head = p; + sbr_get_fd_share(sk)->recoder.tail = p; + } + + sbr_get_fd_share(sk)->recoder.totalLen++; + } + + /* send MSG only if it's a big packet or number of packets larger than 32 */ + if ((p_orig && p_orig->tot_len > MAX_RECV_FREE_LEN) || + (sbr_get_fd_share(sk)->recoder.totalLen >= MAX_RECV_FREE_BUF)) + { + sbr_handle_free_recv_buf(sk); + } + +} + +/***************************************************************************** +* Prototype : sbr_get_sockaddr_and_len +* Description : get addr and len +* Input : u16 port +* spl_ip_addr_t * ipaddr +* struct sockaddr * addr +* socklen_t * addrlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_get_sockaddr_and_len(u16 port, spl_ip_addr_t * ipaddr, + struct sockaddr *addr, socklen_t * addrlen) +{ + int ret; + struct sockaddr_in sin; + + ret = memset_s(&sin, sizeof(sin), 0, sizeof(sin)); + if (0 != ret) + { + NSSBR_LOGERR("MEMSET_S failed]ret=%d.", ret); + return -1; + } + + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_addr_from_ipaddr(&sin.sin_addr, ipaddr); + if (*addrlen > sizeof(struct sockaddr)) + { + *addrlen = sizeof(struct sockaddr); + } + + if (*addrlen > 0) + { + ret = memcpy_s(addr, sizeof(struct sockaddr), &sin, *addrlen); + if (0 != ret) + { + NSSBR_LOGERR("MEMCPY_S failed]ret=%d", ret); + + return -1; + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_com_set_app_info +* Description : set app info to netconn +* Input : sbr_socket_t * sk +* void* appinfo +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void sbr_com_set_app_info(sbr_socket_t * sk, void *appinfo) +{ + return; +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h new file mode 100644 index 0000000..4d542fd --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h @@ -0,0 +1,159 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_PROT_COM_H +#define STACKX_PROT_COM_H +#include "stackx_socket.h" +#include "stackx_ip_addr.h" +#include "stackx_res_mgr.h" +#include "stackx_pbuf.h" +#include "stackx_macro.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_RECV_FREE_BUF 32 +#define MAX_RECV_FREE_LEN (SPL_FRAME_MTU - SPL_IP_HLEN) +#define USEC_TO_SEC 1000000 + +#ifndef NSTACK_SOCKOPT_CHECK +#define NSTACK_SOCKOPT_CHECK +/* setsockopt level type*/ +enum +{ + NSTACK_SOCKOPT = 0xff02 +}; +/*setsockopt optname type*/ +enum +{ + NSTACK_SEM_SLEEP = 0X001 +}; +#endif + +#define sbr_malloc_tx_pbuf(len, offset) sbr_malloc_pbuf(sbr_get_tx_pool(), len, TX_MBUF_MAX_LEN, offset) + +static inline int sbr_spl_err_to_errno(i32 err) +{ + static int table[] = { + 0, /* ERR_OK 0 No error, everything OK. */ + ENOMEM, /* ERR_MEM -1 Out of memory error. */ + ENOBUFS, /* ERR_BUF -2 Buffer error. */ + ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */ + EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */ + EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ + EINVAL, /* ERR_VAL -6 Illegal value. */ + EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EISCONN, /* ERR_ISCONN -9 Already connected. */ + ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ + ECONNRESET, /* ERR_RST -11 Connection reset. */ + ENOTCONN, /* ERR_CLSD -12 Connection closed. */ + ENOTCONN, /* ERR_CONN -13 Not connected. */ + EIO, /* ERR_ARG -14 Illegal argument. */ + -1, /* ERR_IF -15 Low-level netif error */ + EALREADY, /*ERR_ALREADY -16 previous connect attemt has not yet completed */ + EPROTOTYPE, /*ERR_PROTOTYPE -17 prototype error or some other generic error. + the operation is not allowed on current socket */ + EINVAL, /* ERR_CALLBACK -18 callback error */ + EADDRNOTAVAIL, /* ERR_CANTASSIGNADDR -19 Cannot assign requested address */ + EIO, /* ERR_CONTAINER_ID -20 Illegal container id */ + ENOTSOCK, /*ERR_NOTSOCK -21 not a socket */ + -1, /* ERR_CLOSE_WAIT -22 closed in established state */ + EPROTONOSUPPORT, /* ERR_EPROTONOSUPPORT -23 Protocol not supported */ + ECONNABORTED /* ERR_FAULTRECOVERY -24 SPL just recovered from a fatal fault */ + }; + + if (((-(err)) >= 0) + && (-(err)) < (i32) (sizeof(table) / sizeof(table[0]))) + { + return table[-(err)]; + } + else + { + return EIO; + } +} + +int sbr_getsockopt_sol_socket(sbr_socket_t * sk, int optname, void *optval, + socklen_t optlen); +int sbr_getsockopt_ipproto_ip(int optname, void *optval, socklen_t optlen); +int sbr_setsockopt_sol_socket(sbr_socket_t * sk, int optname, + const void *optval, socklen_t optlen, + spl_netconn_type_t type); +int sbr_setsockopt_ipproto_ip(int optname, const void *optval, + socklen_t optlen, spl_netconn_type_t type); +int sbr_dequeue_buf(sbr_socket_t * sk, void **buf, i32 timeout); +int sbr_com_peak(sbr_socket_t * sk); +int sbr_com_try_lock_recv(sbr_socket_t * sk); +/***************************************************************************** +* Prototype : sbr_com_lock_recv +* Description : lock recv +* Input : sbr_socket_t * sk +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_com_lock_recv(sbr_socket_t * sk) +{ +#ifdef SBR_USE_LOCK + while (!common_spinlock_try_lock_with_pid + (&sbr_get_fd_share(sk)->recv_lock, get_sys_pid())) + { + sys_sleep_ns(0, 0); + } +#endif + +} + +/***************************************************************************** +* Prototype : sbr_com_unlock_recv +* Description : unlock recv +* Input : sbr_socket_t * sk +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_com_unlock_recv(sbr_socket_t * sk) +{ +#ifdef SBR_USE_LOCK + common_spinlock_unlock(&sbr_get_fd_share(sk)->recv_lock); +#endif +} + +void sbr_com_lock_common(sbr_socket_t * sk); +void sbr_com_unlock_common(sbr_socket_t * sk); +void sbr_com_free_recv_buf(sbr_socket_t * sk, struct spl_pbuf *p); +int sbr_get_sockaddr_and_len(u16 port, spl_ip_addr_t * ip_addr, + struct sockaddr *addr, socklen_t * addrlen); +void sbr_com_set_app_info(sbr_socket_t * sk, void *appinfo); + +void sbr_com_fork_parent(sbr_socket_t * sk, pid_t p); +void sbr_com_fork_child(sbr_socket_t * sk, pid_t p, pid_t c); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c new file mode 100644 index 0000000..dbcb4e3 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c @@ -0,0 +1,109 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "sbr_protocol_api.h" +#include "stackx_epoll_api.h" +#include "stackx_socket.h" +#include "stackx_res_mgr.h" +#include "stackx_common_opt.h" +#include "common_mem_api.h" +#include "stackx_event.h" + +extern sbr_fdopt tcp_fdopt; +extern sbr_fdopt udp_fdopt; +extern sbr_fdopt raw_fdopt; +extern sbr_fdopt custom_fdopt; + +/***************************************************************************** +* Prototype : sbr_init_protocol +* Description : init protocol +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_init_protocol() +{ + return sbr_init_stackx(); +} + +/***************************************************************************** +* Prototype : sbr_fork_protocol +* Description : init protocol +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_fork_protocol() +{ + pid_t pid = updata_sys_pid(); + + NSSBR_LOGINF("update pid in child]pid=%d", pid); + return sbr_fork_stackx(); +} + +/***************************************************************************** +* Prototype : sbr_get_fdopt +* Description : get fdopt by domain type protocol +* Input : int domain +* int type +* int protocol +* Output : None +* Return Value : sbr_fdopt* +* Calls : +* Called By : +* +*****************************************************************************/ +sbr_fdopt *sbr_get_fdopt(int domain, int type, int protocol) +{ + if (domain != AF_INET) + { + NSSBR_LOGERR("domain is not AF_INET]domain=%d", domain); + sbr_set_errno(EAFNOSUPPORT); + return NULL; + } + + sbr_fdopt *fdopt = NULL; + + switch (type & (~(O_NONBLOCK | SOCK_CLOEXEC))) + { + case SOCK_DGRAM: + fdopt = &udp_fdopt; + break; + case SOCK_STREAM: + fdopt = &tcp_fdopt; + break; + + default: + NSSBR_LOGDBG("type is unknown]type=%d", type); + sbr_set_errno(ESOCKTNOSUPPORT); + return NULL; + } + + return fdopt; +} + +/* app send its version info to nStackMain */ +extern void sbr_handle_app_touch(void); +void sbr_app_touch_in(void) +{ + sbr_handle_app_touch(); +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c new file mode 100644 index 0000000..964a1f9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c @@ -0,0 +1,271 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_res_mgr.h" +#include "stackx_common.h" +#include "nstack_securec.h" +#include "nsfw_msg.h" +#include "stackx_common.h" +#include "nsfw_mgr_com_api.h" +#include "stackx_cfg.h" +#include "nsfw_maintain_api.h" +//#include "stackx_dfx_api.h" +#include "stackx_app_res.h" + +sbr_share_group g_share_group = { 0 }; + +#define SLOW_SLEEP_TIME 500000 + +NSTACK_STATIC inline void sbr_reset_fd_share(sbr_fd_share * fd_share) +{ + common_mem_spinlock_init(&fd_share->recv_lock); + common_mem_spinlock_init(&fd_share->common_lock); + fd_share->err = 0; + fd_share->lastoffset = 0; + fd_share->lastdata = NULL; + fd_share->recoder.head = NULL; + fd_share->recoder.tail = NULL; + fd_share->recoder.totalLen = 0; + fd_share->recv_timeout = 0; + fd_share->send_timeout = 0; + fd_share->rcvlowat = 1; + fd_share->block_polling_time = SLOW_SLEEP_TIME; +} + +/***************************************************************************** +* Prototype : sbr_init_tx_pool +* Description : get tx buf pool +* Input : None +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int sbr_init_tx_pool() +{ + mpool_handle pool[1]; + pool[0] = NULL; + + (void) sbr_malloc_tx_pool(get_sys_pid(), pool, 1); + if (pool[0]) + { + g_share_group.tx_pool = pool[0]; + return 0; + } + + return -1; +} + +/***************************************************************************** +* Prototype : sbr_init_app_res +* Description : get msg, conn pool +* Input : None +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int sbr_init_app_res() +{ + g_share_group.conn_pool = sbr_get_instance_conn_pool(0); + if (!g_share_group.conn_pool) + { + return -1; + } + + return 0; +} + +/*=========== get share config for app =============*/ +NSTACK_STATIC inline int get_share_config() +{ + static nsfw_mem_name g_cfg_mem_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG }; + + mzone_handle base_cfg_mem = nsfw_mem_zone_lookup(&g_cfg_mem_info); + if (NULL == base_cfg_mem) + { + NSSOC_LOGERR("get config share mem failed."); + return -1; + } + + if (get_share_cfg_from_mem(base_cfg_mem) < 0) + { + NSSOC_LOGERR("get share config failed."); + return -1; + } + + NSSOC_LOGDBG("get share config success."); + return 0; +} + +int nstack_set_share_config() +{ + return 0; +} + +/***************************************************************************** +* Prototype : sbr_init_stackx +* Description : init stackx res +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_init_stackx() +{ + sbr_init_cfg(); + if (get_share_config() < 0) + { + NSSBR_LOGERR("get_share_config failed"); + return -1; + } + + if (sbr_attach_group_array() != 0) + { + NSSBR_LOGERR("sbr_attach_group_array failed"); + return -1; + } + + NSSBR_LOGDBG("sbr_attach_group_array ok"); + + if (sbr_init_tx_pool() != 0) + { + NSSBR_LOGERR("init tx pool failed"); + return -1; + } + + NSSBR_LOGDBG("init tx pool ok"); + + if (sbr_init_app_res() != 0) + { + NSSBR_LOGERR("sbr_init_app_res failed"); + return -1; + } + + NSSBR_LOGDBG("sbr_init_app_res ok"); + NSSBR_LOGDBG("sbr_init_stackx ok"); + return 0; +} + +/***************************************************************************** +* Prototype : sbr_fork_stackx +* Description : init stackx res +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_fork_stackx() +{ + + if (sbr_attach_group_array() != 0) + { + NSSBR_LOGERR("sbr_attach_group_array failed"); + return -1; + } + + NSSBR_LOGDBG("sbr_attach_group_array ok"); + + if (sbr_init_tx_pool() != 0) + { + NSSBR_LOGERR("init tx pool failed"); + return -1; + } + + NSSBR_LOGDBG("init tx pool ok"); + NSSBR_LOGDBG("sbr_fork_stackx ok"); + return 0; +} + +/***************************************************************************** +* Prototype : sbr_malloc_conn_for_sk +* Description : malloc netconn for sk,need add pid +* Input : sbr_socket_t* sk +* netconn_type_t type +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_malloc_conn_for_sk(sbr_socket_t * sk, spl_netconn_type_t type) +{ + spl_netconn_t *conn = ss_malloc_conn_app(g_share_group.conn_pool, type); + + if (!conn) + { + NSSBR_LOGERR("malloc conn failed]fd=%d", sk->fd); + sbr_set_errno(ENOBUFS); + return -1; + } + + NSSBR_LOGINF("malloc conn ok]fd=%d,conn=%p", sk->fd, conn); + + u16 thread_index = 0; + ss_set_bind_thread_index(conn, thread_index); + ss_set_msg_box(conn, ss_get_instance_msg_box(thread_index, 0)); + + sbr_fd_share *fd_share = + (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE); + sbr_reset_fd_share(fd_share); + + sk->stack_obj = (void *) conn; + sk->sk_obj = (void *) fd_share; + return 0; +} + +int sbr_init_conn_for_accept(sbr_socket_t * sk, spl_netconn_t * conn) +{ + if (!conn) + { + sbr_set_sk_errno(sk, ENOBUFS); + return -1; + } + + NSSBR_LOGINF("accept conn ok]fd=%d,conn=%p,private_data=%p", sk->fd, conn, + conn->private_data); + + if (ss_add_pid(conn, get_sys_pid()) < 0) + { + NSSBR_LOGERR("ss_add_pid failed]fd=%d", sk->fd); + } + + ss_set_accept_from(conn, NULL); /* need clear flag */ + + sbr_fd_share *fd_share = + (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE); + sbr_reset_fd_share(fd_share); + + sk->stack_obj = (void *) conn; + sk->sk_obj = (void *) fd_share; + + return 0; +} + +void sbr_free_conn_from_sk(sbr_socket_t * sk) +{ + ss_free_conn(sbr_get_conn(sk)); + sk->stack_obj = NULL; + sk->sk_obj = NULL; + NSSBR_LOGDBG("free conn ok]fd=%d", sk->fd); +} diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h new file mode 100644 index 0000000..6fa6501 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h @@ -0,0 +1,67 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_RES_MGR_H +#define STACKX_RES_MGR_H +#include "stackx_socket.h" +#include "stackx_ip_tos.h" +#include "stackx_tx_box.h" +#include "stackx_app_res.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct +{ + mring_handle conn_pool; + mpool_handle tx_pool; +} sbr_share_group; + +extern sbr_share_group g_share_group; + +static inline mpool_handle sbr_get_tx_pool() +{ + return g_share_group.tx_pool; +} + +static inline mring_handle sbr_get_conn_pool() +{ + return (mring_handle) ADDR_LTOSH(g_share_group.conn_pool); +} + +static inline mring_handle sbr_get_spl_msg_box(sbr_socket_t * sk, u8 tos) +{ + return + ss_get_instance_msg_box(ss_get_bind_thread_index(sbr_get_conn(sk)), + stackx_get_prio(tos)); +} + +int sbr_init_stackx(); +int sbr_fork_stackx(); +int sbr_malloc_conn_for_sk(sbr_socket_t * sk, spl_netconn_type_t type); +int sbr_init_conn_for_accept(sbr_socket_t * sk, spl_netconn_t * conn); +void sbr_free_conn_from_sk(sbr_socket_t * sk); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_socket.h b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h new file mode 100644 index 0000000..edc0e86 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h @@ -0,0 +1,138 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef STACKX_SOCKET_H +#define STACKX_SOCKET_H +#include "sbr_protocol_api.h" +#include "stackx_spl_share.h" +#include "nstack_log.h" +#include "stackx_pbuf.h" +#include "common_mem_spinlock.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct +{ + PRIMARY_ADDR struct spl_pbuf *head; + PRIMARY_ADDR struct spl_pbuf *tail; + int totalLen; +} sbr_recvbuf_recoder; + +/* need fork and recycle */ +typedef struct +{ + common_mem_spinlock_t recv_lock; + common_mem_spinlock_t common_lock; + PRIMARY_ADDR void *lastdata; + u32 lastoffset; + sbr_recvbuf_recoder recoder; + i32 recv_timeout; + i32 send_timeout; + i32 rcvlowat; + int err; + u64 block_polling_time; + i64 extend_member_bit; +} sbr_fd_share; + +/* check sbr_fd_share size */ +SIZE_OF_TYPE_NOT_LARGER_THAN_RETURN(sbr_fd_share, SBR_FD_SIZE); + +#define sbr_get_fd_share(sk) ((sbr_fd_share*)sk->sk_obj) + +#define sbr_get_conn(sk) ((spl_netconn_t*)sk->stack_obj) + +#define sbr_get_msg_box(sk) ss_get_msg_box(sbr_get_conn(sk)) + +/***************************************************************************** +* Prototype : sbr_set_sk_errno +* Description : set errno for sk +* Input : sbr_socket_t * sk +* int err +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_set_sk_errno(sbr_socket_t * sk, int err) +{ + sbr_get_fd_share(sk)->err = err; + if (err != 0) + { + if (sbr_get_conn(sk)) + { + NSSBR_LOGERR("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd, + err, sbr_get_conn(sk), + ss_get_private_data(sbr_get_conn(sk))); + } + + sbr_set_errno(err); + } +} + +/***************************************************************************** +* Prototype : sbr_set_sk_io_errno +* Description : set errno for sk in send/recv func, in case of too many logs +* Input : sbr_socket_t * sk +* int err +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_set_sk_io_errno(sbr_socket_t * sk, int err) +{ + sbr_get_fd_share(sk)->err = err; + if (err != 0) + { + if (sbr_get_conn(sk)) + { + NSSBR_LOGDBG("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd, + err, sbr_get_conn(sk), + ss_get_private_data(sbr_get_conn(sk))); + } + + sbr_set_errno(err); + } +} + +/***************************************************************************** +* Prototype : sbr_get_sk_errno +* Description : get sk's errno +* Input : sbr_socket_t * sk +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int sbr_get_sk_errno(sbr_socket_t * sk) +{ + return sbr_get_fd_share(sk)->err; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c new file mode 100644 index 0000000..4bc5317 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c @@ -0,0 +1,1682 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_prot_com.h" +#include "stackx_msg_handler.h" +#include "stackx_pbuf.h" +#include "stackx_epoll_api.h" +#include "nstack_securec.h" +#include "common_pal_bitwide_adjust.h" +#include "common_mem_mbuf.h" +#include "stackx_spl_share.h" +#include "stackx_err.h" +#include "stackx_cfg.h" +#include "spl_opt.h" +//#include "stackx_tcp_sctl.h" +#include "stackx_tcp_opt.h" +//#include "stackx_dfx_api.h" +#include "stackx_spl_msg.h" +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +static void sbr_tcp_init_conn(spl_netconn_t * conn) +{ + conn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE; + conn->conn_pool = sbr_get_conn_pool(); +} + +/* need close after accept failed */ +static void sbr_tcp_accept_failed(sbr_socket_t * sk) +{ + (void) sbr_handle_close(sk, 0); + sk->stack_obj = NULL; + sk->sk_obj = NULL; +} + +NSTACK_STATIC int +sbr_tcp_socket(sbr_socket_t * sk, int domain, int type, int protocol) +{ + int err = 0; + + if (sbr_malloc_conn_for_sk(sk, SPL_NETCONN_TCP) != 0) + { + return -1; + } + + sbr_tcp_init_conn(sbr_get_conn(sk)); + + err = sbr_handle_socket(sk, SPL_NETCONN_TCP, 0); + if (0 == err) + { + /* Prevent automatic window updates, we do this on our own! */ + ss_set_noautorecved_flag(sbr_get_conn(sk), 1); + + ss_set_nonblock_flag(sbr_get_conn(sk), (type & O_NONBLOCK)); + + ss_add_recv_event(sbr_get_conn(sk)); + + ss_set_send_event(sbr_get_conn(sk), 1); + + NSSBR_LOGINF("add write and read events]fd=%d", sk->fd); + + return 0; + } + else + { + sbr_free_conn_from_sk(sk); + return err; + } +} + +NSTACK_STATIC int +sbr_tcp_bind(sbr_socket_t * sk, const struct sockaddr *name, + socklen_t namelen) +{ + const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name; + NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd, + spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port), + sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); + spl_ip_addr_t local_addr; + inet_addr_to_ipaddr(&local_addr, &addr_in->sin_addr); + u16 local_port = addr_in->sin_port; + return sbr_handle_bind(sk, &local_addr, ntohs(local_port)); +} + +NSTACK_STATIC int sbr_tcp_listen(sbr_socket_t * sk, int backlog) +{ + ss_set_is_listen_conn(sbr_get_conn(sk), 1); + return sbr_handle_listen(sk, backlog); +} + +static inline int +sbr_tcp_recv_is_timeout(sbr_socket_t * sk, struct timespec *starttm) +{ + struct timespec currtm; + i64 timediff_ms, timediff_sec; + i64 timeout_thr_ms, timeout_thr_sec; + + timeout_thr_ms = sbr_get_fd_share(sk)->recv_timeout; + if (0 == timeout_thr_ms) + { + return ERR_OK; + } + + timeout_thr_sec = (i64) (timeout_thr_ms / 1000); + + /* Handle system time change side-effects */ + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &currtm))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + + timediff_sec = currtm.tv_sec - starttm->tv_sec; + if (timediff_sec >= timeout_thr_sec) + { + timediff_ms = currtm.tv_nsec > starttm->tv_nsec ? + (timediff_sec * 1000) + (currtm.tv_nsec - + starttm->tv_nsec) / + USEC_TO_SEC : (timediff_sec * 1000) - + ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC); + + /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value + will be negetive if still 0.5 ms is not elapsed. this is intended and we should + not typecast to any unsigned type during this below if check */ + if (timediff_ms > timeout_thr_ms) + { + sbr_set_sk_errno(sk, ETIMEDOUT); + return ETIMEDOUT; + } + } + + return ERR_OK; +} + +static inline int sbr_tcp_wait_new_conn(sbr_socket_t * sk, void **new_buf) +{ + int ret = 0; + int elem_num; + u32 timeout_thr_sec; + struct timespec starttm = { 0, 0 }; + unsigned int retry_count = 0; + mring_handle ring = NULL; + +#define FAST_SLEEP_TIME 10000 +#define SLOW_SLEEP_TIME 500000 +#define FAST_RETRY_COUNT 100 + + ring = ss_get_recv_ring(sbr_get_conn(sk)); //clear codeDEX warning , CID:24284 + timeout_thr_sec = sbr_get_fd_share(sk)->recv_timeout / 1000; + if (0 != timeout_thr_sec) + { + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &starttm))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + } + + while (1) + { + if (ss_is_shut_rd(sbr_get_conn(sk))) + { + sbr_set_sk_errno(sk, EINVAL); + ret = EINVAL; + break; + } + + elem_num = nsfw_mem_ring_dequeue(ring, new_buf); + if (1 == elem_num) + { + break; + } + else if (0 == elem_num) + { + ret = sbr_tcp_recv_is_timeout(sk, &starttm); + if (0 != ret) + { + break; + } + + /* reduce CPU usage in blocking mode- Begin */ + if (retry_count < FAST_RETRY_COUNT) + { + sys_sleep_ns(0, FAST_SLEEP_TIME); + retry_count++; + } + else + { + sys_sleep_ns(0, sbr_get_fd_share(sk)->block_polling_time); + } + + continue; + } + else + { + sbr_set_sk_errno(sk, EINVAL); + ret = EINVAL; + break; + } + } + + return ret; +} + +NSTACK_STATIC inline int +sbr_tcp_get_sockaddr(sbr_socket_t * sk, struct sockaddr *addr, + socklen_t * addrlen) +{ + int ret; + spl_netconn_t *conn = sbr_get_conn(sk); + + ret = (addr + && addrlen) ? sbr_get_sockaddr_and_len(ss_get_remote_port(conn), + ss_get_remote_ip(conn), + addr, addrlen) : 0; + if (0 != ret) + { + sbr_set_sk_io_errno(sk, EINVAL); + NSSBR_LOGERR("sbr_tcp_get_sockaddr]fd=%d", sk->fd); + return -1; + } + + return 0; +} + +static int +sbr_tcp_accept_socket(sbr_socket_t * sk, sbr_socket_t * new_sk, + struct sockaddr *addr, socklen_t * addrlen) +{ + int err; + spl_netconn_t *newconn = NULL; + + err = sbr_tcp_wait_new_conn(sk, (void **) &newconn); + if (ERR_OK != err) + { + return err; + } + + err = sbr_init_conn_for_accept(new_sk, newconn); + if (ERR_OK != err) + { + /*When conn is null, return err; then do not need to free conn */ + return err; + } + + err = sbr_tcp_get_sockaddr(new_sk, addr, addrlen); + if (ERR_OK != err) + { + NSSBR_LOGERR("sbr_get_sockaddr_and_socklen]ret=%d.", err); + sbr_tcp_accept_failed(new_sk); + return -1; + } + + NSSBR_LOGINF + ("return]listen fd=%d,listen conn=%p,listen private_data=%p,accept fd=%d,accept conn=%p,accept private_data=%p", + sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk)), + new_sk->fd, sbr_get_conn(new_sk), + ss_get_private_data(sbr_get_conn(new_sk))); + + //ip_addr_info_print(SOCKETS_DEBUG, &sbr_get_conn(new_sk)->share_remote_ip); + + /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and + send a msg from peer. The event will be given once epoll_wait is called. + Now, modify to IN|OUT. Calling epoll_event should return immediately since + the socket is writable. Currently, returns 0 events. + This issue is fixed here + */ + + /* Prevent automatic window updates, we do this on our own! */ + ss_set_noautorecved_flag(sbr_get_conn(new_sk), 1); + + ss_set_send_event(sbr_get_conn(new_sk), 1); + + /* don't set conn->last_err: it's only ERR_OK, anyway */ + return ERR_OK; +} + +NSTACK_STATIC int +sbr_tcp_accept(sbr_socket_t * sk, sbr_socket_t * new_sk, + struct sockaddr *addr, socklen_t * addrlen) +{ + int err; + + /* If conn is not in listen state then return failure with error code: EINVAL(22) */ + if (!ss_is_listen_state(sbr_get_conn(sk))) + { + NSSBR_LOGERR("fd is not listening for connections]fd=%d,err=%d", + sk->fd, EINVAL); + sbr_set_sk_errno(sk, EINVAL); + + return -1; + } + + if (ss_is_nonblock_flag(sbr_get_conn(sk)) + && (0 >= ss_get_recv_event(sbr_get_conn(sk)))) + { + NSSBR_LOGERR("fd is nonblocking and rcvevent<=0]fd=%d,err=%d", sk->fd, + EWOULDBLOCK); + sbr_set_sk_errno(sk, EWOULDBLOCK); + + return -1; + } + + err = ss_get_last_errno(sbr_get_conn(sk)); + if (SPL_ERR_IS_FATAL(err)) + { + /* don't recv on fatal errors: this might block the application task + waiting on acceptmbox forever! */ + sbr_set_sk_errno(sk, sbr_spl_err_to_errno(err)); + + return -1; + } + + /* wait for a new connection */ + err = sbr_tcp_accept_socket(sk, new_sk, addr, addrlen); + if (ERR_OK != err) + { + NSSBR_LOGERR("sbr_tcp_accept_socket failed]fd=%d,err=%d", sk->fd, + err); + + return -1; + } + + /* Prevent automatic window updates, we do this on our own! */ + ss_sub_recv_event(sbr_get_conn(sk)); + + sbr_set_sk_errno(sk, ERR_OK); + + /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and + send a msg from peer. The event will be given once epoll_wait is called. + Now, modify to IN|OUT. Calling epoll_event should return immediately since + the socket is writable. Currently, returns 0 events. + This issue is fixed here + */ + + ss_set_send_event(sbr_get_conn(new_sk), 1); + + return new_sk->fd; +} + +NSTACK_STATIC int +sbr_tcp_accept4(sbr_socket_t * sk, sbr_socket_t * new_sk, + struct sockaddr *addr, socklen_t * addrlen, int flags) +{ + int fd = sbr_tcp_accept(sk, new_sk, addr, addrlen); + + if (0 > fd) + { + return fd; + } + + if (flags & O_NONBLOCK) + { + int opts = new_sk->fdopt->fcntl(new_sk, F_GETFL, 0); + if (opts < 0) + { + NSSBR_LOGERR("sbr_tcp_fcntl(sock,GETFL)"); + sbr_tcp_accept_failed(new_sk); + return -1; + } + + opts = opts | O_NONBLOCK; + + if (new_sk->fdopt->fcntl(new_sk, F_SETFL, opts) < 0) + + { + NSSBR_LOGERR("sbr_tcp_fcntl(sock,F_SETFL,opts)"); + sbr_tcp_accept_failed(new_sk); + return -1; + } + } + + return new_sk->fd; +} + +NSTACK_STATIC int +sbr_tcp_connect(sbr_socket_t * sk, const struct sockaddr *name, + socklen_t namelen) +{ + const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name; + + NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd, + spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port), + sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); + spl_ip_addr_t remote_addr; + + inet_addr_to_ipaddr(&remote_addr, &addr_in->sin_addr); + u16 remote_port = addr_in->sin_port; + + spl_ip_addr_t local_addr = { IPADDR_ANY }; + + if (sbr_handle_connect(sk, &remote_addr, ntohs(remote_port), &local_addr) + != 0) + { + NSSBR_LOGERR("fail]fd=%d", sk->fd); + return -1; + } + + if (ss_is_shut_rd(sbr_get_conn(sk))) + { + NSSBR_LOGERR("shut_rd]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ECONNRESET); + return -1; + } + + NSSBR_LOGINF("succeeded]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ERR_OK); + + return 0; +} + +static u8 netconn_shutdown_opt[] = { + SPL_NETCONN_SHUT_RD, + SPL_NETCONN_SHUT_WR, + SPL_NETCONN_SHUT_RDWR +}; + +NSTACK_STATIC int sbr_tcp_shutdown(sbr_socket_t * sk, int how) +{ + err_t err; + + if (ss_is_listen_state(sbr_get_conn(sk))) + { + return 0; + } + + ss_set_shut_status(sbr_get_conn(sk), how); + + err = sbr_handle_shutdown(sk, netconn_shutdown_opt[how]); + + return (err == ERR_OK ? 0 : -1); +} + +NSTACK_STATIC int +sbr_tcp_getsockname(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen) +{ + + NSSBR_LOGINF("sockname]fd=%d,tcp_state=%d", sk->fd, + ss_get_tcp_state(sbr_get_conn(sk))); + + return sbr_handle_get_name(sk, name, namelen, SBR_GET_SOCK_NAME); +} + +NSTACK_STATIC int +sbr_tcp_getpeername(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen) +{ + + if (SPL_CLOSED == ss_get_tcp_state(sbr_get_conn(sk))) + { + NSSBR_LOGERR("connection not exist]fd=%d", sk->fd); + sbr_set_sk_errno(sk, ENOTCONN); + return -1; + } + + NSSBR_LOGINF("peername]fd=%d,tcp_state=%d", sk->fd, + ss_get_tcp_state(sbr_get_conn(sk))); + + return sbr_handle_get_name(sk, name, namelen, SBR_GET_PEER_NAME); +} + +static int +sbr_getsockopt_ipproto_tcp(int optname, void *optval, socklen_t optlen) +{ + int err = ERR_OK; + + switch (optname) + { + case SPL_TCP_NODELAY: + break; + case SPL_TCP_KEEPIDLE: + case SPL_TCP_KEEPINTVL: + case SPL_TCP_KEEPCNT: + case SPL_TCP_INFO: + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +NSTACK_STATIC int inline sbr_tcp_set_sockopt_err(sbr_socket_t * sk, int err) +{ + if (ENOPROTOOPT == err) + { + return 0; + } + else + { + sbr_set_sk_errno(sk, err); + return -1; + } +} + +NSTACK_STATIC int inline sbr_tcp_get_sockopt_err(sbr_socket_t * sk, int err) +{ + sbr_set_sk_errno(sk, err); + return -1; +} + +NSTACK_STATIC int +sbr_tcp_getsockopt(sbr_socket_t * sk, int level, int optname, void *optval, + socklen_t * optlen) +{ + int err = 0; + + switch (level) + { + case SOL_SOCKET: + err = sbr_getsockopt_sol_socket(sk, optname, optval, *optlen); + break; + + case IPPROTO_IP: + err = sbr_getsockopt_ipproto_ip(optname, optval, *optlen); + break; + + case IPPROTO_TCP: + err = sbr_getsockopt_ipproto_tcp(optname, optval, *optlen); + break; + + case NSTACK_SOCKOPT: + if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof(u32_t))) + { + *(u32_t *) optval = + sbr_get_fd_share(sk)->block_polling_time / 1000; + NSSOC_LOGINF + ("tcp get recv sleep time success, usleep time = %d,fd = %d", + sbr_get_fd_share(sk)->block_polling_time, sk->fd); + return ERR_OK; + } + else + { + NSSOC_LOGINF("get recv sleep time failed, fd = %d", sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + default: + err = ENOPROTOOPT; + break; + } + + if (0 != err) + { + NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level, + optname, err); + /* for option not support ,getsockopt() should return fail */ + return sbr_tcp_get_sockopt_err(sk, err); + } + + return sbr_handle_getsockopt(sk, level, optname, optval, optlen); +} + +int sbr_setsockopt_ipproto_tcp(int optname, socklen_t optlen) +{ + int err = 0; + + if (optlen < sizeof(int)) + { + return EINVAL; + } + + switch (optname) + { + case SPL_TCP_KEEPIDLE: + case SPL_TCP_KEEPINTVL: + case SPL_TCP_KEEPCNT: + break; + default: + err = ENOPROTOOPT; + break; + } + + return err; +} + +NSTACK_STATIC int +sbr_tcp_setsockopt(sbr_socket_t * sk, int level, int optname, + const void *optval, socklen_t optlen) +{ + int err = 0; + + switch (level) + { + case SOL_SOCKET: + err = + sbr_setsockopt_sol_socket(sk, optname, optval, optlen, + SPL_NETCONN_TCP); + break; + case IPPROTO_IP: + err = + sbr_setsockopt_ipproto_ip(optname, optval, optlen, + SPL_NETCONN_TCP); + break; + case IPPROTO_TCP: + err = sbr_setsockopt_ipproto_tcp(optname, optlen); + break; + case NSTACK_SOCKOPT: + { + u32_t sleep_time = *(u32_t *) optval; + /*sleep time should less than 1s */ + if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof(u32_t)) + && (sleep_time < 1000000)) + { + sbr_get_fd_share(sk)->block_polling_time = + sleep_time * 1000; + NSSOC_LOGINF + ("tcp set recv sleep time success, usleep time = %d,fd = %d", + sbr_get_fd_share(sk)->block_polling_time, sk->fd); + return ERR_OK; + } + else + { + NSSOC_LOGINF("set recv sleep time failed, fd = %d", + sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + } + + default: + err = ENOPROTOOPT; + break; + } + + if (0 != err) + { + NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level, + optname, err); + + return sbr_tcp_set_sockopt_err(sk, err); + } + + return sbr_handle_setsockopt(sk, level, optname, optval, optlen); +} + +static inline u16 sbr_tcp_mbuf_count(struct spl_pbuf *p) +{ + u16 count = 0; + struct spl_pbuf *buf = p; + struct common_mem_mbuf *mbuf; + + while (buf) + { + mbuf = + (struct common_mem_mbuf *) ((char *) buf - + sizeof(struct common_mem_mbuf)); + while (mbuf) + { + count++; +#ifdef HAL_LIB +#else + mbuf = mbuf->next; +#endif + } + + buf = (struct spl_pbuf *) ADDR_SHTOL(buf->next_a); + } + + return count; +} + +static inline void sbr_tcp_free_recvbuf(sbr_socket_t * sk, struct spl_pbuf *p) +{ + int len; + + if (ss_is_noautorecved_flag(sbr_get_conn(sk))) + { + len = sbr_tcp_mbuf_count(p); + sbr_handle_tcp_recv(sk, len, p); + } +} + +static inline void +sbr_tcp_recv_no_peak(sbr_socket_t * sk, struct spl_pbuf *buf, u32 buflen, + u32 copylen) +{ + if ((buflen - copylen) > 0) + { + sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf); + sbr_get_fd_share(sk)->lastoffset += copylen; + } + else + { + sbr_get_fd_share(sk)->lastdata = 0; + sbr_get_fd_share(sk)->lastoffset = 0; + sbr_tcp_free_recvbuf(sk, buf); + } +} + +static inline int +sbr_tcp_recv_from_ring(sbr_socket_t * sk, struct spl_pbuf **buf, i32 timeout) +{ + int err; + spl_netconn_t *conn = sbr_get_conn(sk); + + err = ss_get_last_errno(conn); + if (SPL_ERR_IS_FATAL(err)) + { + /* don't recv on fatal errors: this might block the application task + waiting on recvmbox forever! */ + + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ + NSSBR_LOGDBG("last err when recv:]=%d", err); + if (ERR_CLSD != err) + { + sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err)); + return -1; + } + } + + *buf = NULL; + if (0 != sbr_dequeue_buf(sk, (void **) buf, timeout)) + { + return -1; + } + + ss_sub_recv_avail(sbr_get_conn(sk), (*buf)->tot_len); + + ss_sub_recv_event(sbr_get_conn(sk)); + + return 0; +} + +static inline int sbr_tcp_recv_state_check(sbr_socket_t * sk) +{ + + spl_tcp_state_t state = ss_get_tcp_state(sbr_get_conn(sk)); + + NSSBR_LOGDBG("tcp state when recv:]=%d", state); + + //close_wait state also can recive data + //no connect cannot recive data + if (SPL_ESTABLISHED > state) + { + if (SPL_SHUT_WR != ss_get_shut_status(sbr_get_conn(sk))) + { + /* after all data retrnasmission, connection is active */ + /* patch solution as last_err is not maintained properly */ + if ((SPL_CLOSED == state) + && (ERR_TIMEOUT == ss_get_last_errno(sbr_get_conn(sk)))) + { + sbr_set_sk_io_errno(sk, ETIMEDOUT); + } + else if ((SPL_CLOSED == state) + && (ERR_RST == ss_get_last_errno(sbr_get_conn(sk)))) + { + sbr_set_sk_io_errno(sk, ECONNRESET); + } + else + { + sbr_set_sk_io_errno(sk, ENOTCONN); + } + + return -1; + } + } + + return 0; +} + +NSTACK_STATIC int +sbr_tcp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t * fromlen) +{ + struct spl_pbuf *p; + u32 buflen; + u32 copylen; + u32 off = 0; + u8 done = 0; + int para_len = len; + int retval = 0; + + sbr_com_lock_recv(sk); + NSSOC_LOGINF("recv start, fd = %d last data %p flags to be set %d", + sk->fd, ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata), + MSG_DONTWAIT); + + if (0 != sbr_tcp_recv_state_check(sk)) + { + retval = -1; + goto sbr_tcp_recvfrom_exit; + } + + do + { + if (sbr_get_fd_share(sk)->lastdata) + { + p = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + } + else + { + if ((flags & MSG_DONTWAIT) + || ss_is_nonblock_flag(sbr_get_conn(sk))) + { + NSSOC_LOGINF("call ss_get_recv_event"); + if (0 >= ss_get_recv_event(sbr_get_conn(sk))) + { + NSSOC_LOGINF("no recv event]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + retval = -1; + goto sbr_tcp_recvfrom_exit; + } + } + + if (0 != + sbr_tcp_recv_from_ring(sk, &p, + sbr_get_fd_share(sk)->recv_timeout)) + { + /* already received data, return that */ + if (off > 0) + { + sbr_set_sk_io_errno(sk, ERR_OK); + retval = off; + goto sbr_tcp_recvfrom_exit; + } + + /* we tell the user the connection is closed by returning zero */ + if (sbr_get_sk_errno(sk) == ENOTCONN) + { + retval = 0; + goto sbr_tcp_recvfrom_exit; + } + + retval = -1; + goto sbr_tcp_recvfrom_exit; + } + + sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(p); + } + + buflen = p->tot_len - sbr_get_fd_share(sk)->lastoffset; + copylen = len > buflen ? buflen : len; + + if ((copylen > 0) + && 0 == spl_pbuf_copy_partial(p, (u8 *) mem + off, copylen, + sbr_get_fd_share(sk)->lastoffset)) + { + NSSBR_LOGERR("copy failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EFAULT); + retval = -1; + goto sbr_tcp_recvfrom_exit; + } + + off += copylen; + + len -= copylen; + + if ((len == 0) || (ss_get_recv_event(sbr_get_conn(sk)) <= 0) + || ((flags & MSG_PEEK) != 0)) + { + if ((off >= sbr_get_fd_share(sk)->rcvlowat) + || (para_len <= sbr_get_fd_share(sk)->rcvlowat)) + { + done = 1; + } + } + + if (done) + { + if (sbr_tcp_get_sockaddr(sk, from, fromlen) != 0) + { + retval = -1; + goto sbr_tcp_recvfrom_exit; + } + } + + /* If this is a TCP socket, check if there is data left in the buffer, + If so, it should be saved in the sock structure for next time around. */ + if (!(flags & MSG_PEEK)) + { + sbr_tcp_recv_no_peak(sk, p, buflen, copylen); + } + } + while (!done); + + retval = off; + + NSSOC_LOGINF("recv done, fd = %d last data %p", sk->fd); + sbr_tcp_recvfrom_exit: + + NSSOC_LOGINF("recv exit, fd = %d last data %p", sk->fd); + sbr_com_unlock_recv(sk); + return retval; +} + +/***************************************************************************** +* Prototype : sbr_tcp_recvdata +* Description : recvdata +* Input : sbr_socket_t* sk +* const struct iovec* iov +* int iovcnt +* int flags +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_tcp_recvdata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt) +{ + int max = SBR_MAX_INTEGER; + int len = 0; + int ret = 0; + int i = 0; + + do + { + len += ret; + + if (!iov[i].iov_base || (0 == iov[i].iov_len)) + { + ret = 0; + continue; + } + + ret = + sbr_tcp_recvfrom(sk, (char *) iov[i].iov_base, iov[i].iov_len, 0, + NULL, NULL); + } + while ((ret == (int) iov[i].iov_len) && (iovcnt > (++i)) + && (max - len - ret > (int) iov[i].iov_len)); + + if (len == 0) + { + return ret; + } + else + { + return (ret == -1 ? len : len + ret); + } +} + +/***************************************************************************** +* Prototype : sbr_tcp_readv +* Description : readv +* Input : sbr_socket_t* sk +* const struct iovec* iov +* int iovcnt +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_tcp_readv(sbr_socket_t * sk, const struct iovec *iov, int iovcnt) +{ + return sbr_tcp_recvdata(sk, iov, iovcnt); +} + +/***************************************************************************** +* Prototype : sbr_tcp_recvmsg +* Description : recvmsg,unsupport flags +* Input : sbr_socket_t* sk +* struct msghdr* msg +* int flags +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_tcp_recvmsg(sbr_socket_t * sk, struct msghdr *msg, int flags) +{ + if (sbr_tcp_get_sockaddr + (sk, (struct sockaddr *) msg->msg_name, &msg->msg_namelen) != 0) + { + return -1; + } + + return sbr_tcp_recvdata(sk, msg->msg_iov, msg->msg_iovlen); +} + +static int +sbr_tcp_send_is_timeout(sbr_socket_t * sk, struct timespec *starttm) +{ + struct timespec currtm; + i64 timediff_ms, timediff_sec; + i64 timeout_thr_ms, timeout_thr_sec; + + timeout_thr_ms = sbr_get_fd_share(sk)->send_timeout; + if (0 == timeout_thr_ms) + { + return 0; + } + + /* it is possible that starttm don't be inited, + if send_timeout is change when this write function is running */ + timeout_thr_sec = (timeout_thr_ms + 240) >> 10; + + /* Handle system time change side-effects */ + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &currtm))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + + timediff_sec = currtm.tv_sec - starttm->tv_sec; + if (timediff_sec >= timeout_thr_sec) + { + timediff_ms = currtm.tv_nsec > starttm->tv_nsec ? + (timediff_sec * 1000) + (currtm.tv_nsec - + starttm->tv_nsec) / + USEC_TO_SEC : (timediff_sec * 1000) - + ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC); + + /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value + will be negetive if still 0.5 ms is not elapsed. this is intended and we should + not typecast to any unsigned type during this below if check */ + if (timediff_ms > timeout_thr_ms) + { + return 1; + } + } + + return 0; +} + +static inline int +sbr_tcp_write_is_wait(sbr_socket_t * sk, struct timespec *starttm, + int noneblockFlg) +{ + if (noneblockFlg || sbr_tcp_send_is_timeout(sk, starttm)) + { + return 0; + } + else + { + return 1; + } +} + +static struct spl_pbuf *sbr_tcp_write_alloc_buf(sbr_socket_t * sk, + size_t seglen, u8 api_flag, + struct timespec *starttm, + u8 * errno_flag) +{ + spl_netconn_t *conn = sbr_get_conn(sk); + + struct spl_pbuf *curr_buf = NULL; + size_t head_len = SPL_TCP_HLEN + SPL_PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN; + int noneblockFlg = (api_flag & SPL_NETCONN_DONTBLOCK) + || ss_is_nonblock_flag(sbr_get_conn(sk)); + + do + { + /* When packages are lost more than TCP_MAXRTX times, + * conn will be closed and pcb will be removed. */ + if (ss_get_tcp_state(conn) == SPL_CLOSED) + { + NSSBR_LOGERR("pcb SPL_CLOSED]conn=%p", conn); + sbr_set_sk_io_errno(sk, ECONNABORTED); + /* Must set errno_flag when set errno, to avoid errnno overwritten by sbr_tcp_write */ + *errno_flag = 1; + return NULL; + } + + curr_buf = sbr_malloc_tx_pbuf(seglen + head_len, head_len); + if (NULL == curr_buf) + { + if (!sbr_tcp_write_is_wait(sk, starttm, noneblockFlg)) + { + return NULL; + } + + int err = ss_get_last_errno(sbr_get_conn(sk)); + if (SPL_ERR_IS_FATAL(err)) + { + NSSBR_LOGERR("connection fatal error!err=%d", err); + sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err)); + *errno_flag = 1; + return NULL; + } + + sched_yield(); + } + } + while (curr_buf == NULL); + + return curr_buf; +} + +static inline void +sbr_tcp_write_rel_buf(sbr_socket_t * sk, struct spl_pbuf *buf, + u32 thread_index) +{ + if (buf != NULL) + { + sbr_handle_free_send_buf(sk, buf); + } +} + +static inline int +sbr_tcp_write_fill_buf(const void *data, size_t * pos, + struct spl_pbuf *seg_buf, size_t seglen, size_t optlen) +{ + size_t start = *pos; + size_t copy = seglen; + struct spl_pbuf *first = seg_buf; + + while ((0 < copy) && (NULL != first)) + { + char *dst_ptr = PTR_SHTOL(char *, first->payload_a) + optlen; + + if (NULL == + common_memcpy(dst_ptr, (u8_t *) data + start, + first->len - optlen)) + { + NSSBR_LOGERR("common_memcpy error]dst=%p,src=%p,len=%u", + dst_ptr, (u8_t *) data + start, first->len); + return -1; + } + + start += (first->len - optlen); + copy -= (first->len - optlen); + first = ADDR_SHTOL(first->next_a); + } + + (*pos) = start; + + return 0; +} + +static inline int +sbr_tcp_writev_fill_buf(const struct iovec *iov, size_t * iov_pos, + int *iov_var, size_t * pos, struct spl_pbuf *seg_buf, + size_t seglen, size_t optlen) +{ + size_t valid_copy_len; + size_t iov_data_left; + + size_t copy = seglen; + size_t start = *pos; + size_t current_iov_pos = *iov_pos; + int current_iov_var = *iov_var; + + u32 pbuf_offset = optlen; + u32 pbuf_data_len; + struct spl_pbuf *first = seg_buf; + + while ((0 < copy) && (NULL != first)) + { + iov_data_left = iov[current_iov_var].iov_len - current_iov_pos; + if (seglen == copy) + { + pbuf_offset = optlen; + } + + pbuf_data_len = first->len - pbuf_offset; + valid_copy_len = + (iov_data_left > pbuf_data_len ? pbuf_data_len : iov_data_left); + if (NULL == + common_memcpy((char *) ADDR_SHTOL(first->payload_a) + pbuf_offset, + (u8_t *) iov[current_iov_var].iov_base + + current_iov_pos, valid_copy_len)) + { + NSSBR_LOGERR + ("common_memcpy error]current_iov_var=%d, dst=%p,src=%p,len=%zu", + current_iov_var, + (char *) ADDR_SHTOL(first->payload_a) + pbuf_offset, + (u8_t *) iov[current_iov_var].iov_base + current_iov_pos, + valid_copy_len); + return -1; + } + + start += valid_copy_len; + copy -= valid_copy_len; + + if (iov_data_left == pbuf_data_len) + { + first = PTR_SHTOL(struct spl_pbuf *, first->next_a); + pbuf_offset = optlen; //+= valid_copy_len; + current_iov_var++; + current_iov_pos = 0; + } + else if (iov_data_left > pbuf_data_len) + { + first = PTR_SHTOL(struct spl_pbuf *, first->next_a); + pbuf_offset = optlen; //+= valid_copy_len; + current_iov_pos += valid_copy_len; + } + else + { + pbuf_offset += valid_copy_len; + + current_iov_var++; + current_iov_pos = 0; + } + } + + *iov_pos = current_iov_pos; + *iov_var = current_iov_var; + *pos = start; + + return 0; +} + +static inline void +sbr_tcp_write_add_buf_to_list(struct spl_pbuf **p_head, + struct spl_pbuf **p_tail, + struct spl_pbuf *seg_buf, size_t seglen, + size_t optlen) +{ + seg_buf->len = seglen + optlen; + seg_buf->tot_len = seglen + optlen; + seg_buf->next_a = 0; + + /*put seg_buf after p_head */ + if (NULL == (*p_head)) + { + (*p_head) = seg_buf; + (*p_tail) = seg_buf; + } + else + { + (*p_tail)->next_a = ADDR_LTOSH(seg_buf); + (*p_tail) = seg_buf; + } +} + +NSTACK_STATIC int +sbr_tcp_write(sbr_socket_t * sk, const void *data, size_t size, u8 api_flag, + size_t * written) +{ + err_t err = -1; + size_t pos = 0, left, seglen; + u32 pbuf_seg_cnt = 0; + u32 thread_index = 0; + struct spl_pbuf *seg_buf = NULL; + struct spl_pbuf *p_head = NULL; + struct spl_pbuf *p_tail = p_head; + struct spl_netconn *conn = sbr_get_conn(sk); + u32 mss = ss_get_mss(sbr_get_conn(sk)); + + if (0 == size) + { + NSSBR_LOGERR("fd=%d,size=%u", sk->fd, (u32) size); + return 0; + } + + struct timespec ts; + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &ts))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + + while (pos < size) + { + left = size - pos; + seglen = left > mss ? mss : left; + u8 errno_set = 0; + seg_buf = + sbr_tcp_write_alloc_buf(sk, seglen, api_flag, &ts, &errno_set); + if (NULL == seg_buf) + { + NSSBR_LOGINF("sbr_tcp_write_alloc_buf failed......"); + if (NULL != p_head) + { + err = sbr_handle_tcp_send(sk, size, p_head, api_flag); + if (ERR_OK != err) + { + NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err); + goto err_ref_buf; + } + } + + if (0 == pos) + { + /* If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */ + if (!errno_set) + { + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + } + return -1; + } + + NSSBR_LOGDBG("sent size %zu", pos); + *written = pos; + + return ERR_OK; + } + + if (0 != sbr_tcp_write_fill_buf(data, &pos, seg_buf, seglen, 0)) + { + sbr_set_sk_io_errno(sk, EFAULT); + NSSBR_LOGERR("sbr_tcp_write_fill_buf error]"); + goto err_ref_buf; + } + + sbr_tcp_write_add_buf_to_list(&p_head, &p_tail, seg_buf, seglen, 0); + + ++pbuf_seg_cnt; + if (p_head + && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt) + || (pos >= size))) + { + pbuf_seg_cnt = 0; + err = sbr_handle_tcp_send(sk, size, p_head, api_flag); + if (ERR_OK != err) + { + NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err); + goto err_ref_buf; + } + + p_head = NULL; + } + } + + *written = size; + + (void) conn; + return ERR_OK; + + err_ref_buf: + sbr_tcp_write_rel_buf(sk, p_head, thread_index); + (void) conn; + return -1; +} + +NSTACK_STATIC int +sbr_tcp_writev(sbr_socket_t * sk, const struct iovec *iov, int iovcnt) +{ + err_t err = -1; + int idx = 0; + size_t pos = 0, left, seglen, optlen = 0; + u32 pbuf_seg_cnt = 0; + u32 thread_index = 0; + size_t size = 0; + size_t iov_pos = 0; + int iov_var = 0; + struct spl_pbuf *seg_buf = NULL; + struct spl_pbuf *p_head = NULL; + struct spl_pbuf *p_tail = p_head; + struct spl_netconn *conn = sbr_get_conn(sk); + u32 mss = ss_get_mss(sbr_get_conn(sk)); + + if (mss <= optlen) + { + NSSBR_LOGERR("mss invalid]mss=%u,optlen=%zu,fd=%d", mss, optlen, + sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + + /* mss dose't include the tcp options length */ + mss -= optlen; + + while (idx < iovcnt) + { + if (SBR_MAX_INTEGER - iov[idx].iov_len <= size) + { + size = SBR_MAX_INTEGER; + break; + } + + size += iov[idx].iov_len; + idx++; + } + + struct timespec starttm; + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &starttm))) + { + NSSBR_LOGERR("Failed to get time, errno = %d", errno); + } + + while (pos < size) + { + left = size - pos; + + seglen = left > mss ? mss : left; + u8 errno_set = 0; + seg_buf = + sbr_tcp_write_alloc_buf(sk, seglen + optlen, SPL_NETCONN_COPY, + &starttm, &errno_set); + if (NULL == seg_buf) + { + if (NULL != p_head) + { + err = sbr_handle_tcp_send(sk, size, p_head, SPL_NETCONN_COPY); + /*If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */ + if (err != ERR_OK) + { + NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err); + goto err_ref_buf; + } + } + + /* [Start] + 1)Set SO_SNDTIMEO to 10 + 2)Send a msg of larger buff size.and let the timeout happen for send (dont receive at peer side.) + 3)iRet will be 0 and errno received will be 11 (EAGAIN). + + Above issue is fixed. + */ + if (0 == pos) + { + if (!errno_set) + { + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + } + return -1; + } + /* [End] */ + + NSSBR_LOGDBG("sent size %zu", pos); + + return pos; + } + + if (0 != + sbr_tcp_writev_fill_buf(iov, &iov_pos, &iov_var, &pos, seg_buf, + seglen, optlen)) + { + sbr_set_sk_io_errno(sk, EFAULT); + NSSBR_LOGERR("sbr_tcp_writev_fill_buf error]"); + goto err_ref_buf; + } + + sbr_tcp_write_add_buf_to_list(&p_head, &p_tail, seg_buf, seglen, + optlen); + + /* @todo: for non-blocking write, check if 'size' would ever fit into + snd_queue or snd_buf */ + ++pbuf_seg_cnt; + if (p_head + && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt) + || (pos >= size))) + { + pbuf_seg_cnt = 0; + err = sbr_handle_tcp_send(sk, size, p_head, SPL_NETCONN_COPY); + if (ERR_OK != err) + { + NSSBR_LOGERR("sbr_handle_tcp_send error]err(%d)", err); + goto err_ref_buf; + } + + p_head = NULL; + } + } + (void) conn; + return size; + + err_ref_buf: + sbr_tcp_write_rel_buf(sk, p_head, thread_index); + (void) conn; + return -1; +} + +NSTACK_STATIC int +sbr_tcp_sendto(sbr_socket_t * sk, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + return sk->fdopt->send(sk, data, size, flags); +} + +static inline int sbr_tcp_send_state_check(sbr_socket_t * sk) +{ + if ((SPL_SHUT_WR == ss_get_shut_status(sbr_get_conn(sk))) + || (SPL_SHUT_RDWR == ss_get_shut_status(sbr_get_conn(sk)))) + { + sbr_set_sk_io_errno(sk, EPIPE); + return -1; + } + + spl_tcp_state_t state = ss_get_tcp_state(sbr_get_conn(sk)); + if ((SPL_ESTABLISHED != state) && (SPL_CLOSE_WAIT != state)) + { + /* after all data retrnasmission, connection is active */ + /* patch solution as last_err is not maintained properly */ + if ((SPL_CLOSED == state) + && (ERR_TIMEOUT == ss_get_last_errno(sbr_get_conn(sk)))) + { + sbr_set_sk_io_errno(sk, ETIMEDOUT); + } + else if ((SPL_CLOSED == state) + && (ERR_RST == ss_get_last_errno(sbr_get_conn(sk)))) + { + sbr_set_sk_io_errno(sk, ECONNRESET); + } + else + { + sbr_set_sk_io_errno(sk, EPIPE); + } + + return -1; + } + + return 0; +} + +NSTACK_STATIC int +sbr_tcp_send(sbr_socket_t * sk, const void *data, size_t size, int flags) +{ + int err; + size_t written = 0; + u8 write_flags; + + if (0 != sbr_tcp_send_state_check(sk)) + { + NSSBR_LOGDBG("tcp state not correct]fd=%d, err=%d", sk->fd, + sbr_get_sk_errno(sk)); + return -1; + } + + write_flags = SPL_NETCONN_COPY | + ((flags & MSG_MORE) ? SPL_NETCONN_MORE : 0) | + ((flags & MSG_DONTWAIT) ? SPL_NETCONN_DONTBLOCK : 0); + + NSSBR_LOGINF("Sbr tcp write start"); + err = sbr_tcp_write(sk, data, size, write_flags, &written); + NSSBR_LOGINF("Sbr tcp write end written %d", written); + + return (err == ERR_OK ? written : -1); +} + +NSTACK_STATIC int +sbr_tcp_sendmsg(sbr_socket_t * sk, const struct msghdr *pmsg, int flags) +{ + if (0 != sbr_tcp_send_state_check(sk)) + { + NSSBR_LOGDBG("tcp state not correct]fd=%d, err=%d", sk->fd, + sbr_get_sk_errno(sk)); + return -1; + } + + return sbr_tcp_writev(sk, pmsg->msg_iov, pmsg->msg_iovlen); +} + +NSTACK_STATIC int sbr_tcp_fcntl(sbr_socket_t * sk, int cmd, long arg) +{ + int ret = 0; + + switch (cmd) + { + case F_GETFL: + ret = ss_get_nonblock_flag(sbr_get_conn(sk)); + NSSBR_LOGDBG("F_GETFL]fd=%d,ret=%d", sk->fd, ret); + break; + + case F_SETFL: + if (arg & O_NONBLOCK) + { + NSSBR_LOGDBG("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld", + sk->fd, arg); + ss_set_nonblock_flag(sbr_get_conn(sk), (arg & O_NONBLOCK)); + } + else + { + NSSBR_LOGDBG("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld", + sk->fd, arg); + ss_set_nonblock_flag(sbr_get_conn(sk), 0); + } + + break; + + default: + NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd); + ret = -1; + sbr_set_sk_errno(sk, EINVAL); + break; + } + + return ret; +} + +NSTACK_STATIC int +sbr_tcp_ioctl(sbr_socket_t * sk, unsigned long cmd, void *arg) +{ + int ret = 0; + int recv_avail; + + switch (cmd) + { + case FIONREAD: + { + if (ss_is_listen_state(sbr_get_conn(sk))) + { + ret = -1; + sbr_set_sk_errno(sk, EINVAL); + break; + } + + recv_avail = ss_get_recv_avail(sbr_get_conn(sk)); + *((u32 *) arg) = recv_avail >= 0 ? recv_avail : 0; + if (sbr_get_fd_share(sk)->lastdata) + { + struct spl_pbuf *buf = + ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + *((u32 *) arg) += + (buf->tot_len - sbr_get_fd_share(sk)->lastoffset); + } + } + + break; + + case FIONBIO: + { + u8 val = 0; + + if (arg && *(u32 *) arg) + { + val = 1; + } + + ss_set_nonblock_flag(sbr_get_conn(sk), val); + NSSBR_LOGDBG("FIONBIO]fd=%d,val=%u", sk->fd, val); + } + + break; + + default: + { + NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd); + ret = -1; + sbr_set_sk_errno(sk, ENOTTY); + } + break; + } + + return ret; +} + +NSTACK_STATIC int sbr_tcp_close(sbr_socket_t * sk) +{ + if (sbr_get_fd_share(sk)->lastdata) + { + struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + sbr_tcp_free_recvbuf(sk, p); + } + + return sbr_handle_close(sk, 0); +} + +sbr_fdopt tcp_fdopt = { + .socket = sbr_tcp_socket, + .bind = sbr_tcp_bind, + .listen = sbr_tcp_listen, + .accept = sbr_tcp_accept, + .accept4 = sbr_tcp_accept4, + .connect = sbr_tcp_connect, + .shutdown = sbr_tcp_shutdown, + .getsockname = sbr_tcp_getsockname, + .getpeername = sbr_tcp_getpeername, + .getsockopt = sbr_tcp_getsockopt, + .setsockopt = sbr_tcp_setsockopt, + .recvfrom = sbr_tcp_recvfrom, + .readv = sbr_tcp_readv, + .recvmsg = sbr_tcp_recvmsg, + .send = sbr_tcp_send, + .sendto = sbr_tcp_sendto, + .sendmsg = sbr_tcp_sendmsg, + .writev = sbr_tcp_writev, + .fcntl = sbr_tcp_fcntl, + .ioctl = sbr_tcp_ioctl, + .close = sbr_tcp_close, + .peak = sbr_com_peak, + .lock_common = sbr_com_lock_common, + .unlock_common = sbr_com_unlock_common, + .fork_parent = sbr_com_fork_parent, + .fork_child = sbr_com_fork_child, + .ep_getevt = stackx_eventpoll_getEvt, + .ep_triggle = stackx_eventpoll_triggle, + .set_close_stat = NULL, +}; diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_udp.c b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c new file mode 100644 index 0000000..937c444 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c @@ -0,0 +1,1149 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stackx_prot_com.h" +#include "stackx_msg_handler.h" +#include "stackx_pbuf.h" +#include "stackx_epoll_api.h" +#include "stackx_err.h" +#include "nstack_securec.h" +#include "common_pal_bitwide_adjust.h" +#include "stackx_cfg.h" +#include +#ifdef HAL_LIB +#else +#include "rte_memcpy.h" +#endif + +#define SPL_PBUF_UDP_LEN (SPL_FRAME_MTU + SPL_PBUF_LINK_HLEN) +#define L2_L3_ROOM_LEN (SPL_PBUF_LINK_HLEN + SPL_PBUF_IP_HLEN) +#define L4_ROOM_LEN SPL_PBUF_UDP_HLEN + +/***************************************************************************** +* Prototype : sbr_udp_socket +* Description : create socket +* Input : sbr_socket_t * sk +* int domain +* int type +* int protocol +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_socket(sbr_socket_t * sk, int domain, int type, int protocol) +{ + if (sbr_malloc_conn_for_sk(sk, SPL_NETCONN_UDP) != 0) + { + return -1; + } + + int ret = sbr_handle_socket(sk, SPL_NETCONN_UDP, 0); + if (ret != 0) + { + sbr_free_conn_from_sk(sk); + return ret; + } + + ss_set_nonblock_flag(sbr_get_conn(sk), (type & O_NONBLOCK)); + ss_set_send_event(sbr_get_conn(sk), 1); + return ret; +} + +/***************************************************************************** +* Prototype : sbr_udp_bind +* Description : udp bind +* Input : sbr_socket_t * sk +* const struct sockaddr * name +* socklen_t namelen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_bind(sbr_socket_t * sk, const struct sockaddr *name, + socklen_t namelen) +{ + const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name; + + NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd, + spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port), + sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); + spl_ip_addr_t local_addr; + inet_addr_to_ipaddr(&local_addr, &addr_in->sin_addr); + u16 local_port = addr_in->sin_port; + return sbr_handle_bind(sk, &local_addr, ntohs(local_port)); +} + +/***************************************************************************** +* Prototype : sbr_udp_listen +* Description : unsupport +* Input : sbr_socket_t * sk +* int backlog +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_udp_listen(sbr_socket_t * sk, int backlog) +{ + NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd); + sbr_set_sk_errno(sk, EOPNOTSUPP); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_udp_accept +* Description : unsupport +* Input : sbr_socket_t * sk +* sbr_socket_t * new_sk +* struct sockaddr * addr +* socklen_t * addrlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_accept(sbr_socket_t * sk, sbr_socket_t * new_sk, + struct sockaddr *addr, socklen_t * addrlen) +{ + NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd); + sbr_set_sk_errno(sk, EOPNOTSUPP); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_udp_accept4 +* Description : unsupport +* Input : sbr_socket_t * sk +* sbr_socket_t * new_sk +* struct sockaddr * addr +* socklen_t * addrlen +* int flags +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_accept4(sbr_socket_t * sk, sbr_socket_t * new_sk, + struct sockaddr *addr, socklen_t * addrlen, int flags) +{ + NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd); + sbr_set_sk_errno(sk, EOPNOTSUPP); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_udp_connect +* Description : udp connect +* Input : sbr_socket_t * sk +* const struct sockaddr * name +* socklen_t namelen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_connect(sbr_socket_t * sk, const struct sockaddr *name, + socklen_t namelen) +{ + const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name; + + NSSBR_LOGINF("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd, + spl_inet_ntoa(addr_in->sin_addr), ntohs(addr_in->sin_port), + sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); + spl_ip_addr_t remote_addr; + + inet_addr_to_ipaddr(&remote_addr, &addr_in->sin_addr); + u16 remote_port = addr_in->sin_port; + + spl_ip_addr_t local_addr = { IPADDR_ANY }; + + return sbr_handle_connect(sk, &remote_addr, ntohs(remote_port), + &local_addr); +} + +/***************************************************************************** +* Prototype : sbr_udp_shutdown +* Description : udp shutdown +* Input : sbr_socket_t * sk +* int how +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_udp_shutdown(sbr_socket_t * sk, int how) +{ + ss_set_shut_status(sbr_get_conn(sk), how); + NSSBR_LOGERR("type is not TCP]fd=%d", sk->fd); + sbr_set_sk_errno(sk, EOPNOTSUPP); + return -1; +} + +/***************************************************************************** +* Prototype : sbr_udp_getsockname +* Description : get sock name +* Input : sbr_socket_t * sk +* struct sockaddr * name +* socklen_t * namelen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_getsockname(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen) +{ + return sbr_handle_get_name(sk, name, namelen, SBR_GET_SOCK_NAME); +} + +/***************************************************************************** +* Prototype : sbr_udp_getpeername +* Description : get peer name +* Input : sbr_socket_t * sk +* struct sockaddr * name +* socklen_t * namelen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_getpeername(sbr_socket_t * sk, struct sockaddr *name, + socklen_t * namelen) +{ + return sbr_handle_get_name(sk, name, namelen, SBR_GET_PEER_NAME); +} + +/***************************************************************************** +* Prototype : sbr_udp_getsockopt +* Description : get sockopt +* Input : sbr_socket_t * sk +* int level +* int optname +* void * optval +* socklen_t * optlen +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +sbr_udp_getsockopt(sbr_socket_t * sk, int level, int optname, void *optval, + socklen_t * optlen) +{ + int err = 0; + + switch (level) + { + case SOL_SOCKET: + err = sbr_getsockopt_sol_socket(sk, optname, optval, *optlen); + break; + case IPPROTO_IP: + err = sbr_getsockopt_ipproto_ip(optname, optval, *optlen); + break; + + case NSTACK_SOCKOPT: + if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof(u32_t))) + { + *(u32_t *) optval = + sbr_get_fd_share(sk)->block_polling_time / 1000; + NSSOC_LOGINF + ("udp get recv sleep time success]usleep time=%d,fd=%d", + sbr_get_fd_share(sk)->block_polling_time, sk->fd); + return ERR_OK; + } + else + { + NSSOC_LOGINF("get recv sleep time failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + + default: + err = ENOPROTOOPT; + break; + } + + if (err != 0) + { + NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level, + optname, err); + /* for option not support ,getsockopt() should return fail */ + sbr_set_sk_errno(sk, err); + return -1; + } + + return sbr_handle_getsockopt(sk, level, optname, optval, optlen); +} + +/***************************************************************************** +* Prototype : sbr_udp_setsockopt +* Description : set sockopt +* Input : sbr_socket_t * sk +* int level +* int optname +* const void * optval +* socklen_t optlen +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_setsockopt(sbr_socket_t * sk, int level, int optname, + const void *optval, socklen_t optlen) +{ + NSSBR_LOGDBG("udp setsockopt]fd=%d,level=%d,optname=%d", sk->fd, level, + optname); + int err = 0; + switch (level) + { + case SOL_SOCKET: + err = + sbr_setsockopt_sol_socket(sk, optname, optval, optlen, + SPL_NETCONN_UDP); + break; + case IPPROTO_IP: + err = + sbr_setsockopt_ipproto_ip(optname, optval, optlen, + SPL_NETCONN_UDP); + break; + case NSTACK_SOCKOPT: + { + u32_t sleep_time = *(u32_t *) optval; + /*sleep time should less than 1s */ + if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof(u32_t)) + && (sleep_time < 1000000)) + { + sbr_get_fd_share(sk)->block_polling_time = + sleep_time * 1000; + NSSOC_LOGINF + ("udp set recv sleep time success]usleep time=%d,fd=%d", + sbr_get_fd_share(sk)->block_polling_time, sk->fd); + return ERR_OK; + } + else + { + NSSOC_LOGINF("set recv sleep time failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + } + + default: + err = ENOPROTOOPT; + break; + } + + if (err != 0) + { + NSSBR_LOGERR("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level, + optname, err); + + if (ENOPROTOOPT == err) + { + return 0; + } + else + { + sbr_set_sk_errno(sk, err); + return -1; + } + } + + return sbr_handle_setsockopt(sk, level, optname, optval, optlen); +} + +static inline int +sbr_udp_get_from_addr(sbr_socket_t * sk, struct sockaddr *from, + socklen_t * fromlen, struct spl_netbuf *buf) +{ + int ret; + u16 port = netbuf_fromport(buf); + spl_ip_addr_t *addr = netbuf_fromaddr(buf); + + ret = (from + && fromlen) ? sbr_get_sockaddr_and_len(port, addr, from, + fromlen) : 0; + if (0 != ret) + { + sbr_set_sk_io_errno(sk, EINVAL); + NSSBR_LOGERR("sbr_udp_get_from_addr]fd=%d", sk->fd); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_udp_recv_from_ring +* Description : recv buf from ring +* Input : sbr_socket_t * sk +* struct spl_netbuf ** buf +* i32 timeout +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_udp_recv_from_ring(sbr_socket_t * sk, struct spl_netbuf **buf, + i32 timeout) +{ + void *p = NULL; + spl_netconn_t *conn = sbr_get_conn(sk); + + if (sbr_dequeue_buf(sk, &p, timeout) != 0) + { + return -1; + } + + *buf = (struct spl_netbuf *) ((char *) p + sizeof(struct spl_pbuf)); + ss_sub_recv_event(conn); + return 0; +} + +/***************************************************************************** +* Prototype : _sbr_udp_recvfrom +* Description : base recvfrom,without lock +* Input : sbr_socket_t * sk +* void * mem +* size_t len +* int flags +* struct sockaddr * from +* socklen_t * fromlen +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +_sbr_udp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t * fromlen) +{ + struct spl_netbuf *buf = NULL; + struct spl_pbuf *p; + u32 buflen; + u32 copylen; + u32 off = 0; + + if (sbr_get_fd_share(sk)->lastdata) + { + buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + } + else + { + if ((flags & MSG_DONTWAIT) || ss_is_nonblock_flag(sbr_get_conn(sk))) + { + /* + * return with last err when + * some fatal err occurs, for example, spl just recovered from a fault. + */ + int err = ss_get_last_errno(sbr_get_conn(sk)); + if (SPL_ERR_IS_FATAL(err)) + { + NSSBR_LOGDBG("connection fatal error]sk->fd=%d,errno=%d", + sk->fd, err); + sbr_set_sk_io_errno(sk, sbr_spl_err_to_errno(err)); + return -1; + } + + if (ss_get_recv_event(sbr_get_conn(sk)) <= 0) + { + NSSBR_LOGDBG("no recv event]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EWOULDBLOCK); + return -1; + } + } + + if (sbr_udp_recv_from_ring + (sk, &buf, sbr_get_fd_share(sk)->recv_timeout) != 0) + { + return -1; + } + + sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf); + } + + p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + buflen = p->tot_len; + + if (mem) + { + copylen = len > buflen ? buflen : len; + + if ((copylen > 0) && 0 == spl_pbuf_copy_partial(p, mem, copylen, 0)) + { + NSSBR_LOGERR("copy failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EFAULT); + return -1; + } + + off += copylen; + } + + if (sbr_udp_get_from_addr(sk, from, fromlen, buf) != 0) + { + return -1; + } + + if (!(flags & MSG_PEEK)) + { + sbr_get_fd_share(sk)->lastdata = NULL; + sbr_com_free_recv_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p)); + } + + return off; +} + +/***************************************************************************** +* Prototype : sbr_udp_recvfrom +* Description : recv from +* Input : sbr_socket_t * sk +* void * mem +* size_t len +* int flags +* struct sockaddr * from +* socklen_t * fromlen +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_recvfrom(sbr_socket_t * sk, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t * fromlen) +{ + sbr_com_lock_recv(sk); + int ret = _sbr_udp_recvfrom(sk, mem, len, flags, from, fromlen); + sbr_com_unlock_recv(sk); + return ret; +} + +/***************************************************************************** +* Prototype : sbr_udp_recvdata +* Description : recv data +* Input : sbr_socket_t * sk +* const struct iovec* iov +* int iovcnt +* struct spl_netbuf *buf +* Output : None +* Return Value : static inline +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_udp_recvdata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt, + int flags, struct sockaddr *from, socklen_t * fromlen) +{ + sbr_com_lock_recv(sk); + if (-1 == _sbr_udp_recvfrom(sk, NULL, 0, MSG_PEEK, from, fromlen)) + { + sbr_com_unlock_recv(sk); + return -1; + } + + struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + u32 buflen = p->tot_len; + u32 copylen = 0; + u32 offset = 0; + + int i; + + for (i = 0; i < iovcnt; ++i) + { + if (!iov[i].iov_base || (0 == iov[i].iov_len)) + { + continue; + } + + copylen = buflen > iov[i].iov_len ? iov[i].iov_len : buflen; + if ((copylen > 0) + && 0 == spl_pbuf_copy_partial(p, iov[i].iov_base, copylen, + offset)) + { + NSSBR_LOGERR("copy failed]fd=%d", sk->fd); + goto done; + } + + offset += copylen; + buflen -= copylen; + + if (0 == buflen) + { + goto done; + } + } + + done: + if (!(flags & MSG_PEEK)) + { + sbr_get_fd_share(sk)->lastdata = NULL; + sbr_com_free_recv_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf->p)); + } + + sbr_com_unlock_recv(sk); + return offset; +} + +/***************************************************************************** +* Prototype : sbr_udp_readv +* Description : readv +* Input : sbr_socket_t* sk +* const struct iovec* iov +* int iovcnt +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_readv(sbr_socket_t * sk, const struct iovec *iov, int iovcnt) +{ + return sbr_udp_recvdata(sk, iov, iovcnt, 0, NULL, NULL); +} + +/***************************************************************************** +* Prototype : sbr_udp_recvmsg +* Description : recv msg +* Input : sbr_socket_t* sk +* struct msghdr* msg +* int flags +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_udp_recvmsg(sbr_socket_t * sk, struct msghdr *msg, int flags) +{ + return sbr_udp_recvdata(sk, msg->msg_iov, msg->msg_iovlen, flags, + (struct sockaddr *) msg->msg_name, + &msg->msg_namelen); +} + +/***************************************************************************** +* Prototype : sbr_copy_iov +* Description : copy iov +* Input : sbr_socket_t * sk +* const struct iovec * iov +* int iovcnt +* struct spl_pbuf* buf +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_copy_iov(sbr_socket_t * sk, const struct iovec *iov, int iovcnt, + struct spl_pbuf *buf) +{ + u32 buf_left = buf->len; + i8 *buf_data = (i8 *) ADDR_SHTOL(buf->payload); + u32 iov_left; + i8 *iov_data; + u32 copy_len; + + int i; + + for (i = 0; i < iovcnt; ++i) + { + if (!iov[i].iov_base || (0 == iov[i].iov_len)) + { + continue; + } + + iov_left = (u32) iov[i].iov_len; /* to u32 is ok,len is checked in sbr_udp_senddata */ + iov_data = (i8 *) iov[i].iov_base; + while (iov_left) + { + copy_len = buf_left > iov_left ? iov_left : buf_left; + + if (NULL == common_memcpy(buf_data, iov_data, copy_len)) + { + NSSBR_LOGERR("common_memcpy error]fd=%d", sk->fd); + sbr_set_sk_errno(sk, EFAULT); + return -1; + } + + buf_data += copy_len; + buf_left -= copy_len; + iov_data += copy_len; + iov_left -= copy_len; + if (0 == buf_left) + { + buf = (struct spl_pbuf *) ADDR_SHTOL(buf->next); + if (buf) + { + buf_left = buf->len; + buf_data = (i8 *) ADDR_SHTOL(buf->payload); + } + else + { + return 0; + } + } + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : sbr_udp_senddata +* Description : send data +* Input : sbr_socket_t * sk +* const struct iovec * iov +* int iovcnt +* int flags +* const struct sockaddr * to +* socklen_t tolen +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_udp_senddata(sbr_socket_t * sk, const struct iovec *iov, int iovcnt, + int flags, const struct sockaddr *to, socklen_t tolen) +{ + size_t size = 0; + int iov_idx; + + for (iov_idx = 0; iov_idx < iovcnt; ++iov_idx) + { + if ((SPL_MAX_UDP_MSG_LEN - size) < iov[iov_idx].iov_len) + { + NSSBR_LOGERR + ("size > SPL_MAX_UDP_MSG_LEN]fd=%d,SPL_MAX_UDP_MSG_LEN=%u", + sk->fd, SPL_MAX_UDP_MSG_LEN); + sbr_set_sk_io_errno(sk, EMSGSIZE); + return -1; + } + + size += iov[iov_idx].iov_len; + } + + if (to == NULL) + { + /* if not bind , then dest address should not be NULL */ + if (IPADDR_ANY == ss_get_remote_ip(sbr_get_conn(sk))->addr) + { + NSSBR_LOGERR("dest address is null]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, EDESTADDRREQ); + return -1; + } + } + else if (to->sa_family != AF_INET) + { + NSSBR_LOGERR("invalid address family]fd=%d,family=%d", sk->fd, + to->sa_family); + sbr_set_sk_io_errno(sk, EAFNOSUPPORT); + return -1; + } + else if (tolen != sizeof(struct sockaddr_in)) + { + NSSBR_LOGERR("invalid address len]fd=%d,tolen=%u", sk->fd, tolen); + sbr_set_sk_io_errno(sk, EINVAL); + return -1; + } + + struct spl_netbuf buf; + const struct sockaddr_in *to_in = (const struct sockaddr_in *) to; + buf.p = NULL; + if (to_in) + { + NSSBR_LOGDBG("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd, + spl_inet_ntoa(to_in->sin_addr), ntohs(to_in->sin_port), + sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); + inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr); + netbuf_fromport(&buf) = ntohs(to_in->sin_port); + } + else + { + spl_ip_addr_set_any(&buf.addr); + netbuf_fromport(&buf) = 0; + } + + spl_ip_addr_t local_ip = { IPADDR_ANY }; + + int err = ss_get_last_errno(sbr_get_conn(sk)); + if (SPL_ERR_IS_FATAL(err)) + { + NS_LOG_CTRL(LOG_CTRL_SEND, LOGSBR, "NSSBR", NSLOG_ERR, + "connection fatal error!err=%d", err); + sbr_set_sk_errno(sk, sbr_spl_err_to_errno(err)); + return -1; + } + + u16 remain_len = size; //+ head_room_len; + struct spl_pbuf *p = NULL; + PRIMARY_ADDR struct spl_pbuf *header = NULL; + struct spl_pbuf **tail = &header; + u16 head_len = L2_L3_ROOM_LEN + L4_ROOM_LEN; + u16 copy_len; + u16 alloc_len; + + do + { + copy_len = + remain_len > + (SPL_PBUF_UDP_LEN - head_len) ? (SPL_PBUF_UDP_LEN - + head_len) : remain_len; + alloc_len = head_len + copy_len; + p = sbr_malloc_tx_pbuf(alloc_len, head_len); + if (unlikely(!p)) + { + NSSBR_LOGDBG("malloc pbuf failed]fd=%d", sk->fd); + sbr_set_sk_io_errno(sk, ENOMEM); + sbr_handle_free_send_buf(sk, + (struct spl_pbuf *) ADDR_SHTOL(header)); + // ss_set_send_event(sbr_get_conn(sk), 0); + return -1; + } + + struct spl_pbuf *tmp = (struct spl_pbuf *) ADDR_SHTOL(header); + while (tmp) + { + tmp->tot_len += p->len; + tmp = (struct spl_pbuf *) ADDR_SHTOL(tmp->next); + } + + *tail = (struct spl_pbuf *) ADDR_LTOSH(p); /* header will changed to share */ + tail = &p->next; + + remain_len -= copy_len; + head_len = L2_L3_ROOM_LEN; + } + while (remain_len); + + /*udp support len=0 */ + if (size != 0) + { + if (sbr_copy_iov + (sk, iov, iovcnt, (struct spl_pbuf *) ADDR_SHTOL(header)) != 0) + { + sbr_handle_free_send_buf(sk, + (struct spl_pbuf *) ADDR_SHTOL(header)); + return -1; + } + } + + buf.p = header; + err = sbr_handle_udp_send(sk, &buf, &local_ip); + if (0 == err) + { + epoll_triggle_event_from_api(sk, EPOLL_API_OP_SEND); + //ss_set_send_event(sbr_get_conn(sk), 1); + return size; + } + else + { + sbr_handle_free_send_buf(sk, (struct spl_pbuf *) ADDR_SHTOL(buf.p)); + return -1; + } + +} + +/***************************************************************************** +* Prototype : sbr_udp_sendto +* Description : sendto +* Input : sbr_socket_t * sk +* const void * data +* size_t size +* int flags +* const struct sockaddr * to +* socklen_t tolen +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_sendto(sbr_socket_t * sk, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + struct iovec iov; + + iov.iov_base = (void *) data; + iov.iov_len = size; + return sbr_udp_senddata(sk, &iov, 1, flags, to, tolen); +} + +/***************************************************************************** +* Prototype : sbr_udp_send +* Description : send +* Input : sbr_socket_t * sk +* const void * data +* size_t size +* int flags +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_send(sbr_socket_t * sk, const void *data, size_t size, int flags) +{ + return sk->fdopt->sendto(sk, data, size, flags, NULL, 0); +} + +/***************************************************************************** +* Prototype : sbr_udp_sendmsg +* Description : send msg +* Input : sbr_socket_t * sk +* const struct msghdr * pmsg +* int flags +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_sendmsg(sbr_socket_t * sk, const struct msghdr *pmsg, int flags) +{ + return sbr_udp_senddata(sk, pmsg->msg_iov, pmsg->msg_iovlen, flags, + (struct sockaddr *) pmsg->msg_name, + pmsg->msg_namelen); +} + +/***************************************************************************** +* Prototype : sbr_udp_writev +* Description : writev +* Input : sbr_socket_t * sk +* const struct iovec * iov +* int iovcnt +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int +sbr_udp_writev(sbr_socket_t * sk, const struct iovec *iov, int iovcnt) +{ + return sbr_udp_senddata(sk, iov, iovcnt, 0, NULL, 0); +} + +/***************************************************************************** +* Prototype : sbr_udp_fcntl +* Description : fcntl +* Input : sbr_socket_t * sk +* int cmd +* long arg +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_udp_fcntl(sbr_socket_t * sk, int cmd, long arg) +{ + int ret = 0; + + switch (cmd) + { + case F_GETFL: + ret = ss_get_nonblock_flag(sbr_get_conn(sk)); + NSSBR_LOGDBG("F_GETFL]fd=%d,ret=%d", sk->fd, ret); + break; + case F_SETFL: + if (arg & O_NONBLOCK) + { + NSSBR_LOGDBG("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld", + sk->fd, arg); + ss_set_nonblock_flag(sbr_get_conn(sk), (arg & O_NONBLOCK)); + } + else + { + NSSBR_LOGDBG("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld", + sk->fd, arg); + ss_set_nonblock_flag(sbr_get_conn(sk), 0); + } + + break; + default: + NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd); + ret = -1; + sbr_set_sk_errno(sk, EINVAL); + + break; + } + + return ret; +} + +/***************************************************************************** +* Prototype : sbr_udp_ioctl +* Description : ioctl +* Input : sbr_socket_t * sk +* unsigned long cmd +* void * arg +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_udp_ioctl(sbr_socket_t * sk, unsigned long cmd, void *arg) +{ + int ret = 0; + + switch (cmd) + { + case FIONREAD: + { + if (!sbr_com_try_lock_recv(sk)) + { + return 0; + } + + struct spl_pbuf *p = NULL; + struct spl_netbuf *buf = NULL; + if (!sbr_get_fd_share(sk)->lastdata) + { + ret = sbr_udp_recv_from_ring(sk, &buf, -1); + if (ret != 0) + { + sbr_com_unlock_recv(sk); + return EWOULDBLOCK == errno ? 0 : -1; + } + + sbr_get_fd_share(sk)->lastdata = (void *) ADDR_LTOSH(buf); + p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + } + else + { + buf = + (struct spl_netbuf *) + ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + } + + *((u32 *) arg) = p->tot_len; + sbr_com_unlock_recv(sk); + } + break; + case FIONBIO: + { + u8 val = 0; + + if (arg && *(u32 *) arg) + { + val = 1; + } + + ss_set_nonblock_flag(sbr_get_conn(sk), val); + NSSBR_LOGDBG("FIONBIO]fd=%d,val=%u", sk->fd, val); + } + break; + default: + { + NSSBR_LOGERR("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd); + ret = -1; + sbr_set_sk_errno(sk, ENOTTY); + } + + break; + } + + return ret; +} + +/***************************************************************************** +* Prototype : sbr_udp_close +* Description : close +* Input : sbr_socket_t * sk +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +static int sbr_udp_close(sbr_socket_t * sk) +{ + if (sbr_get_fd_share(sk)->lastdata) + { + struct spl_netbuf *buf = ADDR_SHTOL(sbr_get_fd_share(sk)->lastdata); + struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL(buf->p); + sbr_com_free_recv_buf(sk, p); + } + + /* if failed,free it in recycle */ + return sbr_handle_close(sk, 0); +} + +sbr_fdopt udp_fdopt = { + .socket = sbr_udp_socket, + .bind = sbr_udp_bind, + .listen = sbr_udp_listen, + .accept = sbr_udp_accept, + .accept4 = sbr_udp_accept4, + .connect = sbr_udp_connect, + .shutdown = sbr_udp_shutdown, + .getsockname = sbr_udp_getsockname, + .getpeername = sbr_udp_getpeername, + .getsockopt = sbr_udp_getsockopt, + .setsockopt = sbr_udp_setsockopt, + .recvfrom = sbr_udp_recvfrom, + .readv = sbr_udp_readv, + .recvmsg = sbr_udp_recvmsg, + .send = sbr_udp_send, + .sendto = sbr_udp_sendto, + .sendmsg = sbr_udp_sendmsg, + .writev = sbr_udp_writev, + .fcntl = sbr_udp_fcntl, + .ioctl = sbr_udp_ioctl, + .close = sbr_udp_close, + .peak = sbr_com_peak, + .lock_common = sbr_com_lock_common, + .unlock_common = sbr_com_unlock_common, + .fork_parent = sbr_com_fork_parent, + .fork_child = sbr_com_fork_child, + .ep_getevt = stackx_eventpoll_getEvt, + .ep_triggle = stackx_eventpoll_triggle, + .set_close_stat = NULL, +}; diff --git a/stacks/lwip_stack/patch/.gitkeep b/stacks/lwip_stack/patch/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/lwip_stack/release/configure/ip_data.json b/stacks/lwip_stack/release/configure/ip_data.json new file mode 100644 index 0000000..a7c34fa --- /dev/null +++ b/stacks/lwip_stack/release/configure/ip_data.json @@ -0,0 +1,8 @@ +{ + "ports_list": [ + { + "port_name": "PortA", + "ip_cidr": ["192.168.1.175/24"] + } + ] +} diff --git a/stacks/lwip_stack/release/configure/nStackConfig.json b/stacks/lwip_stack/release/configure/nStackConfig.json new file mode 100644 index 0000000..fbea78c --- /dev/null +++ b/stacks/lwip_stack/release/configure/nStackConfig.json @@ -0,0 +1,32 @@ +{ +"cfg_seg_socket": [ +{ + "socket_num": 8192, + "arp_stale_time": 300, + "arp_bc_retrans_num": 5 +} +], +"cfg_seg_log": [ +{ + "run_log_size": 50, + "run_log_count": 10, + "mon_log_size": 10, + "mon_log_count": 10 +} +], +"cfg_seg_thread_pri": [ +{ + "comment":"0:SCHED_OTHER, 1:SCHED_FIFO, 2:SCHED_RR", + "sched_policy": 0, + "thread_pri": 0 +} +], +"cfg_seg_path": [ +{ + "stackx_log_path": "/var/log/nStack", + "master_log_path": "/var/log/nStack", + "nstack_log_path": "/var/log/nStack", + "dpdk_log_path": "/var/log/nstack-dpdk" +} +] +} diff --git a/stacks/lwip_stack/release/configure/network_data_tonStack.json b/stacks/lwip_stack/release/configure/network_data_tonStack.json new file mode 100644 index 0000000..e1f5e81 --- /dev/null +++ b/stacks/lwip_stack/release/configure/network_data_tonStack.json @@ -0,0 +1,16 @@ +[ + { + "name": "network1", + "type": "nstack-dpdk", + "ipam": { + "subnet": "192.168.1.1/24" + }, + "args": { + "phynet": { + "ref_nic": [ + "ens4" + ] + } + } + }, +] diff --git a/stacks/lwip_stack/release/include/nstack_custom_api.h b/stacks/lwip_stack/release/include/nstack_custom_api.h new file mode 100644 index 0000000..34229ec --- /dev/null +++ b/stacks/lwip_stack/release/include/nstack_custom_api.h @@ -0,0 +1,42 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSTACK_CUSTOM_API_H__ +#define __NSTACK_CUSTOM_API_H__ + +/***************************************************************************** +* Prototype : create a custom socket ,when using this type . +*****************************************************************************/ +#ifndef SOCK_NS_CUSTOM +#define SOCK_NS_CUSTOM 0xf001 +#endif + +/***************************************************************************** +* Prototype : setsockopt level type +*****************************************************************************/ +enum +{ + NSTACK_SOCKOPT = 0xff02 +}; + +/***************************************************************************** +* Prototype : setsockopt optname type +*****************************************************************************/ +enum +{ + NSTACK_SEM_SLEEP = 0X0001 +}; +#endif diff --git a/stacks/lwip_stack/release/lib64/.gitkeep b/stacks/lwip_stack/release/lib64/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/stacks/lwip_stack/release/lwip_helper_files/arch/queue.c b/stacks/lwip_stack/release/lwip_helper_files/arch/queue.c new file mode 100644 index 0000000..4916dae --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/arch/queue.c @@ -0,0 +1,120 @@ +#include +#include "lwip/memp.h" +#include "lwip/mem.h" + +#include "arch/queue.h" +#include "lwip/sys.h" +#include "nstack_log.h" +#include "lwip/sockets.h" +#include "stackx_spl_share.h" +#include "lwip/api.h" +#include "lwip/ip.h" +#include + +err_t +queue_push (queue_t * q, void *pmsg, int isTrypush) +{ + int pushRet; + // struct tcpip_msg* _msg = pmsg; + + //enum tcpip_msg_type tcpip_type = TCPIP_MSG_MAX; + //struct new_api_msg* lo_newapimsg = NULL; + // enum api_msg_type api_type = NEW_MSG_API_MAX; + // struct netconn *lo_conn = NULL; + //u64_t tcp_tx_bytes = 0; + while (1) + { + pushRet = nsfw_mem_ring_enqueue (q->llring, pmsg); + + switch (pushRet) + { + + case -1: + NSSOC_LOGERR ("Box range check has failed]llring_a=%p, msg=%p", + q->llring, pmsg); + return ERR_MEM; + + case 1: + return ERR_OK; + + default: + if (isTrypush) + { + return ERR_MEM; + } + else + { + continue; + } + } + } +} + +void * +queue_pop (queue_t * q, u32_t * timeout, int isTryPop) +{ + void *pmsg; + int popRet; + int retVal; + u32_t ellapsetime = 0; +// struct tcpip_msg* _msg; + struct timespec starttm = { 0 }; + struct timespec endtm; + u32_t timeDiff; + if (*timeout != 0) + { + retVal = clock_gettime (CLOCK_MONOTONIC, &starttm); + if (0 != retVal) + { + NSPOL_LOGERR ("clock_gettime() failed]"); + *timeout = SYS_ARCH_TIMEOUT; + return NULL; + } + } + + while (1) + { + //TODO:May have to consider, take out the data sharing problem + popRet = nsfw_mem_ring_dequeue (q->llring, &pmsg); + + switch (popRet) + { + case 1: + *timeout = ellapsetime; + return pmsg; + + default: + + if (isTryPop) + { + *timeout = SYS_ARCH_TIMEOUT; + return NULL; + } + else + { + if (*timeout != 0) + { + retVal = clock_gettime (CLOCK_MONOTONIC, &endtm); + if (0 != retVal) + { + NSPOL_LOGERR ("clock_gettime() failed]"); + *timeout = SYS_ARCH_TIMEOUT; + return NULL; + } + + timeDiff = endtm.tv_sec - starttm.tv_sec; + if (timeDiff > *timeout) + { + *timeout = SYS_ARCH_TIMEOUT; + return NULL; + } + sys_sleep_ns (0, 100000); + } + + continue; + } + + } + } + +} diff --git a/stacks/lwip_stack/release/lwip_helper_files/arch/sys_arch.c b/stacks/lwip_stack/release/lwip_helper_files/arch/sys_arch.c new file mode 100644 index 0000000..d7aadf7 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/arch/sys_arch.c @@ -0,0 +1,303 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include "nstack_log.h" +#include "lwip/sockets.h" +#include "spl_timers.h" +#include "nstack_securec.h" +#include "nstack_share_res.h" +#include "nstack_log.h" + +#include "stackx_spl_share.h" +#include "lwip/api.h" +#include "lwip/ip.h" +#include +#include + +#include "common_mem_common.h" +#include "common_func.h" +#include "common_mem_api.h" + +#include "mgr_com.h" +#ifdef HAL_LIB +#else +#include "rte_ring.h" +#endif + +#include "timeouts.h" + +sys_sem_st g_global_semaphore; + +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int +sys_mbox_valid (sys_mbox_t * mbox) +{ + return ((*mbox == SYS_MBOX_NULL) ? 0 : 1); +} + +struct lwip_thread +{ + void (*func) (void *arg); + void *arg; +}; + +static void * +lwip_thread_entry (void *arg) +{ + struct lwip_thread *lt = arg; + + lt->func (lt->arg); + + free (lt); + return 0; +} + +NSTACK_STATIC inline void +get_thread_policy (pthread_attr_t * attr) +{ + int policy; + int rs = pthread_attr_getschedpolicy (attr, &policy); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedpolicy failed"); + return; + } + switch (policy) + { + case SCHED_FIFO: + NSFW_LOGINF ("policy= SCHED_FIFO"); + break; + case SCHED_RR: + NSFW_LOGINF ("policy= SCHED_RR"); + break; + case SCHED_OTHER: + NSFW_LOGINF ("policy=SCHED_OTHER"); + break; + default: + NSFW_LOGINF ("policy=UNKNOWN"); + break; + } + + return; +} + +NSTACK_STATIC inline void +get_thread_priority (pthread_attr_t * attr) +{ + struct sched_param param; + int rs = pthread_attr_getschedparam (attr, ¶m); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedparam failed"); + return; + } + + NSFW_LOGINF ("get thread priority] pri=%d", param.sched_priority); +} + +/* support thread priority configuration */ +void +set_thread_attr (pthread_attr_t * pattr, int stacksize, int pri, int policy) +{ + struct sched_param param; + (void) pthread_attr_init (pattr); + + if (stacksize > 0) + { + (void) pthread_attr_setstacksize (pattr, stacksize); + } + + param.sched_priority = pri; + if (SCHED_OTHER != policy) + { + (void) pthread_attr_setschedpolicy (pattr, policy); + (void) pthread_attr_setschedparam (pattr, ¶m); + (void) pthread_attr_setinheritsched (pattr, PTHREAD_EXPLICIT_SCHED); + } + get_thread_policy (pattr); + get_thread_priority (pattr); +} + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t +sys_thread_new2 (const char *name, lwip_thread_fn thread, void *arg, + int stacksize, int prio, int policy) +{ + pthread_attr_t attr; + set_thread_attr (&attr, stacksize, prio, policy); + + struct lwip_thread *lt = malloc (sizeof (*lt)); + if (lt == NULL) + { + NSPOL_LOGERR ("process abort:cannot allocate thread struct"); + abort (); + } + + lt->func = thread; + lt->arg = arg; + + pthread_t t; + int r = pthread_create (&t, &attr, lwip_thread_entry, lt); + + if (r != 0) + { + NSPOL_LOGERR ("process abort:lwip:annot create]errno_string=%s", + strerror (r)); + abort (); + } + else + { + NSPOL_LOGINF (SC_DPDK_INFO, "]thread_name=%s.", name); + } + + (void) pthread_setname_np (t, name); + + return t; +} + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t +sys_thread_new (const char *name, lwip_thread_fn thread, void *arg, + int stacksize, int prio) +{ + pthread_attr_t attr; + set_thread_attr (&attr, stacksize, prio, 0); + + struct lwip_thread *lt = malloc (sizeof (*lt)); + if (lt == NULL) + { + NSPOL_LOGERR ("process abort:cannot allocate thread struct"); + abort (); + } + + lt->func = thread; + lt->arg = arg; + + pthread_t t; + int r = pthread_create (&t, &attr, lwip_thread_entry, lt); + + if (r != 0) + { + NSPOL_LOGERR ("process abort:lwip:annot create]errno_string=%s", + strerror (r)); + abort (); + } + else + { + NSPOL_LOGINF (SC_DPDK_INFO, "]thread_name=%s.", name); + } + + (void) pthread_setname_np (t, name); + + return t; +} + +void +stackx_global_lock (void) +{ + sys_arch_lock_with_pid (&g_global_semaphore); +} + +void +stackx_global_unlock (void) +{ + sys_sem_s_signal (&g_global_semaphore); +} + +void +sys_init (void) +{ + return; +} + +void +sys_timeouts_mbox_fetch (sys_mbox_t * mbox, void **msg) +{ + return; +} + +void +sys_timeout (u32_t msecs, sys_timeout_handler handler, void *arg) +{ + struct ptimer_node *tmo = arg; + + tmo = malloc (sizeof (struct ptimer_node)); /*lint !e586 */ + if (NULL == tmo) + { + NSPOL_LOGERR ("malloc ptimer node failed!"); + return; + } + + int ret = memset_s (tmo, sizeof (struct ptimer_node), 0, + sizeof (struct ptimer_node)); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMSET_S failed]ret=%d", ret); + free (tmo); + return; + } + + NSPOL_LOGDBG (TIMERS_DEBUG, "alloc]ptimer_node=%p", tmo); + + tmo->info.msec = msecs; + tmo->info._phandle = handler; + tmo->info.ctx = arg; + tmo->info.flags = PTIMER_ONESHOT; + tmo->index = 0; + regedit_ptimer (SYS_PTIMEROUT_MSG, handler, tmo); +} + +void +sys_untimeout (sys_timeout_handler handler, void *arg) +{ + regedit_ptimer (SYS_UNPTIMEROUT_MSG, handler, arg); + return; +} + +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +void +cyclic_timer (void *arg) +{ + const struct lwip_cyclic_timer *cyclic = + (const struct lwip_cyclic_timer *) arg; +#if LWIP_DEBUG_TIMERNAMES + LWIP_DEBUGF (TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); +#endif + cyclic->handler (); + sys_timeout (cyclic->interval_ms, cyclic_timer, arg); +} diff --git a/stacks/lwip_stack/release/lwip_helper_files/core/memp.c b/stacks/lwip_stack/release/lwip_helper_files/core/memp.c new file mode 100644 index 0000000..7aca86e --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/core/memp.c @@ -0,0 +1,495 @@ +/** + * @file + * Dynamic pool memory manager + * + * lwIP has dedicated pools for many structures (netconn, protocol control blocks, + * packet buffers, ...). All these pools are managed here. + * + * @defgroup mempool Memory pools + * @ingroup infrastructure + * Custom memory pools + + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include "lwip/opt.h" + +#include "lwip/memp.h" +#include "lwip/sys.h" +#include "lwip/stats.h" + +#include + +/* Make sure we include everything we need for size calculation required by memp_std.h */ +#include "lwip/pbuf.h" +#include "lwip/raw.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/ip4_frag.h" +#include "lwip/netbuf.h" +#include "lwip/api.h" +#include "lwip/priv/tcpip_priv.h" +#include "lwip/priv/api_msg.h" +#include "lwip/sockets.h" +#include "lwip/netifapi.h" +#include "lwip/etharp.h" +#include "lwip/igmp.h" +#include "lwip/timeouts.h" +/* needed by default MEMP_NUM_SYS_TIMEOUT */ +#include "netif/ppp/ppp_opts.h" +#include "lwip/dns.h" +#include "lwip/priv/nd6_priv.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" + +#define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) +#include "lwip/priv/memp_std.h" + +const struct memp_desc* const memp_pools[MEMP_MAX] = { +#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name, +#include "lwip/priv/memp_std.h" +}; + +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + +#if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 +#undef MEMP_OVERFLOW_CHECK +/* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ +#define MEMP_OVERFLOW_CHECK 1 +#endif + +#if MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC +/** + * Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm". + */ +static int +memp_sanity(const struct memp_desc *desc) +{ + struct memp *t, *h; + + t = *desc->tab; + if (t != NULL) { + for (h = t->next; (t != NULL) && (h != NULL); t = t->next, + h = ((h->next != NULL) ? h->next->next : NULL)) { + if (t == h) { + return 0; + } + } + } + + return 1; +} +#endif /* MEMP_SANITY_CHECK && !MEMP_MEM_MALLOC */ + +#if MEMP_OVERFLOW_CHECK +/** + * Check if a memp element was victim of an overflow + * (e.g. the restricted area after it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_overflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE + desc->size; + for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp overflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +/** + * Check if a memp element was victim of an underflow + * (e.g. the restricted area before it has been altered) + * + * @param p the memp element to check + * @param desc the pool p comes from + */ +static void +memp_overflow_check_element_underflow(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + u16_t k; + u8_t *m; + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128] = "detected memp underflow in pool "; + strcat(errstr, desc->desc); + LWIP_ASSERT(errstr, 0); + } + } +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 */ +} + +/** + * Initialize the restricted area of on memp element. + */ +static void +memp_overflow_init_element(struct memp *p, const struct memp_desc *desc) +{ +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + u8_t *m; +#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t*)p + MEMP_SIZE + desc->size; + memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); +#endif +#else /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 || MEMP_SANITY_REGION_AFTER_ALIGNED > 0 */ +} + +#if MEMP_OVERFLOW_CHECK >= 2 +/** + * Do an overflow check for all elements in every pool. + * + * @see memp_overflow_check_element for a description of the check + */ +static void +memp_overflow_check_all(void) +{ + u16_t i, j; + struct memp *p; + SYS_ARCH_DECL_PROTECT(old_level); + SYS_ARCH_PROTECT(old_level); + + for (i = 0; i < MEMP_MAX; ++i) { + p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); + for (j = 0; j < memp_pools[i]->num; ++j) { + memp_overflow_check_element_overflow(p, memp_pools[i]); + memp_overflow_check_element_underflow(p, memp_pools[i]); + p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); + } + } + SYS_ARCH_UNPROTECT(old_level); +} +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +#endif /* MEMP_OVERFLOW_CHECK */ + +/** + * Initialize custom memory pool. + * Related functions: memp_malloc_pool, memp_free_pool + * + * @param desc pool to initialize + */ +void +memp_init_pool(const struct memp_desc *desc) +{ +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); +#else + int i; + struct memp *memp; + + *desc->tab = NULL; + memp = (struct memp*)LWIP_MEM_ALIGN(desc->base); + /* create a linked list of memp elements */ + for (i = 0; i < desc->num; ++i) { + memp->next = *desc->tab; + *desc->tab = memp; +#if MEMP_OVERFLOW_CHECK + memp_overflow_init_element(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + desc->size +#if MEMP_OVERFLOW_CHECK + + MEMP_SANITY_REGION_AFTER_ALIGNED +#endif + ); + } +#if MEMP_STATS + desc->stats->avail = desc->num; +#endif /* MEMP_STATS */ +#endif /* !MEMP_MEM_MALLOC */ + +#if MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) + desc->stats->name = desc->desc; +#endif /* MEMP_STATS && (defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY) */ +} + +/** + * Initializes lwIP built-in pools. + * Related functions: memp_malloc, memp_free + * + * Carves out memp_memory into linked lists for each pool-type. + */ +void +memp_init(void) +{ + u16_t i; + + /* for every pool: */ + for (i = 0; i < LWIP_ARRAYSIZE(memp_pools); i++) { + memp_init_pool(memp_pools[i]); + +#if LWIP_STATS && MEMP_STATS + lwip_stats.memp[i] = memp_pools[i]->stats; +#endif + } + +#if MEMP_OVERFLOW_CHECK >= 2 + /* check everything a first time to see if it worked */ + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ +} + +static void* +#if !MEMP_OVERFLOW_CHECK +do_memp_malloc_pool(const struct memp_desc *desc) +#else +do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + +#if MEMP_MEM_MALLOC + memp = (struct memp *)mem_malloc(MEMP_SIZE + MEMP_ALIGN_SIZE(desc->size)); + SYS_ARCH_PROTECT(old_level); +#else /* MEMP_MEM_MALLOC */ + SYS_ARCH_PROTECT(old_level); + + memp = *desc->tab; +#endif /* MEMP_MEM_MALLOC */ + + if (memp != NULL) { +#if !MEMP_MEM_MALLOC +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + + *desc->tab = memp->next; +#if MEMP_OVERFLOW_CHECK + memp->next = NULL; +#endif /* MEMP_OVERFLOW_CHECK */ +#endif /* !MEMP_MEM_MALLOC */ +#if MEMP_OVERFLOW_CHECK + memp->file = file; + memp->line = line; +#if MEMP_MEM_MALLOC + memp_overflow_init_element(memp, desc); +#endif /* MEMP_MEM_MALLOC */ +#endif /* MEMP_OVERFLOW_CHECK */ + LWIP_ASSERT("memp_malloc: memp properly aligned", + ((mem_ptr_t)memp % MEM_ALIGNMENT) == 0); +#if MEMP_STATS + desc->stats->used++; + if (desc->stats->used > desc->stats->max) { + desc->stats->max = desc->stats->used; + } +#endif + SYS_ARCH_UNPROTECT(old_level); + /* cast through u8_t* to get rid of alignment warnings */ + return ((u8_t*)memp + MEMP_SIZE); + } else { + LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", desc->desc)); +#if MEMP_STATS + desc->stats->err++; +#endif + } + + SYS_ARCH_UNPROTECT(old_level); + return NULL; +} + +/** + * Get an element from a custom pool. + * + * @param desc the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc_pool(const struct memp_desc *desc) +#else +memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int line) +#endif +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if (desc == NULL) { + return NULL; + } + +#if !MEMP_OVERFLOW_CHECK + return do_memp_malloc_pool(desc); +#else + return do_memp_malloc_pool_fn(desc, file, line); +#endif +} + +/** + * Get an element from a specific pool. + * + * @param type the pool to get an element from + * + * @return a pointer to the allocated memory or a NULL pointer on error + */ +void * +#if !MEMP_OVERFLOW_CHECK +memp_malloc(memp_t type) +#else +memp_malloc_fn(memp_t type, const char* file, const int line) +#endif +{ + void *memp; + LWIP_ERROR("memp_malloc: type < MEMP_MAX", (type < MEMP_MAX), return NULL;); + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#if !MEMP_OVERFLOW_CHECK + memp = do_memp_malloc_pool(memp_pools[type]); +#else + memp = do_memp_malloc_pool_fn(memp_pools[type], file, line); +#endif + + return memp; +} + +static void +do_memp_free_pool(const struct memp_desc* desc, void *mem) +{ + struct memp *memp; + SYS_ARCH_DECL_PROTECT(old_level); + + LWIP_ASSERT("memp_free: mem properly aligned", + ((mem_ptr_t)mem % MEM_ALIGNMENT) == 0); + + /* cast through void* to get rid of alignment warnings */ + memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE); + + SYS_ARCH_PROTECT(old_level); + +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + +#if MEMP_STATS + desc->stats->used--; +#endif + +#if MEMP_MEM_MALLOC + LWIP_UNUSED_ARG(desc); + SYS_ARCH_UNPROTECT(old_level); + mem_free(memp); +#else /* MEMP_MEM_MALLOC */ + memp->next = *desc->tab; + *desc->tab = memp; + +#if MEMP_SANITY_CHECK + LWIP_ASSERT("memp sanity", memp_sanity(desc)); +#endif /* MEMP_SANITY_CHECK */ + + SYS_ARCH_UNPROTECT(old_level); +#endif /* !MEMP_MEM_MALLOC */ +} + +/** + * Put a custom pool element back into its pool. + * + * @param desc the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free_pool(const struct memp_desc* desc, void *mem) +{ + LWIP_ASSERT("invalid pool desc", desc != NULL); + if ((desc == NULL) || (mem == NULL)) { + return; + } + + do_memp_free_pool(desc, mem); +} + +/** + * Put an element back into its pool. + * + * @param type the pool where to put mem + * @param mem the memp element to free + */ +void +memp_free(memp_t type, void *mem) +{ +#ifdef LWIP_HOOK_MEMP_AVAILABLE + struct memp *old_first; +#endif + + LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + + if (mem == NULL) { + return; + } + +#if MEMP_OVERFLOW_CHECK >= 2 + memp_overflow_check_all(); +#endif /* MEMP_OVERFLOW_CHECK >= 2 */ + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + old_first = *memp_pools[type]->tab; +#endif + + do_memp_free_pool(memp_pools[type], mem); + +#ifdef LWIP_HOOK_MEMP_AVAILABLE + if (old_first == NULL) { + LWIP_HOOK_MEMP_AVAILABLE(type); + } +#endif +} diff --git a/stacks/lwip_stack/release/lwip_helper_files/core/timeouts.c b/stacks/lwip_stack/release/lwip_helper_files/core/timeouts.c new file mode 100644 index 0000000..efbda94 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/core/timeouts.c @@ -0,0 +1,527 @@ +/** + * @file + * Stack-internal timers implementation. + * This file includes timer callbacks for stack-internal timers as well as + * functions to set up or stop timers and check for expired timers. + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ + +#include "lwip/opt.h" + +#include "lwip/timeouts.h" +#include "lwip/priv/tcp_priv.h" + +#include "lwip/def.h" +#include "lwip/memp.h" +#include "lwip/priv/tcpip_priv.h" + +#include "lwip/ip4_frag.h" +#include "lwip/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/igmp.h" +#include "lwip/dns.h" +#include "lwip/nd6.h" +#include "lwip/ip6_frag.h" +#include "lwip/mld6.h" +#include "lwip/sys.h" +#include "lwip/pbuf.h" + +#if LWIP_DEBUG_TIMERNAMES +#define HANDLER(x) x, #x +#else /* LWIP_DEBUG_TIMERNAMES */ +#define HANDLER(x) x +#endif /* LWIP_DEBUG_TIMERNAMES */ + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ +const struct lwip_cyclic_timer lwip_cyclic_timers[] = { +#if LWIP_TCP + /* The TCP timer is a special case: it does not have to run always and + is triggered to start from TCP using tcp_timer_needed() */ + {TCP_TMR_INTERVAL, HANDLER (tcp_tmr)}, +#endif /* LWIP_TCP */ +#if LWIP_IPV4 +#if IP_REASSEMBLY + {IP_TMR_INTERVAL, HANDLER (ip_reass_tmr)}, +#endif /* IP_REASSEMBLY */ +#if LWIP_ARP + {ARP_TMR_INTERVAL, HANDLER (etharp_tmr)}, +#endif /* LWIP_ARP */ +#if LWIP_DHCP + {DHCP_COARSE_TIMER_MSECS, HANDLER (dhcp_coarse_tmr)}, + {DHCP_FINE_TIMER_MSECS, HANDLER (dhcp_fine_tmr)}, +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + {AUTOIP_TMR_INTERVAL, HANDLER (autoip_tmr)}, +#endif /* LWIP_AUTOIP */ +#if LWIP_IGMP + {IGMP_TMR_INTERVAL, HANDLER (igmp_tmr)}, +#endif /* LWIP_IGMP */ +#endif /* LWIP_IPV4 */ +#if LWIP_DNS + {DNS_TMR_INTERVAL, HANDLER (dns_tmr)}, +#endif /* LWIP_DNS */ +#if LWIP_IPV6 + {ND6_TMR_INTERVAL, HANDLER (nd6_tmr)}, +#if LWIP_IPV6_REASS + {IP6_REASS_TMR_INTERVAL, HANDLER (ip6_reass_tmr)}, +#endif /* LWIP_IPV6_REASS */ +#if LWIP_IPV6_MLD + {MLD6_TMR_INTERVAL, HANDLER (mld6_tmr)}, +#endif /* LWIP_IPV6_MLD */ +#endif /* LWIP_IPV6 */ +}; + +#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM + +/** The one and only timeout list */ +static struct sys_timeo *next_timeout; +static u32_t timeouts_last_time; + +#if LWIP_TCP +/** global variable that shows if the tcp timer is currently scheduled or not */ +static int tcpip_tcp_timer_active; + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +tcpip_tcp_timer (void *arg) +{ + LWIP_UNUSED_ARG (arg); + + /* call TCP timer handler */ + tcp_tmr (); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) + { + /* restart timer */ + sys_timeout (TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } + else + { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +/** + * Called from TCP_REG when registering a new PCB: + * the reason is to have the TCP timer only running when + * there are active (or time-wait) PCBs. + */ +void +tcp_timer_needed (void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) + { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout (TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} +#endif /* LWIP_TCP */ + +/** + * Timer callback function that calls mld6_tmr() and reschedules itself. + * + * @param arg unused argument + */ +static void +cyclic_timer (void *arg) +{ + const struct lwip_cyclic_timer *cyclic = + (const struct lwip_cyclic_timer *) arg; +#if LWIP_DEBUG_TIMERNAMES + LWIP_DEBUGF (TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name)); +#endif + cyclic->handler (); + sys_timeout (cyclic->interval_ms, cyclic_timer, arg); +} + +/** Initialize this module */ +void +sys_timeouts_init (void) +{ + size_t i; + /* tcp_tmr() at index 0 is started on demand */ + for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE (lwip_cyclic_timers); i++) + { + /* we have to cast via size_t to get rid of const warning + (this is OK as cyclic_timer() casts back to const* */ + sys_timeout (lwip_cyclic_timers[i].interval_ms, cyclic_timer, + LWIP_CONST_CAST (void *, &lwip_cyclic_timers[i])); + } + + /* Initialise timestamp for sys_check_timeouts */ + timeouts_last_time = sys_now (); +} + +/** + * Create a one-shot timer (aka timeout). Timeouts are processed in the + * following cases: + * - while waiting for a message using sys_timeouts_mbox_fetch() + * - by calling sys_check_timeouts() (NO_SYS==1 only) + * + * @param msecs time in milliseconds after that the timer should expire + * @param handler callback function to call when msecs have elapsed + * @param arg argument to pass to the callback function + */ +#if LWIP_DEBUG_TIMERNAMES +void +sys_timeout_debug (u32_t msecs, sys_timeout_handler handler, void *arg, + const char *handler_name) +#else /* LWIP_DEBUG_TIMERNAMES */ +void +sys_timeout (u32_t msecs, sys_timeout_handler handler, void *arg) +#endif /* LWIP_DEBUG_TIMERNAMES */ +{ + struct sys_timeo *timeout, *t; + u32_t now, diff; + + timeout = (struct sys_timeo *) memp_malloc (MEMP_SYS_TIMEOUT); + if (timeout == NULL) + { + LWIP_ASSERT + ("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", + timeout != NULL); + return; + } + + now = sys_now (); + if (next_timeout == NULL) + { + diff = 0; + timeouts_last_time = now; + } + else + { + diff = now - timeouts_last_time; + } + + timeout->next = NULL; + timeout->h = handler; + timeout->arg = arg; + timeout->time = msecs + diff; +#if LWIP_DEBUG_TIMERNAMES + timeout->handler_name = handler_name; + LWIP_DEBUGF (TIMERS_DEBUG, + ("sys_timeout: %p msecs=%" U32_F " handler=%s arg=%p\n", + (void *) timeout, msecs, handler_name, (void *) arg)); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + if (next_timeout == NULL) + { + next_timeout = timeout; + return; + } + + if (next_timeout->time > msecs) + { + next_timeout->time -= msecs; + timeout->next = next_timeout; + next_timeout = timeout; + } + else + { + for (t = next_timeout; t != NULL; t = t->next) + { + timeout->time -= t->time; + if (t->next == NULL || t->next->time > timeout->time) + { + if (t->next != NULL) + { + t->next->time -= timeout->time; + } + else if (timeout->time > msecs) + { + /* If this is the case, 'timeouts_last_time' and 'now' differs too much. + This can be due to sys_check_timeouts() not being called at the right + times, but also when stopping in a breakpoint. Anyway, let's assume + this is not wanted, so add the first timer's time instead of 'diff' */ + timeout->time = msecs + next_timeout->time; + } + timeout->next = t->next; + t->next = timeout; + break; + } + } + } +} + +/** + * Go through timeout list (for this task only) and remove the first matching + * entry (subsequent entries remain untouched), even though the timeout has not + * triggered yet. + * + * @param handler callback function that would be called by the timeout + * @param arg callback argument that would be passed to handler +*/ +void +sys_untimeout (sys_timeout_handler handler, void *arg) +{ + struct sys_timeo *prev_t, *t; + + if (next_timeout == NULL) + { + return; + } + + for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) + { + if ((t->h == handler) && (t->arg == arg)) + { + /* We have a match */ + /* Unlink from previous in list */ + if (prev_t == NULL) + { + next_timeout = t->next; + } + else + { + prev_t->next = t->next; + } + /* If not the last one, add time of this one back to next */ + if (t->next != NULL) + { + t->next->time += t->time; + } + memp_free (MEMP_SYS_TIMEOUT, t); + return; + } + } + return; +} + +/** + * @ingroup lwip_nosys + * Handle timeouts for NO_SYS==1 (i.e. without using + * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout + * handler functions when timeouts expire. + * + * Must be called periodically from your main loop. + */ +#if !NO_SYS && !defined __DOXYGEN__ +static +#endif /* !NO_SYS */ + void +sys_check_timeouts (void) +{ + if (next_timeout) + { + struct sys_timeo *tmptimeout; + u32_t diff; + sys_timeout_handler handler; + void *arg; + u8_t had_one; + u32_t now; + + now = sys_now (); + /* this cares for wraparounds */ + diff = now - timeouts_last_time; + do + { + PBUF_CHECK_FREE_OOSEQ (); + had_one = 0; + tmptimeout = next_timeout; + if (tmptimeout && (tmptimeout->time <= diff)) + { + /* timeout has expired */ + had_one = 1; + timeouts_last_time += tmptimeout->time; + diff -= tmptimeout->time; + next_timeout = tmptimeout->next; + handler = tmptimeout->h; + arg = tmptimeout->arg; +#if LWIP_DEBUG_TIMERNAMES + if (handler != NULL) + { + LWIP_DEBUGF (TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", + tmptimeout->handler_name, arg)); + } +#endif /* LWIP_DEBUG_TIMERNAMES */ + memp_free (MEMP_SYS_TIMEOUT, tmptimeout); + if (handler != NULL) + { +#if !NO_SYS + /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the + timeout handler function. */ + LOCK_TCPIP_CORE (); +#endif /* !NO_SYS */ + handler (arg); +#if !NO_SYS + UNLOCK_TCPIP_CORE (); +#endif /* !NO_SYS */ + } + LWIP_TCPIP_THREAD_ALIVE (); + } + /* repeat until all expired timers have been called */ + } + while (had_one); + } +} + +/** Set back the timestamp of the last call to sys_check_timeouts() + * This is necessary if sys_check_timeouts() hasn't been called for a long + * time (e.g. while saving energy) to prevent all timer functions of that + * period being called. + */ +void +sys_restart_timeouts (void) +{ + timeouts_last_time = sys_now (); +} + +/** Return the time left before the next timeout is due. If no timeouts are + * enqueued, returns 0xffffffff + */ +#if !NO_SYS +static +#endif /* !NO_SYS */ + u32_t +sys_timeouts_sleeptime (void) +{ + u32_t diff; + if (next_timeout == NULL) + { + return 0xffffffff; + } + diff = sys_now () - timeouts_last_time; + if (diff > next_timeout->time) + { + return 0; + } + else + { + return next_timeout->time - diff; + } +} + +#if !NO_SYS + +/** + * Wait (forever) for a message to arrive in an mbox. + * While waiting, timeouts are processed. + * + * @param mbox the mbox to fetch the message from + * @param msg the place to store the message + */ +void +sys_timeouts_mbox_fetch (sys_mbox_t * mbox, void **msg) +{ + u32_t sleeptime; + +again: + if (!next_timeout) + { + sys_arch_mbox_fetch (mbox, msg, 0); + return; + } + + sleeptime = sys_timeouts_sleeptime (); + if (sleeptime == 0 + || sys_arch_mbox_fetch (mbox, msg, sleeptime) == SYS_ARCH_TIMEOUT) + { + /* If a SYS_ARCH_TIMEOUT value is returned, a timeout occurred + before a message could be fetched. */ + sys_check_timeouts (); + /* We try again to fetch a message from the mbox. */ + goto again; + } +} + +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ +/* Satisfy the TCP code which calls this function */ +static int tcpip_tcp_timer_active; + +void +tcp_timer_needed (void) +{ + /* timer is off but needed again? */ + if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) + { + /* enable and start timer */ + tcpip_tcp_timer_active = 1; + sys_timeout (TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } +} + +/** + * Timer callback function that calls tcp_tmr() and reschedules itself. + * + * @param arg unused argument + */ +void +tcpip_tcp_timer (void *arg) +{ + LWIP_UNUSED_ARG (arg); + + /* call TCP timer handler */ + tcp_tmr (); + /* timer still needed? */ + if (tcp_active_pcbs || tcp_tw_pcbs) + { + /* restart timer */ + sys_timeout (TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + } + else + { + /* disable timer */ + tcpip_tcp_timer_active = 0; + } +} + +void +sys_timeouts_init (void) +{ + size_t i; + /* tcp_tmr() at index 0 is started on demand */ + for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE (lwip_cyclic_timers); i++) + { + /* we have to cast via size_t to get rid of const warning + (this is OK as cyclic_timer() casts back to const* */ + sys_timeout (lwip_cyclic_timers[i].interval_ms, cyclic_timer, + LWIP_CONST_CAST (void *, &lwip_cyclic_timers[i])); + } +} + +#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */ diff --git a/stacks/lwip_stack/release/lwip_helper_files/download_lwip.sh b/stacks/lwip_stack/release/lwip_helper_files/download_lwip.sh new file mode 100644 index 0000000..c83cf19 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/download_lwip.sh @@ -0,0 +1,36 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +SCRIPT_DIR=$(dirname "$0") +echo $SCRIPT_DIR +LWIP_DOWNLOAD_DIR="${SCRIPT_DIR}/../../lwip_src/" +echo $LWIP_DOWNLOAD_DIR +if [ ! -d "${LWIP_DOWNLOAD_DIR}/lwip/" ]; then + mkdir -p ${LWIP_DOWNLOAD_DIR}/lwip/ + cd ${LWIP_DOWNLOAD_DIR}/ + wget -N --no-check-certificate http://download-mirror.savannah.nongnu.org/releases/lwip/lwip-2.0.3.zip + unzip ${LWIP_DOWNLOAD_DIR}/lwip-2.0.3.zip "lwip-2.0.3/src/*" -d ${LWIP_DOWNLOAD_DIR}/lwip + mv ${LWIP_DOWNLOAD_DIR}/lwip/lwip-2.0.3/src/* ${LWIP_DOWNLOAD_DIR}/lwip/ + rm -rf ${LWIP_DOWNLOAD_DIR}/lwip/lwip-2.0.3/ + cp -r ${SCRIPT_DIR}/arch/ ${LWIP_DOWNLOAD_DIR}/lwip/ + cp -r ${SCRIPT_DIR}/lwip/arch/ ${LWIP_DOWNLOAD_DIR}/lwip/include/lwip/ + cp -r ${SCRIPT_DIR}/core/* ${LWIP_DOWNLOAD_DIR}/lwip/core/ + cp -r ${SCRIPT_DIR}/include/* ${LWIP_DOWNLOAD_DIR}/lwip/include/lwip/ + mv ${LWIP_DOWNLOAD_DIR}/lwip/include/lwip/errno.h ${LWIP_DOWNLOAD_DIR}/lwip/include/lwip/lwip_errno.h + rm -f ${LWIP_DOWNLOAD_DIR}/lwip/include/lwip/netdb.h +fi diff --git a/stacks/lwip_stack/release/lwip_helper_files/include/lwipopts.h b/stacks/lwip_stack/release/lwip_helper_files/include/lwipopts.h new file mode 100644 index 0000000..4b1cf4f --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/include/lwipopts.h @@ -0,0 +1,39 @@ +#ifndef LWIP_LWIPOPTS_H +#define LWIP_LWIPOPTS_H + +#define RING_CACHE_SIZE 1024 +#define LISTEN_CACHE_SIZE 1024 +#define RECV_MAX_POOL 4 +#define MAX_TRY_GET_MEMORY_TIMES 4 +#define MAX_MEMORY_USED_SIZE 80 + +#define IP_HLEN 20 +#define TCP_HLEN 20 +#define TCP_MAX_OPTION_LEN 40 + +#define _cache_aligned __attribute__((__aligned__(64))) +#define LWIP_NETIF_API 1 + +#define TCP_OVERSIZE 1 +#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#define SYS_LIGHTWEIGHT_PROT 1 +#define LWIP_DISABLE_TCP_SANITY_CHECKS 1 +#define LWIP_COMPAT_MUTEX_ALLOWED 1 +#define LWIP_ERRNO_INCLUDE +#define LWIP_SKIP_PACKING_CHECK 1 +#define PBUF_POOL_FREE_OOSEQ 0 + +#define LWIP_DEBUG 1 +#define LWIP_TIMERS 0 +#define LWIP_TIMERS_CUSTOM 1 +#define LWIP_TCPIP_CORE_LOCKING 1 +#define MEM_LIBC_MALLOC 1 +#define MEMP_MEM_MALLOC 1 +#define LWIP_CALLBACK_API 1 +#define LWIP_SOCKET 0 +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#define LWIP_TCP_KEEPALIVE 1 +#define LWIP_TIMEVAL_PRIVATE 0 +#define LWIP_COMPAT_MUTEX 1 + +#endif diff --git a/stacks/lwip_stack/release/lwip_helper_files/include/opt.h b/stacks/lwip_stack/release/lwip_helper_files/include/opt.h new file mode 100644 index 0000000..040e9cf --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/include/opt.h @@ -0,0 +1,2875 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +/* + * NOTE: || defined __DOXYGEN__ is a workaround for doxygen bug - + * without this, doxygen does not see the actual #define + */ + +#if !defined LWIP_HDR_OPT_H +#define LWIP_HDR_OPT_H + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you don't like! + */ +#include "lwipopts.h" +#include "lwip/debug.h" + +/** + * @defgroup lwip_opts Options (lwipopts.h) + * @ingroup lwip + * + * @defgroup lwip_opts_debug Debugging + * @ingroup lwip_opts + * + * @defgroup lwip_opts_infrastructure Infrastructure + * @ingroup lwip_opts + * + * @defgroup lwip_opts_callback Callback-style APIs + * @ingroup lwip_opts + * + * @defgroup lwip_opts_threadsafe_apis Thread-safe APIs + * @ingroup lwip_opts + */ + + /* + ------------------------------------ + -------------- NO SYS -------------- + ------------------------------------ + */ +/** + * @defgroup lwip_opts_nosys NO_SYS + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * NO_SYS==1: Use lwIP without OS-awareness (no thread, semaphores, mutexes or + * mboxes). This means threaded APIs cannot be used (socket, netconn, + * i.e. everything in the 'api' folder), only the callback-style raw API is + * available (and you have to watch out for yourself that you don't access + * lwIP functions/structures from more than one context at a time!) + */ +#if !defined NO_SYS || defined __DOXYGEN__ +#define NO_SYS 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_timers Timers + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_TIMERS==0: Drop support for sys_timeout and lwip-internal cyclic timers. + * (the array of lwip-internal cyclic timers is still provided) + * (check NO_SYS_NO_TIMERS for compatibility to old versions) + */ +#if !defined LWIP_TIMERS || defined __DOXYGEN__ +#ifdef NO_SYS_NO_TIMERS +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) +#else +#define LWIP_TIMERS 1 +#endif +#endif + +/** + * LWIP_TIMERS_CUSTOM==1: Provide your own timer implementation. + * Function prototypes in timeouts.h and the array of lwip-internal cyclic timers + * are still included, but the implementation is not. The following functions + * will be required: sys_timeouts_init(), sys_timeout(), sys_untimeout(), + * sys_timeouts_mbox_fetch() + */ +#if !defined LWIP_TIMERS_CUSTOM || defined __DOXYGEN__ +#define LWIP_TIMERS_CUSTOM 0 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_memcpy memcpy + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#if !defined MEMCPY || defined __DOXYGEN__ +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#if !defined SMEMCPY || defined __DOXYGEN__ +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ----------- Core locking ----------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_lock Core locking and MPU + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MPU_COMPATIBLE: enables special memory management mechanism + * which makes lwip able to work on MPU (Memory Protection Unit) system + * by not passing stack-pointers to other threads + * (this decreases performance as memory is allocated from pools instead + * of keeping it on the stack) + */ +#if !defined LWIP_MPU_COMPATIBLE || defined __DOXYGEN__ +#define LWIP_MPU_COMPATIBLE 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING + * Creates a global mutex that is held during TCPIP thread operations. + * Can be locked by client code to perform lwIP operations without changing + * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and + * UNLOCK_TCPIP_CORE(). + * Your system should provide mutexes supporting priority inversion to use this. + */ +#if !defined LWIP_TCPIP_CORE_LOCKING || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING 1 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, + * this lets tcpip_input() grab the mutex for input packets as well, + * instead of allocating a message and passing it to tcpip_thread. + * + * ATTENTION: this does not work when tcpip_input() is called from + * interrupt context! + */ +#if !defined LWIP_TCPIP_CORE_LOCKING_INPUT || defined __DOXYGEN__ +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * SYS_LIGHTWEIGHT_PROT==1: enable inter-task protection (and task-vs-interrupt + * protection) for certain critical regions during buffer allocation, deallocation + * and memory allocation and deallocation. + * ATTENTION: This is required when using lwIP from more than one context! If + * you disable this, you must be sure what you are doing! + */ +#if !defined SYS_LIGHTWEIGHT_PROT || defined __DOXYGEN__ +#define SYS_LIGHTWEIGHT_PROT 1 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_mem Heap and memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#if !defined MEM_LIBC_MALLOC || defined __DOXYGEN__ +#define MEM_LIBC_MALLOC 0 +#endif + +/** + * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. + * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution + * speed (heap alloc can be much slower than pool alloc) and usage from interrupts + * (especially if your netif driver allocates PBUF_POOL pbufs for received frames + * from interrupt)! + * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, + * not only for internal pools defined in memp_std.h)! + */ +#if !defined MEMP_MEM_MALLOC || defined __DOXYGEN__ +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> \#define MEM_ALIGNMENT 4 + * 2 byte alignment -> \#define MEM_ALIGNMENT 2 + */ +#if !defined MEM_ALIGNMENT || defined __DOXYGEN__ +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#if !defined MEM_SIZE || defined __DOXYGEN__ +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#if !defined MEMP_OVERFLOW_CHECK || defined __DOXYGEN__ +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#if !defined MEMP_SANITY_CHECK || defined __DOXYGEN__ +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#if !defined MEM_USE_POOLS || defined __DOXYGEN__ +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#if !defined MEM_USE_POOLS_TRY_BIGGER_POOL || defined __DOXYGEN__ +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * include path somewhere. + */ +#if !defined MEMP_USE_CUSTOM_POOLS || defined __DOXYGEN__ +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#if !defined LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT || defined __DOXYGEN__ +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_memp Internal memory pools + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#if !defined MEMP_NUM_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#if !defined MEMP_NUM_RAW_PCB || defined __DOXYGEN__ +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#if !defined MEMP_NUM_UDP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_PCB_LISTEN || defined __DOXYGEN__ +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#if !defined MEMP_NUM_TCP_SEG || defined __DOXYGEN__ +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 + * with DMA-enabled MACs where the packet is not yet sent when netif->output + * returns. + */ +#if !defined MEMP_NUM_FRAG_PBUF || defined __DOXYGEN__ +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simultaneously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#if !defined MEMP_NUM_ARP_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members at the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#if !defined MEMP_NUM_IGMP_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simultaneously active timeouts. + * The default number of timeouts is calculated here for all enabled modules. + * The formula expects settings to be either '0' or '1'. + */ +#if !defined MEMP_NUM_SYS_TIMEOUT || defined __DOXYGEN__ +#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETBUF || defined __DOXYGEN__ +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_API || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#if !defined MEMP_NUM_TCPIP_MSG_INPKT || defined __DOXYGEN__ +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#if !defined MEMP_NUM_NETDB || defined __DOXYGEN__ +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#if !defined MEMP_NUM_LOCALHOSTLIST || defined __DOXYGEN__ +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#if !defined PBUF_POOL_SIZE || defined __DOXYGEN__ +#define PBUF_POOL_SIZE 16 +#endif + +/** MEMP_NUM_API_MSG: the number of concurrently active calls to various + * socket, netconn, and tcpip functions + */ +#if !defined MEMP_NUM_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_DNS_API_MSG: the number of concurrently active calls to netconn_gethostbyname + */ +#if !defined MEMP_NUM_DNS_API_MSG || defined __DOXYGEN__ +#define MEMP_NUM_DNS_API_MSG MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA: the number of concurrently active calls + * to getsockopt/setsockopt + */ +#if !defined MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA || defined __DOXYGEN__ +#define MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA MEMP_NUM_TCPIP_MSG_API +#endif + +/** MEMP_NUM_NETIFAPI_MSG: the number of concurrently active calls to the + * netifapi functions + */ +#if !defined MEMP_NUM_NETIFAPI_MSG || defined __DOXYGEN__ +#define MEMP_NUM_NETIFAPI_MSG MEMP_NUM_TCPIP_MSG_API +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_arp ARP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#if !defined LWIP_ARP || defined __DOXYGEN__ +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#if !defined ARP_TABLE_SIZE || defined __DOXYGEN__ +#define ARP_TABLE_SIZE 10 +#endif + +/** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 5) seconds = 5 minutes. + */ +#if !defined ARP_MAXAGE || defined __DOXYGEN__ +#define ARP_MAXAGE 300 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#if !defined ARP_QUEUEING || defined __DOXYGEN__ +#define ARP_QUEUEING 0 +#endif + +/** The maximum number of packets which may be queued for each + * unresolved address by other network layers. Defaults to 3, 0 means disabled. + * Old packets are dropped, new packets are queued. + */ +#if !defined ARP_QUEUE_LEN || defined __DOXYGEN__ +#define ARP_QUEUE_LEN 3 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with + * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and + * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) + * that returns 1 to accept a packet or 0 to drop a packet. + */ +#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__ +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support even though ARP might be disabled + */ +#if !defined LWIP_ETHERNET || defined __DOXYGEN__ +#define LWIP_ETHERNET LWIP_ARP +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#if !defined ETH_PAD_SIZE || defined __DOXYGEN__ +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#if !defined ETHARP_SUPPORT_STATIC_ENTRIES || defined __DOXYGEN__ +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + +/** ETHARP_TABLE_MATCH_NETIF==1: Match netif for ARP table entries. + * If disabled, duplicate IP address on multiple netifs are not supported + * (but this should only occur for AutoIP). + */ +#if !defined ETHARP_TABLE_MATCH_NETIF || defined __DOXYGEN__ +#define ETHARP_TABLE_MATCH_NETIF 0 +#endif +/** + * @} + */ + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv4 IPv4 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV4==1: Enable IPv4 + */ +#if !defined LWIP_IPV4 || defined __DOXYGEN__ +#define LWIP_IPV4 1 +#endif + +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#if !defined IP_FORWARD || defined __DOXYGEN__ +#define IP_FORWARD 0 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#if !defined IP_REASSEMBLY || defined __DOXYGEN__ +#define IP_REASSEMBLY 1 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#if !defined IP_FRAG || defined __DOXYGEN__ +#define IP_FRAG 1 +#endif + +#if !LWIP_IPV4 +/* disable IPv4 extensions when IPv4 is disabled */ +#undef IP_FORWARD +#define IP_FORWARD 0 +#undef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#undef IP_FRAG +#define IP_FRAG 0 +#endif /* !LWIP_IPV4 */ + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#if !defined IP_OPTIONS_ALLOWED || defined __DOXYGEN__ +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#if !defined IP_REASS_MAXAGE || defined __DOXYGEN__ +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#if !defined IP_REASS_MAX_PBUFS || defined __DOXYGEN__ +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#if !defined IP_DEFAULT_TTL || defined __DOXYGEN__ +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#if !defined IP_SOF_BROADCAST || defined __DOXYGEN__ +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#if !defined IP_SOF_BROADCAST_RECV || defined __DOXYGEN__ +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/** + * IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back + * out on the netif where it was received. This should only be used for + * wireless networks. + * ATTENTION: When this is 1, make sure your netif driver correctly marks incoming + * link-layer-broadcast/multicast packets as such using the corresponding pbuf flags! + */ +#if !defined IP_FORWARD_ALLOW_TX_ON_RX_NETIF || defined __DOXYGEN__ +#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0 +#endif + +/** + * LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first + * local TCP/UDP pcb (default==0). This can prevent creating predictable port + * numbers after booting a device. + */ +#if !defined LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS || defined __DOXYGEN__ +#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_icmp ICMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#if !defined LWIP_ICMP || defined __DOXYGEN__ +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#if !defined ICMP_TTL || defined __DOXYGEN__ +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#if !defined LWIP_BROADCAST_PING || defined __DOXYGEN__ +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#if !defined LWIP_MULTICAST_PING || defined __DOXYGEN__ +#define LWIP_MULTICAST_PING 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_raw RAW + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined LWIP_RAW || defined __DOXYGEN__ +#define LWIP_RAW 0 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#if !defined RAW_TTL || defined __DOXYGEN__ +#define RAW_TTL (IP_DEFAULT_TTL) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dhcp DHCP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#if !defined LWIP_DHCP || defined __DOXYGEN__ +#define LWIP_DHCP 0 +#endif +#if !LWIP_IPV4 +/* disable DHCP when IPv4 is disabled */ +#undef LWIP_DHCP +#define LWIP_DHCP 0 +#endif /* !LWIP_IPV4 */ + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#if !defined DHCP_DOES_ARP_CHECK || defined __DOXYGEN__ +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/** + * LWIP_DHCP_CHECK_LINK_UP==1: dhcp_start() only really starts if the netif has + * NETIF_FLAG_LINK_UP set in its flags. As this is only an optimization and + * netif drivers might not set this flag, the default is off. If enabled, + * netif_set_link_up() must be called to continue dhcp starting. + */ +#if !defined LWIP_DHCP_CHECK_LINK_UP +#define LWIP_DHCP_CHECK_LINK_UP 0 +#endif + +/** + * LWIP_DHCP_BOOTP_FILE==1: Store offered_si_addr and boot_file_name. + */ +#if !defined LWIP_DHCP_BOOTP_FILE || defined __DOXYGEN__ +#define LWIP_DHCP_BOOTP_FILE 0 +#endif + +/** + * LWIP_DHCP_GETS_NTP==1: Request NTP servers with discover/select. For each + * response packet, an callback is called, which has to be provided by the port: + * void dhcp_set_ntp_servers(u8_t num_ntp_servers, ip_addr_t* ntp_server_addrs); +*/ +#if !defined LWIP_DHCP_GET_NTP_SRV || defined __DOXYGEN__ +#define LWIP_DHCP_GET_NTP_SRV 0 +#endif + +/** + * The maximum of NTP servers requested + */ +#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_NTP_SERVERS 1 +#endif + +/** + * LWIP_DHCP_MAX_DNS_SERVERS > 0: Request DNS servers with discover/select. + * DHCP servers received in the response are passed to DNS via @ref dns_setserver() + * (up to the maximum limit defined here). + */ +#if !defined LWIP_DHCP_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_DHCP_MAX_DNS_SERVERS DNS_MAX_SERVERS +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_autoip AUTOIP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#if !defined LWIP_AUTOIP || defined __DOXYGEN__ +#define LWIP_AUTOIP 0 +#endif +#if !LWIP_IPV4 +/* disable AUTOIP when IPv4 is disabled */ +#undef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif /* !LWIP_IPV4 */ + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP (the DHCP client keeps + * running in this case). This can be set as low as 1 to get an AutoIP address + * very quickly, but you should be prepared to handle a changing IP address + * when DHCP overrides AutoIP. + */ +#if !defined LWIP_DHCP_AUTOIP_COOP_TRIES || defined __DOXYGEN__ +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- SNMP MIB2 support ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_mib2 SNMP MIB2 callbacks + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_MIB2_CALLBACKS==1: Turn on SNMP MIB2 callbacks. + * Turn this on to get callbacks needed to implement MIB2. + * Usually MIB2_STATS should be enabled, too. + */ +#if !defined LWIP_MIB2_CALLBACKS || defined __DOXYGEN__ +#define LWIP_MIB2_CALLBACKS 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ----- Multicast/IGMP options ----- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_igmp IGMP + * @ingroup lwip_opts_ipv4 + * @{ + */ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#if !defined LWIP_IGMP || defined __DOXYGEN__ +#define LWIP_IGMP 0 +#endif +#if !LWIP_IPV4 +#undef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/** + * LWIP_MULTICAST_TX_OPTIONS==1: Enable multicast TX support like the socket options + * IP_MULTICAST_TTL/IP_MULTICAST_IF/IP_MULTICAST_LOOP + */ +#if !defined LWIP_MULTICAST_TX_OPTIONS || defined __DOXYGEN__ +#define LWIP_MULTICAST_TX_OPTIONS (LWIP_IGMP && LWIP_UDP) +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_dns DNS + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#if !defined LWIP_DNS || defined __DOXYGEN__ +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#if !defined DNS_TABLE_SIZE || defined __DOXYGEN__ +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#if !defined DNS_MAX_NAME_LENGTH || defined __DOXYGEN__ +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers + * The first server can be initialized automatically by defining + * DNS_SERVER_ADDRESS(ipaddr), where 'ipaddr' is an 'ip_addr_t*' + */ +#if !defined DNS_MAX_SERVERS || defined __DOXYGEN__ +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#if !defined DNS_DOES_NAME_CHECK || defined __DOXYGEN__ +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** LWIP_DNS_SECURE: controls the security level of the DNS implementation + * Use all DNS security features by default. + * This is overridable but should only be needed by very small targets + * or when using against non standard DNS servers. */ +#if !defined LWIP_DNS_SECURE || defined __DOXYGEN__ +#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) +#endif + +/* A list of DNS security features follows */ +#define LWIP_DNS_SECURE_RAND_XID 1 +#define LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING 2 +#define LWIP_DNS_SECURE_RAND_SRC_PORT 4 + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, you have to define an initializer: + * \#define DNS_LOCAL_HOSTLIST_INIT {DNS_LOCAL_HOSTLIST_ELEM("host_ip4", IPADDR4_INIT_BYTES(1,2,3,4)), \ + * DNS_LOCAL_HOSTLIST_ELEM("host_ip6", IPADDR6_INIT_HOST(123, 234, 345, 456)} + * + * Instead, you can also use an external function: + * \#define DNS_LOOKUP_LOCAL_EXTERN(x) extern err_t my_lookup_function(const char *name, ip_addr_t *addr, u8_t dns_addrtype) + * that looks up the IP address and returns ERR_OK if found (LWIP_DNS_ADDRTYPE_xxx is passed in dns_addrtype). + */ +#if !defined DNS_LOCAL_HOSTLIST || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#if !defined DNS_LOCAL_HOSTLIST_IS_DYNAMIC || defined __DOXYGEN__ +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/** Set this to 1 to enable querying ".local" names via mDNS + * using a One-Shot Multicast DNS Query */ +#if !defined LWIP_DNS_SUPPORT_MDNS_QUERIES || defined __DOXYGEN__ +#define LWIP_DNS_SUPPORT_MDNS_QUERIES 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_udp UDP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#if !defined LWIP_UDP || defined __DOXYGEN__ +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#if !defined LWIP_UDPLITE || defined __DOXYGEN__ +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#if !defined UDP_TTL || defined __DOXYGEN__ +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#if !defined LWIP_NETBUF_RECVINFO || defined __DOXYGEN__ +#define LWIP_NETBUF_RECVINFO 0 +#endif +/** + * @} + */ + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * @defgroup lwip_opts_tcp TCP + * @ingroup lwip_opts_callback + * @{ + */ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#if !defined LWIP_TCP || defined __DOXYGEN__ +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#if !defined TCP_TTL || defined __DOXYGEN__ +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well. + * ATTENTION: when using TCP_RCV_SCALE, TCP_WND is the total size + * with scaling applied. Maximum window value in the TCP header + * will be TCP_WND >> TCP_RCV_SCALE + */ +#if !defined TCP_WND || defined __DOXYGEN__ +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#if !defined TCP_MAXRTX || defined __DOXYGEN__ +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#if !defined TCP_SYNMAXRTX || defined __DOXYGEN__ +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#if !defined TCP_QUEUE_OOSEQ || defined __DOXYGEN__ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#if !defined TCP_MSS || defined __DOXYGEN__ +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#if !defined TCP_CALCULATE_EFF_SEND_MSS || defined __DOXYGEN__ +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + * To achieve good performance, this should be at least 2 * TCP_MSS. + */ +#if !defined TCP_SND_BUF || defined __DOXYGEN__ +#define TCP_SND_BUF (2 * TCP_MSS) +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#if !defined TCP_SND_QUEUELEN || defined __DOXYGEN__ +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#if !defined TCP_SNDLOWAT || defined __DOXYGEN__ +#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#if !defined TCP_SNDQUEUELOWAT || defined __DOXYGEN__ +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_BYTES || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_BYTES 0 +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb. + * Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_MAX_PBUFS || defined __DOXYGEN__ +#define TCP_OOSEQ_MAX_PBUFS 0 +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#if !defined TCP_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#if !defined TCP_DEFAULT_LISTEN_BACKLOG || defined __DOXYGEN__ +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#if !defined TCP_OVERSIZE || defined __DOXYGEN__ +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#if !defined LWIP_TCP_TIMESTAMPS || defined __DOXYGEN__ +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. This is the default. + */ +#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API) || defined __DOXYGEN__ +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#else +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#endif +#ifndef LWIP_CALLBACK_API +#define LWIP_CALLBACK_API 0 +#endif +#endif + +/** + * LWIP_WND_SCALE and TCP_RCV_SCALE: + * Set LWIP_WND_SCALE to 1 to enable window scaling. + * Set TCP_RCV_SCALE to the desired scaling factor (shift count in the + * range of [0..14]). + * When LWIP_WND_SCALE is enabled but TCP_RCV_SCALE is 0, we can use a large + * send window while having a small receive window only. + */ +#if !defined LWIP_WND_SCALE || defined __DOXYGEN__ +#define LWIP_WND_SCALE 0 +#define TCP_RCV_SCALE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * @defgroup lwip_opts_pbuf PBUF + * @ingroup lwip_opts + * @{ + */ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#if !defined PBUF_LINK_HLEN || defined __DOXYGEN__ +#if defined LWIP_HOOK_VLAN_SET && !defined __DOXYGEN__ +#define PBUF_LINK_HLEN (18 + ETH_PAD_SIZE) +#else /* LWIP_HOOK_VLAN_SET */ +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif /* LWIP_HOOK_VLAN_SET */ +#endif + +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + */ +#if !defined PBUF_LINK_ENCAPSULATION_HLEN || defined __DOXYGEN__ +#define PBUF_LINK_ENCAPSULATION_HLEN 0u +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accommodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#if !defined PBUF_POOL_BUFSIZE || defined __DOXYGEN__ +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_ENCAPSULATION_HLEN+PBUF_LINK_HLEN) +#endif +/** + * @} + */ + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * @defgroup lwip_opts_netif NETIF + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#if !defined LWIP_NETIF_HOSTNAME || defined __DOXYGEN__ +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#if !defined LWIP_NETIF_API || defined __DOXYGEN__ +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquisition) + */ +#if !defined LWIP_NETIF_STATUS_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#if !defined LWIP_NETIF_LINK_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called + * when a netif has been removed + */ +#if !defined LWIP_NETIF_REMOVE_CALLBACK || defined __DOXYGEN__ +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#if !defined LWIP_NETIF_HWADDRHINT || defined __DOXYGEN__ +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#if !defined LWIP_NETIF_TX_SINGLE_PBUF || defined __DOXYGEN__ +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/** + * LWIP_NUM_NETIF_CLIENT_DATA: Number of clients that may store + * data in client_data member array of struct netif. + */ +#if !defined LWIP_NUM_NETIF_CLIENT_DATA || defined __DOXYGEN__ +#define LWIP_NUM_NETIF_CLIENT_DATA 0 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_loop Loopback interface + * @ingroup lwip_opts_netif + * @{ + */ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1). + * This is only needed when no real netifs are available. If at least one other + * netif is available, loopback traffic uses this netif. + */ +#if !defined LWIP_HAVE_LOOPIF || defined __DOXYGEN__ +#define LWIP_HAVE_LOOPIF LWIP_NETIF_LOOPBACK +#endif + +/** + * LWIP_LOOPIF_MULTICAST==1: Support multicast/IGMP on loop interface (127.0.0.1). + */ +#if !defined LWIP_LOOPIF_MULTICAST || defined __DOXYGEN__ +#define LWIP_LOOPIF_MULTICAST 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#if !defined LWIP_NETIF_LOOPBACK || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#if !defined LWIP_LOOPBACK_MAX_PBUFS || defined __DOXYGEN__ +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#if !defined LWIP_NETIF_LOOPBACK_MULTITHREADING || defined __DOXYGEN__ +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_thread Threading + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#if !defined TCPIP_THREAD_NAME || defined __DOXYGEN__ +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_STACKSIZE || defined __DOXYGEN__ +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#if !defined TCPIP_MBOX_SIZE || defined __DOXYGEN__ +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. + */ +#if !defined LWIP_TCPIP_THREAD_ALIVE || defined __DOXYGEN__ +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#if !defined SLIPIF_THREAD_NAME || defined __DOXYGEN__ +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_STACKSIZE || defined __DOXYGEN__ +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined SLIPIF_THREAD_PRIO || defined __DOXYGEN__ +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#if !defined DEFAULT_THREAD_NAME || defined __DOXYGEN__ +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_STACKSIZE || defined __DOXYGEN__ +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#if !defined DEFAULT_THREAD_PRIO || defined __DOXYGEN__ +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_RAW_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_UDP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#if !defined DEFAULT_TCP_RECVMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#if !defined DEFAULT_ACCEPTMBOX_SIZE || defined __DOXYGEN__ +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * @defgroup lwip_opts_netconn Netconn + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#if !defined LWIP_NETCONN || defined __DOXYGEN__ +#define LWIP_NETCONN 1 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout to create + * timers running in tcpip_thread from another thread. + */ +#if !defined LWIP_TCPIP_TIMEOUT || defined __DOXYGEN__ +#define LWIP_TCPIP_TIMEOUT 0 +#endif + +/** LWIP_NETCONN_SEM_PER_THREAD==1: Use one (thread-local) semaphore per + * thread calling socket/netconn functions instead of allocating one + * semaphore per netconn (and per select etc.) + * ATTENTION: a thread-local semaphore for API calls is needed: + * - LWIP_NETCONN_THREAD_SEM_GET() returning a sys_sem_t* + * - LWIP_NETCONN_THREAD_SEM_ALLOC() creating the semaphore + * - LWIP_NETCONN_THREAD_SEM_FREE() freeing the semaphore + * The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup(). + * Ports may call these for threads created with sys_thread_new(). + */ +#if !defined LWIP_NETCONN_SEM_PER_THREAD || defined __DOXYGEN__ +#define LWIP_NETCONN_SEM_PER_THREAD 0 +#endif + +/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread, + * writing from a 2nd thread and closing from a 3rd thread at the same time. + * ATTENTION: This is currently really alpha! Some requirements: + * - LWIP_NETCONN_SEM_PER_THREAD==1 is required to use one socket/netconn from + * multiple threads at once + * - sys_mbox_free() has to unblock receive tasks waiting on recvmbox/acceptmbox + * and prevent a task pending on this during/after deletion + */ +#if !defined LWIP_NETCONN_FULLDUPLEX || defined __DOXYGEN__ +#define LWIP_NETCONN_FULLDUPLEX 0 +#endif +/** + * @} + */ + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * @defgroup lwip_opts_socket Sockets + * @ingroup lwip_opts_threadsafe_apis + * @{ + */ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#if !defined LWIP_SOCKET || defined __DOXYGEN__ +#define LWIP_SOCKET 1 +#endif + +/* LWIP_SOCKET_SET_ERRNO==1: Set errno when socket functions cannot complete + * successfully, as required by POSIX. Default is POSIX-compliant. + */ +#if !defined LWIP_SOCKET_SET_ERRNO || defined __DOXYGEN__ +#define LWIP_SOCKET_SET_ERRNO 1 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names through defines. + * LWIP_COMPAT_SOCKETS==2: Same as ==1 but correctly named functions are created. + * While this helps code completion, it might conflict with existing libraries. + * (only used if you use sockets.c) + */ +#if !defined LWIP_COMPAT_SOCKETS || defined __DOXYGEN__ +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#if !defined LWIP_POSIX_SOCKETS_IO_NAMES || defined __DOXYGEN__ +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_SOCKET_OFFSET==n: Increases the file descriptor number created by LwIP with n. + * This can be useful when there are multiple APIs which create file descriptors. + * When they all start with a different offset and you won't make them overlap you can + * re implement read/write/close/ioctl/fnctl to send the requested action to the right + * library (sharing select will need more work though). + */ +#if !defined LWIP_SOCKET_OFFSET || defined __DOXYGEN__ +#define LWIP_SOCKET_OFFSET 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__ +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#if !defined LWIP_SO_SNDTIMEO || defined __DOXYGEN__ +#define LWIP_SO_SNDTIMEO 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#if !defined LWIP_SO_RCVTIMEO || defined __DOXYGEN__ +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int + * (milliseconds, much like winsock does) instead of a struct timeval (default). + */ +#if !defined LWIP_SO_SNDRCVTIMEO_NONSTANDARD || defined __DOXYGEN__ +#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#if !defined LWIP_SO_RCVBUF || defined __DOXYGEN__ +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * LWIP_SO_LINGER==1: Enable SO_LINGER processing. + */ +#if !defined LWIP_SO_LINGER || defined __DOXYGEN__ +#define LWIP_SO_LINGER 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#if !defined RECV_BUFSIZE_DEFAULT || defined __DOXYGEN__ +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * By default, TCP socket/netconn close waits 20 seconds max to send the FIN + */ +#if !defined LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT || defined __DOXYGEN__ +#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT 20000 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#if !defined SO_REUSE || defined __DOXYGEN__ +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#if !defined SO_REUSE_RXTOALL || defined __DOXYGEN__ +#define SO_REUSE_RXTOALL 0 +#endif + +/** + * LWIP_FIONREAD_LINUXMODE==0 (default): ioctl/FIONREAD returns the amount of + * pending data in the network buffer. This is the way windows does it. It's + * the default for lwIP since it is smaller. + * LWIP_FIONREAD_LINUXMODE==1: ioctl/FIONREAD returns the size of the next + * pending datagram in bytes. This is the way linux does it. This code is only + * here for compatibility. + */ +#if !defined LWIP_FIONREAD_LINUXMODE || defined __DOXYGEN__ +#define LWIP_FIONREAD_LINUXMODE 0 +#endif +/** + * @} + */ + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * @defgroup lwip_opts_stats Statistics + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#if !defined LWIP_STATS || defined __DOXYGEN__ +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#if !defined LWIP_STATS_DISPLAY || defined __DOXYGEN__ +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#if !defined LINK_STATS || defined __DOXYGEN__ +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#if !defined ETHARP_STATS || defined __DOXYGEN__ +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#if !defined IP_STATS || defined __DOXYGEN__ +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#if !defined IPFRAG_STATS || defined __DOXYGEN__ +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#if !defined ICMP_STATS || defined __DOXYGEN__ +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#if !defined IGMP_STATS || defined __DOXYGEN__ +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#if !defined UDP_STATS || defined __DOXYGEN__ +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#if !defined TCP_STATS || defined __DOXYGEN__ +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#if !defined MEM_STATS || defined __DOXYGEN__ +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#if !defined MEMP_STATS || defined __DOXYGEN__ +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#if !defined SYS_STATS || defined __DOXYGEN__ +#define SYS_STATS (NO_SYS == 0) +#endif + +/** + * IP6_STATS==1: Enable IPv6 stats. + */ +#if !defined IP6_STATS || defined __DOXYGEN__ +#define IP6_STATS (LWIP_IPV6) +#endif + +/** + * ICMP6_STATS==1: Enable ICMP for IPv6 stats. + */ +#if !defined ICMP6_STATS || defined __DOXYGEN__ +#define ICMP6_STATS (LWIP_IPV6 && LWIP_ICMP6) +#endif + +/** + * IP6_FRAG_STATS==1: Enable IPv6 fragmentation stats. + */ +#if !defined IP6_FRAG_STATS || defined __DOXYGEN__ +#define IP6_FRAG_STATS (LWIP_IPV6 && (LWIP_IPV6_FRAG || LWIP_IPV6_REASS)) +#endif + +/** + * MLD6_STATS==1: Enable MLD for IPv6 stats. + */ +#if !defined MLD6_STATS || defined __DOXYGEN__ +#define MLD6_STATS (LWIP_IPV6 && LWIP_IPV6_MLD) +#endif + +/** + * ND6_STATS==1: Enable Neighbor discovery for IPv6 stats. + */ +#if !defined ND6_STATS || defined __DOXYGEN__ +#define ND6_STATS (LWIP_IPV6) +#endif + +/** + * MIB2_STATS==1: Stats for SNMP MIB2. + */ +#if !defined MIB2_STATS || defined __DOXYGEN__ +#define MIB2_STATS 0 +#endif + +#else + +#define LINK_STATS 0 +#define ETHARP_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 +#define IP6_STATS 0 +#define ICMP6_STATS 0 +#define IP6_FRAG_STATS 0 +#define MLD6_STATS 0 +#define ND6_STATS 0 +#define MIB2_STATS 0 + +#endif /* LWIP_STATS */ +/** + * @} + */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * @defgroup lwip_opts_checksum Checksum + * @ingroup lwip_opts_infrastructure + * @{ + */ +/** + * LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled + * per netif. + * ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled! + */ +#if !defined LWIP_CHECKSUM_CTRL_PER_NETIF || defined __DOXYGEN__ +#define LWIP_CHECKSUM_CTRL_PER_NETIF 0 +#endif + +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#if !defined CHECKSUM_GEN_IP || defined __DOXYGEN__ +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#if !defined CHECKSUM_GEN_UDP || defined __DOXYGEN__ +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#if !defined CHECKSUM_GEN_TCP || defined __DOXYGEN__ +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets. + */ +#if !defined CHECKSUM_GEN_ICMP || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP 1 +#endif + +/** + * CHECKSUM_GEN_ICMP6==1: Generate checksums in software for outgoing ICMP6 packets. + */ +#if !defined CHECKSUM_GEN_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_GEN_ICMP6 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#if !defined CHECKSUM_CHECK_IP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#if !defined CHECKSUM_CHECK_UDP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#if !defined CHECKSUM_CHECK_TCP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP==1: Check checksums in software for incoming ICMP packets. + */ +#if !defined CHECKSUM_CHECK_ICMP || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP 1 +#endif + +/** + * CHECKSUM_CHECK_ICMP6==1: Check checksums in software for incoming ICMPv6 packets + */ +#if !defined CHECKSUM_CHECK_ICMP6 || defined __DOXYGEN__ +#define CHECKSUM_CHECK_ICMP6 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#if !defined LWIP_CHECKSUM_ON_COPY || defined __DOXYGEN__ +#define LWIP_CHECKSUM_ON_COPY 0 +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_ipv6 IPv6 + * @ingroup lwip_opts + * @{ + */ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#if !defined LWIP_IPV6 || defined __DOXYGEN__ +#define LWIP_IPV6 0 +#endif + +/** + * LWIP_IPV6_NUM_ADDRESSES: Number of IPv6 addresses per netif. + */ +#if !defined LWIP_IPV6_NUM_ADDRESSES || defined __DOXYGEN__ +#define LWIP_IPV6_NUM_ADDRESSES 3 +#endif + +/** + * LWIP_IPV6_FORWARD==1: Forward IPv6 packets across netifs + */ +#if !defined LWIP_IPV6_FORWARD || defined __DOXYGEN__ +#define LWIP_IPV6_FORWARD 0 +#endif + +/** + * LWIP_IPV6_FRAG==1: Fragment outgoing IPv6 packets that are too big. + */ +#if !defined LWIP_IPV6_FRAG || defined __DOXYGEN__ +#define LWIP_IPV6_FRAG 0 +#endif + +/** + * LWIP_IPV6_REASS==1: reassemble incoming IPv6 packets that fragmented + */ +#if !defined LWIP_IPV6_REASS || defined __DOXYGEN__ +#define LWIP_IPV6_REASS (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_SEND_ROUTER_SOLICIT==1: Send router solicitation messages during + * network startup. + */ +#if !defined LWIP_IPV6_SEND_ROUTER_SOLICIT || defined __DOXYGEN__ +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 +#endif + +/** + * LWIP_IPV6_AUTOCONFIG==1: Enable stateless address autoconfiguration as per RFC 4862. + */ +#if !defined LWIP_IPV6_AUTOCONFIG || defined __DOXYGEN__ +#define LWIP_IPV6_AUTOCONFIG (LWIP_IPV6) +#endif + +/** + * LWIP_IPV6_DUP_DETECT_ATTEMPTS=[0..7]: Number of duplicate address detection attempts. + */ +#if !defined LWIP_IPV6_DUP_DETECT_ATTEMPTS || defined __DOXYGEN__ +#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_icmp6 ICMP6 + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ICMP6==1: Enable ICMPv6 (mandatory per RFC) + */ +#if !defined LWIP_ICMP6 || defined __DOXYGEN__ +#define LWIP_ICMP6 (LWIP_IPV6) +#endif + +/** + * LWIP_ICMP6_DATASIZE: bytes from original packet to send back in + * ICMPv6 error messages. + */ +#if !defined LWIP_ICMP6_DATASIZE || defined __DOXYGEN__ +#define LWIP_ICMP6_DATASIZE 8 +#endif + +/** + * LWIP_ICMP6_HL: default hop limit for ICMPv6 messages + */ +#if !defined LWIP_ICMP6_HL || defined __DOXYGEN__ +#define LWIP_ICMP6_HL 255 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_mld6 Multicast listener discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_IPV6_MLD==1: Enable multicast listener discovery protocol. + * If LWIP_IPV6 is enabled but this setting is disabled, the MAC layer must + * indiscriminately pass all inbound IPv6 multicast traffic to lwIP. + */ +#if !defined LWIP_IPV6_MLD || defined __DOXYGEN__ +#define LWIP_IPV6_MLD (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_MLD6_GROUP: Max number of IPv6 multicast groups that can be joined. + * There must be enough groups so that each netif can join the solicited-node + * multicast group for each of its local addresses, plus one for MDNS if + * applicable, plus any number of groups to be joined on UDP sockets. + */ +#if !defined MEMP_NUM_MLD6_GROUP || defined __DOXYGEN__ +#define MEMP_NUM_MLD6_GROUP 4 +#endif +/** + * @} + */ + +/** + * @defgroup lwip_opts_nd6 Neighbor discovery + * @ingroup lwip_opts_ipv6 + * @{ + */ +/** + * LWIP_ND6_QUEUEING==1: queue outgoing IPv6 packets while MAC address + * is being resolved. + */ +#if !defined LWIP_ND6_QUEUEING || defined __DOXYGEN__ +#define LWIP_ND6_QUEUEING (LWIP_IPV6) +#endif + +/** + * MEMP_NUM_ND6_QUEUE: Max number of IPv6 packets to queue during MAC resolution. + */ +#if !defined MEMP_NUM_ND6_QUEUE || defined __DOXYGEN__ +#define MEMP_NUM_ND6_QUEUE 20 +#endif + +/** + * LWIP_ND6_NUM_NEIGHBORS: Number of entries in IPv6 neighbor cache + */ +#if !defined LWIP_ND6_NUM_NEIGHBORS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_NEIGHBORS 10 +#endif + +/** + * LWIP_ND6_NUM_DESTINATIONS: number of entries in IPv6 destination cache + */ +#if !defined LWIP_ND6_NUM_DESTINATIONS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_DESTINATIONS 10 +#endif + +/** + * LWIP_ND6_NUM_PREFIXES: number of entries in IPv6 on-link prefixes cache + */ +#if !defined LWIP_ND6_NUM_PREFIXES || defined __DOXYGEN__ +#define LWIP_ND6_NUM_PREFIXES 5 +#endif + +/** + * LWIP_ND6_NUM_ROUTERS: number of entries in IPv6 default router cache + */ +#if !defined LWIP_ND6_NUM_ROUTERS || defined __DOXYGEN__ +#define LWIP_ND6_NUM_ROUTERS 3 +#endif + +/** + * LWIP_ND6_MAX_MULTICAST_SOLICIT: max number of multicast solicit messages to send + * (neighbor solicit and router solicit) + */ +#if !defined LWIP_ND6_MAX_MULTICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_MULTICAST_SOLICIT 3 +#endif + +/** + * LWIP_ND6_MAX_UNICAST_SOLICIT: max number of unicast neighbor solicitation messages + * to send during neighbor reachability detection. + */ +#if !defined LWIP_ND6_MAX_UNICAST_SOLICIT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_UNICAST_SOLICIT 3 +#endif + +/** + * Unused: See ND RFC (time in milliseconds). + */ +#if !defined LWIP_ND6_MAX_ANYCAST_DELAY_TIME || defined __DOXYGEN__ +#define LWIP_ND6_MAX_ANYCAST_DELAY_TIME 1000 +#endif + +/** + * Unused: See ND RFC + */ +#if !defined LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT || defined __DOXYGEN__ +#define LWIP_ND6_MAX_NEIGHBOR_ADVERTISEMENT 3 +#endif + +/** + * LWIP_ND6_REACHABLE_TIME: default neighbor reachable time (in milliseconds). + * May be updated by router advertisement messages. + */ +#if !defined LWIP_ND6_REACHABLE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_REACHABLE_TIME 30000 +#endif + +/** + * LWIP_ND6_RETRANS_TIMER: default retransmission timer for solicitation messages + */ +#if !defined LWIP_ND6_RETRANS_TIMER || defined __DOXYGEN__ +#define LWIP_ND6_RETRANS_TIMER 1000 +#endif + +/** + * LWIP_ND6_DELAY_FIRST_PROBE_TIME: Delay before first unicast neighbor solicitation + * message is sent, during neighbor reachability detection. + */ +#if !defined LWIP_ND6_DELAY_FIRST_PROBE_TIME || defined __DOXYGEN__ +#define LWIP_ND6_DELAY_FIRST_PROBE_TIME 5000 +#endif + +/** + * LWIP_ND6_ALLOW_RA_UPDATES==1: Allow Router Advertisement messages to update + * Reachable time and retransmission timers, and netif MTU. + */ +#if !defined LWIP_ND6_ALLOW_RA_UPDATES || defined __DOXYGEN__ +#define LWIP_ND6_ALLOW_RA_UPDATES 1 +#endif + +/** + * LWIP_ND6_TCP_REACHABILITY_HINTS==1: Allow TCP to provide Neighbor Discovery + * with reachability hints for connected destinations. This helps avoid sending + * unicast neighbor solicitation messages. + */ +#if !defined LWIP_ND6_TCP_REACHABILITY_HINTS || defined __DOXYGEN__ +#define LWIP_ND6_TCP_REACHABILITY_HINTS 1 +#endif + +/** + * LWIP_ND6_RDNSS_MAX_DNS_SERVERS > 0: Use IPv6 Router Advertisement Recursive + * DNS Server Option (as per RFC 6106) to copy a defined maximum number of DNS + * servers to the DNS module. + */ +#if !defined LWIP_ND6_RDNSS_MAX_DNS_SERVERS || defined __DOXYGEN__ +#define LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0 +#endif +/** + * @} + */ + +/** + * LWIP_IPV6_DHCP6==1: enable DHCPv6 stateful address autoconfiguration. + */ +#if !defined LWIP_IPV6_DHCP6 || defined __DOXYGEN__ +#define LWIP_IPV6_DHCP6 0 +#endif + +/* + --------------------------------------- + ---------- Hook options --------------- + --------------------------------------- +*/ + +/** + * @defgroup lwip_opts_hooks Hooks + * @ingroup lwip_opts_infrastructure + * Hooks are undefined by default, define them to a function if you need them. + * @{ + */ + +/** + * LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. + * Declare your hook function prototypes in there, you may also #include all headers + * providing data types that are need in this file. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h" +#endif + +/** + * LWIP_HOOK_TCP_ISN: + * Hook for generation of the Initial Sequence Number (ISN) for a new TCP + * connection. The default lwIP ISN generation algorithm is very basic and may + * allow for TCP spoofing attacks. This hook provides the means to implement + * the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), + * or any other desired algorithm as a replacement. + * Called from tcp_connect() and tcp_listen_input() when an ISN is needed for + * a new TCP connection, if TCP support (@ref LWIP_TCP) is enabled.\n + * Signature: u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port); + * - it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations\n + * Arguments: + * - local_ip: pointer to the local IP address of the connection + * - local_port: local port number of the connection (host-byte order) + * - remote_ip: pointer to the remote IP address of the connection + * - remote_port: remote port number of the connection (host-byte order)\n + * Return value: + * - the 32-bit Initial Sequence Number to use for the new TCP connection. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port) +#endif + +/** + * LWIP_HOOK_IP4_INPUT(pbuf, input_netif): + * - called from ip_input() (IPv4) + * - pbuf: received struct pbuf passed to ip_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP4_ROUTE(dest): + * - called from ip_route() (IPv4) + * - dest: destination IPv4 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE() +#endif + +/** + * LWIP_HOOK_IP4_ROUTE_SRC(dest, src): + * - source-based routing for IPv4 (see LWIP_HOOK_IP4_ROUTE(), src may be NULL) + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP4_ROUTE_SRC(dest, src) +#endif + +/** + * LWIP_HOOK_ETHARP_GET_GW(netif, dest): + * - called from etharp_output() (IPv4) + * - netif: the netif used for sending + * - dest: the destination IPv4 address + * Returns the IPv4 address of the gateway to handle the specified destination + * IPv4 address. If NULL is returned, the netif's default gateway is used. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv4 routing together with + * LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ETHARP_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_IP6_INPUT(pbuf, input_netif): + * - called from ip6_input() (IPv6) + * - pbuf: received struct pbuf passed to ip6_input() + * - input_netif: struct netif on which the packet has been received + * Return values: + * - 0: Hook has not consumed the packet, packet is processed as normal + * - != 0: Hook has consumed the packet. + * If the hook consumed the packet, 'pbuf' is in the responsibility of the hook + * (i.e. free it when done). + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_INPUT(pbuf, input_netif) +#endif + +/** + * LWIP_HOOK_IP6_ROUTE(src, dest): + * - called from ip6_route() (IPv6) + * - src: sourc IPv6 address + * - dest: destination IPv6 address + * Returns the destination netif or NULL if no destination netif is found. In + * that case, ip6_route() continues as normal. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_IP6_ROUTE(src, dest) +#endif + +/** + * LWIP_HOOK_ND6_GET_GW(netif, dest): + * - called from nd6_get_next_hop_entry() (IPv6) + * - netif: the netif used for sending + * - dest: the destination IPv6 address + * Returns the IPv6 address of the next hop to handle the specified destination + * IPv6 address. If NULL is returned, a NDP-discovered router is used instead. + * The returned address MUST be directly reachable on the specified netif! + * This function is meant to implement advanced IPv6 routing together with + * LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is + * not part of lwIP but can e.g. be hidden in the netif's state argument. +*/ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_ND6_GET_GW(netif, dest) +#endif + +/** + * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): + * - called from ethernet_input() if VLAN support is enabled + * - netif: struct netif on which the packet has been received + * - eth_hdr: struct eth_hdr of the packet + * - vlan_hdr: struct eth_vlan_hdr of the packet + * Return values: + * - 0: Packet must be dropped. + * - != 0: Packet must be accepted. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr) +#endif + +/** + * LWIP_HOOK_VLAN_SET: + * Hook can be used to set prio_vid field of vlan_hdr. If you need to store data + * on per-netif basis to implement this callback, see @ref netif_cd. + * Called from ethernet_output() if VLAN support (@ref ETHARP_SUPPORT_VLAN) is enabled.\n + * Signature: s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);\n + * Arguments: + * - netif: struct netif that the packet will be sent through + * - p: struct pbuf packet to be sent + * - src: source eth address + * - dst: destination eth address + * - eth_type: ethernet type to packet to be sent\n + * + * + * Return values: + * - <0: Packet shall not contain VLAN header. + * - 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order. + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type) +#endif + +/** + * LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): + * - called from memp_free() when a memp pool was empty and an item is now available + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_MEMP_AVAILABLE(memp_t_type) +#endif + +/** + * LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): + * Called from ethernet_input() when an unknown eth type is encountered. + * Return ERR_OK if packet is accepted, any error code otherwise. + * Payload points to ethernet header! + */ +#ifdef __DOXYGEN__ +#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif) +#endif +/** + * @} + */ + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * @defgroup lwip_opts_debugmsg Debug messages + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + * @see debugging_levels + */ +#if !defined LWIP_DBG_MIN_LEVEL || defined __DOXYGEN__ +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + * @see debugging_levels + */ +#if !defined LWIP_DBG_TYPES_ON || defined __DOXYGEN__ +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#if !defined ETHARP_DEBUG || defined __DOXYGEN__ +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#if !defined NETIF_DEBUG || defined __DOXYGEN__ +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#if !defined PBUF_DEBUG || defined __DOXYGEN__ +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#if !defined API_LIB_DEBUG || defined __DOXYGEN__ +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#if !defined API_MSG_DEBUG || defined __DOXYGEN__ +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#if !defined SOCKETS_DEBUG || defined __DOXYGEN__ +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#if !defined ICMP_DEBUG || defined __DOXYGEN__ +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#if !defined IGMP_DEBUG || defined __DOXYGEN__ +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#if !defined INET_DEBUG || defined __DOXYGEN__ +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#if !defined IP_DEBUG || defined __DOXYGEN__ +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#if !defined IP_REASS_DEBUG || defined __DOXYGEN__ +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#if !defined RAW_DEBUG || defined __DOXYGEN__ +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#if !defined MEM_DEBUG || defined __DOXYGEN__ +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#if !defined MEMP_DEBUG || defined __DOXYGEN__ +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#if !defined SYS_DEBUG || defined __DOXYGEN__ +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#if !defined TIMERS_DEBUG || defined __DOXYGEN__ +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#if !defined TCP_DEBUG || defined __DOXYGEN__ +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#if !defined TCP_INPUT_DEBUG || defined __DOXYGEN__ +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#if !defined TCP_FR_DEBUG || defined __DOXYGEN__ +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#if !defined TCP_RTO_DEBUG || defined __DOXYGEN__ +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#if !defined TCP_CWND_DEBUG || defined __DOXYGEN__ +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#if !defined TCP_WND_DEBUG || defined __DOXYGEN__ +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#if !defined TCP_OUTPUT_DEBUG || defined __DOXYGEN__ +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#if !defined TCP_RST_DEBUG || defined __DOXYGEN__ +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#if !defined TCP_QLEN_DEBUG || defined __DOXYGEN__ +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#if !defined UDP_DEBUG || defined __DOXYGEN__ +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#if !defined TCPIP_DEBUG || defined __DOXYGEN__ +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#if !defined SLIP_DEBUG || defined __DOXYGEN__ +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#if !defined DHCP_DEBUG || defined __DOXYGEN__ +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#if !defined AUTOIP_DEBUG || defined __DOXYGEN__ +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#if !defined DNS_DEBUG || defined __DOXYGEN__ +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#if !defined IP6_DEBUG || defined __DOXYGEN__ +#define IP6_DEBUG LWIP_DBG_OFF +#endif +/** + * @} + */ + +/* + -------------------------------------------------- + ---------- Performance tracking options ---------- + -------------------------------------------------- +*/ +/** + * @defgroup lwip_opts_perf Performance + * @ingroup lwip_opts_debug + * @{ + */ +/** + * LWIP_PERF: Enable performance testing for lwIP + * (if enabled, arch/perf.h is included) + */ +#if !defined LWIP_PERF || defined __DOXYGEN__ +#define LWIP_PERF 0 +#endif +/** + * @} + */ + +#endif /* LWIP_HDR_OPT_H */ diff --git a/stacks/lwip_stack/release/lwip_helper_files/include/sys.h b/stacks/lwip_stack/release/lwip_helper_files/include/sys.h new file mode 100644 index 0000000..8eed041 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/include/sys.h @@ -0,0 +1,455 @@ +/** + * @file + * OS abstraction layer + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +#ifndef LWIP_HDR_SYS_H +#define LWIP_HDR_SYS_H + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ + typedef u8_t sys_sem_t; + typedef u8_t sys_mutex_t; + typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_sem_valid(s) 0 +#define sys_sem_valid_val(s) 0 +#define sys_sem_set_invalid(s) +#define sys_sem_set_invalid_val(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mutex_valid(mu) 0 +#define sys_mutex_set_invalid(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) +#define sys_mbox_valid(m) +#define sys_mbox_valid_val(m) +#define sys_mbox_set_invalid(m) +#define sys_mbox_set_invalid_val(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ + typedef void (*lwip_thread_fn) (void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#ifndef LWIP_COMPAT_MUTEX +#define LWIP_COMPAT_MUTEX 0 +#endif + +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** + * @ingroup sys_mutex + * Create a new mutex. + * Note that mutexes are expected to not be taken recursively by the lwIP code, + * so both implementation types (recursive or non-recursive) should work. + * @param mutex pointer to the mutex to create + * @return ERR_OK if successful, another err_t otherwise + */ + err_t sys_mutex_new (sys_mutex_t * mutex); +/** + * @ingroup sys_mutex + * Lock a mutex + * @param mutex the mutex to lock + */ + void sys_mutex_lock (sys_mutex_t * mutex); +/** + * @ingroup sys_mutex + * Unlock a mutex + * @param mutex the mutex to unlock + */ + void sys_mutex_unlock (sys_mutex_t * mutex); +/** + * @ingroup sys_mutex + * Delete a semaphore + * @param mutex the mutex to delete + */ + void sys_mutex_free (sys_mutex_t * mutex); +#ifndef sys_mutex_valid +/** + * @ingroup sys_mutex + * Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid + */ + int sys_mutex_valid (sys_mutex_t * mutex); +#endif +#ifndef sys_mutex_set_invalid +/** + * @ingroup sys_mutex + * Set a mutex invalid so that sys_mutex_valid returns 0 + */ + void sys_mutex_set_invalid (sys_mutex_t * mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** + * @ingroup sys_sem + * Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise + */ + err_t sys_sem_new (sys_sem_t * sem, u8_t count); +/** + * @ingroup sys_sem + * Signals a semaphore + * @param sem the semaphore to signal + */ + void sys_sem_signal (sys_sem_t * sem); +/** + * @ingroup sys_sem + * Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout + */ + u32_t sys_arch_sem_wait (sys_sem_t * sem, u32_t timeout); +/** + * @ingroup sys_sem + * Delete a semaphore + * @param sem semaphore to delete + */ + void sys_sem_free (sys_sem_t * sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** + * @ingroup sys_sem + * Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid + */ + int sys_sem_valid (sys_sem_t * sem); +#endif +#ifndef sys_sem_set_invalid +/** + * @ingroup sys_sem + * Set a semaphore invalid so that sys_sem_valid returns 0 + */ + void sys_sem_set_invalid (sys_sem_t * sem); +#endif +#ifndef sys_sem_valid_val +/** + * Same as sys_sem_valid() but taking a value, not a pointer + */ +#define sys_sem_valid_val(sem) sys_sem_valid(&(sem)) +#endif +#ifndef sys_sem_set_invalid_val +/** + * Same as sys_sem_set_invalid() but taking a value, not a pointer + */ +#define sys_sem_set_invalid_val(sem) sys_sem_set_invalid(&(sem)) +#endif + +#ifndef sys_msleep +/** + * @ingroup sys_misc + * Sleep for specified number of ms + */ + void sys_msleep (u32_t ms); /* only has a (close to) 1 ms resolution. */ +#endif + +/* Mailbox functions. */ + +/** + * @ingroup sys_mbox + * Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (minimum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise + */ + err_t sys_mbox_new (sys_mbox_t * mbox, int size); +/** + * @ingroup sys_mbox + * Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ + void sys_mbox_post (sys_mbox_t * mbox, void *msg); +/** + * @ingroup sys_mbox + * Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ + err_t sys_mbox_trypost (sys_mbox_t * mbox, void *msg); +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever) + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ + u32_t sys_arch_mbox_fetch (sys_mbox_t * mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** + * @ingroup sys_mbox + * Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty + */ + u32_t sys_arch_mbox_tryfetch (sys_mbox_t * mbox, void **msg); +#endif +/** + * For now, we map straight to sys_arch implementation. + */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** + * @ingroup sys_mbox + * Delete an mbox + * @param mbox mbox to delete + */ + void sys_mbox_free (sys_mbox_t * mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** + * @ingroup sys_mbox + * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid + */ + int sys_mbox_valid (sys_mbox_t * mbox); +#endif +#ifndef sys_mbox_set_invalid +/** + * @ingroup sys_mbox + * Set an mbox invalid so that sys_mbox_valid returns 0 + */ + void sys_mbox_set_invalid (sys_mbox_t * mbox); +#endif +#ifndef sys_mbox_valid_val +/** + * Same as sys_mbox_valid() but taking a value, not a pointer + */ +#define sys_mbox_valid_val(mbox) sys_mbox_valid(&(mbox)) +#endif +#ifndef sys_mbox_set_invalid_val +/** + * Same as sys_mbox_set_invalid() but taking a value, not a pointer + */ +#define sys_mbox_set_invalid_val(mbox) sys_mbox_set_invalid(&(mbox)) +#endif + +/** + * @ingroup sys_misc + * The only thread function: + * Creates a new thread + * ATTENTION: although this function returns a value, it MUST NOT FAIL (ports have to assert this!) + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ + sys_thread_t sys_thread_new (const char *name, lwip_thread_fn thread, + void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anything else. */ + void sys_init (void); + +#ifndef sys_jiffies +/** + * Ticks/jiffies since power up. + */ + u32_t sys_jiffies (void); +#endif + +/** + * @ingroup sys_time + * Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. + */ + u32_t sys_now (void); + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** + * @ingroup sys_prot + * SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** + * @ingroup sys_prot + * SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** + * @ingroup sys_prot + * SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) + sys_prot_t sys_arch_protect (void); + void sys_arch_unprotect (sys_prot_t pval); + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) +#define SYS_ARCH_UNPROTECT(lev) + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_SYS_H */ diff --git a/stacks/lwip_stack/release/lwip_helper_files/include/timeouts.h b/stacks/lwip_stack/release/lwip_helper_files/include/timeouts.h new file mode 100644 index 0000000..005db52 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/include/timeouts.h @@ -0,0 +1,134 @@ +/** + * @file + * Timer implementations + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef LWIP_HDR_TIMEOUTS_H +#define LWIP_HDR_TIMEOUTS_H + +#include "lwip/opt.h" +#include "lwip/err.h" +#if !NO_SYS +#include "lwip/sys.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG */ +#endif + +/** Function prototype for a stack-internal timer function that has to be + * called at a defined interval */ + typedef void (*lwip_cyclic_timer_handler) (void); + +/** This struct contains information about a stack-internal timer function + that has to be called at a defined interval */ + struct lwip_cyclic_timer + { + u32_t interval_ms; + lwip_cyclic_timer_handler handler; +#if LWIP_DEBUG_TIMERNAMES + const char *handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ + }; + +/** This array contains all stack-internal cyclic timers. To get the number of + * timers, use LWIP_ARRAYSIZE() */ + extern const struct lwip_cyclic_timer lwip_cyclic_timers[]; + +#if LWIP_TIMERS + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ + typedef void (*sys_timeout_handler) (void *arg); + + struct sys_timeo + { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char *handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ + }; + + void sys_timeouts_init (void); + +#if LWIP_DEBUG_TIMERNAMES + void sys_timeout_debug (u32_t msecs, sys_timeout_handler handler, void *arg, + const char *handler_name); +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ + void sys_timeout (u32_t msecs, sys_timeout_handler handler, void *arg); +#endif /* LWIP_DEBUG_TIMERNAMES */ + + void sys_untimeout (sys_timeout_handler handler, void *arg); + void sys_restart_timeouts (void); +#if NO_SYS + void sys_check_timeouts (void); + u32_t sys_timeouts_sleeptime (void); +#else /* NO_SYS */ + void sys_timeouts_mbox_fetch (sys_mbox_t * mbox, void **msg); +#endif /* NO_SYS */ + +#else /* LWIP_TIMERS */ + typedef void (*sys_timeout_handler) (void *arg); + + void sys_timeouts_init (void); + void sys_timeout (u32_t msecs, sys_timeout_handler handler, void *arg); + void sys_untimeout (sys_timeout_handler handler, void *arg); + void sys_timeouts_mbox_fetch (sys_mbox_t * mbox, void **msg); + void cyclic_timer (void *arg); + void tcpip_tcp_timer (void *arg); + void tcp_timer_needed (void); + +#endif +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_HDR_TIMEOUTS_H */ diff --git a/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/atomic_32.h b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/atomic_32.h new file mode 100644 index 0000000..15a058b --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/atomic_32.h @@ -0,0 +1,53 @@ +/* + * atomic_32.h + * + */ + +#ifndef ATOMIC_32_H_ +#define ATOMIC_32_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct + { + volatile int counter; + } atomic_t; + +#define ATOMIC_INIT(i) {(i)} +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic_set(v, i) (((v)->counter) = (i)) + + static inline void atomic_add (int i, atomic_t * v) + { + __asm__ __volatile__ ( + /*LOCK_PREFIX "addl %1,%0" */ + "addl %1,%0":"+m" (v->counter):"ir" (i)); + } + + static inline void atomic_sub (int i, atomic_t * v) + { + __asm__ __volatile__ ( + /*LOCK_PREFIX "subl %1,%0" */ + "subl %1,%0":"+m" (v->counter):"ir" (i)); + } + + static __inline__ void atomic_inc (atomic_t * v) + { + __asm__ __volatile__ ( + /*LOCK_PREFIX "incl %0" */ + "incl %0":"+m" (v->counter)); + } + + static __inline__ void atomic_dec (atomic_t * v) + { + __asm__ __volatile__ ( + /*LOCK_PREFIX "decl %0" */ + "decl %0":"+m" (v->counter)); + } +#ifdef __cplusplus +} +#endif +#endif /* ATOMIC_32_H_ */ diff --git a/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/cc.h b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/cc.h new file mode 100644 index 0000000..4e21a75 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/cc.h @@ -0,0 +1,82 @@ +#ifndef LWIP_ARCH_CC_H +#define LWIP_ARCH_CC_H + +#include +#include +#include +#include +#include +#include + +#ifndef LWIP_MAX_S16_NUM +#define LWIP_MAX_S16_NUM ((s16_t)0x7fff) +#endif + +#ifndef LWIP_MAX_U16_NUM +#define LWIP_MAX_U16_NUM ((u16_t)0xFfff) +#endif + +#ifndef LWIP_MAX_U32_NUM +#define LWIP_MAX_U32_NUM ((u32_t)0xffffffff) +#endif + +#ifndef LWIP_MAX_S32_NUM +#define LWIP_MAX_S32_NUM ((s32_t)0x7fffffff) +#endif + +#ifndef LWIP_MAX_U64_NUM +#define LWIP_MAX_U64_NUM ((u64_t)0xffffffffffffffff) +#endif + +#ifndef LWIP_MAX_S64_NUM +#define LWIP_MAX_S64_NUM ((s64_t)0x7fffffffffffffff) +#endif + +#define NONBLOCK_MODE_FOR_ALG 2 /* it is possible to get fail */ +#define BLOCK_MODE_FOR_ALG 1 /* will block till success */ +#define NONBLOCK_MODE_NOT_FOR_ALG 0 + +typedef uint64_t u64_t; +typedef int64_t s64_t; + +typedef uint32_t u32_t; +typedef int32_t s32_t; + +typedef uint16_t u16_t; +typedef int16_t s16_t; + +typedef uint8_t u8_t; +typedef int8_t s8_t; + +typedef uintptr_t mem_ptr_t; + +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +#define S16_F "d" +#define U16_F "u" +#define X16_F "x" + +#define S32_F "d" +#define U32_F "u" +#define X32_F "x" + +#define S64_F "ld" +#define U64_F "lu" +#define X64_F "x" + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +//#define LWIP_PROVIDE_ERRNO + +#ifndef LWIP_PLATFORM_DIAG +#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) +#endif +#ifndef LWIP_DEBUG +#define LWIP_DEBUG 1 +#endif +#endif diff --git a/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/queue.h b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/queue.h new file mode 100644 index 0000000..238ef05 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/queue.h @@ -0,0 +1,30 @@ +#ifndef __QUEUE_H__ +#define __QUEUE_H__ +#ifdef __cplusplus +extern "C" +{ + +#endif +#include "common_mem_base_type.h" +#ifdef HAL_LIB +#else +#include "rte_ring.h" +#endif +#include "nsfw_mem_api.h" +//#include "stackx_dfx_api.h" + +#include "sys.h" + + typedef struct queue + { + PRIMARY_ADDR mring_handle llring; + } queue_t; + + err_t queue_push (queue_t * q, void *msg, int isTrypush); + void *queue_pop (queue_t * q, u32_t * timeout, int isTryPop); + +#ifdef __cplusplus + +} +#endif +#endif diff --git a/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/sys_arch.h b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/sys_arch.h new file mode 100644 index 0000000..92ff049 --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/sys_arch.h @@ -0,0 +1,29 @@ +#ifndef STACKX_ARCH_SYS_ARCH_H +#define STACKX_ARCH_SYS_ARCH_H +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#include "cc.h" + +/*add by daifen 2012.7.27*/ + typedef uint64_t sys_thread_t; + + extern u64_t hz_per_ms; + + void stackx_global_lock (void); + void stackx_global_unlock (void); + +#define SYS_ARCH_PROTECT(lev) stackx_global_lock() +#define SYS_ARCH_UNPROTECT(lev) stackx_global_unlock() +#define SYS_ARCH_DECL_PROTECT(lev) + +#ifdef __cplusplus + +} +#endif +#endif diff --git a/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/win_minmax.h b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/win_minmax.h new file mode 100644 index 0000000..e1e64ac --- /dev/null +++ b/stacks/lwip_stack/release/lwip_helper_files/lwip/arch/win_minmax.h @@ -0,0 +1,120 @@ +/** + * lib/minmax.c: windowed min/max tracker by Kathleen Nichols. + * + */ +#ifndef MINMAX_H +#define MINMAX_H + +#include "types.h" +#include "rtp_branch_prediction.h" + +/* A single data point for our parameterized min-max tracker */ +struct minmax_sample +{ + u32_t t; /* time measurement was taken */ + u32_t v; /* value measured */ +}; + +/* State for the parameterized min-max tracker */ +struct minmax +{ + struct minmax_sample s[3]; +}; + +static inline u32_t +minmax_get (const struct minmax *m) +{ + return m->s[0].v; +} + +static inline u32_t +minmax_reset (struct minmax *m, u32_t t, u32_t meas) +{ + struct minmax_sample val = {.t = t,.v = meas }; + + m->s[2] = m->s[1] = m->s[0] = val; + return m->s[0].v; +} + +/* As time advances, update the 1st, 2nd, and 3rd choices. */ +static u32_t +minmax_subwin_update (struct minmax *m, u32_t win, + const struct minmax_sample *val) +{ + u32_t dt = val->t - m->s[0].t; + + if (unlikely (dt > win)) + { + /* + * Passed entire window without a new val so make 2nd + * choice the new val & 3rd choice the new 2nd choice. + * we may have to iterate this since our 2nd choice + * may also be outside the window (we checked on entry + * that the third choice was in the window). + */ + m->s[0] = m->s[1]; + m->s[1] = m->s[2]; + m->s[2] = *val; + if (unlikely (val->t - m->s[0].t > win)) + { + m->s[0] = m->s[1]; + m->s[1] = m->s[2]; + m->s[2] = *val; + } + } + else if (unlikely (m->s[1].t == m->s[0].t) && dt > win / 4) + { + /* + * We've passed a quarter of the window without a new val + * so take a 2nd choice from the 2nd quarter of the window. + */ + m->s[2] = m->s[1] = *val; + } + else if (unlikely (m->s[2].t == m->s[1].t) && dt > win / 2) + { + /* + * We've passed half the window without finding a new val + * so take a 3rd choice from the last half of the window + */ + m->s[2] = *val; + } + return m->s[0].v; +} + +/* Check if new measurement updates the 1st, 2nd or 3rd choice max. */ +static inline u32_t +minmax_running_max (struct minmax *m, u32_t win, u32_t t, u32_t meas) +{ + struct minmax_sample val = {.t = t,.v = meas }; + + if (unlikely (val.v >= m->s[0].v) || /* found new max? */ + unlikely (val.t - m->s[2].t > win)) /* nothing left in window? */ + return minmax_reset (m, t, meas); /* forget earlier samples */ + + if (unlikely (val.v >= m->s[1].v)) + m->s[2] = m->s[1] = val; + else if (unlikely (val.v >= m->s[2].v)) + m->s[2] = val; + + return minmax_subwin_update (m, win, &val); +} + +/* Check if new measurement updates the 1st, 2nd or 3rd choice min. */ +static inline u32_t +minmax_running_min (struct minmax *m, u32_t win, u32_t t, u32_t meas) +{ + struct minmax_sample val = {.t = t,.v = meas }; + + if (unlikely (val.v <= m->s[0].v) || /* found new min? */ + unlikely (val.t - m->s[2].t > win)) /* nothing left in window? */ + return minmax_reset (m, t, meas); /* forget earlier samples */ + + if (unlikely (val.v <= m->s[1].v)) + m->s[2] = m->s[1] = val; + else if (unlikely (val.v <= m->s[2].v)) + m->s[2] = val; + + return minmax_subwin_update (m, win, &val); +} + +#endif diff --git a/stacks/lwip_stack/release/script/nstack_fun.sh b/stacks/lwip_stack/release/script/nstack_fun.sh new file mode 100755 index 0000000..fed3588 --- /dev/null +++ b/stacks/lwip_stack/release/script/nstack_fun.sh @@ -0,0 +1,591 @@ +#!/bin/bash + +check_file_size() +{ + if [ -n "$1" ]&&[ -f "$1" ] + then + local log_size=`stat -c %s $1` + if [ ${log_size} -gt $MAX_LOG_FILE_SIZE ] + then + mv $1 $1.bk + fi + fi +} + +log() +{ + check_file_size $LOG_FILE + + #1 line number + local printStr="$2" + cur_date=`date +'%m%d %H:%M:%S.%6N' -u` + pid=$$ + file=$0 + local log_head="I${cur_date} ${file##*/}:$1 ${pid}]" + + printf "${log_head} $printStr\n" >> $LOG_FILE 2>/dev/null +} + +get_call_stack() +{ + local proc_name="$1" + log $LINENO "gdb info in call stack:" + gdb -batch -ex "t a a bt" -p `pidof $proc_name`>> $LOG_FILE 2>/dev/null + log $LINENO "top in call stack:" + top -H -p `pidof $proc_name` -n 1 -b >> $LOG_FILE 2>/dev/null + log $LINENO "mpstat in call stack:" + mpstat -A >> $LOG_FILE 2>/dev/null +} + +gdb_set() +{ + local mod="$1" + if [ "$mod" = "stop" ];then + gdb -batch -ex "set g_hbt_switch=0" -p `pidof nStackMain` + gdb -batch -ex "set g_hbt_switch=0" -p `pidof nStackMaster` + log $LINENO "gdb stop" + else + gdb -batch -ex "set g_hbt_switch=1" -p `pidof nStackMain` + gdb -batch -ex "set g_hbt_switch=1" -p `pidof nStackMaster` + log $LINENO "gdb start" + fi +} + +get_core_mask() +{ + local sys_core=`cat /proc/cpuinfo | grep processor | wc -l` + log $LINENO "system has ${sys_core} cores" + #if sys_core too large 2^$sys_core will overflow; so reset sys_core; z00203440 20170323 + if [ $sys_core -gt 8 ] + then + sys_core=8 + log $LINENO "sys_core too large reset to ${sys_core}" + fi + + base=`echo | awk -v ex=$sys_core 'BEGIN{a=2^ex; print a}'` + local temp=`expr $base - 1` + printf %X $temp + return $sys_core +} + +init_log_file() +{ + if [ -n $LOG_FILE_DIR ]&&[ ! -f $LOG_FILE_DIR ] + then + sudo mkdir -p $LOG_FILE_DIR + fi + + check_file_size $LOG_FILE + + if [ -n $DPDK_FILE_DIR ]&&[ ! -f $DPDK_FILE_DIR ] + then + sudo mkdir -p $DPDK_FILE_DIR + fi + + check_file_size $DPDK_FILE + + #must create the directory under the current user account + if [ -n $RUNTIME_DIR ]&&[ ! -f $RUNTIME_DIR ] + then + mkdir -p $RUNTIME_DIR + fi +} + +delete_log_file() { + if [ -n $RUNNING_FILE_DIR ]&&[ -d $RUNNING_FILE_DIR ]&&[ -n $RUNNING_FILE_NAME ]; then + rm -rf $RUNNING_FILE_DIR/*${RUNNING_FILE_NAME}* + fi + if [ -n $RUNNING_FILE_DIR ]&&[ -d $RUNNING_FILE_DIR ]&&[ -n $OPERATION_FILE_NAME ]; then + rm -rf $RUNNING_FILE_DIR/*${OPERATION_FILE_NAME}* + fi + if [ -n $RUNNING_FILE_DIR ]&&[ -d $RUNNING_FILE_DIR ]&&[ -n $GLOG_FAILURE_FILE_NAME ]; then + rm -rf $RUNNING_FILE_DIR/*${GLOG_FAILURE_FILE_NAME}* + fi + if [ -n $RUNNING_FILE_DIR ]&&[ -d $RUNNING_FILE_DIR ]&&[ -n $NSTACK_FAILURE_FILE_NAME ]; then + rm -rf $RUNNING_FILE_DIR/*${NSTACK_FAILURE_FILE_NAME}* + fi + if [ -n $MASTER_FILE_DIR ]&&[ -d $MASTER_FILE_DIR ]&&[ -n $MASTER_FILE_NAME ]; then + rm -rf $MASTER_FILE_DIR/*${MASTER_FILE_NAME}* + fi + if [ -n $MASTER_FILE_DIR ]&&[ -d $MASTER_FILE_DIR ]&&[ -n $GLOG_FAILURE_FILE_NAME ]; then + rm -rf $MASTER_FILE_DIR/*${GLOG_FAILURE_FILE_NAME}* + fi + if [ -n $MASTER_FILE_DIR ]&&[ -d $MASTER_FILE_DIR ]&&[ -n $NSTACK_FAILURE_FILE_NAME ]; then + rm -rf $MASTER_FILE_DIR/*${NSTACK_FAILURE_FILE_NAME}* + fi + if [ -n $LOG_FILE_DIR ]&&[ -d $LOG_FILE_DIR ]&&[ -n $LOG_FILE_NAME ]; then + rm -rf $LOG_FILE_DIR/*${LOG_FILE_NAME}* + fi + if [ -n $DPDK_FILE_DIR ]&&[ -d $DPDK_FILE_DIR ]&&[ -n $DPDK_FILE_NAME ]; then + rm -rf $DPDK_FILE_DIR/*${DPDK_FILE_NAME}* + fi + if [ -n $RUNTIME_DIR ]&&[ -d $RUNTIME_DIR ]; then + rm -rf $RUNTIME_DIR + fi + if [ -n ${MASTER_EXEC_PATH} ]&&[ -d $MASTER_EXEC_PATH ]; then + rm -rf $MASTER_EXEC_PATH + fi +} + +init_hugepage() +{ + log $LINENO "init hugepage..." +############################################################## +# +# TO DO: +# verify the free pages carefully, but not with 1G pagesize +# +############################################################# + + #for 1G hugepage + + # check total hugepage number +# local nr_pagedir=/sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages +# if [ ! -f ${nr_pagedir} ] +# then +# log $LINENO "system not support 1G huge pages, exit!" +# exit 1 +# fi + + # local nr_huge_pages=`cat ${nr_pagedir}` + # if [ ${nr_huge_pages} -lt 3 ] + # then + # log $LINENO "total huge pages is not set correctly, current ${nr_huge_pages}, exit!" + # exit 1 + # fi + + # check free hugepage number + # local fr_pagedir=/sys/devices/system/node/node0/hugepages/hugepages-1048576kB/free_hugepages + # if [ ! -f ${fr_pagedir} ] + # then + # log $LINENO "system not support 1G huge pages, exit!" + # exit 1 + # fi + + # local fr_huge_pages=`cat ${fr_pagedir}` + # if [ ${fr_huge_pages} -lt 3 ] + # then + # log $LINENO "free huge pages is not set correctly, current ${fr_huge_pages}, exit!" + # lsof $HUGE_DIR >> $LOG_FILE 2>/dev/null + # exit 1 + # fi + + # mount | grep $HUGE_DIR >> $LOG_FILE 2>/dev/null + # if [ $? -eq 0 ] ; then + # log $LINENO "$HUGE_DIR dir exist" + # if test $(pgrep -f $1 | wc -l) -eq 0 ; then + # log $LINENO "proccess $1 not exist and clean huge files" + # if [ -n $HUGE_DIR ]&&[ -d $HUGE_DIR ]; then + # rm -rf $HUGE_DIR/* + # fi + # else + # log $LINENO "proccess $1 exist" + # fi + # else + # log $LINENO "$HUGE_DIR not exist and create" + # sudo mkdir -p $HUGE_DIR + #directory right can't larger than 750 + + # cur_user=`whoami` + # if [ "root" != "$cur_user" ] + # then + # non_root_uid=`id -u $cur_user` + # non_root_gid=`id -g $cur_user` + # sudo mount -t hugetlbfs -o pagesize=1G,uid=$non_root_uid,gid=$non_root_gid none $HUGE_DIR >> $LOG_FILE 2>/dev/null + # else + # mount -t hugetlbfs -o pagesize=1G none $HUGE_DIR >> $LOG_FILE 2>/dev/null + # fi + # fi +} + +recover_hugepage() +{ + log $LINENO "recover hugepage..." + + if [ -n "$HUGE_DIR" ]&&[ -d "$HUGE_DIR" ]; then + rm -rf $HUGE_DIR/* + fi +} + +init_network() +{ + log $LINENO "init network..." + + recover_network + + sudo modprobe uio + + local script_path=$(cd "$(dirname "$0")"; pwd) + local is_igb_uio_loaded=`lsmod | grep igb_uio | wc -l` + if [ ${is_igb_uio_loaded} -eq 0 ] + then + log $LINENO "igb_uio is not installed. install it now." + sudo insmod $DPDK_MOD_PATH/igb_uio.ko + fi + + # check if there is un-recognized nic + sudo $DPDK_TOOL_DIR/dpdk-devbind.py -s | grep -A32 "Other network" | \ + grep unused | awk -F"'" '{print $1, $2}' | while read NIC_BFS BIND_DRIVER_NAME + do + local TYPE_CHECK_ixgbe=`echo $BIND_DRIVER_NAME |grep "82599ES 10-Gigabit SFI/SFP+ Network Connection"|wc -l` + local TYPE_CHECK_ixgbevf=`echo $BIND_DRIVER_NAME |grep "82599 Ethernet Controller Virtual Function"|wc -l` + local TYPE_CHECK_vmxnet3=`echo $BIND_DRIVER_NAME |grep "VMXNET3 Ethernet Controller"|wc -l` + local TYPE_CHECK_virtio=`echo $BIND_DRIVER_NAME |grep "Virtio network device"|wc -l` + + if [ $TYPE_CHECK_ixgbe -gt 0 ]; then + sudo $DPDK_TOOL_DIR/dpdk-devbind.py --bind=ixgbe $NIC_BFS + elif [ $TYPE_CHECK_ixgbevf -gt 0 ]; then + sudo $DPDK_TOOL_DIR/dpdk-devbind.py --bind=ixgbevf $NIC_BFS + elif [ $TYPE_CHECK_vmxnet3 -gt 0 ]; then + sudo $DPDK_TOOL_DIR/dpdk-devbind.py --bind=vmxnet3 $NIC_BFS + elif [ $TYPE_CHECK_virtio -gt 0 ]; then + sudo $DPDK_TOOL_DIR/dpdk-devbind.py --bind=virtio-pci $NIC_BFS + fi + + done +} + +recover_network() +{ + log $LINENO "recover network..." + + if [ -z "$DPDK_NIC_LIST_FILE" ]||[ ! -f "$DPDK_NIC_LIST_FILE" ] + then + log $LINENO "$DPDK_NIC_LIST_FILE is not exist. There is no nic used by nstack to unbind." + else + log $LINENO "The NIC(s) to unbind: " + cat $DPDK_NIC_LIST_FILE | awk -F" '|' | drv=| unused=" '{print $1,$4}' >> $LOG_FILE 2>/dev/null + cat $DPDK_NIC_LIST_FILE | awk -F" '|' | drv=| unused=" '{print $1,$4}' | while read NIC_BFS BIND_DRIVER_TYPE + do + sudo $DPDK_TOOL_DIR/dpdk-devbind.py --bind=$BIND_DRIVER_TYPE $NIC_BFS >> $LOG_FILE 2>/dev/null + done + rm $DPDK_NIC_LIST_FILE + fi + + touch $DPDK_NIC_LIST_FILE + chmod 600 $DPDK_NIC_LIST_FILE +} + + +check_args_main() +{ +if [ -z $HUGE_DIR ]||[ -z $MEM_SIZE ]||[ -z $RTP_CORE_MASK ]||[ -z $SLEEP_INTERVAL ]||\ + [ -z $BIND_CPU ]||[ -z $START_TYPE ] +then + log $LINENO "nStackMain Args is null" + return 1 +fi + +# check CORE_MASK -- see in get_core_mask() +# check HUGE_DIR +if [ -z $HUGE_DIR ]||[ ! -d $HUGE_DIR ]; then + log $LINENO "HUGE_DIR="$HUGE_DIR" is invalid" + return 1 +fi + +# check MEM_SIZE +if [ $MEM_SIZE -lt 2048 ]||[ $MEM_SIZE -gt 32768 ]; then + log $LINENO "MEM_SIZE="$MEM_SIZE" is invalid" + return 1 +fi + +# check RTP_CORE_MASK +if [ $RTP_CORE_MASK -lt 1 ]; then + log $LINENO "RTP_CORE_MASK="$RTP_CORE_MASK" is invalid" + return 1 +fi + +# check SLEEP_INTERVAL +if [ $SLEEP_INTERVAL -lt 0 ]; then + log $LINENO "SLEEP_INTERVAL="$SLEEP_INTERVAL" is invalid" + return 1 +fi + +# check BIND_CPU +if [ $BIND_CPU -lt 0 ]; then + log $LINENO "BIND_CPU="$BIND_CPU" is invalid" + return 1 +fi + +# check START_TYPE +if [ $START_TYPE -lt 0 ]||[ $START_TYPE -gt 5 ]; then + log $LINENO "START_TYPE="$START_TYPE" is invalid" + return 1 +fi + +return 0 +} + +run_nStackMain() +{ + + log $LINENO "run nstack main..." + + sudo setcap CAP_IPC_OWNER,CAP_FOWNER,CAP_NET_ADMIN,CAP_IPC_LOCK,CAP_NET_RAW,CAP_SYS_RAWIO,CAP_SYS_ADMIN,CAP_CHOWN,CAP_SYS_NICE=eip ./bin/nStackMain 2>/dev/null + + local script_path=$(cd "$(dirname "$0")"; pwd) + export NSTACK_CONFIG_PATH=${script_path}/../configure + export LD_LIBRARY_PATH=${script_path}/lib64/:$LD_LIBRARY_PATH + export NSTACK_LOG_ON=INF + + log $LINENO "$env NSTACK_CONFIG_PATH=$NSTACK_CONFIG_PATH" + log $LINENO "$env DPDK_TOOL_DIR=$DPDK_TOOL_DIR" + log $LINENO "$env LD_LIBRARY_PATH=$LD_LIBRARY_PATH" + log $LINENO "$env DPDK_LIB_PATH=$DPDK_LIB_PATH" + log $LINENO "./nStackMain -c $1 -n 4 --huge-dir=$2 --proc-type=primary --file-prefix nStackMain -m $3 $7 $8 stack -c $4 -sleep $5 -bind_cpu $6" + check_file_size $DPDK_FILE + cd ..; cd bin/ + ./nStackMain -c $1 -n 4 --huge-dir=$2 --proc-type=primary --file-prefix nStackMain -m $3 $7 $8 stack -c $4 -sleep $5 -bind_cpu $6 >> $DPDK_FILE & +} + + +stop_nStackProcess() +{ + log $LINENO "$1 exiting..." + + local i=0 + + while [ ${i} -lt $2 ] + do + #pid=`ps aux | grep $1 |grep -v grep| awk '{print $2}'` + pid=`pidof $1` + if [ "x${pid}" != "x" ] + then + kill -9 $pid 2>/dev/null + else + break + fi + i=`expr ${i} + 1` + sleep 1 + done +} + +stop_nStackApps() +{ + log $LINENO "stop the apps that use the shared nstackhuge memory..." + + app_pid=`lsof $HUGE_DIR | awk '{print $2}'` + if [ "x${app_pid}" != "x" ] + then + kill -9 ${app_pid} 2>/dev/null + fi +} + +get_nstack_bin() +{ + local app=$1 + master_pid=`pidof $app | head -n 1` + if [ "x${master_pid}" != "x" ];then + sudo readlink -f "/proc/${master_pid}/exe" | sed "s/$app$//g" 2>/dev/null + fi +} + + + +get_abs_path() +{ + local input_path=$1 + if [ -d "$input_path" -o -f "$input_path" ]; then + echo "$(dirname $(readlink -e $input_path))/$(basename $input_path)" + return 0 + fi + echo $input_path + return 1 +} + + + +CONFIG_FILE="nStackConfig.json" +VAR_FILE="nstack_var.sh" + +modify_nstack_log_path() +{ + if echo $1 |grep -Eq '^((/[a-zA-Z_]+[a-zA-Z0-9_-]+(/[a-zA-Z0-9_-]+)*/?)|/)$' > /dev/null + then + local parameter=$1 + else + log $LINENO "the path is invalid, use the default config path!" + return + fi + + if [ ! -d $1 ]; then + log $LINENO "the folder is not existed, use the default config!" + return + fi + + if [ ! -w $1 ]; then + log $LINENO "the folder has no permission, use the default config!" + return + fi + + local script_path=$(cd "$(dirname "$0")"; pwd) + local config_name=${script_path}/configure/$CONFIG_FILE + + if [ ! -f $config_name ]; then + log $LINENO "$CONFIG_FILE no exit! use default config in code." + return + fi + + sed -i 's#\("stackpool_log_path": "\).*#\1'"$1"'",#g' ${config_name} + sed -i 's#\("master_log_path": "\).*#\1'"$1"'",#g' ${config_name} + sed -i 's#\("nstack_log_path": "\).*#\1'"$1"'",#g' ${config_name} + sed -i 's#\("dpdk_log_path": "\).*#\1'"$1"'"#g' ${config_name} +} + +modify_log_var() +{ + local script_path=$(cd "$(dirname "$0")"; pwd) + local config_name=${script_path}/configure/$CONFIG_FILE + + if [ ! -f $config_name ]; then + log $LINENO "$CONFIG_FILE no exit! use default config in code." + return + fi + + local running_log_path=`grep -Po '"stackpool_log_path": ".*?"' $config_name | sed -n -e 's/"//gp' | awk -F' ' '{print $2}'` + local master_log_path=`grep -Po '"master_log_path": ".*?"' $config_name | sed -n -e 's/"//gp' | awk -F' ' '{print $2}'` + local nstack_log_path=`grep -Po '"nstack_log_path": ".*?"' $config_name | sed -n -e 's/"//gp' | awk -F' ' '{print $2}'` + local dpdk_log_path=`grep -Po '"dpdk_log_path": ".*?"' $config_name | sed -n -e 's/"//gp' | awk -F' ' '{print $2}'` + +#modify the nstack_var.sh + local var_config_name=${script_path}/script/$VAR_FILE + + if [ ! -f $var_config_name ]; then + log $LINENO "$VAR_FILE not exist , exit!" + exit 1 + fi + +#check the path from json if it is OK. + if [ -n "$running_log_path" ]&&[ -w "$running_log_path" ]; then + sed -i "s:RUNNING_FILE_DIR=.*:RUNNING_FILE_DIR=${running_log_path}:g" $var_config_name + else + log $LINENO "stackpool_log_path:$running_log_path in $CONFIG_FILE is invalid, use the default config!" + fi + + if [ -n "$master_log_path" ]&&[ -w "$master_log_path" ]; then + sed -i "s:MASTER_FILE_DIR=.*:MASTER_FILE_DIR=${master_log_path}:g" $var_config_name + else + log $LINENO "master_log_path:$master_log_path in $CONFIG_FILE is invalid, use the default config!" + fi + + if [ -n "$nstack_log_path" ]&&[ -w "$nstack_log_path" ]; then + sed -i "s:LOG_FILE_DIR=.*:LOG_FILE_DIR=${nstack_log_path}:g" $var_config_name + else + log $LINENO "nstack_log_path:$nstack_log_path in $CONFIG_FILE is invalid, use the default config!" + fi + + if [ -n "$dpdk_log_path" ]&&[ -w "$dpdk_log_path" ]; then + sed -i "s:DPDK_FILE_DIR=.*:DPDK_FILE_DIR=${dpdk_log_path}:g" $var_config_name + else + log $LINENO "dpdk_log_path:$dpdk_log_path in $CONFIG_FILE is invalid, use the default config!" + fi +} + + +modify_local_ip_env() +{ + +#modify the nstack_var.sh + local var_config_name=${script_path}/script/$VAR_FILE + + if [ ! -f $var_config_name ]; then + log $LINENO "$VAR_FILE not exist , exit!" + exit 1 + fi + + sed -i "s:VM_ID=.*:VM_ID=${nstack_alarm_local_ip}:g" $var_config_name 2>/dev/null +} + + +delete_pid_file() +{ + if [ -n "$PID_FILE" ]&&[ -f "$PID_FILE" ] + then + rm -rf ${PID_FILE} + fi +} + +save_pid_file() +{ + if [ ! -d ${PID_FILE_DIR} ]; + then + sudo mkdir -p ${PID_FILE_DIR} + chmod 750 ${PID_FILE_DIR} + fi + + if [ -f ${PID_FILE} ]; + then + cur_pid=`cat ${PID_FILE}` + if [ ${cur_pid} != $1 ]; + then + rm -rf ${PID_FILE} + else + return + fi + fi + + touch ${PID_FILE} + echo $1 > $PID_FILE + + chown paas:paas $PID_FILE + chmod 640 $PID_FILE +} + +write_pid_to_file() +{ + retry=3 + i=0 + fail=1 + + while [ ${i} -lt ${retry} ] + do + PID=`pidof nStackMaster` + if [ ${PID} ] + then + fail=0 + break + fi + + i=`expr ${i} + 1` + + sleep 1 + done + + if [ ${fail} -ne 0 ] + then + return 1 + fi + + if [ ! -d ${PID_FILE_DIR} ]; + then + sudo mkdir -p ${PID_FILE_DIR} + chmod 750 ${PID_FILE_DIR} + fi + + touch ${PID_FILE} + echo $PID > $PID_FILE + #check log file right + chown paas:paas $PID_FILE + chmod 640 $PID_FILE + return 0 +} + + + +install_config() +{ + # set nStackConfig values + if [ -n "$DEF_SOCK_NUM" ] ;then + sed -i "s/\"socket_num\":[ \t0-9]*,/\"socket_num\":$DEF_SOCK_NUM,/g" ./configure/nStackConfig.json + fi +} + +copy_config() +{ + # $1 for src nStackServer path + # $2 for dst nStackServer path + + # NOTE: set src socket_num value into dst path config file, this is for copying old configuration from old version to new version path when upgrading. + SRC_SOCK_NUM=`grep 'socket_num' $1/configure/nStackConfig.json | awk -F"," '{for (i=1;i<=NF;++i) print $i}' | awk 'gsub("\"socket_num\":","") {sub("^[ \t]*","");sub("[ \t]*$",""); print $0}'` + sed -i "s/\"socket_num\":[ \t0-9]*,/\"socket_num\":$SRC_SOCK_NUM,/g" $2/configure/nStackConfig.json +} diff --git a/stacks/lwip_stack/release/script/nstack_var.sh b/stacks/lwip_stack/release/script/nstack_var.sh new file mode 100755 index 0000000..a654d34 --- /dev/null +++ b/stacks/lwip_stack/release/script/nstack_var.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +PID_FILE_DIR=/var/ICTS_BASE/run +PID_FILE=${PID_FILE_DIR}/nstack.pid + +RUNNING_FILE_DIR=/var/log/nStack +RUNNING_FILE_NAME=running.log + +OPERATION_FILE_NAME=operation.log +NSTACK_CTRL_LOG_FILE_NAME=omc_ctrl.log +GLOG_FAILURE_FILE_NAME=fail_dump.log +NSTACK_FAILURE_FILE_NAME=nstack_error.log + +MASTER_FILE_DIR=/var/log/nStack +MASTER_FILE_NAME=master.log + +LOG_FILE_DIR=/var/log/nStack +LOG_FILE=${LOG_FILE_DIR}/nstack.log +LOG_FILE_NAME=nstack.log + +DPDK_FILE_DIR=/var/log/nstack-dpdk +DPDK_FILE=${DPDK_FILE_DIR}/nstack_dpdk.log +DPDK_FILE_NAME=nstack_dpdk.log + +#this is env variable, it is for nstack usage, it will be modified from ./start_nstack -i hostinfo.ini + +export VM_ID=agent-node-x + +export DPDK_INSTALL_PATH="/usr/share/dpdk/" +export DPDK_LIB_PATH=${DPDK_INSTALL_PATH}/x86_64-native-linuxapp-gcc/lib +export DPDK_TOOL_DIR=${DPDK_INSTALL_PATH}/usertools +export DPDK_MOD_PATH=/usr/lib/modules/`uname -r`/extra/dpdk + +cur_user=`whoami` +if [ "root" != "${cur_user}" ] +then + HOME_DIR=$HOME + if [ -z "${HOME}" ] + then + HOME_DIR=/var/run + fi +else + HOME_DIR=/var/run +fi +RUNTIME_DIR=$HOME_DIR/ip_module + +DPDK_NIC_LIST_FILE=$RUNTIME_DIR/.nstack_dpdk_nic_list + +#single file is 50M=50*1024*1024 +MAX_LOG_FILE_SIZE=52428800 +HUGE_PAGES=2048 +HUGE_DIR=/mnt/nstackhuge + +SLEEP_INTERVAL=100 # tcpip thread sleep time, unit: us +BIND_CPU=1 + +MEM_SIZE=3072 +RTP_CORE_MASK=2 + +MASTER_EXEC_PATH="/product/gpaas/nStackMaster/bin" +RUN_NSTACK_FILE=run_nstack.sh + + +#default config definitions +DEF_SOCK_NUM=8192 diff --git a/stacks/lwip_stack/release/script/run_nstack_main.sh b/stacks/lwip_stack/release/script/run_nstack_main.sh new file mode 100755 index 0000000..9d6049a --- /dev/null +++ b/stacks/lwip_stack/release/script/run_nstack_main.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +DIR=`S=\`readlink "$0"\`; [ -z "$S" ] && S=$0; dirname $S` +cd $DIR + +. ./nstack_var.sh +. ./nstack_fun.sh + +######################################################## +# check parameter + +log $LINENO "dir=$DIR" + +######################################################## +# init netrork:unbind->/* modprobe uio->insmod igb_uio */->bind +init_network + +######################################################## +# start nstack main +CORE_MASK=1 +log $LINENO "start run nstackmain" +log $LINENO "COREMASK=$CORE_MASK, HUGE_DIR=$1, MEM_SIZE=$2, RTP_CORE_MASK=$RTP_CORE_MASK, SLEEP_INTERVAL=$SLEEP_INTERVAL, BIND_CPU=$BIND_CPU" +log $LINENO "VDEV=$VDEV, NO_PCI=$NO_PCI" + +run_nStackMain $CORE_MASK $1 $2 $RTP_CORE_MASK $SLEEP_INTERVAL $BIND_CPU $3 $4 + +exit 0 diff --git a/stacks/lwip_stack/release/script/run_nstack_master.sh b/stacks/lwip_stack/release/script/run_nstack_master.sh new file mode 100755 index 0000000..8da0d49 --- /dev/null +++ b/stacks/lwip_stack/release/script/run_nstack_master.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +DIR=`S=\`readlink "$0"\`; [ -z "$S" ] && S=$0; dirname $S` +cd $DIR +. ./nstack_var.sh + + +if [ -n "${MASTER_EXEC_PATH}" ]; then + mkdir -p $MASTER_EXEC_PATH + chown -R paas: $MASTER_EXEC_PATH + chmod 750 $MASTER_EXEC_PATH + cp ../bin/nStackMaster $MASTER_EXEC_PATH -rf + cp ../configure/nStackConfig.json $MASTER_EXEC_PATH -rf + ln -s -f $(cd "$(dirname "$0")"; pwd)/run_nstack_main.sh $MASTER_EXEC_PATH/${RUN_NSTACK_FILE} + cd $MASTER_EXEC_PATH +fi + +runnStackMaster(){ + sudo setcap CAP_IPC_OWNER,CAP_NET_ADMIN,CAP_DAC_OVERRIDE=eip ./nStackMaster + + script_path=$(cd "$(dirname "$0")"; pwd) + export NSTACK_CONFIG_PATH=${script_path} + + ./nStackMaster -c $1 -n 4 --huge-dir=$2 -m $3 --proc-type=$4 >> ${DPDK_FILE} +} + +runnStackMaster $1 $2 $3 $4 & + +exit 0 diff --git a/stacks/lwip_stack/release/send_alarm.sh b/stacks/lwip_stack/release/send_alarm.sh new file mode 100755 index 0000000..46ea413 --- /dev/null +++ b/stacks/lwip_stack/release/send_alarm.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +cur_dir=$(cd "$(dirname "$0")"; pwd) +alarm_history=${cur_dir}/.nstack_fault_alarm + +. ./script/nstack_var.sh +. ./script/nstack_fun.sh + +if [ ! -f ${alarm_history} ]; then + ./nStackCtrl --module alm -n nsMain -t abnormal + log $LINENO "nstack is not running ok, send fault alarm" + touch ${alarm_history} +else + log $LINENO "nstack is not running ok, send fault alarm already" +fi + +exit 0 \ No newline at end of file diff --git a/stacks/lwip_stack/release/start_nstack.sh b/stacks/lwip_stack/release/start_nstack.sh new file mode 100755 index 0000000..35fe9df --- /dev/null +++ b/stacks/lwip_stack/release/start_nstack.sh @@ -0,0 +1,149 @@ +#!/bin/bash + + +script_path=$(cd "$(dirname "$0")"; pwd) + +. ${script_path}/script/nstack_var.sh +. ${script_path}/script/nstack_fun.sh + +config_name=${script_path}/script/nstack_var.sh +if [ ! -e $config_name ]; then + log $LINENO "nstack_var.sh not exit, plz check!" + exit 1 +fi + +######################################################## +##get the log info from the parameter of ./start -l XXX -a XXX ### +nstack_log_path="" +hostinfo_path="" +ARGS=`getopt -o "l:i:a:" -l "vdev:,file-prefix:,no-pci" -n "start_nstack.sh" -- "$@"` +eval set -- "${ARGS}" +while true +do + case "$1" in + -l) + nstack_log_path="$2" + shift 2 + ;; + -i) + hostinfo_path="$2" + shift 2 + ;; + --vdev) + VDEV="--vdev=$2" + shift 2 + ;; + --file-prefix) + FILE_PREFIX="--file-prefix=$2" + shift 2 + ;; + --no-pci) + NO_PCI="--no-pci" + shift 1 + ;; + --) + shift + break + ;; + *) + echo "Option illegal, please check input!" + exit 1 + ;; + esac +done + +hostinfo_stat=0 + +( +flock -e -n 200 +if [ $? -eq 1 ] +then + log $LINENO "another process is running now, exit" + exit 1 +fi + +######################################################## +# modify the nstack & dpdk log path config: nStackConfig.json +if [ -n "$nstack_log_path" ]; then + modify_nstack_log_path $nstack_log_path +fi + +if [ -n "$hostinfo_path" -a -e "$hostinfo_path" -a -r "$hostinfo_path" ]; then + nstack_alarm_local_ip=($(awk -F '=' '/\['AGENT'\]/{a=1}a==1&&$1"="~/^(\s*)(VM_ID)(\s*)(=)/{print $2 ;exit}' $hostinfo_path)) + modify_local_ip_env +else + hostinfo_stat=1 +fi + + +######################################################## +#set the log path in nstack_var.sh##### +modify_log_var +) 200>>./lockfile + +if [ -f "lockfile" ]; then + rm lockfile +fi + +. ${script_path}/script/nstack_var.sh + + +######################################################## +# init_log_file:nstack.log and dpdk.log +# if need print log, the messgae need add after init_log_file +init_log_file + +if [ "$hostinfo_stat" -ne 0 ]; then + log $LINENO "please use correct -i parameter for start_nstack.sh" + log $LINENO "host info path:$hostinfo_path" + hostinfo_stat=0 +fi + +log $LINENO "######################start nstack######################" + +######################################################## +# check application running +process_nstack_main=nStackMain + +pid_nstack=`pidof $process_nstack_main` + +nstack_ctrl_path=${script_path}/bin + +pgrep nStackMain +main_run_status=$? +if [ ${main_run_status} -eq 0 ]; then + log $LINENO "nStackMain is running ok, please stop it first!" + save_pid_file ${pid_master} + exit 0 +fi + +huge_files=`ls /mnt/nstackhuge` +if [ "x${huge_files}" != "x" ] +then + if [ "x${pid_nstack}" = "x" ] + then + log $LINENO "huge page file exist and nStackMain not exist" + exit 1 + fi +fi + + +######################################################## +# set hugepage +init_hugepage $process_nstack_main + + +######################################################## +# install config +install_config + +######################################################## +core_mask=1 +START_TYPE="primary" +log $LINENO "./script/run_nstack_main.sh ${core_mask} $HUGE_DIR $MEM_SIZE $START_TYPE $VDEV $NO_PCI" +${script_path}/script/run_nstack_main.sh $HUGE_DIR $MEM_SIZE $VDEV $NO_PCI + +print_pid=$(ps -ux | grep nStackMain | awk '{print $2}' | awk 'NR == 2') +echo "nStackMain PID:$print_pid" +log $LINENO "nstack start success" +exit 0 diff --git a/stacks/lwip_stack/release/stop_nstack.sh b/stacks/lwip_stack/release/stop_nstack.sh new file mode 100755 index 0000000..48d1af7 --- /dev/null +++ b/stacks/lwip_stack/release/stop_nstack.sh @@ -0,0 +1,51 @@ +#!/bin/bash + + +script_path=$(cd "$(dirname "$0")"; pwd) + +. ${script_path}/script/nstack_var.sh +. ${script_path}/script/nstack_fun.sh + +config_name=${script_path}/script/nstack_var.sh +if [ ! -e $config_name ]; then + log $LINENO "$config_name not exit, plz pay attention and add back!,or it has resourcce leak." +fi + +cur_user=`whoami` + +######################################################## +# init_log_file:nstack.log and dpdk.log +init_log_file +log $LINENO "#######################stop nstack#######################" + +############################################# +# step1 stop nstack master +retry=3 +stop_nStackProcess nStackMaster $retry + +############################################# +# step2 stop nstack +stop_nStackProcess nStackMain $retry + + +############################################# +# step3 stop all apps that usg the nstack hugepage +if [ ${cur_user} = "root" ]; then + stop_nStackApps +else + log $LINENO "not root, app not stopped" +fi + +############################################# +# step4 delete the huge page files created by nstack +recover_hugepage + +############################################# +# step5 recover the nic configuration +recover_network + +############################################# +# step6 delete pid file +delete_pid_file + +exit 0 diff --git a/stacks/lwip_stack/release/uninstall.sh b/stacks/lwip_stack/release/uninstall.sh new file mode 100755 index 0000000..92ae5fe --- /dev/null +++ b/stacks/lwip_stack/release/uninstall.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +. ./script/nstack_var.sh +. ./script/nstack_fun.sh + +######################################################## +# init_log_file:nstack.log and dpdk.log +init_log_file +log $LINENO "#######################uninstall nstack#######################" + + +############################################# +# step1 stop the applications that use the shared huge memory of nstack +stop_nStackApps + +############################################# +# step2 delete the huge page files created by nstack +recover_hugepage + + +############################################# +# step3 recover the nic configuration +recover_network + + +############################################# +# step4 delete nstack log files +delete_log_file + + +# log file has been deleted, should print on screen now +echo "uninstall nStack successfully!" + +exit 0 diff --git a/stacks/lwip_stack/release_tar.sh b/stacks/lwip_stack/release_tar.sh new file mode 100644 index 0000000..d3cfa68 --- /dev/null +++ b/stacks/lwip_stack/release_tar.sh @@ -0,0 +1,86 @@ +if [ ! -d "./nStackServer" ]; then + mkdir ./nStackServer +else + rm -rf ./nStackServer/* +fi + +if [ ! -d "./nStackClient" ]; then + mkdir ./nStackClient +else + rm -rf ./nStackClient/* +fi + +if [ ! -d "./nStackTools" ]; then + mkdir ./nStackTools +else + rm -rf ./nStackTools/* +fi + +if [ -f "./nStackServer.tar.gz" ]; then + rm -rf ./nStackServer.tar.gz +fi + +if [ -f "./nStackClient.tar.gz" ]; then + rm -rf ./nStackClient.tar.gz +fi + +if [ -f "./nStackTools.tar.gz" ]; then + rm -rf ./nStackTools.tar.gz +fi + +mkdir ./nStackServer/lib64 +cp ./release/lib64/liblwip_dpdk.so ./release/lib64/libnStackAPI.so ./release/lib64/libnstackcmd.so ./release/lib64/libsecurec.so ./nStackServer/lib64 +mkdir ./nStackServer/bin +cp ./release/bin/nStackCtrl ./release/bin/nStackMain ./release/bin/nStackMaster ./release/bin/set_permission.sh ./nStackServer/bin +mkdir ./nStackServer/conf +cp ./release/conf/nstack.monitrc ./release/conf/nstack_ctl ./release/conf/srvnstack ./nStackServer/conf +mkdir ./nStackServer/configure +cp ./release/configure/ip_data.json ./release/configure/network_data_tonStack.json ./release/configure/nStackConfig.json ./nStackServer/configure +mkdir ./nStackServer/script +cp -d ./release/script/nstack_fun.sh ./release/script/nstack_var.sh ./release/script/run_nstack_main.sh ./release/script/run_nstack_master.sh ./nStackServer/script +mkdir ./nStackServer/tools +cp ./release/tools/nping ./nStackServer/tools/ + +cp ./release/check_status.sh ./release/send_alarm.sh ./release/start_nstack.sh ./release/stop_nstack.sh ./release/graceful_stop_nstack.sh ./release/uninstall.sh ./release/upgrade_nstack.sh ./nStackServer/ + +dos2unix ./nStackServer/*.sh +find ./nStackServer -type f | grep -E "*.sh|*.py" | xargs chmod +x + +mkdir ./nStackClient/lib64 +cp ./release/lib64/liblwip_dpdk.so ./release/lib64/libnStackAPI.so ./release/lib64/libsecurec.so ./nStackClient/lib64 +mkdir ./nStackClient/include +cp ./release/include/nstack_custom_api.h ./nStackClient/include + +cp ./release/tools/nping ./release/tools/ntcpdump ./nStackTools/ + +# set permission +chown -R paas: ./nStackServer/ +chown -R paas: ./nStackClient/ +chown -R paas: ./nStackTools/ + +chmod 750 ./nStackServer +chmod 550 ./nStackServer/bin/ +chmod 750 ./nStackServer/configure +chmod 750 ./nStackServer/script +chmod 750 ./nStackServer/conf +chmod 750 ./nStackServer/lib64 +chmod 750 ./nStackServer/tools +chmod 750 ./nStackClient +chmod 750 ./nStackClient/include +chmod 750 ./nStackClient/lib64 +chmod 750 ./nStackTools + +chmod 750 ./nStackServer/bin/nStack* +chmod 750 ./nStackServer/*.sh +chmod 750 ./nStackServer/bin/*.sh +chmod 750 ./nStackServer/conf/* +chmod 750 ./nStackServer/script/*.sh +chmod 640 ./nStackServer/lib64/* +chmod 640 ./nStackServer/configure/* +chmod 500 ./nStackServer/bin/set_permission.sh +chmod 750 ./nStackTools/* + + +tar -zcvf nStackServer.tar.gz nStackServer +tar -zcvf nStackClient.tar.gz nStackClient +tar -zcvf nStackTools.tar.gz nStackTools diff --git a/stacks/lwip_stack/run_stackx.txt b/stacks/lwip_stack/run_stackx.txt new file mode 100644 index 0000000..71cdd20 --- /dev/null +++ b/stacks/lwip_stack/run_stackx.txt @@ -0,0 +1,49 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +#build DPDK, DMM, lwip stack by calling build script: +==================================================== + cd dmm/stacks/lwip_stack/vagrant + build.sh + +#update interface name if required(default enp0s8) in dmm/stacks/lwip_stack/vagrant/start_nstackMain.sh +#Start nStackMain: +================= + 1.for the first time (to configure json files and start nStackMain) + cd dmm/stacks/lwip_stack/vagrant + ./start_nstackMain.sh + + 2.from secod time: + cd dmm/stacks/lwip_stack/release + ./start_nstack.sh + +#get configured client/server ip from dmm/stacks/lwip_stack/release/bin/ip_data.json +#can get the log path details from dmm/stacks/lwip_stack/release/bin/nStackConfig.json + +#run app: +======== + cd dmm/stacks/lwip_stack/app_test + + #server + ./vs_epoll -p 20000 -d {client_ip} -a 10000 -s {ser_ip} -l 200 -t 5000000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 + + #client + ./vc_epoll -p 20000 -d {ser_ip} -a 10000 -s {client_ip} -l 200 -t 50000 -i 1000 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 + +#stop nStackMain: +================ + cd dmm/stacks/lwip_stack/release + ./stop_nstack.sh diff --git a/stacks/lwip_stack/src/CMakeLists.txt b/stacks/lwip_stack/src/CMakeLists.txt new file mode 100644 index 0000000..1bf74ec --- /dev/null +++ b/stacks/lwip_stack/src/CMakeLists.txt @@ -0,0 +1,61 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +SET(RTP_DIRECTORIES "${PROJECT_SOURCE_DIR}/src/include/") + +INCLUDE_DIRECTORIES( + framework/log/ + framework/include/ + framework/common/include/ + framework/common/base/include/ + ${RTP_DIRECTORIES} + ${RTP_DIRECTORIES}/generic + ../../SecureC/include/ + ../../../thirdparty/glog/glog-0.3.5/src/ +) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIC -m64 -mssse3 -std=gnu89") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags,--rpath,../lib64") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium") + +if(WITH_HAL_LIB) +SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/src/include/rtp_config.h) +else() + SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/mem/include/common_sys_config.h) +endif() +SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/common/compile_config.h) +ADD_DEFINITIONS(-include ${RTP_CONFIG}) +ADD_DEFINITIONS(-include ${COMPLE_CONFIG}) +ADD_DEFINITIONS(-D_GNU_SOURCE) +ADD_DEFINITIONS(-DDPDK_MODULE=0) +#ADD_DEFINITIONS(-DNSTACK_RSRDMA) +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) + +if(WITH_SECUREC_LIB) +LINK_LIBRARIES(pthread dl securec) +else() +LINK_LIBRARIES(pthread dl) +endif() + +#ADD_SUBDIRECTORY(maintain) +ADD_SUBDIRECTORY(sbr) +ADD_SUBDIRECTORY(io_adpt) +ADD_SUBDIRECTORY(nStackMain) +ADD_SUBDIRECTORY(tools) +ADD_SUBDIRECTORY(alarm) +ADD_SUBDIRECTORY(mem) diff --git a/stacks/lwip_stack/src/alarm/CMakeLists.txt b/stacks/lwip_stack/src/alarm/CMakeLists.txt new file mode 100644 index 0000000..d46220a --- /dev/null +++ b/stacks/lwip_stack/src/alarm/CMakeLists.txt @@ -0,0 +1,38 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +FILE(GLOB_RECURSE ALARM *.c) + +LINK_LIBRARIES(m dl rt nStackFw) +if(WITH_SECUREC_LIB) +INCLUDE_DIRECTORIES( + ./ + ${JSON_C_SRC} + ${SECUREC_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ +) +else() +INCLUDE_DIRECTORIES( + ./ + ${JSON_C_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ +) +endif() +ADD_LIBRARY(nStackAlarm STATIC ${ALARM}) diff --git a/stacks/lwip_stack/src/alarm/alarm.c b/stacks/lwip_stack/src/alarm/alarm.c new file mode 100644 index 0000000..82e7e54 --- /dev/null +++ b/stacks/lwip_stack/src/alarm/alarm.c @@ -0,0 +1,857 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "types.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_fd_timer_api.h" +#include "alarm.h" +#include "alarm_api.h" +#include +#include +#include "nsfw_init_api.h" +#include "nstack_log.h" +#include "json.h" +#include "nstack_securec.h" +#include +#include "nstack_dmm_adpt.h" + +char g_vmid[MAX_VMID_LEN + 1] = "agent-node-x"; + +extern nsfw_timer_info *nsfw_timer_reg_timer(u32 timer_type, void *data, + nsfw_timer_proc_fun fun, + struct timespec time_left); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +// note:the first element is reserved +alarm_data g_alarm_data[ALARM_EVENT_MAX] = { }; + +alarm_result ms_alarm_check_func(void *para) +{ + alarm_result ret_alarm; + int para_value = (long) para; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_MAIN_ABNORMAL; + + if (para_value == ALARM_PRODUCT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + } + else if (para_value == ALARM_CLEAN) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_NSMAIN; + + return ret_alarm; + +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : period check alarm expire handle function +********************************************************************/ + +int ns_alarm_timer_resend_fun(u32 timer_type, void *argv) +{ + int i; + struct timespec time_left; + alarm_data *alarm_value; + + for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++) + { + alarm_value = &g_alarm_data[i]; + + if ((alarm_value->valid_flag == 1) + && (alarm_value->send_succ_flag == ALARM_SEND_FAIL)) + { + /* nStack only send nsMain normal alarm */ + ns_send_alarm_inner(alarm_value->_alarm_id, + (void *) (alarm_value->_alarm_flag), 1, 0); + } + } + + time_left.tv_sec = ALARM_RESEND_TIMER_LENGTH; + time_left.tv_nsec = 0; + nsfw_timer_info *timer_info = + nsfw_timer_reg_timer(0, NULL, ns_alarm_timer_resend_fun, time_left); + if (NULL == timer_info) + { + NSAM_LOGERR("nsfw_timer_reg_timer fail"); + } + + return 0; +} + +void ns_alarm_set_sendFlag(enum_alarm_id alarmId, int flag) +{ + if ((alarmId <= 0) || (alarmId >= ALARM_EVENT_MAX) + || (0 == g_alarm_data[alarmId].valid_flag) + || ((flag != ALARM_SEND_FAIL) && (flag != ALARM_SEND_SUCC))) + { + NSAM_LOGERR("alarm_id is invalid or not reg or flag invalid"); + return; + } + g_alarm_data[alarmId].send_succ_flag = flag; +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : alarm module init +********************************************************************/ +int ns_alarm_module_init(void *param) +{ + u32 proc_type = (u32) ((long long) param); + enum_alarm_id i = ALARM_EVENT_BASE; + alarm_reason j = ALARM_REASON_BEGIN; + const char *pst_vm_id = NULL; + alarm_para tcp_alarm_para; + struct timespec time_left; + + for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++) + { + g_alarm_data[i]._alarm_type = ALARM_SEND_ONCE; + + for (j = ALARM_REASON_BEGIN; j < ALARM_REASON_MAX; j++) + { + g_alarm_data[i]._alarm_para.func_alarm_check[j] = NULL; + g_alarm_data[i]._alarm_para.alarm_reason_set[j] = + ALARM_REASON_MAX; + g_alarm_data[i].alarm_time_laps[j] = 0; + } + g_alarm_data[i]._alarm_para.period_alarm.time_length = 0; + g_alarm_data[i]._alarm_id = i; + g_alarm_data[i].valid_flag = 0; + g_alarm_data[i]._alarm_flag = ALARM_CLEAN; + g_alarm_data[i].alarm_reason_cnt = 0; + g_alarm_data[i].send_succ_flag = ALARM_SEND_SUCC; + } + + switch (proc_type) + { + case NSFW_PROC_MAIN: + case NSFW_PROC_CTRL: + + /* modify ip address to vm id */ + pst_vm_id = getenv("VM_ID"); + + if (INVALID_STR_LEN(pst_vm_id, MIN_VM_ID_LEN, MAX_VM_ID_LEN)) + { + NSAM_LOGWAR + ("invalid VM_ID,please check env VM_ID]vm_id=%s, proc_type=%u", + pst_vm_id, proc_type); + } + else + { + int retVal = strncpy_s(g_vmid, MAX_VMID_LEN + 1, pst_vm_id, + strlen(pst_vm_id)); + + if (EOK != retVal) + { + NSAM_LOGERR("STRNCPY_S failed]ret=%d", retVal); + } + } + + tcp_alarm_para.period_alarm.time_length = 0; /* 5 second period */ + tcp_alarm_para.alarm_reason_count = 1; /*both resource */ + + tcp_alarm_para.func_alarm_check[0] = ms_alarm_check_func; + tcp_alarm_para.alarm_reason_set[0] = ALARM_REASON_NSMAIN; + (void) ns_reg_alarm(ALARM_EVENT_NSTACK_MAIN_ABNORMAL, + ALARM_SEND_ONCE, &tcp_alarm_para); + + time_left.tv_sec = ALARM_INIT_RESEND_TIMER_LENGTH; + time_left.tv_nsec = 0; + nsfw_timer_info *timer_info = + nsfw_timer_reg_timer(0, NULL, ns_alarm_timer_resend_fun, + time_left); + if (NULL == timer_info) + { + NSAM_LOGERR("nsfw_timer_reg_timer fail"); + } + + break; + default: + break; + } + + return 0; +} + +#define JSON_NEW_OBJ(obj, cb, para1, para2)\ + {\ + obj = json_object_new_object();\ + if (obj == NULL)\ + {\ + (void)cb(para1);\ + (void)cb(para2);\ + return -1;\ + }\ + } + +#define JSON_NEW_STRING_OBJ(str, obj, cb, para1, para2)\ + {\ + obj = json_object_new_string((str));\ + if (obj == NULL)\ + {\ + (void)cb(para1);\ + (void)cb(para2);\ + return -1;\ + }\ + } + +#define JSON_NEW_STRING_OBJ_1(val, obj, cb, para1, para2,para3)\ + {\ + obj = json_object_new_string((val));\ + if (obj == NULL)\ + {\ + (void)cb(para1);\ + (void)cb(para2);\ + (void)cb(para3);\ + return -1;\ + }\ + } + +#define JSON_NEW_INT_OBJ(val, obj, cb, para1, para2)\ + {\ + obj = json_object_new_int((val));\ + if (obj == NULL)\ + {\ + (void)cb(para1);\ + (void)cb(para2);\ + return -1;\ + }\ + } + +/***************************************************************************** +* Prototype : ns_get_alarm_body +* Description : get body by alarm parameter +* Input : char *buf +* int buf_len +* alarm_result alarm_res +* Output : None +* Return Value : int +*****************************************************************************/ +int ns_get_alarm_body(char *buf, int buf_len, alarm_result alarm_res) +{ +#define ALARM_NAME_LENGTH 100 +#define COMPONENT_NAME "nStack" + int retVal; + size_t str_len; + int alarm_id = alarm_res.alarm_id_get + 27000; + struct timeval t_val; + struct tm now_time; + char *alarm_string = NULL, *alarm_reason_info = NULL, *alarm_desc = NULL; + json_object *temp_jso = NULL, *alarm_info = NULL; + alarm_info_s_out *alarmpara_out = NULL; + int perceivedSeverity_value = 0; + char *action_string = NULL; + if (buf == NULL || (buf_len < (int) sizeof(alarm_info_s_out))) + { + NSAM_LOGERR("input para invalid"); + return -1; + } + alarmpara_out = (alarm_info_s_out *) buf; + + /*use sizeof(alarmpara_out->alarmId) instead of devil figure 16 */ + retVal = + sprintf_s(alarmpara_out->alarmId, sizeof(alarmpara_out->alarmId), + "%d", alarm_id); + if (-1 == retVal) + { + NSAM_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return -1; + } + + (void) gettimeofday(&t_val, NULL); + time_t t_sec = (time_t) t_val.tv_sec; + /*return value check */ + if (NULL == localtime_r(&t_sec, &now_time)) + { + NSAM_LOGERR("localtime_r failed]"); + return -1; + } + + /*use sizeof(alarmpara_out->alarmtime) instead of devil figure 32 */ + retVal = + sprintf_s(alarmpara_out->alarmtime, sizeof(alarmpara_out->alarmtime), + "%4d%02d%02d%02d%02d%02d%06ld", now_time.tm_year + 1900, + now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_hour, + now_time.tm_min, now_time.tm_sec, (long) t_val.tv_usec); + if (-1 == retVal) + { + NSAM_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return -1; + } + + retVal = + strncpy_s(alarmpara_out->comptentname, + sizeof(alarmpara_out->comptentname), COMPONENT_NAME, + strlen(COMPONENT_NAME)); + if (EOK != retVal) + { + NSAM_LOGERR("STRNCPY_S failed]ret=%d", retVal); + return -1; + } + + switch (alarm_res.alarm_reason_get) + { + case ALARM_REASON_SOCKET: + /* alarmName and reason info is incorrect */ + alarm_reason_info = "socketResource"; + if (alarm_res.alarm_flag_get == ALARM_PRODUCT) + { + alarm_string = "networkResourceOverload"; + alarm_desc = "more than 80 percent used"; + perceivedSeverity_value = 2; + action_string = "alarm"; + } + else + { + alarm_string = "networkResourceNormal"; + alarm_desc = "less than 60 percent used"; + perceivedSeverity_value = 5; + action_string = "clear"; + } + + break; + case ALARM_REASON_MSG_BUF: + alarm_reason_info = "SendBufResource"; + if (alarm_res.alarm_flag_get == ALARM_PRODUCT) + { + alarm_string = "networkResourceOverload"; + alarm_desc = "more than 80 percent used"; + perceivedSeverity_value = 2; + action_string = "alarm"; + } + else + { + alarm_string = "networkResourceNormal"; + alarm_desc = "less than 60 percent used"; + perceivedSeverity_value = 5; + action_string = "clear"; + } + + break; + case ALARM_REASON_NSMAIN: + /* process status alarm change from event to alarm/clear */ + alarm_reason_info = "networkProcStatus"; + if (alarm_res.alarm_flag_get == ALARM_PRODUCT) + { + alarm_string = "network-data-down"; + alarm_desc = "networkProcDown"; + perceivedSeverity_value = 2; + action_string = "alarm"; + } + else + { + alarm_string = "network-data-up"; + alarm_desc = "networkProcUp"; + perceivedSeverity_value = 5; + action_string = "clear"; + } + + break; + default: + NSAM_LOGERR("alarm_reason incorrect]ret=%d", + alarm_res.alarm_reason_get); + return -1; + } + + str_len = 0; + + json_object *alarmlist = json_object_new_object(); + if (NULL == alarmlist) + { + NSAM_LOGERR("alarmlist is NULL"); + return -1; + } + + json_object *alarmItem = json_object_new_object(); + + if (NULL == alarmItem) + { + NSAM_LOGERR("alarmItem is NULL"); + (void) json_object_put(alarmlist); + return -1; + } + + JSON_NEW_STRING_OBJ("ICTS_BASE=1", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "neDN", temp_jso); + JSON_NEW_STRING_OBJ("service", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "neType", temp_jso); + JSON_NEW_STRING_OBJ("ICTS_BASE", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "neName", temp_jso); + JSON_NEW_STRING_OBJ("service", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "objectClass", temp_jso); + JSON_NEW_STRING_OBJ("nStack", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "moDN", temp_jso); + JSON_NEW_STRING_OBJ("nStack", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "moName", temp_jso); + JSON_NEW_STRING_OBJ("default", temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "userId", temp_jso); + + JSON_NEW_INT_OBJ(alarm_id, temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "alarmId", temp_jso); + + JSON_NEW_INT_OBJ(10001, temp_jso, json_object_put, alarmlist, alarmItem); + json_object_object_add(alarmItem, "groupId", temp_jso); + + JSON_NEW_STRING_OBJ(g_vmid, temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "objectInstance", temp_jso); + JSON_NEW_INT_OBJ(8, temp_jso, json_object_put, alarmlist, alarmItem); + json_object_object_add(alarmItem, "eventType", temp_jso); + + JSON_NEW_STRING_OBJ(alarm_string, temp_jso, json_object_put, alarmlist, + alarmItem); + json_object_object_add(alarmItem, "alarmName", temp_jso); + + JSON_NEW_INT_OBJ(perceivedSeverity_value, temp_jso, json_object_put, + alarmlist, alarmItem); + + json_object_object_add(alarmItem, "perceivedSeverity", temp_jso); + + JSON_NEW_OBJ(alarm_info, json_object_put, alarmlist, alarmItem); + JSON_NEW_STRING_OBJ_1(alarm_reason_info, temp_jso, json_object_put, + alarmlist, alarmItem, alarm_info); + json_object_object_add(alarm_info, "reason", temp_jso); + JSON_NEW_STRING_OBJ_1(alarm_desc, temp_jso, json_object_put, alarmlist, + alarmItem, alarm_info); + json_object_object_add(alarm_info, "desc", temp_jso); + json_object_object_add(alarmItem, "alarmInfo", alarm_info); + + JSON_NEW_STRING_OBJ(action_string, temp_jso, json_object_put, alarmlist, + alarmItem); + + json_object_object_add(alarmlist, "data", alarmItem); + + json_object_object_add(alarmlist, "action", temp_jso); + + const char *str = json_object_to_json_string(alarmlist); + if (str == NULL) + { + NSMON_LOGERR("json_object_to_json_string fail"); + (void) json_object_put(alarmlist); + return -1; + } + + str_len = strlen(str); + + if (str_len >= ALARM_PARA_LENGTH_OUTER) + { + NSAM_LOGERR("str_len >= ALARM_PARA_LENGTH_OUTER"); + (void) json_object_put(alarmlist); + return -1; + } + + retVal = + strncpy_s(alarmpara_out->alarmcontent, ALARM_PARA_LENGTH_OUTER, str, + str_len + 1); + + if (EOK != retVal) + { + NSAM_LOGERR("STRNCPY_S failed]ret=%d", retVal); + (void) json_object_put(alarmlist); + return -1; + } + + (void) json_object_put(alarmlist); + + return 0; + +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : send alarm to thirdparty alarm module, now only log +********************************************************************/ +int ns_send_alarm_to_alarm_module(alarm_result alarm_res) +{ + int retVal = -1; + + nsfw_mgr_msg *req_msg = + nsfw_mgr_msg_alloc(MGR_MSG_LARGE_ALARM_RSP, NSFW_PROC_ALARM); + + if (NULL == req_msg) + { + NSAM_LOGERR("mgr_msg_alloc fail]alarm_id=%d", alarm_res.alarm_id_get); + return -1; + } + + if (req_msg->msg_len < (NSFW_MGR_MSG_HDR_LEN + sizeof(alarm_info_s_out))) + { + NSAM_LOGERR("mgr_msg_alloc length fail]alarm_id=%d", + alarm_res.alarm_id_get); + nsfw_mgr_msg_free(req_msg); + return -1; + } + /* husky agent receive alarm info using fixed length */ + req_msg->msg_len = (NSFW_MGR_MSG_HDR_LEN + sizeof(alarm_info_s_out)); + + retVal = + ns_get_alarm_body((char *) req_msg->msg_body, + NSFW_MGR_LARGE_MSG_BODY_LEN, alarm_res); + + if (-1 == retVal) + { + NSAM_LOGERR("ns_get_alarm_body fail]alarm_id=%d", + alarm_res.alarm_id_get); + nsfw_mgr_msg_free(req_msg); + return -1; + } + + u8 ret = nsfw_mgr_send_msg(req_msg); + + if (FALSE == ret) + { + NSAM_LOGERR("nsfw_mgr_send_msg fail]alarm_id=%d,reason=%d,flag=%d", + alarm_res.alarm_id_get, alarm_res.alarm_reason_get, + alarm_res.alarm_flag_get); + ns_alarm_set_sendFlag(alarm_res.alarm_id_get, ALARM_SEND_FAIL); + nsfw_mgr_msg_free(req_msg); + return -1; + } + + NSAM_LOGINF("nsfw_mgr_send_msg succ]alarm_id=%d,reason=%d,flag=%d", + alarm_res.alarm_id_get, alarm_res.alarm_reason_get, + alarm_res.alarm_flag_get); + ns_alarm_set_sendFlag(alarm_res.alarm_id_get, ALARM_SEND_SUCC); + + nsfw_mgr_msg_free(req_msg); + + return 0; +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : alarm product common func +********************************************************************/ +void +ns_send_alarm_inner(enum_alarm_id alarm_id, void *para, int check_times, + int check_state_flag) +{ + alarm_data *alarm_value = NULL; + alarm_result alarm_id_report; + int alarm_idx; + int alarm_loop; + int temp_alarm_time_laps; + int abnormal_alarm_flag = 0, normal_alarm_flag = + 0, total_abnormal_alarm_flag = 0; + int need_check_flag = check_state_flag; + int ret = 0; + + if ((alarm_id <= 0) || (alarm_id >= ALARM_EVENT_MAX) + || (0 == g_alarm_data[alarm_id].valid_flag)) + { + NSAM_LOGERR("alarm_id is invalid or not reg"); + return; + } + + alarm_id_report.alarm_id_get = ALARM_EVENT_MAX; + + alarm_idx = alarm_id; + + alarm_value = &g_alarm_data[alarm_idx]; + + for (alarm_loop = 0; alarm_loop < alarm_value->alarm_reason_cnt; + alarm_loop++) + { + abnormal_alarm_flag = 0; + if (ALARM_PERIOD_CHECK == alarm_value->_alarm_type) + { + if (NULL == + alarm_value->_alarm_para.func_alarm_check_period[alarm_loop]) + { + NSAM_LOGERR + ("alarm id func_alarm_check is invalid]alarm_id=%d", + alarm_id); + return; + } + alarm_id_report = + alarm_value-> + _alarm_para.func_alarm_check_period[alarm_loop] (); + } + else if (ALARM_SEND_ONCE == alarm_value->_alarm_type) + { + if (NULL == alarm_value->_alarm_para.func_alarm_check[alarm_loop]) + { + NSAM_LOGERR + ("alarm id func_alarm_check is invalid]alarm_id=%d", + alarm_id); + return; + } + alarm_id_report = + alarm_value->_alarm_para.func_alarm_check[alarm_loop] (para); + } + + if ((alarm_id_report.alarm_id_get <= ALARM_EVENT_BASE) + || alarm_id_report.alarm_id_get >= ALARM_EVENT_MAX) + { + NSAM_LOGDBG("don't satisfy alarm condition"); + return; + } + + alarm_idx = alarm_id_report.alarm_id_get; + + if (ALARM_EVENT_NSTACK_MAIN_ABNORMAL == alarm_idx) + { + need_check_flag = 0; + } + /* for send current status alarm, needn't check count also status. */ + /* for sending current state alarm, needn't check current state */ + if ((alarm_id_report.alarm_flag_get == ALARM_PRODUCT) + && (((alarm_value->alarm_time_laps[alarm_loop] < check_times) + && (alarm_value->_alarm_flag != ALARM_PRODUCT)) + || (need_check_flag == 0))) + { + if ((0 == check_state_flag) + || ++(alarm_value->alarm_time_laps[alarm_loop]) >= + check_times) + { + alarm_value->_alarm_flag = ALARM_PRODUCT; + abnormal_alarm_flag = 1; + total_abnormal_alarm_flag++; + } + + } + else if ((alarm_id_report.alarm_flag_get == ALARM_CLEAN) + && ((alarm_value->_alarm_flag == ALARM_PRODUCT) + || (need_check_flag == 0))) + { + if ((1 == check_state_flag) + && (alarm_value->alarm_time_laps[alarm_loop] > 0)) + { + --alarm_value->alarm_time_laps[alarm_loop]; + } + if ((alarm_value->alarm_time_laps[alarm_loop] <= 0) + || (0 == check_state_flag)) + { + normal_alarm_flag++; + } + } + + temp_alarm_time_laps = alarm_value->alarm_time_laps[alarm_loop]; + + /* can't product same alarm multi times */ + /* only overload alarm can send */ + if (abnormal_alarm_flag != 1) + { + NSAM_LOGDBG + ("don't satisfy alarm condition]alarm_idx=%d,alarm_time_laps=%d", + alarm_idx, temp_alarm_time_laps); + continue; + } + + ret = ns_send_alarm_to_alarm_module(alarm_id_report); + + if (-1 == ret) + { + ns_alarm_set_sendFlag(alarm_id, ALARM_SEND_FAIL); + } + else + { + ns_alarm_set_sendFlag(alarm_id, ALARM_SEND_SUCC); + } + /* for alarm current status, only can send one */ + /* if it have multi-scearo, only can send a overload alarm */ + if (0 == need_check_flag) + { + break; + } + + } + + if ((total_abnormal_alarm_flag == 0) + && (alarm_value->alarm_reason_cnt == normal_alarm_flag)) + { + alarm_value->_alarm_flag = ALARM_CLEAN; + ret = ns_send_alarm_to_alarm_module(alarm_id_report); + if (-1 == ret) + { + ns_alarm_set_sendFlag(alarm_id, ALARM_SEND_FAIL); + } + else + { + ns_alarm_set_sendFlag(alarm_id, ALARM_SEND_SUCC); + } + } + + return; + +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : API, any app want to product alarm,need call this function +********************************************************************/ +void ns_send_alarm(enum_alarm_id alarm_id, void *para) +{ + ns_send_alarm_inner(alarm_id, para, 1, 1); +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : period check alarm expire handle function +********************************************************************/ +int ns_alarm_timer_proc_fun(u32 timer_type, void *argv) +{ + struct timespec time_left; + if (NULL == argv) + { + NSAM_LOGERR("abnormal: argv is NULL "); + return -1; + } + + alarm_data *alarm_value = (alarm_data *) argv; + + if (alarm_value->_alarm_type == ALARM_PERIOD_CHECK) + { + ns_send_alarm_inner(alarm_value->_alarm_id, NULL, + ALARM_PERIOD_CHECK_TIMES, 1); + time_left.tv_sec = alarm_value->_alarm_para.period_alarm.time_length; + time_left.tv_nsec = 0; + nsfw_timer_info *timer_info = + nsfw_timer_reg_timer(0, (void *) (u64) alarm_value, + ns_alarm_timer_proc_fun, time_left); + if (NULL == timer_info) + { + NSAM_LOGERR("nsfw_timer_reg_timer fail"); + return -1; + } + } + NSAM_LOGDBG("abnormal: alarm is not period "); + + return 0; + +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : app reg alarm info to alarm module +********************************************************************/ +int +ns_reg_alarm(enum_alarm_id alarm_id, alarm_type alarmType, + alarm_para * alarmPara) +{ + alarm_data *alarm_value = NULL; + alarm_reason loop = ALARM_REASON_BEGIN; + struct timespec time_left; + + if ((alarm_id <= ALARM_EVENT_BASE) || (alarm_id >= ALARM_EVENT_MAX) + || (NULL == alarmPara) + || (alarmPara->alarm_reason_count > ALARM_REASON_MAX)) + { + NSAM_LOGERR("para invalid]alarm_id=%d ", alarm_id); + return -1; + } + + for (loop = ALARM_REASON_BEGIN; loop < alarmPara->alarm_reason_count; + loop++) + { + if (NULL == alarmPara->func_alarm_check[loop]) + { + NSAM_LOGERR("para invalid]func_alarm_check=NULL,loop=%d", loop); + return -1; + } + } + + alarm_value = &g_alarm_data[alarm_id]; + alarm_value->_alarm_type = alarmType; + alarm_value->_alarm_para.period_alarm.time_length = + alarmPara->period_alarm.time_length; + alarm_value->_alarm_id = alarm_id; + alarm_value->alarm_reason_cnt = alarmPara->alarm_reason_count; + alarm_value->_alarm_flag = ALARM_CLEAN; + + for (loop = ALARM_REASON_BEGIN; loop < alarmPara->alarm_reason_count; + loop++) + { + alarm_value->alarm_time_laps[loop] = + alarmPara->alarm_reason_set[loop]; + alarm_value->_alarm_para.func_alarm_check[loop] = + alarmPara->func_alarm_check[loop]; + alarm_value->_alarm_para.func_alarm_check_period[loop] = + alarmPara->func_alarm_check_period[loop]; + alarm_value->alarm_time_laps[loop] = 0; + } + + alarm_value->valid_flag = 1; + + if (ALARM_PERIOD_CHECK == alarmType) + { + time_left.tv_sec = alarm_value->_alarm_para.period_alarm.time_length; + time_left.tv_nsec = 0; + nsfw_timer_info *timer_info = + nsfw_timer_reg_timer(0, (void *) (u64) alarm_value, + ns_alarm_timer_proc_fun, time_left); + if (NULL == timer_info) + { + NSAM_LOGERR("nsfw_timer_reg_timer fail"); + } + } + + return 0; +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : send alarm as per current state +********************************************************************/ +void ns_send_init_alarm(enum_alarm_id alarm_id) +{ + if ((alarm_id <= 0) || (alarm_id >= ALARM_EVENT_MAX)) + { + NSAM_LOGDBG("alarm_id is invalid"); + return; + } + ns_send_alarm_inner(alarm_id, + (void *) (g_alarm_data[alarm_id]._alarm_flag), 1, 0); +} + +NSFW_MODULE_NAME(NSFW_ALARM_MODULE) +NSFW_MODULE_PRIORITY(10) +NSFW_MODULE_DEPENDS(NSFW_TIMER_MODULE) NSFW_MODULE_INIT(ns_alarm_module_init) +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/stacks/lwip_stack/src/alarm/alarm.h b/stacks/lwip_stack/src/alarm/alarm.h new file mode 100644 index 0000000..6c55400 --- /dev/null +++ b/stacks/lwip_stack/src/alarm/alarm.h @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _ALARM_H_ +#define _ALARM_H_ + +#include +#include "alarm_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* alarm clean time = 1*3 */ + +#define ALARM_RESEND_TIMER_LENGTH 60 +#define ALARM_INIT_RESEND_TIMER_LENGTH 40 + +#define ALARM_SEND_SUCC 1 +#define ALARM_SEND_FAIL 0 + +#define ALARM_PARA_LENGTH_OUTER 2048 + +#define ALARM_PERIOD_CHECK_TIMES 3 + +#define MAX_VMID_LEN 256 + +#define MIN_VM_ID_LEN 1 +#define MAX_VM_ID_LEN 256 + +#define INVALID_STR_LEN(_str, _min_len, _maxlen) (NULL == _str || strlen(_str) < _min_len || strlen(_str) > _maxlen) + +typedef struct _alarm_data +{ + alarm_para _alarm_para; + alarm_type _alarm_type; + enum_alarm_id _alarm_id; + int alarm_time_laps[ALARM_REASON_MAX]; + alarm_flag _alarm_flag; + int alarm_reason_cnt; + int valid_flag; + int send_succ_flag; + +} alarm_data; + +typedef struct _alarm_info_s_out +{ + char alarmId[16]; + char comptentname[32]; + char alarmtime[32]; + char alarmcontent[ALARM_PARA_LENGTH_OUTER]; +} alarm_info_s_out; + +int ns_send_alarm_to_alarm_module(alarm_result alarm_res); + +void ns_send_alarm_inner(enum_alarm_id alarm_id, void *para, int check_times, + int check_state_flag); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/alarm/alarm_api.h b/stacks/lwip_stack/src/alarm/alarm_api.h new file mode 100644 index 0000000..c9dcafb --- /dev/null +++ b/stacks/lwip_stack/src/alarm/alarm_api.h @@ -0,0 +1,107 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _ALARM_API_H_ +#define _ALARM_API_H_ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSFW_ALARM_MODULE "nstack_alarm" + +/* alarm ID for every event, when need add new alarm, here add a alarm_id define */ +typedef enum _alarm_id +{ + ALARM_EVENT_BASE, + ALARM_EVENT_NSTACK_RESOURCE_ALARM, + ALARM_EVENT_NSTACK_NO_USE, + ALARM_EVENT_NSTACK_MAIN_ABNORMAL, + ALARM_EVENT_MAX +} enum_alarm_id; + +/* support both type alarm: + 1. support other module call func:ns_send_alarm to product alarm; + 2. alarm module call function periodly to check whether need product alarm */ +typedef enum _alarm_type +{ + ALARM_PERIOD_CHECK, + ALARM_SEND_ONCE +} alarm_type; + +typedef enum _alarm_flag +{ + ALARM_PRODUCT, + ALARM_CLEAN, + ALARM_MAX +} alarm_flag; + +typedef enum _alarm_reason +{ + ALARM_REASON_BEGIN, + ALARM_REASON_SOCKET = 0, + ALARM_REASON_MSG_BUF, + ALARM_REASON_NSMAIN, + ALARM_REASON_MAX +} alarm_reason; + +typedef struct _alarm_result +{ + enum_alarm_id alarm_id_get; + alarm_reason alarm_reason_get; + alarm_flag alarm_flag_get; +} alarm_result; + +/* check whether need product alarm,if return 0, then product alarm */ +typedef alarm_result(*alarm_check_func) (void *para); +typedef alarm_result(*alarm_check_func_period) (void); + +typedef struct _alarm_para +{ + union + { + int time_length; + } period_alarm; + union + { + alarm_check_func func_alarm_check[ALARM_REASON_MAX]; + alarm_check_func_period func_alarm_check_period[ALARM_REASON_MAX]; + }; + + alarm_reason alarm_reason_set[ALARM_REASON_MAX]; + int alarm_reason_count; + +} alarm_para; + +/* for any alarm added, firstly call following function to reg */ +int ns_reg_alarm(enum_alarm_id alarm_id, alarm_type _alarm_type, + alarm_para * _alarm_para); + +void ns_send_init_alarm(enum_alarm_id alarm_id); + +/* other module call this func to product alarm, here para is same as alarm_check_func's para */ +void ns_send_alarm(enum_alarm_id alarm_id, void *para); +int ns_alarm_module_init(void *param); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_func.h b/stacks/lwip_stack/src/include/common_func.h new file mode 100644 index 0000000..db1aee7 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_func.h @@ -0,0 +1,140 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _RTE_COMM_FUNC_H_ +#define _RTE_COMM_FUNC_H_ + +#ifdef HAL_LIB + +#else +#include "common_mem_rwlock.h" + +#define common_mem_rwlock_t rte_rwlock_t +#define common_mem_spinlock_t rte_spinlock_t + //typedef rte_rwlock_t common_mem_rwlock_t; + +#define nsfw_write_lock(plock) rte_rwlock_write_lock(plock) +#define nsfw_write_unlock(plock) rte_rwlock_write_unlock(plock) +#define nsfw_read_lock(plock) rte_rwlock_read_lock(plock) +#define nsfw_read_unlock(plock) rte_rwlock_read_unlock(plock) + +#define common_mem_align32pow2 rte_align32pow2 + +#define common_mem_atomic32_cmpset rte_atomic32_cmpset +#define common_mem_pause rte_pause + +#define COMMON_MEM_MAX_MEMZONE RTE_MAX_MEMZONE + +#define common_mem_atomic32_t rte_atomic32_t + +#define common_mem_memseg rte_memseg +#define common_mem_mem_config rte_mem_config + +#define common_mem_pal_get_configuration rte_eal_get_configuration + + //#define commem_mem_pal_module_info rte_eal_module_info + // +#define common_mem_pal_init rte_eal_init + +#define COMMON_MEM_MEMPOOL_NAMESIZE RTE_MEMPOOL_NAMESIZE + +#define common_mem_memzone_lookup rte_memzone_lookup +#define common_mem_memzone rte_memzone +#define common_mem_atomic32_add_return rte_atomic32_add_return + +#define common_mem_spinlock_init rte_spinlock_init +#define common_mem_spinlock_lock rte_spinlock_lock +#define common_mem_spinlock_unlock rte_spinlock_unlock + +#define common_mem_memzone_free rte_memzone_free +#define common_mem_pktmbuf_pool_create rte_pktmbuf_pool_create + +#define common_mem_pktmbuf_alloc rte_pktmbuf_alloc + +#define common_mem_mempool rte_mempool + +#define common_mem_pktmbuf_free rte_pktmbuf_free +#define common_mem_mbuf rte_mbuf + +#define common_mem_mempool_lookup rte_mempool_lookup + +#define common_mem_ring_get_memsize rte_ring_get_memsize +#define common_mem_ring rte_ring + +#define COMMON_MEM_MAX_MEMSEG RTE_MAX_MEMSEG + +#define common_mem_memzone_reserve rte_memzone_reserve +#define common_mem_rwlock_read_lock rte_rwlock_read_lock +#define common_mem_rwlock_read_unlock rte_rwlock_read_unlock + +#define common_mem_rwlock_write_lock rte_rwlock_write_lock +#define common_mem_rwlock_write_unlock rte_rwlock_write_unlock +#define common_mem_spinlock_trylock rte_spinlock_trylock + +#define common_mem_socket_id rte_socket_id +#define common_mem_malloc_socket_stats rte_malloc_socket_stats + +#define COMMON_MEM_MIN RTE_MIN + +#define common_pal_module_init nscomm_pal_module_init +#define common_memzone_data_reserve_name nscomm_memzone_data_reserve_name +#define common_memzone_data_lookup_name nscomm_memzone_data_lookup_name + +#define common_dump_stack rte_dump_stack +#define COMMON_PKTMBUF_HEADROOM RTE_PKTMBUF_HEADROOM + +#define common_pktmbuf_mtod rte_pktmbuf_mtod +#define common_memcpy rte_memcpy +#define common_spinlock_try_lock_with_pid dmm_spinlock_try_lock_with_pid +#define common_spinlock_unlock rte_spinlock_unlock +#define common_atomic64_t rte_atomic64_t +#define common_atomic64_inc rte_atomic64_inc +#define common_atomic64_read rte_atomic64_read +#define common_atomic64_dec rte_atomic64_dec +#define common_mbuf_refcnt_set rte_mbuf_refcnt_set +#define common_mbuf_refcnt_read rte_mbuf_refcnt_read +#define common_exit rte_exit +#define COMMON_CACHE_LINE_SIZE RTE_CACHE_LINE_SIZE +#define common_eal_process_type rte_eal_process_type +#define COMMON_PROC_PRIMARY RTE_PROC_PRIMARY + +void dmm_addr_print(void); + +#define NSFW_NAME_LENCHECK_RET(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSRTP_LOGERR("name length check fail]desc=%s,name len=%d,expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_NAME_LENCHECK_RET_NULL(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSRTP_LOGERR("name length check fail]desc=%s,name len=%d,expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NULL; \ + } \ + } + +#endif + +#endif // _RTE_COMM_FUNC_H_ diff --git a/stacks/lwip_stack/src/include/common_mem_api.h b/stacks/lwip_stack/src/include/common_mem_api.h new file mode 100644 index 0000000..a799677 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_api.h @@ -0,0 +1,134 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_MEM_API_H__ +#define __COMMON_MEM_API_H__ + +#ifdef HAL_LIB +#else + +#include "rte_atomic.h" +#include "common_mem_spinlock.h" +#include +#include +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef NSTACK_LINT_CODE_DISABLE +#define NSTACK_LINT_CODE_DISABLE(code) /*lint -e#code */ +#endif + +#ifndef NSTACK_LINT_CODE_ENABLE +#define NSTACK_LINT_CODE_ENABLE(code) /*lint +e#code */ +#endif + +#define SYS_MBOX_NULL (sys_mbox_t)0 + +typedef sem_t *sys_sem_t_v1; +typedef sem_t sys_sem_st_v1; +typedef struct queue *sys_mbox_t; + +typedef rte_spinlock_t *sys_sem_t_v2; +typedef rte_spinlock_t sys_sem_st_v2; + +#ifndef u32_t +typedef uint32_t u32_t; +#endif + +#ifndef u8_t +typedef uint8_t u8_t; +#endif + +#ifndef s8_t +typedef int8_t s8_t; +#endif + +#ifndef err_t +typedef s8_t err_t; +#endif + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +void sys_sem_signal_s_v2(sys_sem_t_v2 sem); +void sys_sem_init_v2(sys_sem_t_v2 sem); +u32_t sys_arch_sem_trywait_v2(sys_sem_t_v2 * sem); + +u32_t sys_arch_sem_wait_s_v2(sys_sem_t_v2 sem); + +#define SYS_HOST_INITIAL_PID 1 +extern volatile pid_t g_sys_host_pid; +pid_t sys_get_hostpid_from_file(pid_t pid); + +u32_t sys_now(void); + +#define sys_sem_t sys_sem_t_v2 +#define sys_sem_st sys_sem_st_v2 +#define sys_sem_new(sem, count) sys_sem_new_v2(sem, count) +#define sys_sem_free(sem) sys_sem_free_v2(sem) +#define sys_sem_signal(sem) sys_sem_signal_v2(sem) +#define sys_arch_sem_wait(sem, timeout) sys_arch_sem_wait_v2(sem) +#define sys_arch_sem_trywait(sem) sys_arch_sem_trywait_v2(sem) + +#define sys_sem_init(sem) sys_sem_init_v2(sem) +#define sys_sem_s_signal(sem) sys_sem_signal_s_v2(sem) +#define sys_arch_sem_s_wait(sem, timeout) sys_arch_sem_wait_s_v2(sem) +#define sys_arch_lock_with_pid(sem) (void)sys_arch_lock_with_pid_v2(sem) + +#define BUF_SIZE_FILEPATH 256 +#define STR_PID "pid:" +#define READ_FILE_BUFLEN 512 + +extern pid_t sys_get_hostpid_from_file(pid_t pid); +extern pid_t get_hostpid_from_file(u32_t pid); +extern void get_exec_name_by_pid(pid_t pid, char *task_name, + int task_name_len); + +static inline u32_t sys_arch_lock_with_pid_v2(sys_sem_t_v2 sem) +{ + if (SYS_HOST_INITIAL_PID == g_sys_host_pid) + (void) sys_get_hostpid_from_file(getpid()); + dmm_spinlock_lock_with_pid(sem, g_sys_host_pid); + return 0; +} + +#define NSTACK_SEM_MALLOC(sys_sem,count) \ +{ \ + rte_spinlock_init(&(sys_sem)); \ + if (!(count)) \ + { \ + rte_spinlock_lock(&(sys_sem)); \ + } \ +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif + +#endif /* __COMMON_MEM_API_H__ */ diff --git a/stacks/lwip_stack/src/include/common_mem_base_type.h b/stacks/lwip_stack/src/include/common_mem_base_type.h new file mode 100644 index 0000000..01707d9 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_base_type.h @@ -0,0 +1,85 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BASE_TYPE_H_ +#define _COMMON_MEM_BASE_TYPE_H_ + +#ifdef HAL_LIB + +#else + +#define ALIGN_TYPE uint64_t +#define PTR_ALIGN_TYPE uint64_t + +/*alignment define*/ +#define ALIGNMENT_DEF(name, type, aligntype) \ + union { \ + type name; \ + aligntype name##_align; \ + } + +#define PTR_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, PTR_ALIGN_TYPE) + +#define OTHER_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, ALIGN_TYPE) + +/* + * * List definitions. + * */ +#define DMM_LIST_HEAD(name, type) \ +struct name { \ + PTR_ALIGNMENT_DEF(lh_first, struct type *); /* first element */ \ +} + +#define DMM_LIST_ENTRY(type) \ +struct { \ + PTR_ALIGNMENT_DEF(le_next, struct type *); /* next element */\ + PTR_ALIGNMENT_DEF(le_prev, struct type **); /* address of previous next element */ \ +} + +/* + * * Tail queue definitions. + * */ +#define _DMM_TAILQ_HEAD(name, type, qual) \ +struct name { \ + PTR_ALIGNMENT_DEF(tqh_first, qual type *); /* first element */ \ + PTR_ALIGNMENT_DEF(tqh_last, qual type * qual *); /* addr of last next element */ \ +} + +#define DMM_TAILQ_HEAD(name, type) _DMM_TAILQ_HEAD(name, struct type,) + +#define _DMM_TAILQ_ENTRY(type, qual) \ +struct { \ + PTR_ALIGNMENT_DEF(tqe_next, qual type *); /* next element */\ + PTR_ALIGNMENT_DEF(tqe_prev, qual type * qual*); /* address of previous next element */\ +} +#define DMM_TAILQ_ENTRY(type) _DMM_TAILQ_ENTRY(struct type,) + +/* + * * Singly-linked Tail queue declarations. + * */ +#define DMM_STAILQ_HEAD(name, type) \ + struct name { \ + PTR_ALIGNMENT_DEF(stqh_first, struct type *); /* first element */ \ + PTR_ALIGNMENT_DEF(stqh_last, struct type **); /* addr of last next element */ \ + } + +#define DMM_STAILQ_ENTRY(type) \ + struct { \ + PTR_ALIGNMENT_DEF(stqe_next, struct type *); /* next element */ \ + } +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_buf.h b/stacks/lwip_stack/src/include/common_mem_buf.h new file mode 100644 index 0000000..9ba0008 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_buf.h @@ -0,0 +1,78 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BUF_H_ +#define _COMMON_MEM_BUF_H_ + +#ifdef HAL_LIB +#else + +#include "nsfw_mem_api.h" +#include "common_mem_base_type.h" +#include "types.h" + +typedef enum __DMM_PROC_TYPE +{ + DMM_PROC_T_AUTO = 0, /*auto detect */ + DMM_PROC_T_PRIMARY = 1, /* set to primary */ + DMM_PROC_T_SECONDARY = 2, /* set to secondary */ + DMM_PROC_T_INVALID +} DMM_PROC_TYPE; + +#define DMM_MBUF_RET_OK 0 +#define DMM_MBUF_RET_ERR 1 + +#define LCORE_MAX 128 +#define LCORE_MASK_PER (sizeof(int) * 8) +#define LCORE_MASK_MAX (LCORE_MAX/LCORE_MASK_PER) + +#define LCORE_MASK_SET(ilcoremask, value) \ + if (value < LCORE_MAX) \ + { \ + ilcoremask[(value/LCORE_MASK_PER)] = (int) ( (ilcoremask[(value/LCORE_MASK_PER)]) | (1< (value%LCORE_MASK_PER))); \ + } \ + +#define DMM_HUGTBL_ENABLE 0 +#define DMM_HUGTBL_DISABLE 1 + +typedef struct __common_pal_module_info +{ + int ishare_mem_size; /*shared memory size */ + int ilcoremask[LCORE_MASK_MAX]; + /**/ unsigned char uchugeflag; + unsigned char ucproctype; + unsigned char ucinstance; + unsigned char ucresrv2; +} common_mem_pal_module_info; + +/** + * rte pal module init. + * + * + * @param name + * The name of the buf pool. + */ +int nscomm_pal_module_init(nsfw_mem_para * para, + common_mem_pal_module_info * pinfo, u8 app_mode); + +void *nscomm_memzone_data_reserve_name(const char *name, size_t len, + int socket_id); + +void *nscomm_memzone_data_lookup_name(const char *name); + +#endif + +#endif /* _COMMON_MEM_BUF_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_common.h b/stacks/lwip_stack/src/include/common_mem_common.h new file mode 100644 index 0000000..1e4cf56 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_common.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_COMMON_H_ +#define _COMMON_MEM_COMMON_H_ + +#ifdef HAL_LIB +#else +#include "rte_common.h" +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_mbuf.h b/stacks/lwip_stack/src/include/common_mem_mbuf.h new file mode 100644 index 0000000..ee8cfa2 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_mbuf.h @@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/******************************************************************* + Copyright 2017 - 2047, Huawei Tech. Co., Ltd. + ALL RIGHTS RESERVED + +Filename : common_mem_mbuf.h +Description : +Version : 1.1 +********************************************************************/ + +#ifndef _COMMON_MEM_MBUF_H_ +#define _COMMON_MEM_MBUF_H_ + +#ifdef HAL_LIB +#else +#include "rte_mbuf.h" +#include "common_func.h" + +typedef uint32_t(*dmm_mbuf_item_fun) (void *data, void *argv); +int32_t dmm_pktmbuf_pool_iterator(struct common_mem_mempool *mp, + uint32_t start, uint32_t end, + dmm_mbuf_item_fun fun, void *argv); +#endif + +#endif /* _COMMON_MEM_MBUF_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_mempool.h b/stacks/lwip_stack/src/include/common_mem_mempool.h new file mode 100644 index 0000000..58a8e82 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_mempool.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMPOOL_H_ +#define _COMMON_MEM_MEMPOOL_H_ + +#ifdef HAL_LIB +#else +#include "rte_mempool.h" +#endif + +#endif /* _COMMON_MEM_MEMPOOL_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h b/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h new file mode 100644 index 0000000..65b6e04 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h @@ -0,0 +1,26 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_PAL_MEMCONFIG_H_ +#define _COMMON_MEM_PAL_MEMCONFIG_H_ + +#ifdef HAL_LIB +#else +#include "rte_eal_memconfig.h" + +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_rwlock.h b/stacks/lwip_stack/src/include/common_mem_rwlock.h new file mode 100644 index 0000000..2eed259 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_rwlock.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_RWLOCK_H_ +#define _COMMON_MEM_RWLOCK_H_ + +#ifdef HAL_LIB +#else +#include "rte_rwlock.h" +#endif + +#endif /* _COMMON_MEM_RWLOCK_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_spinlock.h b/stacks/lwip_stack/src/include/common_mem_spinlock.h new file mode 100644 index 0000000..482e87b --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_spinlock.h @@ -0,0 +1,38 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_SPINLOCK_X86_64_H_ +#define _COMMON_MEM_SPINLOCK_X86_64_H_ + +#ifdef HAL_LIB +#else +#include "rte_spinlock.h" + +static inline void dmm_spinlock_lock_with_pid(rte_spinlock_t * sl, int pid) +{ + while (!__sync_bool_compare_and_swap(&sl->locked, 0, pid)) + while (sl->locked) + rte_pause(); +} + +static inline int dmm_spinlock_try_lock_with_pid(rte_spinlock_t * sl, int pid) +{ + return __sync_bool_compare_and_swap(&sl->locked, 0, pid); +} + +#endif + +#endif /* _COMMON_MEM_SPINLOCK_X86_64_H_ */ diff --git a/stacks/lwip_stack/src/include/nsfw_msg.h b/stacks/lwip_stack/src/include/nsfw_msg.h new file mode 100644 index 0000000..9efa694 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_msg.h @@ -0,0 +1,201 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef MSG_H +#define MSG_H +#include "types.h" +#include "common_mem_api.h" +#include "nsfw_rti.h" +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define MAX_MSG_SIZE 512 +COMPAT_PROTECT_RETURN(MAX_MSG_SIZE, 512); +#define MAX_MSG_PARAM_SIZE 128 +COMPAT_PROTECT_RETURN(MAX_MSG_PARAM_SIZE, 128); + +#define MSG_ASYN_POST 0 +#define MSG_SYN_POST 1 + +typedef struct +{ + u16 module_type; + u16 major_type; + u16 minor_type; + u16 op_type; /* MSG_SYN_POST or MSG_ASYN_POST */ + sys_sem_st op_completed; + i32 err; + PRIMARY_ADDR void *msg_from; /* use it to free msg */ + i64 receiver; + i64 comm_receiver; + nsfw_res res_chk; + u32 src_pid; + u32 recycle_pid; /* use it in recycle */ + u64 span_pid; + i64 extend_member_bit; +} msg_param; + +typedef struct msg_t +{ + msg_param param; + i8 msg_param_pad[MAX_MSG_PARAM_SIZE - sizeof(msg_param)]; /* sizeof(msg_param) + sizeof(msg_param_pad) = MAX_MSG_PARAM_SIZE */ + i64 buffer[(MAX_MSG_SIZE - MAX_MSG_PARAM_SIZE) / 8]; +} +data_com_msg; + +#define MAX_MODULE_TYPE 64 +#define MAX_MAJOR_TYPE 256 +#define MAX_MINOR_TYPE 256 + +struct rti_queue +{ + /* corresponding to enum spl_tcpip_msg_type */ + volatile u64 tcpip_msg_enq[MAX_MAJOR_TYPE]; + volatile u64 tcpip_msg_enq_fail[MAX_MAJOR_TYPE]; + u64 tcpip_msg_deq[MAX_MAJOR_TYPE]; + + /* corresponding to enum api_msg_type, this is sub-type of SPL_TCPIP_NEW_MSG_API */ + volatile u64 api_msg_enq[MAX_MINOR_TYPE]; + volatile u64 api_msg_enq_fail[MAX_MINOR_TYPE]; + u64 api_msg_deq[MAX_MINOR_TYPE]; + + u64 extend_member_bit; +}; + +enum MSG_MODULE_TYPE +{ + MSG_MODULE_IP, + MSG_MODULE_SBR, + MSG_MODULE_HAL, + MSG_MODULE_SPL, + MSG_MODULE_TIMER, + MSG_MODULE_MT, + MSG_MODULE_DFX, + MSG_MODULE_MAX = MAX_MODULE_TYPE +}; + +typedef int (*msg_fun) (data_com_msg * m); + +/* *INDENT-OFF* */ +extern msg_fun g_msg_module_fun_array[MAX_MODULE_TYPE]; +extern msg_fun g_msg_module_major_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE]; +extern msg_fun g_msg_module_major_minor_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE][MAX_MINOR_TYPE]; +extern msg_fun g_msg_unsupport_fun; +/* *INDENT-ON* */ + +#define REGIST_MSG_MODULE_FUN(module, fun) \ + static void regist_ ## module ## _function (void) \ + __attribute__((__constructor__)); \ + static void regist_ ## module ## _function (void) \ + { \ + g_msg_module_fun_array[module] = fun; \ + } \ + +#define REGIST_MSG_MODULE_MAJOR_FUN(module, major, fun) \ + static void regist_ ## module ## major ## _function (void) \ + __attribute__((__constructor__)); \ + static void regist_ ## module ## major ## _function (void) \ + { \ + g_msg_module_major_fun_array[module][major] = fun; \ + } \ + +#define REGIST_MSG_MODULE_MAJOR_MINOR_FUN(module, major, minor, fun) \ + static void regist_ ## module ## major ## minor ## _function (void) \ + __attribute__((__constructor__)); \ + static void regist_ ## module ## major ## minor ## _function (void) \ + { \ + g_msg_module_major_minor_fun_array[module][major][minor] = fun; \ + } \ + +#define REGIST_MSG_UNSUPPORT_FUN(fun) \ + static void regist_msg_unsupport_function (void) \ + __attribute__((__constructor__)); \ + static void regist_msg_unsupport_function (void) \ + { \ + g_msg_unsupport_fun = fun; \ + } + +static inline int unsupport_msg(data_com_msg * m) +{ + if (g_msg_unsupport_fun) + { + return g_msg_unsupport_fun(m); + } + + return -1; +} + +/***************************************************************************** +* Prototype : call_msg_fun +* Description : call msg fun +* Input : data_com_msg* m +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int call_msg_fun(data_com_msg * m) +{ + u16 module = m->param.module_type; + u16 major = m->param.major_type; + u16 minor = m->param.minor_type; + + if ((module >= MAX_MODULE_TYPE) || (major >= MAX_MAJOR_TYPE) + || (minor >= MAX_MINOR_TYPE)) + { + return unsupport_msg(m); + } + + nsfw_rti_stat_macro(NSFW_STAT_PRIMARY_DEQ, m); + + if (g_msg_module_fun_array[module] + && (g_msg_module_fun_array[module] (m) != 0)) + { + return -1; + } + + if (g_msg_module_major_fun_array[module][major] + && (g_msg_module_major_fun_array[module][major] (m) != 0)) + { + return -1; + } + + if (g_msg_module_major_minor_fun_array[module][major][minor]) + { + return g_msg_module_major_minor_fun_array[module][major][minor] (m); + } + + if (!g_msg_module_fun_array[module] + && !g_msg_module_major_fun_array[module][major] + && !g_msg_module_major_minor_fun_array[module][major][minor]) + { + return unsupport_msg(m); + } + + return 0; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/nsfw_msg_api.h b/stacks/lwip_stack/src/include/nsfw_msg_api.h new file mode 100644 index 0000000..b7e0d1c --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_msg_api.h @@ -0,0 +1,305 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef MSG_API_H +#define MSG_API_H +#include "nsfw_msg.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_rti.h" +#include "common_mem_api.h" +#include "nsfw_recycle_api.h" +#include "common_pal_bitwide_adjust.h" +#include "pid_common.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define SET_MSG_ERR(m, error) ((m)->param.err = (error)) +#define GET_MSG_ERR(m) ((m)->param.err) + +/* for sync message from sbr we should signal sem */ +#define SYNC_MSG_ACK(m) sys_sem_s_signal(&((m)->param.op_completed)) + +/* for async message from sbr we should free the message */ +#define ASYNC_MSG_FREE(m) msg_free(m) + +#define MSG_ENTRY(_ptr, _type, _member) container_of((void *)_ptr, _type, _member) + +#ifndef NSTACK_STATIC_CHECK +/***************************************************************************** +* Prototype : msg_malloc +* Description : malloc msg +* Input : mring_handle mhandle +* Output : None +* Return Value : static inline data_com_msg* +* Calls : +* Called By : +*****************************************************************************/ +static inline data_com_msg *msg_malloc(mring_handle mhandle) +{ + if (!mhandle) + { + NSFW_LOGERR("mhandle is null"); + return NULL; + } + + data_com_msg *m = NULL; + if (nsfw_mem_ring_dequeue(mhandle, (void **) &m) != 1) + { + return NULL; + } + + m->param.recycle_pid = get_sys_pid(); + res_alloc(&m->param.res_chk); + return m; +} + +/***************************************************************************** +* Prototype : msg_free +* Description : free msg +* Input : data_com_msg* m +* mring_handle mhandle +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +*****************************************************************************/ +static inline void msg_free(data_com_msg * m) +{ + if (!m) + { + NSFW_LOGERR("m is NULL"); + return; + } + + mring_handle mhandle = ADDR_SHTOL(m->param.msg_from); + if (!mhandle) + { + return; + } + + if (res_free(&m->param.res_chk)) + { + NSFW_LOGERR("m refree!]m=%p", m); + return; + } + + m->param.recycle_pid = 0; + + if (nsfw_mem_ring_enqueue(mhandle, (void *) m) != 1) + { + NSFW_LOGERR("nsfw_mem_ring_enqueue failed,this can not happen"); + } +} + +/***************************************************************************** +* Prototype : msg_post +* Description : post msg +* Input : data_com_msg* m +* mring_handle mhandle +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +*****************************************************************************/ +static inline int msg_post(data_com_msg * m, mring_handle mhandle) +{ + int ret; + if (!m || !mhandle) + { + NSFW_LOGERR("param is not ok]m=%p,mhandle=%p", m, mhandle); + return -1; + } + + while (1) + { + ret = nsfw_mem_ring_enqueue(mhandle, (void *) m); + switch (ret) + { + case 1: + if (MSG_SYN_POST == m->param.op_type) + { + sys_arch_sem_s_wait(&m->param.op_completed, 0); + } + + return 0; + case 0: + continue; + default: + nsfw_rti_stat_macro(NSFW_STAT_PRIMARY_ENQ_FAIL, m); + return -1; + } + } +} + +#define MSG_POST_FAILED 50 +/***************************************************************************** +* Prototype : msg_post_with_lock_rel +* Description : post msg to tcpip thread in mgrcom thread +* Input : data_com_msg* m +* mring_handle mhandle +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +*****************************************************************************/ +static inline int +msg_post_with_lock_rel(data_com_msg * m, mring_handle mhandle) +{ + int ret; + int try_count = 0; + if (!m || !mhandle) + { + NSFW_LOGERR("param is not ok]m=%p,mhandle=%p", m, mhandle); + return -1; + } + + while (1) + { + ret = nsfw_mem_ring_enqueue(mhandle, (void *) m); + switch (ret) + { + case 1: + if (MSG_SYN_POST == m->param.op_type) + { + sys_arch_sem_s_wait(&m->param.op_completed, 0); + } + + return 0; + case 0: + try_count++; + if (try_count > MSG_POST_FAILED) + { + try_count = 0; + nsfw_recycle_rechk_lock(); + } + sys_sleep_ns(0, 1000000); + continue; + default: + nsfw_rti_stat_macro(NSFW_STAT_PRIMARY_ENQ_FAIL, m); + return -1; + } + } +} + +/***************************************************************************** +* Prototype : msg_try_post +* Description : try post msg +* Input : data_com_msg* m +* mring_handle mhandle +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +*****************************************************************************/ +static inline int msg_try_post(data_com_msg * m, mring_handle mhandle) +{ + if (!m || !mhandle) + { + NSFW_LOGERR("param is not ok]m=%p,mhandle=%p", m, mhandle); + return -1; + } + + int ret = nsfw_mem_ring_enqueue(mhandle, (void *) m); + if (1 == ret) + { + if (MSG_SYN_POST == m->param.op_type) + { + sys_arch_sem_s_wait(&m->param.op_completed, 0); + } + + return 0; + } + + return -1; +} + +/***************************************************************************** +* Prototype : msg_fetch +* Description : fetch msg +* Input : mring_handle mhandle +* data_com_msg** m +* u32 num +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +*****************************************************************************/ +static inline int msg_fetch(mring_handle mhandle, data_com_msg ** m, u32 num) +{ + if (!m || !mhandle) + { + NSFW_LOGERR("param is not ok]m=%p,mhandle=%p", m, mhandle); + return -1; + } + + int ret; + while (1) + { + ret = nsfw_mem_ring_dequeuev(mhandle, (void *) m, num); + if (ret > 0) + { + break; + } + } + + return ret; +} + +/***************************************************************************** +* Prototype : msg_try_fetch +* Description : try fetch msg +* Input : mring_handle mhandle +* data_com_msg** m +* u32 num +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +*****************************************************************************/ +static inline int +msg_try_fetch(mring_handle mhandle, data_com_msg ** m, u32 num) +{ + if (!m || !mhandle) + { + NSFW_LOGERR("param is not ok]m=%p,mhandle=%p", m, mhandle); + return -1; + } + + return nsfw_mem_ring_dequeuev(mhandle, (void *) m, num); +} + +#else +data_com_msg *msg_malloc(mring_handle mhandle); +void msg_free(data_com_msg * m); +int msg_post(data_com_msg * m, mring_handle mhandle); +int msg_try_post(data_com_msg * m, mring_handle mhandle); +int msg_fetch(mring_handle mhandle, data_com_msg ** m, u32 num); +int msg_try_fetch(mring_handle mhandle, data_com_msg ** m, u32 num); +int msg_post_with_lock_rel(data_com_msg * m, mring_handle mhandle); +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/nsfw_mt_config.h b/stacks/lwip_stack/src/include/nsfw_mt_config.h new file mode 100644 index 0000000..3735be4 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_mt_config.h @@ -0,0 +1,63 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_MT_CONFIG_H +#define _FW_MT_CONFIG_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#include "nsfw_maintain_api.h" + +/* socket num config */ +#define SOCKET_NUM_PER_THREAD 1024 /* socket number per thread */ + +#define APP_POOL_NUM 32 + +#define DEF_HAL_RX_RING_SIZE 2048 + +/* stackx recv ring size config */ +#define DEF_SPL_MAX_RING_SIZE 1024 + +/* pcb number config */ +#define DEF_TCP_PCB_NUM 4096 /* tcp pcb number, per thread */ +#define DEF_UDP_PCB_NUM 512 /* udp pcb number, per thread */ +#define DEF_RAW_PCB_NUM 600 /* raw pcb number, per thread */ + +#define DEF_ARP_QUEUE_NUM 300 + +/* tx mbuf pool size config */ +#define DEF_TX_MBUF_POOL_SIZE (4*POOL_RING_BASE_SIZE) + +/* rx mbuf pool size config */ +#define DEF_RX_MBUF_POOL_SIZE (8*POOL_RING_BASE_SIZE) /* rx mbuf pool size */ + +/* stackx internal msg number config */ +#define DEF_TX_MSG_POOL_SIZE (DEF_TX_MBUF_POOL_SIZE*APP_POOL_NUM + MAX_VF_NUM*DEF_RX_MBUF_POOL_SIZE + DEF_RING_BASE_SIZE) + +/* mbox ring size config */ +#define DEF_MBOX_RING_SIZE (DEF_RING_BASE_SIZE/4) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/nsfw_rti.h b/stacks/lwip_stack/src/include/nsfw_rti.h new file mode 100644 index 0000000..f6eb1b8 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_rti.h @@ -0,0 +1,49 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef RTI_H +#define RTI_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define nsfw_rti_stat_macro(type, m) if (1 == g_dfx_switch) { nsfw_rti_stat(type, m); } + +typedef enum nsfw_rti_stat_type +{ + NSFW_STAT_PRIMARY_ENQ, + NSFW_STAT_PRIMARY_ENQ_FAIL, + NSFW_STAT_PRIMARY_DEQ, +} nsfw_rti_stat_type_t; + +struct rti_queue; +struct msg_t; + +extern char g_dfx_switch; +extern struct rti_queue *g_nsfw_rti_primary_stat; + +void nsfw_rti_stat(nsfw_rti_stat_type_t statType, const struct msg_t *m); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/nstack_dmm_adpt.h b/stacks/lwip_stack/src/include/nstack_dmm_adpt.h new file mode 100644 index 0000000..7e6e9cb --- /dev/null +++ b/stacks/lwip_stack/src/include/nstack_dmm_adpt.h @@ -0,0 +1,64 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#ifndef __NSTACK_DMM_ADPT_H__ +#define __NSTACK_DMM_ADPT_H__ + +typedef enum +{ + NSTACK_MODEL_TYPE1 = 1, /*nSocket and stack belong to the same process */ + NSTACK_MODEL_TYPE2 = 2, /*nSocket and stack belong to different processes, + *and nStack don't take care the communication between stack and stack adpt + */ + NSTACK_MODEL_TYPE3 = 3, /*nSocket and stack belong to different processes, and sbr was supplied to communicate whit stack */ + NSTACK_MODEL_TYPE_SIMPLE_STACK = 4, /* like TYPE1, DMM will NOT provide SBR or pipeline mode, just allocate 32M, and use dpdk file + * prefix to support multiple running app under DMM */ + NSTACK_MODEL_INVALID, +} nstack_model_deploy_type; + +#define NSTACK_DMM_MODULE "nstack_dmm_module" + +typedef struct nsfw_com_attr +{ + int policy; + int pri; +} nsfw_com_attr; + +typedef struct __nstack_dmm_para +{ + nstack_model_deploy_type deploy_type; + int proc_type; + nsfw_com_attr attr; + int argc; + char **argv; +} nstack_dmm_para; + +extern int nstack_adpt_init(nstack_dmm_para * para); +extern int nstack_event_callback(void *pdata, int events); + +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/stacks/lwip_stack/src/io_adpt/CMakeLists.txt b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt new file mode 100644 index 0000000..53915f1 --- /dev/null +++ b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt @@ -0,0 +1,41 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +FILE(GLOB_RECURSE HAL *.c) + +if(WITH_SECUREC_LIB) +INCLUDE_DIRECTORIES( + ./ + ${JSON_C_SRC} + ${SECUREC_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ +) +else() +SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +INCLUDE_DIRECTORIES( + ${PAL_H_DIRECTORIES} + ./ + ${JSON_C_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/hal/ +) +endif() +ADD_LIBRARY(nStackHal STATIC ${HAL}) +LINK_LIBRARIES(m dl rt nStackFw) diff --git a/stacks/lwip_stack/src/io_adpt/dpdk.c b/stacks/lwip_stack/src/io_adpt/dpdk.c new file mode 100644 index 0000000..e662a21 --- /dev/null +++ b/stacks/lwip_stack/src/io_adpt/dpdk.c @@ -0,0 +1,2499 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "nstack_log.h" +#include "nsfw_init_api.h" +#include "common_mem_mbuf.h" +#include "common_mem_mempool.h" +#include "common_func.h" +#include "hal.h" +#include "nstack_securec.h" +#include + +#define DPDK_NON_ROOT_USER_NAME "paas" +#define DPDK_TOOL_ENV "DPDK_TOOL_DIR" +#define DPDK_NIC_LIST_FILE "%s/ip_module/.nstack_dpdk_nic_list" +#define SOCKET_ID_0 0 + +NSTACK_STATIC struct passwd *dpdk_non_root_user; +NSTACK_STATIC char dpdk_tool_path[HAL_MAX_PATH_LEN] = { 0 }; + +/* Default configuration for rx and tx thresholds etc. */ +NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_igb = { + .rx_thresh = { + .pthresh = 8, + .hthresh = 8, + .wthresh = 1, //not bigger than 1 + }, +}; + +/* + * These default values are optimized for use with the Intel(R) 82576 1 GbE + * Controller and the DPDK e1000 PMD. Consider using other values for other + * network controllers and/or network drivers. + */ +NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_igb = { + .tx_thresh = { + .pthresh = 8, + .hthresh = 1, + .wthresh = 16, + }, + .tx_free_thresh = 0, /* Use PMD default values */ + .tx_rs_thresh = 0, /* Use PMD default values */ +}; + +/* + * RX and TX Prefetch, Host, and Write-back threshold values should be + * carefully set for optimal performance. Consult the network + * controller's datasheet and supporting DPDK documentation for guidance + * on how these parameters should be set. + */ + +/* Default configuration for rx and tx thresholds etc. */ +NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_ixgbe = { + .rx_thresh = { + .pthresh = 8, + .hthresh = 8, + .wthresh = 4, + }, + .rx_free_thresh = 0, +}; + +/* + * These default values are optimized for use with the Intel(R) 82599 10 GbE + * Controller and the DPDK ixgbe PMD. Consider using other values for other + * network controllers and/or network drivers. + */ +NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_ixgbe = { + .tx_thresh = { + .pthresh = 36, + .hthresh = 0, + .wthresh = 0, + }, + .tx_free_thresh = 0, /* Use PMD default values */ + .tx_rs_thresh = 0, /* Use PMD default values */ + .txq_flags = 0, +}; + +/* the port configuration of normal port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_normal = { + .rxmode = { + .mq_mode = ETH_RSS, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + .hw_ip_checksum = 1, + .hw_vlan_filter = 1, + .hw_vlan_strip = 1, + .jumbo_frame = 0, + .hw_strip_crc = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key + }, + }, + .txmode = { + .mq_mode = ETH_DCB_NONE, + }, + .intr_conf = { + .lsc = 0, + }, +}; + +/* the port configuration of virtio port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_virtio = { + .rxmode = { + .mq_mode = ETH_RSS, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + .hw_ip_checksum = 0, /* Virtio NIC doesn't support HW IP CheckSUM */ + .hw_vlan_filter = 1, + .hw_vlan_strip = 1, + .jumbo_frame = 0, + .hw_strip_crc = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key + }, + }, + .txmode = { + .mq_mode = ETH_DCB_NONE, + }, + .intr_conf = { + .lsc = 0, + }, +}; + +/* the port configuration of bond port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_bond = { + .rxmode = { + .mq_mode = ETH_MQ_RX_NONE, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + /**< Header Split disabled */ + .hw_ip_checksum = 0, + /**< IP checksum offload enabled */ + .hw_vlan_filter = 1, + /**< VLAN filtering enabled */ + .hw_vlan_strip = 1, + .jumbo_frame = 0, + /**< Jumbo Frame Support disabled */ + .hw_strip_crc = 0, + /**< CRC stripped by hardware */ + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = ETH_RSS_IP, + }, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; + +NSTACK_STATIC struct rte_eth_conf port_conf_default_vhost = { + .rxmode = { + .hw_ip_checksum = 0, /* vhost nic doesn't support hw_ip_checksum and hw_vlan_filter */ + .hw_vlan_filter = 0, + } +}; + +/***************************************************************************** +* Prototype : dpdk_mbuf_to_file +* Description : write the packet data into a file +* Input : uint16_t pkt_number +* struct rte_mbuf **pkts +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC void +dpdk_mbuf_to_file(uint16_t pkt_number, struct rte_mbuf **pkts) +{ + char line[100] = { 0 }; + FILE *f = NULL; + struct rte_mbuf *p = NULL; + uint16_t len = 0, offset, i; + uint16_t pktlen = 0; + uint16_t start = 0; + uint16_t number = 0; + unsigned char *data = NULL; + + f = fopen("/var/log/nStack/packet.txt", "a+"); + if (f == NULL) + { + NSHAL_LOGERR("can not open the file:%s", "packet.txt"); + return; + } + + for (i = 0; i < pkt_number; i++) + { + pktlen = 0; + p = pkts[i]; + while (p) + { + len = 0; + data = rte_pktmbuf_mtod(p, unsigned char *); + while (len < p->data_len) + { + start = pktlen % 16; /* start of the line */ + if (start == 0) + { + number = snprintf_s(line, sizeof(line), sizeof(line) - 1, + "%08X", len); + } + + for (offset = 0; + ((offset + start) < 16) + && ((len + offset) < p->data_len); offset++) + { + number += + snprintf_s(line + number, sizeof(line), + sizeof(line) - 1, " %02X", + data[len + offset]); + } + + fprintf(f, "%s", line); + if ((offset + start) == 16) + fprintf(f, "\n"); + + len += offset; + pktlen += offset; + (void) memset_s(line, sizeof(line), 0, sizeof(line)); + } + + p = p->next; + + } + fprintf(f, "\n"); + } + + fclose(f); + return; +} + +/***************************************************************************** +* Prototype : hal_rte_eth_rx_burst +* Description : a copy of rte_eth_rx_burst, because this function invokes + a global(rte_eth_devices), which cannt be access by dlsym + symbols +* Input : uint8_t port_id +* uint16_t queue_id +* struct rte_mbuf **rx_pkts +* const uint16_t nb_pkts +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC inline uint16_t +hal_rte_eth_rx_burst(uint8_t port_id, uint16_t queue_id, + struct rte_mbuf ** rx_pkts, const uint16_t nb_pkts) +{ +#ifdef RTE_ETHDEV_RXTX_CALLBACKS + struct rte_eth_rxtx_callback *cb; +#endif + int16_t nb_rx; + char *pst_capture_packet = NULL; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + + if (NULL == dev->rx_pkt_burst) + { + NSHAL_LOGERR("dev->rx_pkt_burst is NULL,dev=%p", dev); + return 0; + } + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); + RTE_FUNC_PTR_OR_ERR_RET(*dev->rx_pkt_burst, 0); + + if (queue_id >= dev->data->nb_rx_queues) + { + RTE_PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id); + return 0; + } +#endif + nb_rx = (*dev->rx_pkt_burst) (dev->data->rx_queues[queue_id], + rx_pkts, nb_pkts); + +#ifdef RTE_ETHDEV_RXTX_CALLBACKS + cb = dev->post_rx_burst_cbs[queue_id]; + + if (unlikely(cb != NULL)) + { + do + { + nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx, + nb_pkts, cb->param); + cb = cb->next; + } + while (cb != NULL); + } +#endif + + //pst_capture_packet = getenv ("NSTACK_CAPTURE_PACKET"); + if (pst_capture_packet && strcmp(pst_capture_packet, "1") == 0) + { + dpdk_mbuf_to_file(nb_rx, rx_pkts); + } + return (uint16_t) nb_rx; +} + +/***************************************************************************** +* Prototype : hal_rte_eth_tx_burst +* Description : a copy of rte_eth_tx_burst, because this function invokes + +* Input : uint8_t port_id +* uint16_t queue_id +* struct rte_mbuf **tx_pkts +* uint16_t nb_pkts +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC inline uint16_t +hal_rte_eth_tx_burst(uint8_t port_id, uint16_t queue_id, + struct rte_mbuf ** tx_pkts, uint16_t nb_pkts) +{ +#ifdef RTE_ETHDEV_RXTX_CALLBACKS + struct rte_eth_rxtx_callback *cb; +#endif + int16_t nb_tx = 0; + char *pst_capture_packet = NULL; + struct rte_eth_dev *dev = &rte_eth_devices[port_id]; + + if (NULL == dev->tx_pkt_burst) + { + NSHAL_LOGERR("dev->tx_pkt_burst is NULL"); + return 0; + } + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0); + RTE_FUNC_PTR_OR_ERR_RET(*dev->tx_pkt_burst, 0); + + if (queue_id >= dev->data->nb_tx_queues) + { + RTE_PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id); + return 0; + } +#endif + +#ifdef RTE_ETHDEV_RXTX_CALLBACKS + cb = dev->pre_tx_burst_cbs[queue_id]; + + if (unlikely(cb != NULL)) + { + do + { + nb_pkts = cb->fn.tx(port_id, queue_id, tx_pkts, nb_pkts, + cb->param); + cb = cb->next; + } + while (cb != NULL); + } +#endif + + nb_tx = (*dev->tx_pkt_burst) (dev->data->tx_queues[queue_id], tx_pkts, + nb_pkts); + + //pst_capture_packet = getenv ("NSTACK_CAPTURE_PACKET"); + if (pst_capture_packet && strcmp(pst_capture_packet, "1") == 0) + { + dpdk_mbuf_to_file(nb_tx, tx_pkts); + } + + return nb_tx; +} + +/***************************************************************************** + Prototype : dpdk_get_hugepage_size + Description : get the free hugepage size + Input : the dir of the nstack hugepage + Output : free hugepage size + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +int dpdk_read_hugepage_size(int *freehuge) +{ + int fd_huge; + int len; + char buf[5] = { '\0' }; + fd_huge = + open("/sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages", + O_RDONLY); + if (fd_huge < 0) + { + NSHAL_LOGERR("errno=%d", errno); + return -1; + } + + len = read(fd_huge, buf, sizeof(buf)); + if (len < 0) + { + NSHAL_LOGERR("errno=%d", errno); + close(fd_huge); //fix codeDEX 124547 + return -1; + } + *freehuge = buf[0] - '0'; + NSHAL_LOGINF("hugepage size=%d", *freehuge); + close(fd_huge); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_clear_hugedir + Description : clear the hugepage which is used by dpdk + Input : the dir of the nstack hugepage + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_clear_hugedir(const char *hugedir) +{ + DIR *dir; + struct dirent *dirent_dpdk; + int dir_fd, fd, lck_result, lk_result; + const char filter[] = "*mapns*"; /* matches hugepage files */ + + /* open directory */ + dir = opendir(hugedir); + if (!dir) + { + NSHAL_LOGERR("the path %s is not exist, errno = %d", hugedir, errno); + goto error; + } + dir_fd = dirfd(dir); + + dirent_dpdk = readdir(dir); + if (!dirent_dpdk) + { + NSHAL_LOGERR("the dir %s can not read, errno = %d", hugedir, errno); + goto error; + } + + while (dirent_dpdk != NULL) + { + /* skip files that don't match the hugepage pattern */ + if (fnmatch(filter, dirent_dpdk->d_name, 0) > 0) + { + NSHAL_LOGWAR("the file name %s is not match mapns, errno = %d", + dirent_dpdk->d_name, errno); + dirent_dpdk = readdir(dir); + continue; + } + + /* try and lock the file */ + fd = openat(dir_fd, dirent_dpdk->d_name, O_RDONLY); + + /* skip to next file */ + if (fd == -1) + { + NSHAL_LOGERR("the file name %s can not be lock, errno = %d", + dirent_dpdk->d_name, errno); + dirent_dpdk = readdir(dir); + continue; + } + + /* non-blocking lock */ + lck_result = flock(fd, LOCK_EX | LOCK_NB); + + /* if lock succeeds, unlock and remove the file */ + if (lck_result != -1) + { + NSHAL_LOGWAR + ("the file name %s can be lock and will delete, errno = %d", + dirent_dpdk->d_name, errno); + lck_result = flock(fd, LOCK_UN); + if (-1 == lck_result) + NSHAL_LOGERR("the file name %s unlock fail, errno = %d", + dirent_dpdk->d_name, errno); + lk_result = unlinkat(dir_fd, dirent_dpdk->d_name, 0); + if (-1 == lk_result) + NSHAL_LOGERR("the file name %s is unlinkat fail, errno = %d", + dirent_dpdk->d_name, errno); + } + close(fd); + dirent_dpdk = readdir(dir); + } + + (void) closedir(dir); + return 0; + + error: + if (dir) + (void) closedir(dir); + + return -1; +} + +/***************************************************************************** + Prototype : dpdk_init_global + Description : DPDK global init + Input : int argc + char** argv + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_init_global(int argc, char **argv) +{ + //int ret; + const char hugepath[] = "/mnt/nstackhuge"; + //int freeHuge = 0; + //int retryCount = 10; + + if (-1 == dpdk_clear_hugedir(hugepath)) + { + NSHAL_LOGERR("clear hugedir fail, try again!"); + sys_sleep_ns(0, 100000000); + (void) dpdk_clear_hugedir(hugepath); + } + NSHAL_LOGINF("init global succ"); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_init_env + Description : init dpdk run env + Input : void + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_init_env(void) +{ + int ret; + size_t len_size; + char *dpdk_env; + char *dpdk_path; + + /* Get dpdk_tool_path */ + dpdk_env = getenv(DPDK_TOOL_ENV); + if (NULL == dpdk_env) + { + NSHAL_LOGERR("please set enviroment:%s before start this stack" + "\nthe value of the %s must be the path of dpdk tools", + DPDK_TOOL_ENV, DPDK_TOOL_ENV); + return -1; + } + + /* modify ugly len_size judgement and strcpy */ + /* check len_size for malloc */ + len_size = strlen(dpdk_env); + if (0 == len_size || len_size >= HAL_MAX_PATH_LEN) + { + NSHAL_LOGERR("fail to dpdk_env strlen(DPDK_TOOL_ENV)"); + return -1; + } + + /* DPDK_TOOL_ENV's value will be use as popen's paramter,we need check's validity */ + dpdk_path = realpath(dpdk_env, NULL); + if (NULL == dpdk_path) + { + NSHAL_LOGERR("env:%s value incorrect]value=%s,errno=%d", + DPDK_TOOL_ENV, dpdk_env, errno); + return -1; + } + + len_size = strlen(dpdk_path); + if (0 == len_size || len_size >= HAL_MAX_PATH_LEN) + { + NSHAL_LOGERR("fail to dpdk_path strlen(DPDK_TOOL_ENV)"); + return -1; + } + + ret = strcpy_s(dpdk_tool_path, HAL_MAX_PATH_LEN, dpdk_path); + if (EOK != ret) + { + NSHAL_LOGERR("STRCPY_S failed]ret=%d", ret); + return -1; + } + + if (!hal_is_script_valid(dpdk_tool_path)) + { + NSHAL_LOGERR("dpdk_tool_path is invalid]dpdk_tool_path=%s", + dpdk_tool_path); + return -1; + } + + /* get non-root user's id */ + dpdk_non_root_user = getpwnam(DPDK_NON_ROOT_USER_NAME); + if (dpdk_non_root_user) + { + NSHAL_LOGINF("non-root]name=%s,uid=%u,gid=%u,errno=%d", + dpdk_non_root_user->pw_name, dpdk_non_root_user->pw_uid, + dpdk_non_root_user->pw_gid, errno); + } + else + { + NSHAL_LOGERR("non-root]cannot find user %s", DPDK_NON_ROOT_USER_NAME); + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_init_local + Description : DPDK local init + Input : void + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_init_local(void) +{ + int ret; + + ret = dpdk_init_env(); + + if (ret < 0) + { + NSHAL_LOGERR("dpdk_init_env failed"); + return -1; + } + + NSHAL_LOGINF("init local succ"); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_set_port + Description : check and save the port num + Input : netif_inst_t* inst + int port + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_port(netif_inst_t * inst, uint8_t port) +{ + if (port >= rte_eth_dev_count()) + { + NSHAL_LOGERR + ("the number of port=%d is more than rte_eth_dev_count=%d", port, + rte_eth_dev_count()); + return -1; + } + + inst->data.dpdk_if.port_id = port; + + return 0; + +} + +/***************************************************************************** + Prototype : dpdk_set_nic_type + Description : check and save nic type + Input : netif_inst_t* inst + const char* type + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_nic_type(netif_inst_t * inst, const char *type) +{ + int ret; + + ret = + strcpy_s(inst->data.dpdk_if.nic_type, + sizeof(inst->data.dpdk_if.nic_type), type); + if (EOK != ret) + { + NSHAL_LOGERR("strcpy_s set nic_type failed]ret=%d", ret); + return -1; + } + + /* + * *nic_type is first checked at read_ipmoduleoperateadd_configuration, + * *thus here we dont boring validating it once more and just return. + * */ + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_set_nic_name + Description : check and save nic name + Input : netif_inst_t* inst + const char* name + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_nic_name(netif_inst_t * inst, const char *name) +{ + int ret; + + /* sizeof(pointer) always = 8 in 64 bit system */ + ret = + strcpy_s(inst->data.dpdk_if.nic_name, + sizeof(inst->data.dpdk_if.nic_name), name); + if (EOK != ret) + { + NSHAL_LOGERR("STRCPY_S set nic_name failed]ret=%d", ret); + return -1; + } + + if (!hal_is_script_valid(inst->data.dpdk_if.nic_name)) + { + NSHAL_LOGERR("nic_name is invalid"); + return -1; + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_driver_name + Description : get and save driver name + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_get_driver_name(netif_inst_t * inst) +{ + int ret_len, ret; + char script_cmmd[HAL_SCRIPT_LENGTH]; + char driver_name[HAL_SCRIPT_LENGTH] = { 0 }; + + ret = hal_snprintf(script_cmmd, sizeof(script_cmmd), + "readlink -f /sys/class/net/" "%s" + "/device/driver| awk -F'/' '{print $6}'", + inst->data.dpdk_if.nic_name); + if (-1 == ret) + { + NSHAL_LOGERR("hal_snprintf failed"); + return -1; + } + + ret_len = + hal_run_script(script_cmmd, driver_name, sizeof(driver_name) - 1); + + if (ret_len > HAL_MAX_DRIVER_NAME_LEN) + { + ret_len = HAL_MAX_DRIVER_NAME_LEN; + } + + if (ret_len <= 0) + { + NSHAL_LOGERR("%s does't have a driver", driver_name); + + ret = + strncpy_s(inst->data.dpdk_if.driver_name, + sizeof(inst->data.dpdk_if.driver_name), "NULL", + sizeof("NULL")); + + if (EOK != ret) + { + NSHAL_LOGERR("STRNCPY_S failed]ret=%d.", ret); + return -1; + } + + return -1; + } + else + { + ret = + strncpy_s(inst->data.dpdk_if.driver_name, + sizeof(inst->data.dpdk_if.driver_name), driver_name, + ret_len); + + if (EOK != ret) + { + NSHAL_LOGERR("STRNCPY_S failed]ret=%d.", ret); + return -1; + } + + inst->data.dpdk_if.driver_name[(ret_len - 1)] = '\0'; + + return 0; + } +} + +/***************************************************************************** + Prototype : dpdk_set_pci_permission + Description : set pci permission + Input : char *pci_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_pci_permission(char *pci_addr) +{ + DIR *dir_desc; + char file_path[HAL_SCRIPT_LENGTH] = { 0 }, dir_path[HAL_SCRIPT_LENGTH] = + { + 0}; + struct dirent *ent; + struct stat statbuf; + int ret; + + ret = + snprintf_s(dir_path, sizeof(dir_path), sizeof(dir_path) - 1, + "/sys/bus/pci/devices/%s", pci_addr); + if (ret < 0) + { + NSHAL_LOGERR("SNPRINTF_S fail"); + return -1; + } + + if ((dir_desc = opendir(dir_path)) == NULL) + { + NSHAL_LOGERR("opendir fail:errno=%d", errno); + return -1; + } + + while ((ent = readdir(dir_desc)) != NULL) + { + if (strstr(ent->d_name, "resource")) + { + ret = + snprintf_s(file_path, sizeof(file_path), + sizeof(file_path) - 1, "%s/%s", dir_path, + ent->d_name); + if (ret < 0) + { + NSHAL_LOGERR("SNPRINTF_S fail"); + (void) closedir(dir_desc); + return -1; + } + + if (!lstat(file_path, &statbuf) && !S_ISDIR(statbuf.st_mode)) + { + ret = + chown(file_path, dpdk_non_root_user->pw_uid, + dpdk_non_root_user->pw_gid); + if (ret < 0) + { + NSHAL_LOGERR("chown fail]file_path=%s,ret=%d,errno=%d", + file_path, ret, errno); + (void) closedir(dir_desc); + return -1; + } + NSHAL_LOGWAR("chown succ]file_path=%s,ret=%d", file_path, + ret); + ret = chmod(file_path, 0640); + if (ret < 0) + { + NSHAL_LOGERR("chmod fail]file_path=%s,ret=%d,errno=%d", + file_path, ret, errno); + (void) closedir(dir_desc); + return -1; + } + NSHAL_LOGWAR("chmod succ]file_path=%s,ret=%d", file_path, + ret); + } + } + } + + (void) closedir(dir_desc); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_pci_addr + Description : get and save pci addr + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_get_pci_addr(netif_inst_t * inst) +{ + int ret, pci_len; + struct ethtool_drvinfo edata = { 0 }; + struct ifreq ifr; + int fd = -1; + + /* use ioctl to get pci address instead of call dpdk-devbind.py to reduce time cost */ + ret = memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)); + if (EOK != ret) + { + NSHAL_LOGERR("MEMSET_S fail"); + return -1; + } + edata.cmd = ETHTOOL_GDRVINFO; + ret = + strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), + inst->data.dpdk_if.nic_name); + if (EOK != ret) + { + NSHAL_LOGERR("STRCPY_S fail"); + return -1; + } + + ifr.ifr_data = (char *) (&edata); + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + NSHAL_LOGERR("cannot init socket, errno=%d", errno); + return -1; + } + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) + { + NSHAL_LOGERR("ioctl to the device %s err, errno=%d", + inst->data.dpdk_if.nic_name, errno); + close(fd); + return -1; + } + close(fd); + + pci_len = strlen(edata.bus_info); + if (pci_len == 0 + || pci_len > (int) sizeof(inst->data.dpdk_if.pci_addr) - 1) + { + NSHAL_LOGERR("does't have a pci_addr"); + inst->data.dpdk_if.pci_addr[0] = '\0'; + return -1; + } + + NSHAL_LOGINF("nic_name=%s,nic_pci_addr=%s", inst->data.dpdk_if.nic_name, + edata.bus_info); + + ret = + strncpy_s(inst->data.dpdk_if.pci_addr, + sizeof(inst->data.dpdk_if.pci_addr), edata.bus_info, + pci_len); + if (EOK != ret) + { + NSHAL_LOGERR("STRNCPY_S failed]ret=%d.", ret); + return -1; + } + + if (!hal_is_script_valid(inst->data.dpdk_if.pci_addr)) + { + NSHAL_LOGERR("pci_addr is invalid]pci_addr=%s", + inst->data.dpdk_if.pci_addr); + return -1; + } + + if (dpdk_non_root_user && getuid()) + { + ret = dpdk_set_pci_permission(inst->data.dpdk_if.pci_addr); + if (ret < 0) + { + NSHAL_LOGERR("dpdk_set_pci_permission fail"); + return -1; + } + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_mlx_linkup + Description : linkup the port for mlx + In bonding mode, mlx4 NICs should be set up manually, + in order to make bond port up + Input : char* name + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_mlx_linkup(char *name) +{ + struct ifreq st_ifreq; + int sock; + int retVal; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + NSHAL_LOGERR("socket fail]errno=%d", errno); + return 2; + } + + retVal = strcpy_s(st_ifreq.ifr_name, sizeof(st_ifreq.ifr_name), name); + + if (EOK != retVal) + { + NSHAL_LOGERR("STRCPY_S fail]"); + close(sock); + return 1; + } + + if (ioctl(sock, (uint64_t) SIOCGIFFLAGS, &st_ifreq) < 0) + { + NSHAL_LOGERR("ioctl SIOCGIFFLAGS fail]errno=%d", errno); + close(sock); + return 3; + } + + st_ifreq.ifr_flags |= IFF_UP; + st_ifreq.ifr_flags |= IFF_RUNNING; + + if (ioctl(sock, (uint64_t) SIOCSIFFLAGS, &st_ifreq) < 0) + { + NSHAL_LOGERR("ioctl SIOCSIFFLAGS fail]errno=%d", errno); + close(sock); + return 3; + } + + close(sock); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_nonmlx_linkdown + Description : linkdown the port for nonmlx + Input : char* name + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_nonmlx_linkdown(char *name) +{ + int ret, ret_len; + char script_cmmd[HAL_SCRIPT_LENGTH]; + char result_buf[HAL_SCRIPT_LENGTH]; + + ret = + hal_snprintf(script_cmmd, sizeof(script_cmmd), + "sudo ifconfig %s down", name); + if (-1 == ret) + { + NSHAL_LOGERR("spl_snprintf failed]"); + return -1; + } + + ret_len = hal_run_script(script_cmmd, result_buf, sizeof(result_buf)); + NSHAL_LOGINF("ifconfig]script_cmmd=%s,ret_len=%d", script_cmmd, ret_len); + if (0 > ret_len) + { + NSHAL_LOGERR("cannot able to ifconfig %s down", name); + return -1; + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_uio_by_pci_addr + Description : get uio + Input : char *pci_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_get_uio_by_pci_addr(char *pci_addr) +{ + int i, ret, ret_len; + char script_cmmd[HAL_SCRIPT_LENGTH]; + char result_buf[HAL_SCRIPT_LENGTH]; + + for (i = 0; i < RTE_MAX_ETHPORTS; i++) + { + ret = hal_snprintf(script_cmmd, sizeof(script_cmmd), + "readlink ls /sys/class/uio/uio%d/device | awk -F '/' '{print $4}'", + i); + if (-1 == ret) + { + NSHAL_LOGERR("hal_snprintf fail]pci=%s,i=%d", pci_addr, i); + return -1; + } + + ret_len = hal_run_script(script_cmmd, result_buf, sizeof(result_buf)); + if (0 > ret_len) + { + NSHAL_LOGERR("hal_run_script fail]pci=%s,i=%d", pci_addr, i); + return -1; + } + if (strcmp(result_buf, pci_addr) == 0) + return i; + } + + return -1; +} + +/***************************************************************************** + Prototype : dpdk_set_uio_permission + Description : set uio permission + Input : char *pci_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_uio_permission(char *pci_addr) +{ + int ret, uio_idx; + char file_path[HAL_SCRIPT_LENGTH / 2] = { 0 }; + + /* get /dev/uio by pci addr */ + uio_idx = dpdk_get_uio_by_pci_addr(pci_addr); + if (uio_idx < 0) + { + NSHAL_LOGERR("dpdk_get_uio_by_pci_addr fail]pci_addr=%s", pci_addr); + return -1; + } + + NSHAL_LOGINF("uio_idx]pci=%s,uio%d", pci_addr, uio_idx); + + /* change /dev/uio%u permission */ + if (snprintf_s + (file_path, sizeof(file_path), sizeof(file_path) - 1, "/dev/uio%d", + uio_idx) < 0) + { + NSHAL_LOGERR("SNPRINTF_S failed]uio%d", uio_idx); + return -1; + } + sys_sleep_ns(0, 500000000); + ret = + chown(file_path, dpdk_non_root_user->pw_uid, + dpdk_non_root_user->pw_gid); + if (ret < 0) + { + NSHAL_LOGERR("chown fail]file_path=%s,ret=%d,errno=%d", file_path, + ret, errno); + return -1; + } + NSHAL_LOGWAR("chown succ]file_path=%s,ret=%d", file_path, ret); + + ret = chmod(file_path, 0640); + if (ret < 0) + { + NSHAL_LOGERR("chmod fail]file_path=%s,ret=%d,errno=%d", file_path, + ret, errno); + return -1; + } + NSHAL_LOGWAR("chmod succ]file_path=%s,ret=%d", file_path, ret); + + /* change /sys/class/uio/uio%u/device/config permission */ + if (snprintf_s + (file_path, sizeof(file_path), sizeof(file_path) - 1, + "/sys/class/uio/uio%d/device/config", uio_idx) < 0) + { + NSHAL_LOGERR("SNPRINTF_S failed]uio%d", uio_idx); + return -1; + } + + ret = + chown(file_path, dpdk_non_root_user->pw_uid, + dpdk_non_root_user->pw_gid); + if (ret < 0) + { + NSHAL_LOGERR("chown fail]file_path=%s,ret=%d,errno=%d", file_path, + ret, errno); + return -1; + } + NSHAL_LOGWAR("chown succ]file_path=%s,ret=%d", file_path, ret); + + ret = chmod(file_path, 0640); + if (ret < 0) + { + NSHAL_LOGERR("chmod fail]file_path=%s,ret=%d,errno=%d", file_path, + ret, errno); + return -1; + } + NSHAL_LOGWAR("chmod succ]file_path=%s,ret=%d", file_path, ret); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_nic_list_file + Description : get dpdk bind nic list file + Input : void + Output : char* + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC char *dpdk_get_nic_list_file(void) +{ + int ret; + static char buffer[HAL_MAX_PATH_LEN]; /* static so auto-zeroed */ + const char *directory = "/var/run"; + const char *home_dir = getenv("HOME"); + + if (getuid() != 0 && home_dir != NULL) + directory = home_dir; + + ret = + snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, + DPDK_NIC_LIST_FILE, directory); + if (-1 == ret) + { + NSHAL_LOGERR("SNPRINTF_S failed]ret=%d", ret); + return NULL; + } + + return buffer; +} + +/***************************************************************************** + Prototype : dpdk_bind_uio + Description : bind uio + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_bind_uio(netif_inst_t * inst) +{ + char script_cmmd[HAL_SCRIPT_LENGTH]; + char result_buf[HAL_SCRIPT_LENGTH]; + int ret, ret_len; + + result_buf[0] = '\0'; + + if (strncmp("mlx4_co", inst->data.dpdk_if.driver_name, (size_t) 7) == 0) + { + /*For MLX4: NIC should be set link up before rte_eth_dev_start() is called. */ + ret = dpdk_mlx_linkup(inst->data.dpdk_if.nic_name); + if (0 != ret) + { + NSHAL_LOGERR("set mlx linkup fail]nic_name=%s,ret=%d", + inst->data.dpdk_if.nic_name, ret); + + return -1; + } + } + else + { + /*For other drivers: NIC should be set link down before bind uio. */ + ret = dpdk_nonmlx_linkdown(inst->data.dpdk_if.nic_name); + if (-1 == ret) + { + NSHAL_LOGERR("dpdk_nonmlx_linkdown fail]nic_name=%s", + inst->data.dpdk_if.nic_name); + return -1; + } + + /* save binded VF list to file /var/run/ip_module/.nstack_dpdk_nic_list */ + ret = hal_snprintf(script_cmmd, sizeof(script_cmmd), + "sudo %s" + "/dpdk-devbind.py -s | grep `ethtool -i %s| grep bus-info |awk '{print $2}'` >> %s 2>&1", + dpdk_tool_path, inst->data.dpdk_if.nic_name, + dpdk_get_nic_list_file()); + + if (-1 == ret) + { + NSHAL_LOGERR("hal_snprintf fail]nic_name=%s", + inst->data.dpdk_if.nic_name); + return -1; + } + + ret_len = + hal_run_script(script_cmmd, result_buf, sizeof(result_buf) - 1); + NSHAL_LOGINF("bind]script_cmmd=%s,ret_len=%d", script_cmmd, ret_len); + if (0 > ret_len) + { + NSHAL_LOGERR("hal_run_script fail]script_cmmd=%s", script_cmmd); + return -1; + } + + if (strncmp("virtio", inst->data.dpdk_if.driver_name, (size_t) 6) == + 0) + { + /* For Virtio NIC, should call "./devbind.sh ethX" to bind the VF */ + ret = hal_snprintf(script_cmmd, sizeof(script_cmmd), + "sudo %s" + "/dpdk-devbind.py --bind=igb_uio `ethtool -i %s| grep bus-info |awk '{print $2}'`", + dpdk_tool_path, inst->data.dpdk_if.nic_name); + //"sudo %s" "/devbind.sh " "%s", dpdk_tool_path, inst->data.dpdk_if.nic_name); + + } + else + { + ret = hal_snprintf(script_cmmd, sizeof(script_cmmd), + "sudo %s" "/dpdk-devbind.py --bind=igb_uio " + "%s", dpdk_tool_path, + inst->data.dpdk_if.nic_name); + } + + if (-1 == ret) + { + NSHAL_LOGERR("hal_snprintf failed"); + return -1; + } + + ret_len = + hal_run_script(script_cmmd, result_buf, sizeof(result_buf) - 1); + NSHAL_LOGINF("bind]script_cmmd=%s,retlen=%d", script_cmmd, ret_len); + if (0 > ret_len) + { + NSHAL_LOGERR("hal_run_script fail]script_cmmd=%s", script_cmmd); + return -1; + } + + if (dpdk_non_root_user && getuid()) + { + ret = dpdk_set_uio_permission(inst->data.dpdk_if.pci_addr); + + if (ret < 0) + { + NSHAL_LOGERR("set_uio_permission fail]nic_name=%s", + inst->data.dpdk_if.nic_name); + return -1; + } + } + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_probe_pci + Description : probe pci + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_probe_pci(netif_inst_t * inst) +{ + int ret; + uint16_t port_id; + struct rte_eth_dev *eth_dev; + char *pci_addr = inst->data.dpdk_if.pci_addr; + + ret = rte_eal_iopl_init(); + if (0 != ret) + { + NSHAL_LOGERR("rte_eal_iopl_init fail]pci_addr=%s,ret=%d", pci_addr, + ret); + return -1; + } + + ret = rte_eth_dev_attach(pci_addr, &port_id); + if (0 != ret) + { + NSHAL_LOGWAR + ("pci attach to DPDK fail, the pci may have attached, try to get port id]pci_addr=%s,ret=%d", + pci_addr, ret); + + eth_dev = rte_eth_dev_allocated(inst->data.dpdk_if.nic_name); + if (NULL != eth_dev && NULL != eth_dev->data) + { + port_id = eth_dev->data->port_id; + ret = 0; + } + } + + if (!ret) + { + ret = dpdk_set_port(inst, port_id); + + if (0 == ret) + { + NSHAL_LOGINF("set port success]pci_addr=%s,port_id=%u", pci_addr, + port_id); + } + else + { + NSHAL_LOGERR("set port fail]pci_addr=%s,port_id=%u", pci_addr, + port_id); + return -1; + } + } + else + { + NSHAL_LOGERR("get port fail]pci_addr=%s,ret=%d", pci_addr, ret); + return -1; + } + + /*[TA33635][2017-04-24][l00408818] Start: support bond mode */ + ret = rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI, pci_addr); + if (!ret) + { + NSHAL_LOGINF("pci attach to whitelist success]pci_addr=%s", pci_addr); + } + else + { + NSHAL_LOGERR("pci attach to whitelist fail]pci_addr=%s", pci_addr); + return -1; + } + /*[TA33635][2017-04-24][l00408818] End */ + + return 0; +} + +/*nic_name->driver_name->pci_addr->get port*/ +/***************************************************************************** + Prototype : dpdk_open + Description : open the port + Input : netif_inst_t* inst + const char* name + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_open(netif_inst_t * inst, const char *name, const char *type) +{ + int ret; + + if ((inst == NULL) || (name == NULL) || (type == NULL)) + { + NSHAL_LOGERR + ("invaliad arguments]inst==NULL, nic_type==NULL or type==NULL"); + return -1; + } + + ret = dpdk_set_nic_type(inst, type); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_set_nic_type fail]nic_type=%s, ret=%d", type, ret); + return -1; + } + + ret = dpdk_set_nic_name(inst, name); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_set_nic_name fail]nic_name=%s, ret=%d", name, ret); + return -1; + } + + if (!strncmp(type, "vhost", strlen("vhost"))) + { + /*for vhost-user device, the remaining steps is unnecessary, y0413485 */ + NSHAL_LOGERR("initting vhost device]nic_name=%s type=%s", name, type); + return 0; + } + + ret = dpdk_get_driver_name(inst); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_get_driver_name fail]nic_name=%s, ret=%d", name, + ret); + return -1; + } + + ret = dpdk_get_pci_addr(inst); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_get_pci_addr fail]nic_name=%s, ret=%d", name, ret); + return -1; + } + + ret = dpdk_bind_uio(inst); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_bind_uio fail]nic_name=%s, ret=%d", name, ret); + return -1; + } + + ret = dpdk_probe_pci(inst); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_probe_pci fail]nic_name=%s, ret=%d", name, ret); + return -1; + } + + NSHAL_LOGINF("open port succ]port_id=%u, nic_name=%s", + inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_close + Description : close the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_close(netif_inst_t * inst) +{ + int i; + + /* close slave NIC first */ + for (i = 0; i < inst->data.dpdk_if.slave_num; i++) + { + rte_eth_dev_close(inst->data.dpdk_if.slave_port[i]); + NSHAL_LOGINF("close slave port succ]port_id=%u, nic_name=%s", + inst->data.dpdk_if.slave_port[i], + inst->data.dpdk_if.nic_name); + } + + rte_eth_dev_close(inst->data.dpdk_if.port_id); + NSHAL_LOGINF("close port succ]port_id=%u, nic_name=%s", + inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_queue_conf + Description : get the port queue configure + Input : netif_inst_t* inst + struct rte_eth_rxconf** rx_conf + struct rte_eth_txconf** tx_conf + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_get_queue_conf(netif_inst_t * inst, + struct rte_eth_rxconf **rx_conf, + struct rte_eth_txconf **tx_conf) +{ + static struct rte_eth_dev_info slave_dev_info; + + if (strncmp("igb", inst->data.dpdk_if.driver_name, (size_t) 3) == 0) + { + *rx_conf = (struct rte_eth_rxconf *) &rx_conf_default_igb; + *tx_conf = (struct rte_eth_txconf *) &tx_conf_default_igb; + NSHAL_LOGINF("igb config is enable]port_id=%u", + inst->data.dpdk_if.port_id); + } + else if (strncmp("ixgbe", inst->data.dpdk_if.driver_name, (size_t) 5) == + 0) + { + *rx_conf = (struct rte_eth_rxconf *) &rx_conf_default_ixgbe; + *tx_conf = (struct rte_eth_txconf *) &tx_conf_default_ixgbe; + NSHAL_LOGINF("igxbe config is enable]port_id=%u", + inst->data.dpdk_if.port_id); + } + else if (strncmp("bond", inst->data.dpdk_if.driver_name, (size_t) 4) == 0) + { + *rx_conf = NULL; + rte_eth_dev_info_get(inst->data.dpdk_if.slave_port[0], + &slave_dev_info); + *tx_conf = &(slave_dev_info.default_txconf); + NSHAL_LOGINF("bond config is enable]port_id=%u", + inst->data.dpdk_if.port_id); + } + else + { + *rx_conf = NULL; + *tx_conf = NULL; + NSHAL_LOGINF("default config is enable]port_id=%u", + inst->data.dpdk_if.port_id); + } + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_port_conf + Description : get the port configure + Input : netif_inst_t* inst + struct rte_eth_conf** port_conf + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC void +dpdk_get_port_conf(netif_inst_t * inst, struct rte_eth_conf **port_conf) +{ + if (strncmp("virtio", inst->data.dpdk_if.driver_name, (size_t) 6) == 0) + { + *port_conf = &port_conf_default_virtio; + } + else if (strncmp("bond", inst->data.dpdk_if.driver_name, (size_t) 4) == 0) + { + *port_conf = &port_conf_default_bond; + } + else if (strncmp("vhost", inst->data.dpdk_if.nic_type, (size_t) 5) == 0) + { + *port_conf = &port_conf_default_vhost; + return; + } + else + { + *port_conf = &port_conf_default_normal; + } + + (*port_conf)->rxmode.hw_vlan_filter = inst->data.dpdk_if.hw_vlan_filter; + (*port_conf)->rxmode.hw_vlan_strip = inst->data.dpdk_if.hw_vlan_strip; +} + +/***************************************************************************** + Prototype : dpdk_setup_port + Description : setup the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_setup_port(netif_inst_t * inst) +{ + int ret; + uint32_t i; + struct rte_eth_conf *port_conf; + struct rte_eth_rxconf *rx_conf; + struct rte_eth_txconf *tx_conf; + + uint8_t port_id = inst->data.dpdk_if.port_id; + struct rte_mempool **mp = + (struct rte_mempool **) inst->data.dpdk_if.rx_pool; + uint32_t *rx_ring_size = inst->data.dpdk_if.rx_ring_size; + uint32_t *tx_ring_size = inst->data.dpdk_if.tx_ring_size; + uint32_t rx_queue_num = inst->data.dpdk_if.rx_queue_num; + uint32_t tx_queue_num = inst->data.dpdk_if.tx_queue_num; + + dpdk_get_port_conf(inst, &port_conf); + + ret = + rte_eth_dev_configure(port_id, rx_queue_num, tx_queue_num, port_conf); + if (ret < 0) + { + NSHAL_LOGERR("rte_eth_dev_configure]port_id=%u,ret=%d", port_id, ret); + return ret; + } + + if (dpdk_get_queue_conf(inst, &rx_conf, &tx_conf) < 0) + { + NSHAL_LOGERR("dpdk_get_queue_conf failed]inst=%p,rx_conf=%p", inst, + rx_conf); + return -1; + } + /* fix "FORTIFY.Out-of-Bounds_Read" type codedex issue CID 33436 */ + if (rx_queue_num > HAL_ETH_MAX_QUEUE_NUM + || tx_queue_num > HAL_ETH_MAX_QUEUE_NUM) + { + NSHAL_LOGERR + ("queue num error]rx_queue_num=%u, tx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d", + rx_queue_num, tx_queue_num, HAL_ETH_MAX_QUEUE_NUM); + + return -1; + } + + for (i = 0; i < rx_queue_num; i++) + { + ret = + rte_eth_rx_queue_setup(port_id, i, rx_ring_size[i], SOCKET_ID_ANY, + rx_conf, mp[i]); + if (ret < 0) + { + NSHAL_LOGERR("rx queue setup fail]index=%u,port_id=%u,ret=%d", i, + port_id, ret); + return ret; + } + } + + for (i = 0; i < tx_queue_num; i++) + { + ret = + rte_eth_tx_queue_setup(port_id, i, tx_ring_size[i], SOCKET_ID_ANY, + tx_conf); + + if (ret < 0) + { + NSHAL_LOGERR("tx queue setup fail]q=%u,ret=%d", i, ret); + return ret; + } + } + + rte_eth_promiscuous_enable(port_id); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_start + Description : start the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_start(netif_inst_t * inst) +{ + int ret; + struct ether_addr eth_addr; + + ret = dpdk_setup_port(inst); + + if (ret < 0) + { + NSHAL_LOGERR("call dpdk_setup_port fail]ret=%d", ret); + return ret; + } + + ret = rte_eth_dev_start(inst->data.dpdk_if.port_id); + if (ret < 0) + { + NSHAL_LOGERR("rte_eth_dev_start fail]ret=%d", ret); + return ret; + } + + rte_eth_macaddr_get(inst->data.dpdk_if.port_id, ð_addr); + NSHAL_LOGINF("port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X", + inst->data.dpdk_if.port_id, + inst->data.dpdk_if.nic_name, + eth_addr.addr_bytes[0], + eth_addr.addr_bytes[1], + eth_addr.addr_bytes[2], + eth_addr.addr_bytes[3], + eth_addr.addr_bytes[4], eth_addr.addr_bytes[5]); + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_stop + Description : stop the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_stop(netif_inst_t * inst) +{ + int i; + + /* stop slave NIC first */ + for (i = 0; i < inst->data.dpdk_if.slave_num; i++) + { + rte_eth_dev_stop(inst->data.dpdk_if.slave_port[i]); + NSHAL_LOGINF("stop slave port succ]port_id=%u, nic_name=%s", + inst->data.dpdk_if.slave_port[i], + inst->data.dpdk_if.nic_name); + } + rte_eth_dev_stop(inst->data.dpdk_if.port_id); + + NSHAL_LOGINF("stop port succ]port_id=%u, nic_name=%s", + inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_get_mtu + Description : get the port mtu + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC uint32_t dpdk_get_mtu(netif_inst_t * inst) +{ + uint32_t mtu; + + if (rte_eth_dev_get_mtu(inst->data.dpdk_if.port_id, (uint16_t *) & mtu)) + { + return 0; + } + + return mtu; +} + +/***************************************************************************** + Prototype : dpdk_get_macaddr + Description : get the port mac addr + Input : netif_inst_t* inst + void* mac_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_get_macaddr(netif_inst_t * inst, void *mac_addr) +{ + /*bond port */ + int primary_port = rte_eth_bond_primary_get(inst->data.dpdk_if.port_id); + if (0 <= primary_port) + { + rte_eth_macaddr_get((uint8_t) primary_port, + (struct ether_addr *) mac_addr); + + NSHAL_LOGDBG + ("primary_port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X", + primary_port, inst->data.dpdk_if.nic_name, + ((struct ether_addr *) mac_addr)->addr_bytes[0], + ((struct ether_addr *) mac_addr)->addr_bytes[1], + ((struct ether_addr *) mac_addr)->addr_bytes[2], + ((struct ether_addr *) mac_addr)->addr_bytes[3], + ((struct ether_addr *) mac_addr)->addr_bytes[4], + ((struct ether_addr *) mac_addr)->addr_bytes[5]); + } + /*normal port */ + else + { + rte_eth_macaddr_get(inst->data.dpdk_if.port_id, + (struct ether_addr *) mac_addr); + + NSHAL_LOGDBG + ("normal_port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X", + inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name, + ((struct ether_addr *) mac_addr)->addr_bytes[0], + ((struct ether_addr *) mac_addr)->addr_bytes[1], + ((struct ether_addr *) mac_addr)->addr_bytes[2], + ((struct ether_addr *) mac_addr)->addr_bytes[3], + ((struct ether_addr *) mac_addr)->addr_bytes[4], + ((struct ether_addr *) mac_addr)->addr_bytes[5]); + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_capa_convert + Description : convert format from dpdk to hal + Input : const struct rte_eth_dev_info* dev_info + hal_netif_capa_t* capa + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC inline void +dpdk_capa_convert(const struct rte_eth_dev_info *dev_info, + struct hal_netif_hw_feature *capa) +{ + int retVal = memset_s(capa, sizeof(struct hal_netif_hw_feature), 0, + sizeof(struct hal_netif_hw_feature)); + if (EOK != retVal) + { + NSHAL_LOGERR("MEMSET_S fail]retVal=%d", retVal); + } + + /* Set Rx checksum checking */ + if (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) + { + NSHAL_LOGINF("RX IP checksum offload supported."); + capa->rx_csum_ip = 1; + } + if ((dev_info->rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) && + (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) + { + NSHAL_LOGINF("RX L4 checksum offload supported."); + capa->rx_csum_l4 = 1; + } + if (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) + { + NSHAL_LOGINF("RX LRO supported."); + capa->rx_lro = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) + { + NSHAL_LOGINF("TX IP checksum offload supported."); + capa->tx_csum_ip = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) + { + NSHAL_LOGINF("TX UDP checksum offload supported."); + capa->tx_csum_udp = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) + { + NSHAL_LOGINF("TX TCP checksum offload supported."); + capa->tx_csum_tcp = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) + { + NSHAL_LOGINF("TSO is supported."); + capa->tx_tso = 1; + } + else + { + NSHAL_LOGINF("TSO is disabled."); + capa->tx_tso = 0; + } +} + +/***************************************************************************** + Prototype : dpdk_get_capability + Description : get the port capability + Input : netif_inst_t* inst + hal_netif_capa_t* capa + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_get_capability(netif_inst_t * inst, struct hal_netif_hw_feature *capa) +{ + struct rte_eth_dev_info dev_info; + + rte_eth_dev_info_get(inst->data.dpdk_if.port_id, &dev_info); + dpdk_capa_convert(&dev_info, capa); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_recv + Description : recv packet from the port + Input : netif_inst_t* inst + uint16_t queue_id + struct common_mem_mbuf** rx_pkts + uint16_t nb_pkts + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC uint16_t +dpdk_recv(netif_inst_t * inst, uint16_t queue_id, + void **rx_pkts, uint16_t nb_pkts) +{ + return hal_rte_eth_rx_burst(inst->data.dpdk_if.port_id, queue_id, + (struct rte_mbuf **) rx_pkts, nb_pkts); +} + +/***************************************************************************** + Prototype : dpdk_send + Description : send packet to the port + Input : netif_inst_t* inst + uint16_t queue_id + struct common_mem_mbuf** tx_pkts + uint16_t nb_pkts + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC uint16_t +dpdk_send(netif_inst_t * inst, uint16_t queue_id, + void **tx_pkts, uint16_t nb_pkts) +{ + return hal_rte_eth_tx_burst(inst->data.dpdk_if.port_id, queue_id, + (struct rte_mbuf **) tx_pkts, nb_pkts); +} + +/***************************************************************************** + Prototype : dpdk_link_status + Description : get link status form the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC uint32_t dpdk_link_status(netif_inst_t * inst) +{ + struct rte_eth_link eth_link; + + /* add log output when failed */ + int retVal = memset_s(ð_link, sizeof(struct rte_eth_link), 0, + sizeof(struct rte_eth_link)); + if (EOK != retVal) + { + NSHAL_LOGERR("MEMSET_S fail]retVal=%d", retVal); + } + + rte_eth_link_get(inst->data.dpdk_if.port_id, ð_link); + + return eth_link.link_status; +} + +/***************************************************************************** + Prototype : dpdk_stats_convert + Description : convert format from dpdk to hal + Input : const struct rte_eth_stats* rte_stats + hal_netif_stats_t* stats + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC inline void +dpdk_stats_convert(const struct rte_eth_stats *rte_stats, + hal_netif_stats_t * stats) +{ + int i; + + /* give fail error number when failed */ + int retVal = memset_s(stats, sizeof(hal_netif_stats_t), 0, + sizeof(hal_netif_stats_t)); + if (EOK != retVal) + { + NSHAL_LOGERR("MEMSET_S fail]retVal=%d", retVal); + } + + stats->ipackets = rte_stats->ipackets; + stats->opackets = rte_stats->opackets; + stats->ibytes = rte_stats->ibytes; + stats->obytes = rte_stats->obytes; + stats->imissed = rte_stats->imissed; + stats->ierrors = rte_stats->ierrors; + stats->oerrors = rte_stats->oerrors; + stats->rx_nombuf = rte_stats->rx_nombuf; + + for (i = 0; i < HAL_ETH_QUEUE_STAT_CNTRS; i++) + { + stats->q_ipackets[i] = rte_stats->q_ipackets[i]; + stats->q_opackets[i] = rte_stats->q_opackets[i]; + stats->q_ibytes[i] = rte_stats->q_ibytes[i]; + stats->q_obytes[i] = rte_stats->q_obytes[i]; + stats->q_errors[i] = rte_stats->q_errors[i]; + } +} + +/***************************************************************************** + Prototype : dpdk_stats + Description : get stats form the port + Input : netif_inst_t* inst + hal_netif_stats_t* stats + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_stats(netif_inst_t * inst, hal_netif_stats_t * stats) +{ + int ret; + struct rte_eth_stats rte_stats; + + ret = rte_eth_stats_get(inst->data.dpdk_if.port_id, &rte_stats); + if (ret == 0) + { + dpdk_stats_convert(&rte_stats, stats); + return 0; + } + + return -1; +} + +/***************************************************************************** + Prototype : dpdk_stats_reset + Description : reset stats to the port + Input : netif_inst_t* inst + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_stats_reset(netif_inst_t * inst) +{ + rte_eth_stats_reset(inst->data.dpdk_if.port_id); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_config + Description : config the port queue and ring + Input : netif_inst_t* inst + hal_netif_config_t* conf + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_config(netif_inst_t * inst, hal_netif_config_t * conf) +{ + uint32_t i; + + inst->data.dpdk_if.hw_vlan_filter = conf->bit.hw_vlan_filter; + inst->data.dpdk_if.hw_vlan_strip = conf->bit.hw_vlan_strip; + + inst->data.dpdk_if.rx_queue_num = conf->rx.queue_num; + /* fix Buffer Overflow type code-dex issue */ + if (inst->data.dpdk_if.rx_queue_num > HAL_ETH_MAX_QUEUE_NUM) + { + NSHAL_LOGERR + ("rx queue num error]rx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d", + inst->data.dpdk_if.rx_queue_num, HAL_ETH_MAX_QUEUE_NUM); + + return -1; + } + + for (i = 0; i < inst->data.dpdk_if.rx_queue_num; i++) + { + inst->data.dpdk_if.rx_ring_size[i] = conf->rx.ring_size[i]; + inst->data.dpdk_if.rx_pool[i] = + (struct rte_mempool *) conf->rx.ring_pool[i]; + } + + inst->data.dpdk_if.tx_queue_num = conf->tx.queue_num; + /* fix "FORTIFY.Out-of-Bounds_Read--Off-by-One" type codedex issue */ + if (inst->data.dpdk_if.tx_queue_num > HAL_ETH_MAX_QUEUE_NUM) + { + NSHAL_LOGERR + ("tx queue num error]rx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d", + inst->data.dpdk_if.tx_queue_num, HAL_ETH_MAX_QUEUE_NUM); + + return -1; + } + for (i = 0; i < inst->data.dpdk_if.tx_queue_num; i++) + { + inst->data.dpdk_if.tx_ring_size[i] = conf->tx.ring_size[i]; + } + + return 0; +} + +/***************************************************************************** + Prototype : dpdk_bond_config + Description : config the port for bond mode + Input : netif_inst_t* inst + uint8_t slave_num + netif_inst_t* slave_inst[] + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_bond_config(netif_inst_t * inst, uint8_t slave_num, + netif_inst_t * slave_inst[]) +{ + int ret; + uint32_t i, queue; + + inst->data.dpdk_if.slave_num = slave_num; + + for (i = 0; i < slave_num; i++) + { + inst->data.dpdk_if.slave_port[i] = + slave_inst[i]->data.dpdk_if.port_id; + + if (0 == i) + { + inst->data.dpdk_if.hw_vlan_filter = + slave_inst[i]->data.dpdk_if.hw_vlan_filter; + inst->data.dpdk_if.hw_vlan_strip = + slave_inst[i]->data.dpdk_if.hw_vlan_strip; + inst->data.dpdk_if.rx_queue_num = + slave_inst[i]->data.dpdk_if.rx_queue_num; + inst->data.dpdk_if.tx_queue_num = + slave_inst[i]->data.dpdk_if.tx_queue_num; + + /*will be used in function dpdk_get_queue_conf and dpdk_get_port_conf */ + ret = + strcpy_s(inst->data.dpdk_if.driver_name, + sizeof(inst->data.dpdk_if.driver_name), "bond"); + + if (EOK != ret) + { + NSHAL_LOGERR("STRCPY_S failed]ret=%d.", ret); + return -1; + } + + for (queue = 0; queue < HAL_ETH_MAX_QUEUE_NUM; queue++) + { + inst->data.dpdk_if.rx_pool[queue] = + slave_inst[i]->data.dpdk_if.rx_pool[queue]; + inst->data.dpdk_if.rx_ring_size[queue] = + slave_inst[i]->data.dpdk_if.rx_ring_size[queue]; + inst->data.dpdk_if.tx_ring_size[queue] = + slave_inst[i]->data.dpdk_if.tx_ring_size[queue]; + } + } + } + + return 0; + +} + +/***************************************************************************** + Prototype : dpdk_bond + Description : bond port + Input : netif_inst_t* inst + const char* bond_name + uint8_t slave_num + netif_inst_t* slave_inst[] + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_bond(netif_inst_t * inst, const char *bond_name, uint8_t slave_num, + netif_inst_t * slave_inst[]) +{ + int i, ret; + int port; + struct ether_addr eth_addr; + + /* check if all the slaves' drivers are same, not support different drivers */ + for (i = 1; i < slave_num; i++) + { + if (strncmp + (slave_inst[0]->data.dpdk_if.driver_name, + slave_inst[i]->data.dpdk_if.driver_name, + strlen(slave_inst[0]->data.dpdk_if.driver_name))) + { + NSHAL_LOGERR + ("dpdk does not support different types of network card]slave[0]=%s, slave[%i]=%s", + slave_inst[0]->data.dpdk_if.driver_name, i, + slave_inst[i]->data.dpdk_if.driver_name); + return -1; + } + } + + ret = dpdk_set_nic_name(inst, bond_name); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_set_nic_name fail]ret=%d", ret); + return -1; + } + + port = + rte_eth_bond_create(bond_name, BONDING_MODE_ACTIVE_BACKUP, + SOCKET_ID_0); + if (port < 0) + { + NSHAL_LOGERR("rte_eth_bond_create fail]ret=%i", ret); + return -1; + } + + ret = dpdk_set_port(inst, (uint8_t) port); + + if (ret < 0) + { + NSHAL_LOGERR("dpdk_set_port fail]ret=%i", ret); + return ret; + } + + ret = dpdk_bond_config(inst, slave_num, slave_inst); + + if (ret < 0) + { + NSHAL_LOGERR("dpdk_bond_config fail]ret=%i", ret); + return ret; + } + + ret = dpdk_setup_port(inst); + + if (ret < 0) + { + NSHAL_LOGERR("dpdk_setup_port fail]ret=%i", ret); + return ret; + } + + for (i = 0; i < slave_num; i++) + { + NSHAL_LOGINF("add slave port_id=%u, nic_name=%s", + slave_inst[i]->data.dpdk_if.port_id, + slave_inst[i]->data.dpdk_if.nic_name); + + if (rte_eth_bond_slave_add + ((uint8_t) port, slave_inst[i]->data.dpdk_if.port_id) == -1) + { + NSHAL_LOGERR("adding slave (%u) to bond (%u) failed]", + slave_inst[i]->data.dpdk_if.port_id, port); + return -1; + } + } + + rte_eth_macaddr_get(slave_inst[0]->data.dpdk_if.port_id, ð_addr); + + ret = rte_eth_bond_mac_address_set((uint8_t) port, ð_addr); + if (ret < 0) + { + NSHAL_LOGERR("rte_eth_bond_mac_address_set fail]ret=%i", ret); + return ret; + } + + ret = rte_eth_dev_start(inst->data.dpdk_if.port_id); + if (ret < 0) + { + NSHAL_LOGERR("rte_eth_dev_start fail]ret=%i, port_id=%d", ret, + inst->data.dpdk_if.port_id); + return ret; + } + + NSHAL_LOGINF("port_id=%d,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X", + port, + inst->data.dpdk_if.nic_name, + eth_addr.addr_bytes[0], + eth_addr.addr_bytes[1], + eth_addr.addr_bytes[2], + eth_addr.addr_bytes[3], + eth_addr.addr_bytes[4], eth_addr.addr_bytes[5]); + return 0; +} + +/***************************************************************************** + Prototype : dpdk_add_mcastaddr + Description : add mcastaddr to the port + Input : netif_inst_t* inst + void* mc_addr_set + void* mc_addr + uint32_t nb_mc_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int +dpdk_set_mcastaddr(netif_inst_t * inst, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr) +{ + uint8_t port = inst->data.dpdk_if.port_id; + int iRetVal; + + NSHAL_LOGINF("mc_addr_set number=%u", nb_mc_addr); + iRetVal = rte_eth_dev_set_mc_addr_list(port, mc_addr_set, nb_mc_addr); + if (iRetVal != 0) + { + NSHAL_LOGWAR("fail to set_mc_addr_list]port=%u,ret=%d", port, + iRetVal); + } + + return iRetVal; +} + +/***************************************************************************** + Prototype : dpdk_add_mac_addr + Description : add mcastaddr to the port + Input : netif_inst_t* inst + void* mc_addr + Output : None + Return Value : NSTACK_STATIC int + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_add_mac_addr(netif_inst_t * inst, void *mc_addr) +{ + uint8_t port = inst->data.dpdk_if.port_id; + int iRetVal; + + /* for MLX: set_mc_addr_list() is not callback, so call mac_addr_add() instead */ + iRetVal = rte_eth_dev_mac_addr_add(port, mc_addr, 0); + if (0 != iRetVal) + { + NSHAL_LOGWAR("fail to add_mac_addr]port=%u,ret=%d", port, iRetVal); + } + + return iRetVal; +} + +/***************************************************************************** + Prototype : dpdk_rmv_mac_addr + Description : remove mcastaddr to the port + Input : netif_inst_t* inst + void* mc_addr + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_rmv_mac_addr(netif_inst_t * inst, void *mc_addr) +{ + uint8_t port = inst->data.dpdk_if.port_id; + int iRetVal; + + /* for MLX: set_mc_addr_list() is not callback, so call mac_addr_remove() instead */ + iRetVal = rte_eth_dev_mac_addr_remove(port, mc_addr); + if (0 != iRetVal) + { + NSHAL_LOGWAR("fail to rmv_mac_addr]port=%u,ret=%d", port, iRetVal); + } + + return iRetVal; +} + +/***************************************************************************** + Prototype : dpdk_allmcast + Description : set allmcast mode to the port + Input : netif_inst_t* inst + uint8_t enable + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_allmcast(netif_inst_t * inst, uint8_t enable) +{ + if (enable) + { + rte_eth_allmulticast_enable(inst->data.dpdk_if.port_id); + } + else + { + rte_eth_allmulticast_disable(inst->data.dpdk_if.port_id); + } + + return 0; +} + +const netif_ops_t dpdk_netif_ops = { + .name = "dpdk", + .init_global = dpdk_init_global, + .init_local = dpdk_init_local, + .open = dpdk_open, + .close = dpdk_close, + .start = dpdk_start, + .stop = dpdk_stop, + .bond = dpdk_bond, + .mtu = dpdk_get_mtu, + .macaddr = dpdk_get_macaddr, + .capability = dpdk_get_capability, + .recv = dpdk_recv, + .send = dpdk_send, + .link_status = dpdk_link_status, + .stats = dpdk_stats, + .stats_reset = dpdk_stats_reset, + .config = dpdk_config, + .mcastaddr = dpdk_set_mcastaddr, + .add_mac = dpdk_add_mac_addr, + .rmv_mac = dpdk_rmv_mac_addr, + .allmcast = dpdk_allmcast +}; + +HAL_IO_REGISTER(dpdk, &dpdk_netif_ops); diff --git a/stacks/lwip_stack/src/mem/CMakeLists.txt b/stacks/lwip_stack/src/mem/CMakeLists.txt new file mode 100644 index 0000000..eb4e0b5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/CMakeLists.txt @@ -0,0 +1,36 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +endif() + + +FILE(GLOB_RECURSE MEM *.c) +ADD_LIBRARY(nsfw_mem STATIC ${MEM}) +ADD_DEPENDENCIES(nsfw_mem GLOG) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${PAL_H_DIRECTORIES} + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include + nsfw_shmem/ + include/ + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/nsfw_nshmem/ +) diff --git a/stacks/lwip_stack/src/mem/include/common_mem_memzone.h b/stacks/lwip_stack/src/mem/include/common_mem_memzone.h new file mode 100644 index 0000000..20e18c2 --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_mem_memzone.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMZONE_H_ +#define _COMMON_MEM_MEMZONE_H_ + +#ifdef HAL_LIB +#else +#include "rte_memzone.h" +#endif + +#endif /* _COMMON_MEM_MEMZONE_H_ */ diff --git a/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h b/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h new file mode 100644 index 0000000..086460c --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h @@ -0,0 +1,204 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_PAL_BITWIDE_ADJUST_H_ +#define _COMMON_PAL_BITWIDE_ADJUST_H_ + +#ifdef HAL_LIB +#include "pal_bitwide_adjust.h" +#else +#define MODULE(name) (1) + +#include "common_mem_common.h" + +#include "common_func.h" + +#define ALIGN_SIZET(size) ((uint64_t)(size)) +#define ALIGN_PTR(PTR) ((uint64_t)(PTR)) + +extern struct common_mem_memseg *g_PMemSegArry; +extern void **g_LMegAddrArry; + +/*get Local Seg addr by segIdx*/ +#define HMEM_SEG_LVADDR(segid) (g_LMegAddrArry[segid]) +/*get SegIDX by PrimSegAddr, just get the array Idx of g_PMemSegArry*/ +#define HMEM_SEGID(segaddr) ((struct common_mem_memseg*)segaddr - &(g_PMemSegArry[0])) + +/***************************************************************** +Parameters : LMegAddrArry[] Local common_mem_memseg addr Array + SegNum common_mem_memseg Num. +Return : +Description : init g_PrimAddr2LocalMap g_LocalAddr2PrimMap while the process start +*****************************************************************/ +void *pal_shddr_to_laddr(uint64_t shaddr); +uint64_t pal_laddr_to_shddr(void *laddr); +int dmm_pal_addr_align(); +void *shmem_shddr_to_laddr(void *addr); +uint64_t shmem_laddr_to_shddr(void *addr); + +extern int g_PrimSameFlg; + +/* if __NSTACK_MAIN__ is defined, no need do addr trans*/ +#ifndef __NSTACK_MAIN__ +/* g_PrimSameFlg check should be done before calling cast functions */ + +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) (g_PrimSameFlg ? ((void*) (addr)) : pal_shddr_to_laddr((uint64_t)(addr))) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) (g_PrimSameFlg ? ((uint64_t)(addr)) : pal_laddr_to_shddr((void*)(addr))) + +#define PTR_SHTOL(type, addr) ((type)ADDR_SHTOL(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#else +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) ((void*)(addr)) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) ((uint64_t)(addr)) + +#define PTR_SHTOL(type, addr) ((type)(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#endif + +#if MODULE("list") +#define COMMON_LIST_INSERT_HEAD(lhead, lelm, field) do { \ + if (((lelm)->field.le_next_align = (lhead)->lh_first_align) != ((typeof((lhead)->lh_first_align))(long)NULL)) \ + ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align))->field.le_prev_align = \ + ADDR_LTOSH(&(lelm)->field.le_next); \ + (lhead)->lh_first_align = ADDR_LTOSH(lelm); \ + (lelm)->field.le_prev_align = ADDR_LTOSH(&(lhead)->lh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_REMOVE(lelm, field) do { \ + if ((lelm)->field.le_next_align != ((typeof((lelm)->field.le_next_align))ALIGN_PTR(NULL))) \ + ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align))->field.le_prev_align = \ + (lelm)->field.le_prev_align; \ + if (EOK != (MEMCPY_S((typeof((lelm)->field.le_prev))ADDR_SHTOL((lelm)->field.le_prev_align), \ + sizeof((lelm)->field.le_next_align), \ + &((lelm)->field.le_next_align), \ + sizeof((lelm)->field.le_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + return;\ + }\ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_EMPTY(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align) == NULL) +#define COMMON_LIST_FIRST(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align)) +#define COMMON_LIST_NEXT(lelm, field) ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align)) + +#endif + +#if MODULE("tailq") + +#define COMMON_TAILQ_INSERT_TAIL(lhead, lelm, field) do { \ + (lelm)->field.tqe_next_align = (typeof((lelm)->field.tqe_next_align))NULL; \ + (lelm)->field.tqe_prev_align = (lhead)->tqh_last_align; \ + typeof((lhead)->tqh_last_align) tempelm = ADDR_LTOSH(lelm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lhead)->tqh_last_align), sizeof(tempelm), &tempelm, sizeof(tempelm)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (lhead)->tqh_last_align = ADDR_LTOSH(&(lelm)->field.tqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_TAILQ_FOREACH(lvar, lhead, field) \ + for ((lvar) = (typeof(lvar))ADDR_SHTOL((lhead)->tqh_first_align); \ + (lvar); \ + (lvar) = (typeof(lvar))ADDR_SHTOL((lvar)->field.tqe_next_align)) + +#define COMMON_TAILQ_REMOVE(lhead, lelm, field) do { \ + if (((lelm)->field.tqe_next_align) != (typeof((lelm)->field.tqe_next_align))NULL) \ + ((typeof((lelm)->field.tqe_next))ADDR_SHTOL((lelm)->field.tqe_next_align))->field.tqe_prev_align = \ + (lelm)->field.tqe_prev_align; \ + else \ + (lhead)->tqh_last_align = (lelm)->field.tqe_prev_align; \ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lelm)->field.tqe_prev_align), \ + sizeof((lelm)->field.tqe_next_align), \ + &((lelm)->field.tqe_next_align), \ + sizeof((lelm)->field.tqe_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + } while (/*CONSTCOND*/0) + +/* + * Tail queue functions. + */ +#define COMMON_TAILQ_INIT(head) do { \ + (head)->tqh_first_align = (typeof((head)->tqh_first_align))NULL; \ + (head)->tqh_last_align = ADDR_LTOSH(&(head)->tqh_first); \ + } while (/*CONSTCOND*/0) + +/* + * Tail queue access methods. + */ +#define COMMON_TAILQ_EMPTY(head) ((head)->tqh_first_align == (typeof((head)->tqh_first_align))NULL) +#define COMMON_TAILQ_FIRST(head) ((typeof((head)->tqh_first))ADDR_SHTOL((head)->tqh_first_align)) +#define COMMON_TAILQ_NEXT(elm, field) ((typeof((elm)->field.tqe_next))ADDR_SHTOL((elm)->field.tqe_next_align)) + +#endif + +#if MODULE("stailq") +/* +* Singly-linked Tail queue functions. +*/ +#define COMMON_STAILQ_INIT(head) do { \ + (head)->stqh_first_align = ALIGN_PTR(NULL); \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next_align = ALIGN_PTR(NULL); \ + typeof((head)->stqh_last_align) telm = ADDR_LTOSH(elm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((head)->stqh_last_align), sizeof(telm), &telm, sizeof(telm))))\ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (head)->stqh_last_align = ADDR_LTOSH(&(elm)->field.stqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first_align = \ + ((typeof((head)->stqh_first))ADDR_SHTOL((head)->stqh_first_align))->field.stqe_next_align) == \ + (PTR_ALIGN_TYPE)NULL) \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_FOREACH(var, head, field) \ + for ((var) = ADDR_SHTOL((head)->stqh_first_align); \ + (var); \ + (var) = ADDR_SHTOL((var)->field.stqe_next_align)) + +/* +* Singly-linked Tail queue access methods. +*/ + +#define COMMON_STAILQ_EMPTY(head) ((head)->stqh_first_align == (PTR_ALIGN_TYPE)NULL) + +#define COMMON_STAILQ_FIRST(head) (ADDR_SHTOL((head)->stqh_first_align)) + +#define COMMON_STAILQ_NEXT(elm, field) (ADDR_SHTOL((elm)->field.stqe_next_align)) +#endif + +#endif + +#endif diff --git a/stacks/lwip_stack/src/mem/include/common_sys_config.h b/stacks/lwip_stack/src/mem/include/common_sys_config.h new file mode 100644 index 0000000..736c47b --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_sys_config.h @@ -0,0 +1,46 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_SYS_CONFIG_H_ +#define __COMMON_SYS_CONFIG_H_ + +/* Below compile macro is used only in UT makefile */ +#if (HAL_LIB) +#else +#undef RTE_CACHE_LINE_SIZE +#define RTE_CACHE_LINE_SIZE 64 /* RTE_CACHE_LINE_SIZE */ +#undef RTE_MAX_LCORE +#define RTE_MAX_LCORE 128 /* RTE_MAX_LCORE */ +#undef RTE_MAX_NUMA_NODES +#define RTE_MAX_NUMA_NODES 8 /* RTE_MAX_NUMA_NODES */ +#undef RTE_MAX_MEMSEG +#define RTE_MAX_MEMSEG 256 /* RTE_MAX_MEMSEG */ +#undef RTE_MAX_MEMZONE +#define RTE_MAX_MEMZONE 2560 /* RTE_MAX_MEMZONE */ +#undef RTE_MAX_TAILQ +#define RTE_MAX_TAILQ 32 /* RTE_MAX_TAILQ */ +#undef RTE_ARCH_X86 +#define RTE_ARCH_X86 1 /* RTE_ARCH_64 */ +#undef RTE_ARCH_64 +#define RTE_ARCH_64 1 /* RTE_ARCH_64 */ +#undef RTE_PKTMBUF_HEADROOM +#define RTE_PKTMBUF_HEADROOM 128 /* RTE_PKTMBUF_HEADROOM */ +#undef RTE_MEMPOOL_CACHE_MAX_SIZE +#define RTE_MEMPOOL_CACHE_MAX_SIZE 512 /* RTE_MEMPOOL_CACHE_MAX_SIZE */ + +#endif + +#endif // __COMMON_SYS_CONFIG_H_ diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c new file mode 100644 index 0000000..453f33f --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c @@ -0,0 +1,163 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "common_mem_api.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "common_func.h" +#include "pid_common.h" + +void sys_sem_init_v2(sys_sem_t_v2 sem) +{ + sem->locked = 1; +} + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void) +{ + struct timespec now; + + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &now))) + { + NSRTP_LOGERR("Failed to get time, errno = %d", errno); + } + + return 1000 * now.tv_sec + now.tv_nsec / 1000000; +} + +long sys_jiffies(void) +{ + return sys_now(); +} + +err_t sys_sem_new_v2(sys_sem_t_v2 * sem, u8_t isUnLockd) +{ + int retVal; + if (!sem) + { + return -1; + } + *sem = malloc(sizeof(common_mem_spinlock_t)); + + if (NULL == *sem) + { + return -1; + } + else + { + retVal = + memset_s(*sem, sizeof(common_mem_spinlock_t), 0, + sizeof(common_mem_spinlock_t)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + free(*sem); + *sem = NULL; + return -1; + } + common_mem_spinlock_init(*sem); + } + + if (!isUnLockd) + { + common_mem_spinlock_lock(*sem); + } + + return 0; +} + +void sys_sem_free_v2(sys_sem_t_v2 * sem) +{ + if ((sem != NULL) && (*sem != NULL)) + { + free(*sem); + *sem = NULL; + } + else + { + } +} + +void sys_sem_signal_v2(sys_sem_t_v2 * sem) +{ + common_mem_spinlock_unlock(*sem); +} + +void sys_sem_signal_s_v2(sys_sem_t_v2 sem) +{ + common_mem_spinlock_unlock(sem); +} + +u32_t sys_arch_sem_trywait_v2(sys_sem_t_v2 * sem) +{ + return (u32_t) common_mem_spinlock_trylock(*sem); +} + +u32_t sys_arch_sem_wait_v2(sys_sem_t_v2 * pstsem) +{ + common_mem_spinlock_lock(*pstsem); + return 0; +} + +u32_t sys_arch_sem_wait_s_v2(sys_sem_t_v2 sem) +{ + common_mem_spinlock_lock(sem); + return 0; +} + +/***************************************************************************** +* Prototype : get_pid_namespace +* Description : Get namespace of pid +* Input : uint32_t pid +* Output : None +* Return Value : uint64_t +* Calls : +* Called By : +*****************************************************************************/ +uint64_t get_pid_namespace(pid_t pid) +{ + char buf[BUF_SIZE_FILEPATH] = { 0 }; + char path[BUF_SIZE_FILEPATH] = { 0 }; + const char *pstart; + int ret = 0; + if (!pid) + { + NSSOC_LOGERR("Pid is zero!"); + return 0; + } + + ret = + snprintf_s(path, sizeof(path), sizeof(path) - 1, "/proc/%d/ns/pid", + pid); + if (-1 == ret) + { + NSSOC_LOGERR("SNPRINTF_S failed]ret=%d", ret); + return 0; + } + + ret = readlink(path, buf, sizeof(buf) - 1); + if (ret <= (int) sizeof(STR_PID)) + { + NSSOC_LOGERR("readlink pid ns file error]ret=%d", ret); + return 0; + } + + buf[ret - 1] = 0; + pstart = &(buf[sizeof(STR_PID)]); + return strtoull(pstart, NULL, 10); +} diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c new file mode 100644 index 0000000..98983d5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c @@ -0,0 +1,299 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_mem_base_type.h" + +#include "common_mem_common.h" + +#include "common_mem_memzone.h" + +#include "common_mem_mempool.h" +#include "common_mem_buf.h" + +#include "nstack_log.h" +#include "nstack_securec.h" + +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +#define LOG_ERR 0 +#define LOG_WARN 1 +#define LOG_INFO 2 +#define LOG_DEBUG 3 +#define LOG_MAX 4 + +#define COMMON_LOG_PRINT(level, fmt, args...) \ + if (level <= log_level) NSRTP_LOGERR("===>[COMMON]"fmt, ##args); \ + +#define COMMON_PANIC(fmt) \ + NSRTP_LOGERR("==>[COMMON_PANIC]"fmt); \ + common_dump_stack(); \ + +#define PARA1_SET(argv, tempargv, Index, para1) do {\ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para1);\ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PARA2_SET(argv, tempargv, Index, para1, para2) do {\ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para1); \ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index++; \ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para2); \ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PATA_STRLENT 64 +#define PATA_NUM_MAX 12 + +int log_level = LOG_INFO; + +int +nscomm_pal_module_init(nsfw_mem_para * para, + common_mem_pal_module_info * pinfo, u8 app_mode) +{ + char tempargv[PATA_NUM_MAX][PATA_STRLENT]; + char *argv[PATA_NUM_MAX]; + char tempbuf[PATA_STRLENT]; + unsigned int Index = 0; + int ioffset = 0; + int agindex = 0; + int intmask = 0; + int retVal; + char name[10] = { '\0' }; + + if (para == NULL) + { + NSRTP_LOGERR("para is null"); + return DMM_MBUF_RET_ERR; + } + + retVal = memset_s(tempargv, sizeof(tempargv), '\0', sizeof(tempargv)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = memset_s(argv, sizeof(argv), 0, sizeof(argv)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + if (NSFW_PROC_MAIN == para->enflag) + { + if (para->iargsnum != 0) + { + if (common_mem_pal_init(para->iargsnum, para->pargs) < 0) + { + COMMON_LOG_PRINT(LOG_ERR, "Cannot init pal\r\n"); + return DMM_MBUF_RET_ERR; + } + else + { + return DMM_MBUF_RET_OK; + } + } + + PARA1_SET(argv, tempargv, agindex, "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "-c", "0x1"); + PARA2_SET(argv, tempargv, agindex, "-n", "4"); + PARA1_SET(argv, tempargv, agindex, "--huge-dir=/mnt/nstackhuge"); + PARA1_SET(argv, tempargv, agindex, "--proc-type=primary"); + + if (app_mode == 1) + { + sprintf(name, "dmm_app_%ld", (long) getpid()); + PARA2_SET(argv, tempargv, agindex, "--file-prefix", name); + PARA1_SET(argv, tempargv, agindex, "--no-pci"); + + // TODO: the size of the memory should not be fixed + PARA2_SET(argv, tempargv, agindex, "-m", "32"); + } + else + { + // TODO: replay the name 'nStackMain' + /* snprintf(name, 10, "dmm_main_%ld", (long) getpid()); */ + PARA2_SET(argv, tempargv, agindex, "--file-prefix", "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "-m", "2048"); + } + + } + else + { + PARA1_SET(argv, tempargv, agindex, "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "--file-prefix", "nStackMain"); + + retVal = sprintf_s(tempbuf, PATA_STRLENT, "0x"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = retVal; + for (Index = 0; Index < LCORE_MASK_MAX; Index++) + { + if (ioffset >= PATA_STRLENT) + { + NSRTP_LOGERR("SPRINTF_S tempbuf overflow]ioffset=%d", + ioffset); + return DMM_MBUF_RET_ERR; + } + retVal = + sprintf_s(&(tempbuf[ioffset]), PATA_STRLENT - ioffset, "%8u", + pinfo->ilcoremask[Index]); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = ioffset + retVal; + intmask |= pinfo->ilcoremask[Index]; + } + if (0 == intmask) + { + PARA2_SET(argv, tempargv, agindex, "-c", "0x1"); + } + else + { + PARA2_SET(argv, tempargv, agindex, "-c", tempbuf); + } + if (pinfo->ishare_mem_size > 0) + { + retVal = memset_s(tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "%d", + pinfo->ishare_mem_size); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + PARA2_SET(argv, tempargv, agindex, "-m", tempbuf); + } + + retVal = memset_s(tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + + switch (pinfo->ucproctype) + { + case DMM_PROC_T_PRIMARY: + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=primary"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_SECONDARY: + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=secondary"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_AUTO: + default: + retVal = sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=auto"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + } + PARA1_SET(argv, tempargv, agindex, tempbuf); + + if (DMM_HUGTBL_DISABLE == pinfo->uchugeflag) + { + PARA1_SET(argv, tempargv, agindex, "--no-huge"); + } + } + if (common_mem_pal_init(agindex, argv) < 0) + { + COMMON_LOG_PRINT(LOG_ERR, "Cannot init pal\r\n"); + return DMM_MBUF_RET_ERR; + } + return DMM_MBUF_RET_OK; +} + +void *nscomm_memzone_data_reserve_name(const char *name, size_t len, + int socket_id) +{ + const struct common_mem_memzone *mz = NULL; + /* + rte_memzone_reserve must Call first, cause rte_memzone_reserve has a globe lock. + while proc race happen, who(calls A) got lock first will create memzone success. + others create same memzone proc will got lock after A, and rte_memzone_reserve return NULL; + so while rte_memzone_reserve return NULL we need do rte_memzone_lookup; + */ + mz = common_mem_memzone_reserve(name, len, socket_id, 0); + if (mz == NULL) + { + mz = common_mem_memzone_lookup(name); + } + + return mz ? (void *) ADDR_SHTOL(mz->addr_64) : NULL; +} + +void *nscomm_memzone_data_lookup_name(const char *name) +{ + void *addr = NULL; + const struct common_mem_memzone *mz = NULL; + mz = common_mem_memzone_lookup(name); + if (mz == NULL) + { + return NULL; + } + addr = (void *) ADDR_SHTOL(mz->addr_64); + return addr; +} diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c new file mode 100644 index 0000000..6dd3d13 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c @@ -0,0 +1,211 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_mem_pal_memconfig.h" +#include "common_mem_mbuf.h" +#include "common_mem_common.h" +#include "nstack_log.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_func.h" + +#include "nstack_securec.h" + +#define COMMON_PROCESS_MAPS "/proc/self/maps" + +int g_PrimSameFlg = 1; + +NSTACK_STATIC void **g_PrimAddr2LocalMap = NULL; +NSTACK_STATIC void *g_LocalBaseAddr = NULL; +NSTACK_STATIC void *g_LocalMaxAddr = NULL; +NSTACK_STATIC void *g_LocalCfgAddrBase = NULL; + +NSTACK_STATIC uint64_t *g_LocalAddr2PrimMap = NULL; +NSTACK_STATIC uint64_t g_PrimBaseAddr = 0; +NSTACK_STATIC uint64_t g_PrimMaxAddr = 0; +NSTACK_STATIC uint64_t g_PrimCfgAddrBase = 0; + +NSTACK_STATIC uint64_t g_LBitMask = 0; +NSTACK_STATIC int g_LBitMaskLen = 0; + +uint64_t pal_laddr_to_shddr(void *LAddr) +{ + size_t l2pIdx; + + if (g_PrimSameFlg || LAddr == NULL) + { + return (uint64_t) LAddr; + } + + /*calculate the IDX */ + l2pIdx = (ALIGN_PTR(LAddr) - ALIGN_PTR(g_LocalBaseAddr)) >> g_LBitMaskLen; + + /*check the Hugepage Addr Rang */ + if (LAddr <= g_LocalMaxAddr && LAddr >= g_LocalBaseAddr + && g_LocalAddr2PrimMap[l2pIdx]) + { + return g_LocalAddr2PrimMap[l2pIdx] + (ALIGN_PTR(LAddr) & g_LBitMask); + } + + /*check the Cfg Mapping Addr Rang */ + if (LAddr >= g_LocalCfgAddrBase + && LAddr <= + (void *) ((char *) g_LocalCfgAddrBase + + sizeof(struct common_mem_mem_config))) + { + return g_PrimCfgAddrBase + ((char *) LAddr - + (char *) g_LocalCfgAddrBase); + } + + NSRTP_LOGWAR + ("WARNING!!! Input invalid LAddr]LAddr=%p, g_LocalBaseAddr=%p, g_LocalMaxAddr=%p, g_LocalCfgAddrBase=%p, g_LocalCfgAddrMax=%p.", + LAddr, g_LocalBaseAddr, g_LocalMaxAddr, g_LocalCfgAddrBase, + (char *) g_LocalCfgAddrBase + sizeof(struct common_mem_mem_config)); + + return (uint64_t) LAddr; +} + +void *pal_shddr_to_laddr(uint64_t PAddr) +{ + size_t p2lIdx; + + if (g_PrimSameFlg || PAddr == ALIGN_PTR(NULL)) + { + return (void *) PAddr; + } + + p2lIdx = (PAddr - g_PrimBaseAddr) >> g_LBitMaskLen; + /*check the Hugepage Addr Rang */ + if (PAddr <= g_PrimMaxAddr && PAddr >= g_PrimBaseAddr + && g_PrimAddr2LocalMap[p2lIdx]) + { + return (void *) ((uint64_t) g_PrimAddr2LocalMap[p2lIdx] + + (PAddr & g_LBitMask)); + } + + /*check the Cfg Mapping Addr Rang */ + if (PAddr >= g_PrimCfgAddrBase + && PAddr <= g_PrimCfgAddrBase + sizeof(struct common_mem_mem_config)) + { + return (void *) ((uint64_t) g_LocalCfgAddrBase + PAddr - + g_PrimCfgAddrBase); + } + + NSRTP_LOGWAR + ("WARNING!!! Input invalid PAddr]PAddr=%lx, g_PrimBaseAddr=%lx, g_PrimMaxAddr=%lx, g_PrimCfgAddrBase=%lx, g_PrimCfgAddrMax=%lx.", + PAddr, g_PrimBaseAddr, g_PrimMaxAddr, g_PrimCfgAddrBase, + g_PrimCfgAddrBase + sizeof(struct common_mem_mem_config)); + + return (void *) PAddr; +} + +/*lint +e539 */ + +int dmm_pal_addr_align() +{ + return g_PrimSameFlg; +} + +int32_t +dmm_pktmbuf_pool_iterator(struct common_mem_mempool * mp, uint32_t start, + uint32_t end, dmm_mbuf_item_fun fun, void *argv) +{ + if (NULL == mp || fun == NULL) + { + return 0; + } + + if (start >= mp->size || end <= start) + { + return 0; + } + + int32_t elm_size = mp->elt_size + mp->header_size + mp->trailer_size; + struct common_mem_mbuf *elm_mbuf = (struct common_mem_mbuf *) (STAILQ_FIRST(&mp->mem_list)->addr + start * elm_size + mp->header_size); /*lint !e647 */ + + uint32_t i; + uint32_t mbuf_end = COMMON_MEM_MIN(end, mp->size) - start; + for (i = 0; i < mbuf_end; i++) + { + (void) fun(elm_mbuf, argv); + elm_mbuf = (struct common_mem_mbuf *) ((char *) elm_mbuf + elm_size); + } + + return mbuf_end; +} + +void dmm_addr_print(void) +{ + const struct common_mem_mem_config *mcfg = + common_mem_pal_get_configuration()->mem_config; + int s; + FILE *fd; + char *ptembuf = NULL; + if (!mcfg) + { + NSRTP_LOGERR("mcfg is null"); + return; + } + /*printf base address */ + NSRTP_LOGINF("********master baseaddr begin***************"); + for (s = 0; s < COMMON_MEM_MAX_MEMSEG; ++s) + { + if ((mcfg->memseg[s].len > 0) && (mcfg->memseg[s].addr != 0)) + { + NSRTP_LOGINF("addr:%p, len:%u", mcfg->memseg[s].addr, + mcfg->memseg[s].len); + } + } + NSRTP_LOGINF("********master baseaddr end***************"); + + fd = fopen(COMMON_PROCESS_MAPS, "r"); + if (!fd) + { + NSRTP_LOGERR("/proc/self/maps open fail, erro:%d", errno); + return; + } + + ptembuf = (char *) malloc(BUFSIZ); + if (!ptembuf) + { + NSRTP_LOGERR("malloc buff failed]buff_len=%d", BUFSIZ); + fclose(fd); + return; + } + if (EOK != memset_s(ptembuf, BUFSIZ, 0, BUFSIZ)) + { + NSRTP_LOGERR("MEMSET_S failed] buff=%p", ptembuf); + } + NSRTP_LOGINF("********self process addr space begin***************"); + while (fgets(ptembuf, BUFSIZ, fd) != NULL) + { + NSRTP_LOGERR("%s", ptembuf); + } + NSRTP_LOGINF("********self process addr space end*****************"); + fclose(fd); + free(ptembuf); + return; +} + +void *shmem_shddr_to_laddr(void *addr) +{ + return ADDR_SHTOL(addr); +} + +uint64_t shmem_laddr_to_shddr(void *addr) +{ + return ADDR_LTOSH(addr); +} diff --git a/stacks/lwip_stack/src/mem/lwip_mem_api.c b/stacks/lwip_stack/src/mem/lwip_mem_api.c new file mode 100644 index 0000000..72dd9e5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lwip_mem_api.c @@ -0,0 +1,86 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include "nsfw_mem_api.h" +#include "nstack_securec.h" +#include "nsfw_ring_data.h" +#include "nsfw_init_api.h" +#include "nsfw_shmem_mng.h" + +#define NSFW_MEM_MBUF_CHECK_RET_ERR(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSRTP_LOGERR("input para error]desc=%s,mhandle=%p,mtype=%d", desc, mhandle, entype); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_MBUF_CHECK_RET_NULL(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSRTP_LOGERR("input para error]desc=%s,mhandle=%p,mtype=%d", desc, mhandle, entype); \ + return NULL; \ + } \ + } + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_alloc +* Description : alloc a mbuf from mbuf pool +* Input : mpool_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : mbuf_handle +* Calls : +* Called By : +*****************************************************************************/ +mbuf_handle nsfw_mem_mbf_alloc(mpool_handle mhandle, nsfw_mem_type entype) +{ + if (entype == NSFW_SHMEM) + { + return nsfw_shmem_mbfalloc(mhandle); + } + + NSPOL_LOGINF(NS_LOG_STACKPOOL_ON, "mbf alloc fail] handle=%p, type=%d", + mhandle, entype); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_free +* Description : put a mbuf backintp mbuf pool +* Input : mbuf_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_mem_mbf_free(mbuf_handle mhandle, nsfw_mem_type entype) +{ + if (entype == NSFW_SHMEM) + { + return nsfw_shmem_mbffree(mhandle); + } + + NSPOL_LOGINF(NS_LOG_STACKPOOL_ON, "mbf free fail] handle=%p, type=%d", + mhandle, entype); + return NSFW_MEM_ERR; + +} diff --git a/stacks/lwip_stack/src/mem/lwip_mem_desc.c b/stacks/lwip_stack/src/mem/lwip_mem_desc.c new file mode 100644 index 0000000..217649a --- /dev/null +++ b/stacks/lwip_stack/src/mem/lwip_mem_desc.c @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "nsfw_mem_api.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_nshmem_ring.h" + +/* *INDENT-OFF* */ +nsfw_ring_ops g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX] = { + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_singlethread_dequeuev + } + }, + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_singlethread_dequeuev + } + } +}; +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c new file mode 100644 index 0000000..1be5f82 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c @@ -0,0 +1,44 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_api.h" +#include "nsfw_nshmem_mng.h" +#include "nsfw_nshmem_mdesc.h" + +/*no share memory access inferface*/ +nsfw_mem_ops g_nshmem_ops = { + nsfw_nshmem_init, + nsfw_nshmem_destory, + nsfw_nshmem_create, + NULL, + nsfw_nshmem_lookup, + nsfw_nshmem_release, + NULL, + NULL, + NULL, + NULL, + nsfw_nshmem_spcreate, + NULL, + NULL, + nsfw_nshmem_sprelease, + nsfw_nshmem_sp_lookup, + nsfw_nshmem_ringcreate, + NULL, + nsfw_nshmem_ringrelease, + nsfw_nshmem_static, + NULL, /*mem_ops_sp_iterator */ + NULL, /*mem_ops_mbuf_iterator */ +}; diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h new file mode 100644 index 0000000..1b63520 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MDESC_H +#define _NSFW_NSHMEM_MDESC_H + +extern nsfw_mem_ops g_nshmem_ops; + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c new file mode 100644 index 0000000..a3c7f60 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c @@ -0,0 +1,529 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_mem_api.h" +#include "nsfw_ring_fun.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_nshmem_mng.h" + +#include "common_func.h" + +#define nsfw_get_glb_lock() (&g_nshmem_internal_cfg->mlock) + +#define NSFW_NSHMEM_INIT_CHK_RET_NULL() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSRTP_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NULL; \ + } + +#define NSFW_NSHMEM_INIT_CHK_RET() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSRTP_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NSFW_MEM_ERR; \ + } + +nsfw_mem_localdata *g_nshmem_localdata = NULL; +nsfw_nshmem_cfg *g_nshmem_internal_cfg = NULL; + +/*look up a mem zone*/ +NSTACK_STATIC inline nsfw_nshmem_mzone *nsfw_nshmem_get_free_zone(void) +{ + int icnt = 0; + + /*g_nshmem_internal_cfg must not be null if come here */ + for (icnt = 0; icnt < COMMON_MEM_MAX_MEMZONE; icnt++) + { + if (g_nshmem_internal_cfg->amemzone[icnt].addr == NULL) + { + return &g_nshmem_internal_cfg->amemzone[icnt]; + } + } + + return NULL; +} + +NSTACK_STATIC inline void nsfw_nshmem_free_zone(nsfw_nshmem_mzone * pzone) +{ + nsfw_nshmem_mzone *pzonebase = &g_nshmem_internal_cfg->amemzone[0]; + nsfw_nshmem_mzone *pzoneend = + &g_nshmem_internal_cfg->amemzone[NSFW_NSHMEM_ZONE_MAX - 1]; + + if ((((int) ((char *) pzone - (char *) pzonebase) < 0) + || ((int) ((char *) pzone - (char *) pzoneend) > 0)) + && ((unsigned int) ((char *) pzone - (char *) pzonebase) % + sizeof(nsfw_nshmem_mzone) != 0)) + { + NSRTP_LOGERR("nshmem free fail] mem=%p", pzone); + return; + } + if (pzone->addr) + { + free(pzone->addr); + } + pzone->addr = NULL; + + int ret = memset_s((void *) pzone, sizeof(nsfw_nshmem_mzone), 0, + sizeof(nsfw_nshmem_mzone)); + if (EOK != ret) + { + NSRTP_LOGERR("MEMSET_S failed] mem=%p, ret=%d", pzone, ret); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_init +* Description : nsh module init +* Input : nsfw_mem_para* para +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 nsfw_nshmem_init(nsfw_mem_para * para) +{ + i32 iret = NSFW_MEM_OK; + NSRTP_LOGINF("nsfw nshmem init begin"); + g_nshmem_localdata = + (nsfw_mem_localdata *) malloc(sizeof(nsfw_mem_localdata)); + + if (NULL == g_nshmem_localdata) + { + NSRTP_LOGERR("nshmem init g_nshmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + memset_s(g_nshmem_localdata, sizeof(nsfw_mem_localdata), 0, + sizeof(nsfw_mem_localdata)); + + if (EOK != iret) + { + NSRTP_LOGERR("nshmem init g_nshmem_localdata MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_internal_cfg = + (nsfw_nshmem_cfg *) malloc(sizeof(nsfw_nshmem_cfg)); + + if (NULL == g_nshmem_internal_cfg) + { + NSRTP_LOGERR("nshmem init g_nshmem_internal_cfg malloc fail"); + goto ERROR; + } + + iret = + memset_s(g_nshmem_internal_cfg, sizeof(nsfw_nshmem_cfg), 0, + sizeof(nsfw_nshmem_cfg)); + + if (EOK != iret) + { + NSRTP_LOGERR("nshmem init g_nshmem_internal_cfg MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_localdata->enflag = para->enflag; + NSRTP_LOGINF("nsfw nshmem init end"); + goto OK; + + ERROR: + iret = NSFW_MEM_ERR; + nsfw_nshmem_destory(); + return iret; + OK: + iret = NSFW_MEM_OK; + return iret; +} + +/* + * memory destory + */ +void nsfw_nshmem_destory(void) +{ + if (g_nshmem_localdata) + { + free(g_nshmem_localdata); + g_nshmem_localdata = NULL; + } + + if (g_nshmem_internal_cfg) + { + free(g_nshmem_internal_cfg); + g_nshmem_internal_cfg = NULL; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_reserv_safe +* Description : malloc a memory and save to memzone +* Input : const char* name +* size_t length +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle nsfw_nshmem_reserv_safe(const char *name, size_t length) +{ + void *addr = NULL; + i32 iret = NSFW_MEM_OK; + nsfw_nshmem_mzone *pmemzone = NULL; + + if (length <= 0) + { + return NULL; + } + + nsfw_write_lock(nsfw_get_glb_lock()); + + addr = malloc(length); + if (!addr) + { + NSRTP_LOGERR("nshmem malloc addr fail] addr=%p", addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + iret = memset_s(addr, length, 0, length); + if (EOK != iret) + { + NSRTP_LOGERR("nshmem malloc addr MEMSET_S fail] addr=%p", addr); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + pmemzone = nsfw_nshmem_get_free_zone(); + + if (!pmemzone) + { + NSRTP_LOGERR("nshmem get free zone fail"); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + pmemzone->addr = addr; + pmemzone->length = length; + /*name must be less than NSFW_MEM_APPNAME_LENGTH */ + if (EOK != + strcpy_s((char *) pmemzone->aname, sizeof(pmemzone->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + nsfw_write_unlock(nsfw_get_glb_lock()); + return addr; +} + +/* + * create no shared memory + * nsfw_mem_zone::stname no shared memory name + * nsfw_mem_zone::isize memory size + */ +mzone_handle nsfw_nshmem_create(nsfw_mem_zone * pinfo) +{ + + NSFW_NAME_LENCHECK_RET_NULL(pinfo->stname.aname, "nshmem create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + return nsfw_nshmem_reserv_safe(pinfo->stname.aname, pinfo->lenth); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_lookup +* Description : find a block memory by name +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle nsfw_nshmem_lookup(nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "nshmem lookup"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + nsfw_read_lock(nsfw_get_glb_lock()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp(pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_read_unlock(nsfw_get_glb_lock()); + return mz->addr; + } + } + + nsfw_read_unlock(nsfw_get_glb_lock()); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_release +* Description : free a block memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_release(nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem release"); + NSFW_NSHMEM_INIT_CHK_RET(); + nsfw_read_lock(nsfw_get_glb_lock()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp(pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_nshmem_free_zone(mz); + nsfw_read_unlock(nsfw_get_glb_lock()); + return NSFW_MEM_OK; + } + } + + nsfw_read_unlock(nsfw_get_glb_lock()); + return NSFW_MEM_OK; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_spcreate +* Description : create a memory pool by ring +* Input : nsfw_mem_sppool* pmpinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle nsfw_nshmem_spcreate(nsfw_mem_sppool * pmpinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2(pmpinfo->usnum + 1); + unsigned int uselt_size = pmpinfo->useltsize; + struct nsfw_mem_ring *pringhead = NULL; + unsigned int uscnt = 0; + char *pmz = NULL; + NSFW_NAME_LENCHECK_RET_NULL(pmpinfo->stname.aname, "nshmem sp create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + + len = + sizeof(struct nsfw_mem_ring) + + (size_t) usnum *sizeof(union RingData_U) + (size_t) usnum *uselt_size; + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe(pmpinfo-> + stname.aname, len); + + if (!pringhead) + { + NSRTP_LOGERR("nshmem sp create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init(pringhead, usnum, pringhead, NSFW_NSHMEM, + pmpinfo->enmptype); + pmz = + ((char *) pringhead + sizeof(struct nsfw_mem_ring) + + usnum * sizeof(union RingData_U)); + + for (uscnt = 0; uscnt < usnum; uscnt++) + { + if (0 == + g_ring_ops_arry[pringhead->memtype][pringhead-> + ringflag].ring_ops_enqueue + (pringhead, (void *) pmz)) + { + NSRTP_LOGERR("nsfw_nshmem_ringenqueue enqueue fail] uscnt=%u", + uscnt); + } + + pmz = pmz + uselt_size; + } + + return pringhead; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sp_lookup +* Description : look up a sppool memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle nsfw_nshmem_sp_lookup(nsfw_mem_name * pname) +{ + return nsfw_nshmem_lookup(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sprelease +* Description : release a sp pool +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_sprelease(nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem sp mempool release"); + NSFW_NSHMEM_INIT_CHK_RET(); + return nsfw_nshmem_release(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringcreate +* Description : create a ring +* Input : nsfw_mem_mring* pringinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle nsfw_nshmem_ringcreate(nsfw_mem_mring * pringinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2(pringinfo->usnum + 1); + struct nsfw_mem_ring *pringhead = NULL; + NSFW_NAME_LENCHECK_RET_NULL(pringinfo->stname.aname, + "nshmem ring create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + + len = sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe(pringinfo-> + stname.aname, len); + + if (!pringhead) + { + NSRTP_LOGERR("nshmem ring create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init(pringhead, usnum, (void *) pringhead, NSFW_NSHMEM, + pringinfo->enmptype); + return pringhead; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringrelease +* Description : release a nsh ring memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_ringrelease(nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem ring mempool release"); + NSFW_NSHMEM_INIT_CHK_RET(); + return nsfw_nshmem_release(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sppool_statics +* Description : static the memory size of sppool +* Input : mring_handle sppool +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_sppool_statics(mring_handle sppool) +{ + struct nsfw_mem_ring *phead = (struct nsfw_mem_ring *) sppool; + + return sizeof(struct nsfw_mem_ring) + + (ssize_t) phead->size * sizeof(union RingData_U) + + (ssize_t) phead->size * phead->eltsize; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ring_statics +* Description : static the memory size of ring +* Input : mring_handle handle +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_ring_statics(mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof(union RingData_U) + + sizeof(struct nsfw_mem_ring); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_static +* Description : static the memory size according to mem type +* Input : void* handle +* nsfw_mem_struct_type type +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_static(void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return -1; + case NSFW_MEM_SPOOL: + return nsfw_nshmem_sppool_statics(handle); + case NSFW_MEM_RING: + return nsfw_nshmem_ring_statics(handle); + default: + break; + } + return -1; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h new file mode 100644 index 0000000..fa5bc6b --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h @@ -0,0 +1,70 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MNG_H_ +#define _NSFW_NSHMEM_MNG_H_ + +#include "common_mem_rwlock.h" + +#include "common_func.h" + +#define NSFW_NSHMEM_ZONE_MAX 2560 + +typedef struct +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + void *addr; + int length; +} nsfw_nshmem_mzone; + +typedef struct +{ + nsfw_nshmem_mzone amemzone[NSFW_NSHMEM_ZONE_MAX]; + common_mem_rwlock_t mlock; +} nsfw_nshmem_cfg; + +/* + * no share memory module init + */ +i32 nsfw_nshmem_init(nsfw_mem_para * para); + +/* + * no share memory module destory + */ +void nsfw_nshmem_destory(void); + +/* + * create a no shared memory + */ +mzone_handle nsfw_nshmem_create(nsfw_mem_zone * pinfo); + +mzone_handle nsfw_nshmem_lookup(nsfw_mem_name * pname); + +i32 nsfw_nshmem_release(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_spcreate(nsfw_mem_sppool * pmpinfo); + +i32 nsfw_nshmem_sprelease(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_sp_lookup(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_ringcreate(nsfw_mem_mring * pringinfo); + +i32 nsfw_nshmem_ringrelease(nsfw_mem_name * pname); + +ssize_t nsfw_nshmem_static(void *handle, nsfw_mem_struct_type type); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c new file mode 100644 index 0000000..51f1fa4 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c @@ -0,0 +1,434 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include "nstack_securec.h" + +#include "nsfw_mem_api.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_func.h" + +/*copy the data to obj*/ +NSTACK_STATIC inline void +nsfw_nshmem_ring_obj_copy(struct nsfw_mem_ring *r, uint32_t cons_head, + void **obj_table, unsigned n) +{ + uint32_t idx = cons_head & r->mask; + unsigned i = 0; + const uint32_t size = r->size; + + if (likely(idx + n < size)) + { + for (i = 0; i < (n & (~(unsigned) 0x3)); i += 4, idx += 4) + { + obj_table[i] = (void *) r->ring[idx].data_l; + obj_table[i + 1] = (void *) r->ring[idx + 1].data_l; + obj_table[i + 2] = (void *) r->ring[idx + 2].data_l; + obj_table[i + 3] = (void *) r->ring[idx + 3].data_l; + } + switch (n & 0x3) + { + case 3: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 2: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 1: + obj_table[i++] = (void *) r->ring[idx++].data_l; + } + } + else + { + for (i = 0; idx < size; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + + for (idx = 0; i < n; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + } +} + +/*fork recover*/ +NSTACK_STATIC inline void +nsfw_nshmem_enqueue_fork_recov(struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid(); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->prodhflag; + + if (unlikely(pidflag != curpid)) + { + success = common_mem_atomic32_cmpset(&r->prodhflag, pidflag, curpid); + + if (unlikely(success != 0)) + { + /*recover it */ + if (r->prod.tail != r->prod.head) + { + r->prod.head = r->prod.tail; + } + + r->prodtflag = curpid; + } + } + + return; +} + +NSTACK_STATIC inline void +nsfw_nshmem_dequeue_fork_recov(struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid(); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->conshflag; + + if (unlikely(pidflag != curpid)) + { + success = common_mem_atomic32_cmpset(&r->conshflag, pidflag, curpid); + + if (unlikely(success != 0)) + { + /*recover it */ + if (r->cons.tail != r->cons.head) + { + r->cons.head = r->cons.tail; + } + + r->constflag = curpid; + } + } + + return; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int +nsfw_nshmem_ring_mp_enqueue(struct nsfw_mem_ring *mem_ring, void *obj_table) +{ + uint32_t producer_head, producer_next; + uint32_t consumer_tail, free_entries; + int success; + unsigned rep = 0; + uint32_t mask = mem_ring->mask; + uint32_t size = mem_ring->size; + uint32_t n = 1; + + /* move prod.head atomically */ + do + { + + producer_head = mem_ring->prod.head; + consumer_tail = mem_ring->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * producer_head > consumer_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = (size + consumer_tail - producer_head); + + /* check that we have enough room in ring */ + if (unlikely(n > free_entries)) + { + return 0; + /* Below code is commented currenlty as its a dead code. */ + } + + /*if pid is not the same, maybe mult thread fork happen */ + nsfw_nshmem_enqueue_fork_recov(mem_ring); + + while (unlikely + ((mem_ring->prod.tail != mem_ring->prod.head) + || (mem_ring->prodtflag != mem_ring->prodhflag))) + { + common_mem_pause(); + } + + producer_next = producer_head + n; + success = + common_mem_atomic32_cmpset(&mem_ring->prod.head, producer_head, + producer_next); + } + while (unlikely(success == 0)); + + mem_ring->ring[producer_head & mask].data_l = (u64) obj_table; + + /* + * If there are other enqueues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely(mem_ring->prod.tail != producer_head)) + { + common_mem_pause(); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-emptied thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield(); + } + } + + mem_ring->prod.tail = producer_next; + return (int) n; +} + +/* + this is a single thread/process enqueue function + */ +int nsfw_nshmem_ring_sp_enqueue(struct nsfw_mem_ring *r, void *obj_table) +{ + uint32_t producer_head, consumer_tail; + uint32_t producer_next, free_entries; + uint32_t mask = r->mask; + uint32_t n = 1; + uint32_t size = r->size; + + producer_head = r->prod.head; + consumer_tail = r->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * producer_head > consumer_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = size + consumer_tail - producer_head; + + /* check that we have enough room in ring */ + if (unlikely(n > free_entries)) + { + return 0; + } + + nsfw_nshmem_enqueue_fork_recov(r); + + producer_next = producer_head + n; + r->prod.head = producer_next; + + r->ring[producer_head & mask].data_l = (u64) obj_table; + + r->prod.tail = producer_next; + return (int) n; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_nshmem_ring_mc_dequeuev(struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t consumer_head, producer_tail; + uint32_t consumer_next, entries; + int success; + unsigned rep = 0; + uint32_t num = n; + + /* Avoid the unnecessary cmpset operation below, which is also + * potentially harmful when n equals 0. */ + if (unlikely(num == 0)) + { + return 0; + } + + nsfw_nshmem_dequeue_fork_recov(r); + + /* move cons.head atomically */ + do + { + num = n; + consumer_head = r->cons.head; + producer_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = (producer_tail - consumer_head); + + /* Set the actual entries for dequeue */ + if (unlikely(num > entries)) + { + if (likely(entries > 0)) + { + num = entries; + } + else + { + return 0; + } + } + + /* check the queue can be operate */ + while (unlikely + ((r->cons.tail != r->cons.head) + || (r->conshflag != r->constflag))) + { + common_mem_pause(); + } + + consumer_next = consumer_head + num; + + success = + common_mem_atomic32_cmpset(&r->cons.head, consumer_head, + consumer_next); + } + while (unlikely(success == 0)); + + nsfw_nshmem_ring_obj_copy(r, consumer_head, obj_table, num); + + /* + * If there are other dequeues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely(r->cons.tail != consumer_head)) + { + common_mem_pause(); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-emptied thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield(); + } + } + + r->cons.tail = consumer_next; + + return (int) num; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +1. while dequeue corrupt, the tail no one added, may multi the try times. +*/ +int nsfw_nshmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_mc_dequeuev(ring, box, 1); +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_nshmem_ring_sc_dequeuev(struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t consumer_head, producer_tail; + uint32_t consumer_next, entries; + uint32_t inum = n; + consumer_head = r->cons.head; + producer_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = producer_tail - consumer_head; + + if (unlikely(inum > entries)) + { + if (likely(entries > 0)) + { + inum = entries; + } + else + { + return 0; + } + } + + nsfw_nshmem_dequeue_fork_recov(r); + + consumer_next = consumer_head + inum; + r->cons.head = consumer_next; + + nsfw_nshmem_ring_obj_copy(r, consumer_head, obj_table, inum); + + r->cons.tail = consumer_next; + return (int) inum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int nsfw_nshmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_sc_dequeuev(ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + + /*if queue is full, just return 0 */ + if (unlikely(ring->prod.head >= (ring->size + ring->cons.tail))) + { + return 0; + } + + head = ring->prod.head; + ring->ring[head & ring->mask].data_l = (u64) box; + ring->prod.head++; + return 1; +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_singlethread_dequeuev(ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return num; + } + + box[num] = (void *) ring->ring[tail & ring->mask].data_l; + ring->cons.tail++; + num++; + } + + return num; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h new file mode 100644 index 0000000..f7f7732 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h @@ -0,0 +1,38 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_RING_H_ +#define _NSFW_NSHMEM_RING_H_ + +#include +#include "nsfw_ring_data.h" + +int nsfw_nshmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, + void *box); +int nsfw_nshmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, + void **box); +int nsfw_nshmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_NSHMEM_RING_H_*/ diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c new file mode 100644 index 0000000..9016282 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c @@ -0,0 +1,989 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_buf.h" +#include "common_mem_common.h" + +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +/*get the base address of msg data */ +#define NSFW_SHMEM_GET_DATA(pmsg, type) (type *)&((pmsg)->aidata[0]) + +/*if input point is nun, just return null*/ +#define NSFW_POINT_CHK_RET_NULL(p, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGERR("point check fail] desc_para=%s", desc); \ + return NULL; \ + } + +/*if input point is nun, just return err num*/ +#define NSFW_POINT_CHK_RET_ERR(p, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGDBG("point check fail] desc_para=%s", desc); \ + return NSFW_MEM_ERR; \ + } + +/*if input point is nun, goto flag*/ +#define NSFW_POINT_CHK_RET_GOTO(p, gotoflag, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGERR("point check fail] desc_para=%s", desc); \ + goto gotoflag; \ + } + +/*init the msg head*/ +#define NSFW_SHMEM_MSG_HEAD_INIT(pmsg, type, length) { \ + (pmsg)->usmsg_type = (type); \ + (pmsg)->uslenth = (length); \ + } + +/*rsp msg head check, and if err goto*/ +#define NSFW_SHMEM_MSGHEAD_CHK_GOTO(pmsg, type, length, gotoflag) { \ + if (((type) != pmsg->usmsg_type) && ((length) != pmsg->uslenth)) \ + { \ + NSRTP_LOGERR("check fail] msgtype=%d, type_para=%d, len=%d", (pmsg->usmsg_type), (type), (length)); \ + goto gotoflag; \ + } \ + } + +/*rsp check the state*/ +#define NSFW_SHMEM_ACKSTATE_CHK_GOTO(expret, ret, expseg, seg, gotoflag) { \ + if (((ret) != (expret)) || ((expseg) != (seg))) \ + { \ + NSRTP_LOGERR("ackstate check fail]msgack exp=%d, real=%d,eseg=%d, rseg=%d", (expret), (ret), (expseg), (seg)); \ + goto gotoflag; \ + } \ + } + +/*mzone msg init*/ +#define NSFW_SHMEM_MZONE_DATA_INIT(pdata, slength, seg, socketid) { \ + (pdata)->isocket_id = (socketid); \ + (pdata)->lenth = (slength); \ + (pdata)->usseq = (seg); \ + (pdata)->ireserv = 0; \ + } + +/*mbuf msg init*/ +#define NSFW_SHMEM_MBUF_DATA_INIT(pdata, seg, num, cashsize, priv_size, data_room, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->uscash_size = (cashsize); \ + (pdata)->uspriv_size = (priv_size); \ + (pdata)->usdata_room = (data_room); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mpool msg init*/ +#define NSFW_SHMEM_MPOOL_DATA_INIT(pdata, seg, num, eltsize, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->useltsize = (eltsize); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mring msg init*/ +#define NSFW_SHMEM_MRING_DATA_INIT(pdata, seg, num, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +#define NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg) {\ + if (pmsg) \ + { \ + nsfw_mgr_msg_free(pmsg); \ + } \ + if (prsp_msg) \ + { \ + nsfw_mgr_msg_free(prsp_msg); \ + } \ +} + +/* + * create a block memory by send a msg + * + */ +mzone_handle +nsfw_memzone_remote_reserv(const i8 * name, size_t mlen, i32 socket_id) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head point define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data point define */ + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + /*ack msg define */ + nsfw_shmem_ack *pack_data = NULL; + + mzone_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote reserv pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, "remote reserv rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RESERV_REQ_MSG, + sizeof(nsfw_shmem_reserv_req)); + + /*msg data init */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_reserv_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("reserv mem copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MZONE_DATA_INIT(pdata, mlen, (u16) 0, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("reserv mem req rsp fail] ret=%u", ucret); + goto release; + } + + /*interrupt msg head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RESERV_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, release); + + hhandle = (mzone_handle) ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mem reserve] name=%s, handle=%p, seg=%u", name, hhandle, + pack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some memories by send a msg + */ +i32 +nsfw_memzone_remote_reserv_v(nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_reserv_req *ptempdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + u16 ussegbase = 0; + u16 ustempv = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_reserv_req); + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(pmsg, err, "remote reserv_v msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, err, "remote reserv_v rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = + NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_reserv_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RESERV_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_reserv_req)); + + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT(ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("reserv v mem req rsp fail] ret=%u", ucret); + goto err; + } + + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RESERV_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + err); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + ustempv = ussegbase + iindex; + + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, ustempv, + (u16) pack_data->usseq, err); + + paddr_array[ustempv] = ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("remote reserve]index=%u, seg=%u, handle=%p", + ustempv, pack_data->usseq, paddr_array[ustempv]); + pack_data++; + } + + ussegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT(ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + iretval = NSFW_MEM_OK; + goto free; + + err: + iretval = NSFW_MEM_ERR; + free: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *release a block memory with name by send msg + */ +i32 nsfw_remote_free(const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_free_req *pdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_ERR(pmsg, "remote free msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, terr, "remote free rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RELEASE_REQ_MSG, + sizeof(nsfw_shmem_free_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_free_req); + if (EOK != strcpy_s(pdata->aname, sizeof(pdata->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("free mem req rsp fail] ret=%u", ucret); + goto release; + } + + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RELEASE_ACK_MSG, + sizeof(nsfw_shmem_ack), terr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, terr); + + iretval = NSFW_MEM_OK; + goto release; + terr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *create a mbuf pool by send a msg + */ +mpool_handle +nsfw_remote_shmem_mbf_create(const i8 * name, unsigned n, + unsigned cache_size, unsigned priv_size, + unsigned data_room_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_msg_head *tpack_head = NULL; + nsfw_shmem_ack *tpack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote mbf create pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, "remote mbf create msg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MBUF_REQ_MSG, + sizeof(nsfw_shmem_mbuf_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_mbuf_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("mbf create name cpy fail] ret=%d", iretval); + goto release; + } + + NSFW_SHMEM_MBUF_DATA_INIT(pdata, 0, n, cache_size, priv_size, + data_room_size, (u16) entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mbf create mem req rsp fail] ret=%u", ucret); + goto release; + } + + tpack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(tpack_head, NSFW_MBUF_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + tpack_data = NSFW_SHMEM_GET_DATA(tpack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, tpack_data->cstate, 0, + tpack_data->usseq, release); + + hhandle = ADDR_SHTOL(tpack_data->pbase_addr); + NSRTP_LOGDBG("mbf create] name=%s, handle=%p, seg=%u", name, hhandle, + tpack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some mbuf pools + */ +i32 +nsfw_remote_shmem_mbf_createv(nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *mbpmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_mbuf_req *ptempdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_mbuf_req); + + mbpmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(mbpmsg, lerr, "remote mbf createv msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, lerr, + "remote mbf createv rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, mbpmsg); + + ptempdata = pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_mbuf_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MBUF_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_mbuf_req)); + + /*fill msg data */ + itindex = icount - 1; + if (-1 == + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT(ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(mbpmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mbf createv mem req rsp fail] ret=%d", ucret); + goto lerr; + } + + /*interrupt msg head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_MBUF_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + lerr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, lerr); + phandle_array[isegbase + iindex] = + ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mbf createv] seg=%d, handle=%p", + pack_data->usseq, hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + if (-1 == + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT(ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + /*release memory */ + iretval = NSFW_MEM_OK; + goto release; + + lerr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(mbpmsg, prsp_msg); + return iretval; +} + +/* + *create a simpile pool + */ +mring_handle +nsfw_remote_shmem_mpcreate(const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_msg_head *mppack_head = NULL; + nsfw_shmem_ack *mppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote mbf mpcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, + "remote mpcreate rspmsg alloc"); + + /*init msg head */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_SPPOOL_REQ_MSG, + sizeof(nsfw_shmem_sppool_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_sppool_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("mp create copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MPOOL_DATA_INIT(pdata, 0, n, elt_size, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mp create rsp fail] ret=%d", ucret); + goto release; + } + + /*get msg head */ + mppack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(mppack_head, NSFW_SPPOOL_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + mppack_data = NSFW_SHMEM_GET_DATA(mppack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, mppack_data->cstate, 0, + mppack_data->usseq, release); + + hhandle = ADDR_SHTOL(mppack_data->pbase_addr); + NSRTP_LOGDBG("mpcreate] name=%s, handle=%p, seg=%d", name, hhandle, + mppack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some simpile pools by send a msg + */ +i32 +nsfw_remote_shmem_mpcreatev(nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_sppool_req *ptempdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + /*the max members that a msg can take */ + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_sppool_req); + + /*alloc a msg */ + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(pmsg, mperr, "remote mpcreatev pmsg alloc"); + + /*alloc rsp msg */ + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, mperr, "remote mpcreatev rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = + NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_sppool_req); + + do + { + icount++; + ieltnum++; + + /*if the element num reach the bigest, or already send all, just deal */ + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + /*init msg header */ + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_SPPOOL_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_sppool_req)); + + /*fill the msg data */ + itindex = icount - 1; + + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT(ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mpcreatev create fail] ret=%u", ucret); + goto mperr; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_SPPOOL_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + mperr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, mperr); + pringhandle_array[isegbase + iindex] = + ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mpcreatev] seg=%u, handle=%p", pack_data->usseq, + hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT(ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ptempdata++; + } + } + while (icount < inum); + + /*release the memory */ + iretval = NSFW_MEM_OK; + goto release; + + mperr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *create a ring + */ +mring_handle +nsfw_remote_shmem_ringcreate(const char *name, unsigned int n, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_ring_req *pdata = NULL; + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *ppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote ringcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, + "remote ringcreate rspmsg alloc"); + + /*fill msg head */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RING_REQ_MSG, + sizeof(nsfw_shmem_ring_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_ring_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("ring create cpy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MRING_DATA_INIT(pdata, 0, n, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("ring create rsp fail] ret=%d", ucret); + goto release; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RING_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + ppack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, ppack_data->cstate, 0, + ppack_data->usseq, release); + + hhandle = ADDR_SHTOL(ppack_data->pbase_addr); + NSRTP_LOGDBG("ring create] name=%s, handle=%p, seg=%u", name, hhandle, + ppack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create a mem pool that the members are rings by send a msg + *ieltnum:the num of ring member + *iringnum:the num of ring in simple mem pool + *entype:the default the of ring + */ +i32 +nsfw_remote_shmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + unsigned int useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + /*the num of ring member must be power of 2 */ + unsigned int usnum = common_mem_align32pow2(ieltnum + 1); + + useltsize = + sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + nhandle = + nsfw_remote_shmem_mpcreate(name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + NSFW_POINT_CHK_RET_ERR(nhandle, "remote ringcreatev msg alloc"); + + n = nsfw_shmem_ring_sc_dequeuev(nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSRTP_LOGERR("ring dequeue fail] ringnum=%d, retnum=%d", iringnum, n); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query(&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init(pringhandle_array[icount], usnum, + (void *) baseaddr, NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +/* + *look up a msg by send a msg + */ +void *nsfw_remote_shmem_lookup(const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + void *addr = NULL; + /*msg head data define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_lookup_req *pdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *lpack_data = NULL; + u8 ucret = TRUE; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote lookup pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, perr, "remote lookup rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MEM_LOOKUP_REQ_MSG, + sizeof(nsfw_shmem_lookup_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_lookup_req); + if (EOK != strcpy_s(pdata->aname, sizeof(pdata->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mem lookup fail] ret=%u", ucret); + goto release; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_MEM_LOOKUP_ACK_MSG, + sizeof(nsfw_shmem_ack), perr); + + lpack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, lpack_data->cstate, 0, + lpack_data->usseq, perr); + + addr = ADDR_SHTOL(lpack_data->pbase_addr); + NSRTP_LOGDBG("shmem lookup] name=%s, handle=%p, seg=%u", name, addr, + lpack_data->usseq); + goto release; + perr: + addr = NULL; + + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return addr; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h new file mode 100644 index 0000000..0ae5cd5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RSHMEM_MNG_H +#define _NSFW_RSHMEM_MNG_H + +mzone_handle nsfw_memzone_remote_reserv(const i8 * name, size_t mlen, + i32 socket_id); +i32 nsfw_memzone_remote_reserv_v(nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, + pid_t pid); +i32 nsfw_remote_free(const i8 * name, nsfw_mem_struct_type entype); +mpool_handle nsfw_remote_shmem_mbf_create(const i8 * name, unsigned int n, + unsigned cache_size, + unsigned priv_size, + unsigned data_room_size, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mbf_createv(nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_mpcreate(const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mpcreatev(nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_ringcreate(const char *name, unsigned int n, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, + i32 iringnum, i32 socket_id, + nsfw_mpool_type entype); + +void *nsfw_remote_shmem_lookup(const i8 * name, nsfw_mem_struct_type entype); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c new file mode 100644 index 0000000..3d4dd42 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c @@ -0,0 +1,48 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_api.h" +#include "nsfw_shmem_mng.h" +#include "nsfw_shmem_mdesc.h" +#include "common_pal_bitwide_adjust.h" +/*the inferaces accessing memory*/ +nsfw_mem_ops g_shmem_ops = { + nsfw_shmem_init, + nsfw_shmem_destroy, + nsfw_shmem_create, + nsfw_shmem_createv, + nsfw_shmem_lookup, + nsfw_shmem_release, + nsfw_shmem_mbfmpcreate, + nsfw_shmem_mbfmpcreatev, + nsfw_shmem_mbfmplookup, + nsfw_shmem_mbfmprelease, + nsfw_shmem_spcreate, + nsfw_shmem_spcreatev, + nswf_shmem_sp_ringcreate, + nsfw_shmem_sprelease, + nsfw_shmem_sp_lookup, + nsfw_shmem_ringcreate, + nsfw_shmem_ring_lookup, + nsfw_shmem_ringrelease, + nsfw_shmem_static, + nsfw_shmem_sp_iterator, + nsfw_shmem_mbuf_iterator, + NULL, + shmem_shddr_to_laddr, + shmem_laddr_to_shddr, + nsfw_attach_core_id +}; diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h new file mode 100644 index 0000000..afd9e29 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MDESC_H_ +#define _NSFW_SHMEM_MDESC_H_ + +extern nsfw_mem_ops g_shmem_ops; + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c new file mode 100644 index 0000000..1066b9a --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c @@ -0,0 +1,800 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_mem_api.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_mempool.h" +#include "common_mem_memzone.h" +#include "common_mem_buf.h" +#include "common_mem_mbuf.h" +#include "nsfw_rshmem_mng.h" +#include "common_mem_api.h" +#include "common_sys_config.h" +#include "nsfw_maintain_api.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_func.h" + +#define NSFW_SHMEM_PID (get_sys_pid()) +#define NSFW_SHMEM_FLAG (g_shmem_localdata->enflag) + +/* app_mode 1: simple stack with APP*/ +extern u8 app_mode; +u8 app_mode = 0; + +nsfw_mem_localdata *g_shmem_localdata = NULL; + +/*check g_mem_localdata*/ +#define NSFW_INIT_CHK_RET() \ + if (!g_shmem_localdata) \ + { \ + return NSFW_MEM_ERR; \ + } + +#define NSFW_INIT_CHK_RET_NULL() \ + if (!g_shmem_localdata) \ + { \ + return NULL; \ + } + +/* + *share memory mng module init + * + */ +i32 nsfw_shmem_init(nsfw_mem_para * para) +{ + common_mem_pal_module_info rteinfo = { 0 }; + i32 iret = NSFW_MEM_ERR; + int flag = 0; + if (!para) + { + return NSFW_MEM_ERR; + } + + NSRTP_LOGINF("nsfw shmem init begin"); + + LCORE_MASK_SET(rteinfo.ilcoremask, 1); + rteinfo.ucproctype = DMM_PROC_T_SECONDARY; + iret = common_pal_module_init(para, &rteinfo, app_mode); + + if (DMM_MBUF_RET_OK != iret) + { + NSRTP_LOGERR("rte init fail] ret=0x%x", iret); + return NSFW_MEM_ERR; + } + + flag = dmm_pal_addr_align(); + if ((0 == flag) && (NSFW_PROC_MAIN == para->enflag)) + { + dmm_addr_print(); + NSRTP_LOGERR + ("rte init addr is not the same with primary] nstackmain flag=%d", + flag); + return NSFW_MEM_ERR; + } + + g_shmem_localdata = + (nsfw_mem_localdata *) malloc(sizeof(nsfw_mem_localdata)); + + if (NULL == g_shmem_localdata) + { + NSRTP_LOGERR("g_shmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + memset_s(g_shmem_localdata, sizeof(nsfw_mem_localdata), 0, + sizeof(nsfw_mem_localdata)); + if (EOK != iret) + { + NSRTP_LOGERR("memset fail] g_shmem_localdata=%p ", g_shmem_localdata); + free(g_shmem_localdata); + g_shmem_localdata = NULL; + return NSFW_MEM_ERR; + } + + g_shmem_localdata->enflag = para->enflag; + + NSRTP_LOGINF("nsfw shmem init end] enflag=%d", para->enflag); + return NSFW_MEM_OK; + +} + +/* + *module destroy + */ +void nsfw_shmem_destroy(void) +{ + if (g_shmem_localdata) + { + free(g_shmem_localdata); + g_shmem_localdata = NULL; + } + + return; +} + +/* + * create a shared memory + * nsfw_mem_zone::stname memory name + * nsfw_mem_zone::isize + */ +mzone_handle nsfw_shmem_create(nsfw_mem_zone * pinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL()if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_reserve_name(pinfo->stname.aname, + pinfo->lenth, + pinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pinfo->stname.aname, "shmem create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + return NULL; + } + } + + return nsfw_memzone_remote_reserv((char *) &aname[0], pinfo->lenth, + SOCKET_ID_ANY); +} + +/* + *create some memory + *inum must be equal iarray_num + */ +i32 +nsfw_shmem_createv(nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_memzone_remote_reserv_v(pmeminfo, paddr_array, iarray_num, + 0); + } + else + { + return nsfw_memzone_remote_reserv_v(pmeminfo, paddr_array, iarray_num, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +mzone_handle nsfw_shmem_lookup(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_lookup_name(pname->aname); + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NULL; + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "shmem lookup") + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, + NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NULL; + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_MZONE); +} + +i32 nsfw_shmem_release(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + const struct common_mem_memzone *pmzone = NULL; + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + pmzone = common_mem_memzone_lookup(pname->aname); + + if (pmzone) + { + common_mem_memzone_free(pmzone); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET(pname->aname, "shmem free") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NSFW_MEM_ERR; + } + } + + return nsfw_remote_free(aname, NSFW_MEM_MZONE); +} + +mpool_handle nsfw_shmem_mbfmpcreate(nsfw_mem_mbfpool * pbufinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_pktmbuf_pool_create(pbufinfo->stname.aname, + pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, + pbufinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pbufinfo->stname.aname, "mbufpool create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pbufinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_mbf_create(aname, pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, SOCKET_ID_ANY, + pbufinfo->enmptype); +} + +/* + *create some mbuf pools + */ +i32 +nsfw_shmem_mbfmpcreatev(nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mbf_createv(pmbfname, phandle_array, + iarray_num, 0); + } + else + { + return nsfw_remote_shmem_mbf_createv(pmbfname, phandle_array, + iarray_num, NSFW_SHMEM_PID); + } + + return NSFW_MEM_ERR; +} + +mbuf_handle nsfw_shmem_mbfalloc(mpool_handle mhandle) +{ + return (mbuf_handle) + common_mem_pktmbuf_alloc((struct common_mem_mempool *) mhandle); +} + +i32 nsfw_shmem_mbffree(mbuf_handle mhandle) +{ + common_mem_pktmbuf_free((struct common_mem_mbuf *) mhandle); + return NSFW_MEM_OK; +} + +i32 nsfw_shmem_mbfmprelease(nsfw_mem_name * pname) +{ + return NSFW_MEM_OK; +} + +mpool_handle nsfw_shmem_mbfmplookup(nsfw_mem_name * pmbfname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_mempool_lookup(pmbfname->aname); + } + + if ((NSFW_PROC_NULL == pmbfname->enowner) + || (NSFW_PROC_MAIN == pmbfname->enowner)) + { + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", + pmbfname->aname)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pmbfname->aname, "shmem lookup") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmbfname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_MBUF); +} + +mring_handle nsfw_shmem_spcreate(nsfw_mem_sppool * pmpinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_pool_create(pmpinfo->stname.aname, pmpinfo->usnum, + pmpinfo->useltsize, pmpinfo->isocket_id, + pmpinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL(pmpinfo->stname.aname, "mpool create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmpinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_mpcreate(aname, pmpinfo->usnum, + pmpinfo->useltsize, SOCKET_ID_ANY, + pmpinfo->enmptype); +} + +i32 +nsfw_shmem_spcreatev(nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mpcreatev(pmpinfo, pringhandle_array, inum, + 0); + } + else + { + return nsfw_remote_shmem_mpcreatev(pmpinfo, pringhandle_array, inum, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +i32 +nsfw_lshmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + i32 useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + i32 usnum = common_mem_align32pow2(ieltnum + 1); + + useltsize = + sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + nhandle = + nsfw_shmem_pool_create(name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + if (NULL == (nhandle)) + { + return NSFW_MEM_ERR; + } + + n = nsfw_shmem_ring_sc_dequeuev(nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSRTP_LOGERR + ("ring dequeuev failed] ring=%p, dequeue num=%d, expect num=%d", + nhandle, n, iringnum); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query(&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init(pringhandle_array[icount], usnum, + (void *) baseaddr, NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +i32 +nswf_shmem_sp_ringcreate(nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_lshmem_ringcreatev(prpoolinfo->stname.aname, + prpoolinfo->usnum, pringhandle_array, + iringnum, SOCKET_ID_ANY, + prpoolinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET(prpoolinfo->stname.aname, "ring pool") + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + prpoolinfo->stname.aname, NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_ringcreatev(aname, prpoolinfo->usnum, + pringhandle_array, iringnum, + SOCKET_ID_ANY, prpoolinfo->enmptype); +} + +i32 nsfw_shmem_sprelease(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name(pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct + nsfw_shmem_ring_head)); + nsfw_shmem_pool_free(ring_ptr); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET(pname->aname, "shmem free") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_free(aname, NSFW_MEM_SPOOL); +} + +mring_handle nsfw_shmem_sp_lookup(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name(pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct + nsfw_shmem_ring_head)); + return ring_ptr; + } + return mz_mem; + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname)) + { + NSRTP_LOGERR("SPRINTF_S fails]"); + } + } + else + { + /*app's name can not over NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "shmem lookup") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_SPOOL); +} + +mring_handle nsfw_shmem_ringcreate(nsfw_mem_mring * pringinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_ring_create(pringinfo->stname.aname, + pringinfo->usnum, pringinfo->isocket_id, + pringinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL(pringinfo->stname.aname, "ring create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pringinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_ringcreate(aname, pringinfo->usnum, + SOCKET_ID_ANY, pringinfo->enmptype); +} + +mring_handle nsfw_shmem_ring_lookup(nsfw_mem_name * pname) +{ + return nsfw_shmem_lookup(pname); +} + +i32 nsfw_shmem_ringrelease(nsfw_mem_name * pname) +{ + return nsfw_shmem_release(pname); +} + +size_t nsfw_shmem_mbufpool_statics(mpool_handle mbufpool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) mbufpool; + return (size_t) mp->size * (mp->header_size + mp->elt_size + + mp->trailer_size) + + (size_t) mp->private_data_size + + (size_t) + common_mem_ring_get_memsize(common_mem_align32pow2(mp->size + 1)); +} + +size_t nsfw_shmem_sppool_statics(mring_handle sppool) +{ + struct nsfw_shmem_ring_head *temp = NULL; + size_t lent = 0; + temp = + (struct nsfw_shmem_ring_head *) ((char *) sppool - + sizeof(struct nsfw_shmem_ring_head)); + + while (temp) + { + lent += temp->mem_zone->len; + temp = temp->next; + } + + return lent; +} + +size_t nsfw_shmem_ring_statics(mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof(union RingData_U) + + sizeof(struct nsfw_mem_ring); +} + +ssize_t nsfw_shmem_static(void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return nsfw_shmem_mbufpool_statics(handle); + case NSFW_MEM_SPOOL: + return nsfw_shmem_sppool_statics(handle); + case NSFW_MEM_RING: + return nsfw_shmem_ring_statics(handle); + default: + break; + } + return -1; +} + +i32 nsfw_shmem_mbuf_recycle(mpool_handle handle) +{ + return NSFW_MEM_OK; +} + +/***************************************************************************** +* Prototype : nsfw_shmem_sp_iterator +* Description : sp pool iterator +* Input : mpool_handle handle +* u32 start +* u32 end +* nsfw_mem_item_fun fun +* void *argv +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_shmem_sp_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + struct nsfw_mem_ring *perfring_ptr = (struct nsfw_mem_ring *) handle; + if (NULL == perfring_ptr || NULL == fun) + { + return 0; + } + + if (0 == perfring_ptr->eltsize) + { + return 0; + } + + int num = perfring_ptr->size; + if (start >= (u32) num || end <= start) + { + return 0; + } + + struct nsfw_shmem_ring_head *ring_head = + (struct nsfw_shmem_ring_head *) ((char *) handle - + sizeof(struct nsfw_shmem_ring_head)); + void *mz = + (void *) ((char *) perfring_ptr + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)); + + if (ring_head->mem_zone->len < + sizeof(struct nsfw_shmem_ring_head) + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)) + { + return 0; + } + + u32 mz_len = + ring_head->mem_zone->len - sizeof(struct nsfw_shmem_ring_head) - + sizeof(struct nsfw_mem_ring) - num * sizeof(union RingData_U); + + u32 start_idx = 0; + u32 elm_num = 0; + elm_num = mz_len / perfring_ptr->eltsize; + while (start > start_idx + elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + return 0; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next-> + mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - sizeof(struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = (void *) ((char *) ring_head + + sizeof(struct nsfw_shmem_ring_head)); + start_idx += elm_num; + } + + u32 cur_idx = start - start_idx; + char *cur_elm = NULL; + int proc_count = 0; + while (cur_idx + start_idx < end && cur_idx + start_idx < (u32) num) + { + if (cur_idx >= elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + break; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next-> + mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - + sizeof(struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = (void *) ((char *) ring_head + + sizeof(struct nsfw_shmem_ring_head)); + start_idx += elm_num; + + cur_idx = 0; + cur_elm = NULL; + continue; + } + + if (NULL == cur_elm) + { + cur_elm = ((char *) mz + cur_idx * perfring_ptr->eltsize); + } + else + { + cur_elm += perfring_ptr->eltsize; + } + + cur_idx++; + proc_count++; + (void) fun(cur_elm, argv); + } + + return proc_count; +} + +i32 +nsfw_shmem_mbuf_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + return dmm_pktmbuf_pool_iterator((struct common_mem_mempool *) handle, + start, end, (dmm_mbuf_item_fun) fun, + argv); +} + +int nsfw_attach_core_id(nsfw_mem_name * name) +{ + return 0; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h new file mode 100644 index 0000000..6fbff59 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h @@ -0,0 +1,135 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MNG_H +#define _NSFW_SHMEM_MNG_H + +/* + * mem mgr module init + * para:point to nstack_fwmem_para + */ +i32 nsfw_shmem_init(nsfw_mem_para * para); + +/* + * mem mgr module destory + * + */ +void nsfw_shmem_destroy(void); + +/* + * create a block memory with name + * fw_mem_zone::stname name of memory + * fw_mem_zone::isize memory size + */ +mzone_handle nsfw_shmem_create(nsfw_mem_zone * pinfo); + +/* + *create some blocks memory + */ +i32 nsfw_shmem_createv(nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num); + +/* + *lookup a memory + */ +mzone_handle nsfw_shmem_lookup(nsfw_mem_name * pname); + +/*release the memory*/ +i32 nsfw_shmem_release(nsfw_mem_name * pname); + +/* + *create mbuf pool + */ +mpool_handle nsfw_shmem_mbfmpcreate(nsfw_mem_mbfpool * pbufinfo); + +/* + *create some mbuf pool + */ +i32 nsfw_shmem_mbfmpcreatev(nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num); + +/* + *alloc a mbuf from mbuf pool + */ +mbuf_handle nsfw_shmem_mbfalloc(mpool_handle mhandle); + +/* + *release a mbuf pool + */ +i32 nsfw_shmem_mbffree(mbuf_handle mhandle); + +/* + *put mbuf back to mbuf pool + */ +i32 nsfw_shmem_mbfmprelease(nsfw_mem_name * pname); + +/*look up mbuf mpool*/ +mpool_handle nsfw_shmem_mbfmplookup(nsfw_mem_name * pmbfname); + +/* + *create simple pool + */ +mring_handle nsfw_shmem_spcreate(nsfw_mem_sppool * pmpinfo); + +/* + *create some simple pools + */ +i32 nsfw_shmem_spcreatev(nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num); + +/* + *create a simple pool that members are rings + */ +i32 nswf_shmem_sp_ringcreate(nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum); + +/* + *release a simple pool + */ +i32 nsfw_shmem_sprelease(nsfw_mem_name * pname); + +/* + *look up a simple pool + */ +mring_handle nsfw_shmem_sp_lookup(nsfw_mem_name * pname); + +/* + *create a ring with name + */ +mring_handle nsfw_shmem_ringcreate(nsfw_mem_mring * pringinfo); + +/* + *look up a ring with name + */ +mring_handle nsfw_shmem_ring_lookup(nsfw_mem_name * pname); + +/* + *release ring + */ +i32 nsfw_shmem_ringrelease(nsfw_mem_name * pname); + +ssize_t nsfw_shmem_static(void *handle, nsfw_mem_struct_type type); + +i32 nsfw_shmem_mbuf_recycle(mpool_handle handle); + +i32 nsfw_shmem_sp_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); +i32 nsfw_shmem_mbuf_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); + +int nsfw_attach_core_id(nsfw_mem_name * name); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c new file mode 100644 index 0000000..f580640 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c @@ -0,0 +1,843 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include + +#include "common_mem_pal_memconfig.h" +#include "nstack_securec.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_mem_buf.h" +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +void +nsfw_shmem_ring_baseaddr_query(uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr) +{ + struct common_mem_mem_config *pMemCfg = + common_mem_pal_get_configuration()->mem_config; + struct common_mem_memseg *PMemSegArry = pMemCfg->memseg; + + *rte_lowest_addr = PMemSegArry[0].addr_64; + *rte_highest_addr = PMemSegArry[0].addr_64 + PMemSegArry[0].len; + + int s = 1; + + while (s < COMMON_MEM_MAX_MEMSEG && PMemSegArry[s].len > 0) + { + if (*rte_lowest_addr > PMemSegArry[s].addr_64) + { + *rte_lowest_addr = PMemSegArry[s].addr_64; + } + + if (*rte_highest_addr < PMemSegArry[s].addr_64 + PMemSegArry[s].len) + { + *rte_highest_addr = PMemSegArry[s].addr_64 + PMemSegArry[s].len; + } + + s++; + } + +} + +static unsigned +nsfw_shmem_pool_node_alloc(struct nsfw_mem_ring *perfring_ptr, + unsigned alloc_index, unsigned max_index, + void *mz, size_t mz_len, unsigned elt_size) +{ + size_t alloc_size = 0; + unsigned offset_idx = 0; + NSTCP_LOGINF("mz(%p), mz_len = 0x%x", mz, mz_len); + + while (alloc_size + elt_size <= mz_len) + { + perfring_ptr->ring[alloc_index + offset_idx].data_s.ver = + alloc_index + offset_idx; + perfring_ptr->ring[alloc_index + offset_idx].data_s.val = + ADDR_LTOSH_EXT(mz) - ((uint64_t) perfring_ptr->Addrbase); + mz = (char *) mz + elt_size; + alloc_size += elt_size; + offset_idx++; + + if (alloc_index + offset_idx == max_index) + { + break; + } + } + + return offset_idx; +} + +void nsfw_shmem_pool_free(struct nsfw_mem_ring *perfring_ptr) +{ + struct nsfw_shmem_ring_head *ptemp; + + if (NULL == perfring_ptr) + { + return; + } + + struct nsfw_shmem_ring_head *pnode = + (struct nsfw_shmem_ring_head *) ((char *) perfring_ptr - + sizeof(struct nsfw_shmem_ring_head)); + + while (pnode) + { + // phead is involved in phead->mem_zone + ptemp = pnode->next; + common_mem_memzone_free(pnode->mem_zone); + pnode = ptemp; + } +} + +struct nsfw_mem_ring *nsfw_shmem_pool_create(const char *name, unsigned int n, + unsigned int elt_size, + int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr = NULL; + struct common_mem_memzone *mz_mem; + void *mz = NULL; + + /*get pool size, pool size must pow of 2 */ + unsigned int num = common_mem_align32pow2(n + 1); + + struct nsfw_shmem_ring_head *pcur = NULL; + /*calculate the empty rte_perf_ring Size */ + size_t len = + sizeof(struct nsfw_shmem_ring_head) + sizeof(struct nsfw_mem_ring) + + (size_t) num * sizeof(union RingData_U) + (size_t) num * elt_size; + size_t alloc_len = len; + unsigned int alloc_num = 0; + unsigned int alloc_index = 0; + + size_t mz_len = 0; + + unsigned int mz_index = 1; + char mz_name[128] = { 0 }; + int retVal; + /*we'd better use `strlen(src)` or `sizeof(dst)` to explain copying length of src string. + it's meaningless using `sizeof(dst) - 1` to reserve 1 byte for '\0'. + if copying length equals to or bigger than dst length, just let STRNCPY_S() returns failure. */ + retVal = strncpy_s(mz_name, sizeof(mz_name), name, sizeof(mz_name)); + + if (EOK != retVal) + { + NSTCP_LOGERR("STRNCPY_S failed]ret=%d", retVal); + return NULL; + } + + mz_mem = common_memzone_data_lookup_name(name); + NSTCP_LOGINF("memzone data look up] n=%u,num=%u,len=%zu", n, num, len); + + if (mz_mem) + { + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct nsfw_shmem_ring_head)); + return perfring_ptr; + } + + while (alloc_len > 0) + { + if (NULL != perfring_ptr) + { + retVal = + sprintf_s(mz_name, sizeof(mz_name), "%s_%03d", name, + mz_index); + + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + } + + mz_mem = + (struct common_mem_memzone *) common_mem_memzone_reserve(mz_name, + alloc_len, + socket_id, + 0); + + if (mz_mem == NULL) + { + mz_mem = + (struct common_mem_memzone *) + common_mem_memzone_reserve(mz_name, 0, socket_id, 0); + } + + if (mz_mem == NULL) + { + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + + if (NULL == perfring_ptr + && (mz_mem->len < + sizeof(struct nsfw_shmem_ring_head) + + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U))) + { + common_mem_memzone_free(mz_mem); + return NULL; + } + + if (NULL == perfring_ptr) + { + pcur = + (struct nsfw_shmem_ring_head *) ADDR_SHTOL(mz_mem->addr_64); + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) pcur + + sizeof(struct + nsfw_shmem_ring_head)); + + mz = (void *) ((char *) perfring_ptr + + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)); + mz_len = + mz_mem->len - sizeof(struct nsfw_shmem_ring_head) - + sizeof(struct nsfw_mem_ring) - num * sizeof(union RingData_U); + + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + nsfw_shmem_ring_baseaddr_query(&rte_base_addr, &rte_highest_addr); + nsfw_mem_pool_head_init(perfring_ptr, num, elt_size, + (void *) rte_base_addr, NSFW_SHMEM, + (nsfw_mpool_type) flag); + } + else + { + if (pcur) + { + pcur->next = + (struct nsfw_shmem_ring_head *) + ADDR_SHTOL(mz_mem->addr_64); + pcur = pcur->next; + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + if (mz_mem->len < sizeof(struct nsfw_shmem_ring_head)) + { + NSRTP_LOGERR("mz_len error %d", mz_mem->len); + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + + mz = (void *) ((char *) pcur + + sizeof(struct nsfw_shmem_ring_head)); + mz_len = mz_mem->len - sizeof(struct nsfw_shmem_ring_head); + } + } + + alloc_num = + nsfw_shmem_pool_node_alloc(perfring_ptr, alloc_index, num, mz, + mz_len, elt_size); + alloc_index += alloc_num; + + if (alloc_index >= num) + { + break; + } + + // second time allocate should not contained all ring head + alloc_len = + (size_t) (num - alloc_index) * elt_size + + sizeof(struct nsfw_shmem_ring_head); + mz_index++; + } + + return perfring_ptr; +} + +/*ring create*/ +struct nsfw_mem_ring *nsfw_shmem_ring_create(const char *name, unsigned int n, + int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr; + struct common_mem_memzone *mz; + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + + unsigned int num = common_mem_align32pow2(n); + + mz = (struct common_mem_memzone *) common_mem_memzone_reserve(name, + sizeof + (struct + nsfw_mem_ring) + + + num * + sizeof(union + RingData_U), + socket_id, + 0); + + if (mz == NULL) + { + return NULL; + } + + perfring_ptr = mz->addr; + + nsfw_shmem_ring_baseaddr_query(&rte_base_addr, &rte_highest_addr); + nsfw_mem_ring_init(perfring_ptr, num, (void *) rte_base_addr, NSFW_SHMEM, + flag); + + return perfring_ptr; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int nsfw_shmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U expectPostVal; + union RingData_U curVal; + unsigned int tmpHead; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int size = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + /*do box range check */ + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + /*invalid addr of box, can't put in rte_perf_ring, maybe should set a errno here */ + return -1; + } + + do + { + /* + if the ring is Full return directly; this not a exact check, cause we made tail++ after dequeue success. + the thing we could make sure is ring[ring->Tail&mask] already dequeue + */ + tmpTail = ring->cons.tail; + + if (tmpTail + size - CurHead == 0) + { + /* + here we give enqueue a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + + /* + the old version of ring->ring[CurHead&mask] must CurHead - size, which enqueue set to this pos lasttime + & the val must already dequeue. otherwise this pos can't enqueue; + */ + expectPostVal.data_l = + (((unsigned long long) (CurHead - size)) << VALUE_LEN); + + /* + the new version of ring->ring[CurHead&mask] must CurHead, which enqueue set to this pos this time. + */ + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + if (ring->ring[CurHead & mask].data_s.ver == expectPostVal.data_s.ver + && __sync_bool_compare_and_swap(&ring-> + ring[CurHead & mask].data_l, + expectPostVal.data_l, + curVal.data_l)) + { + /* + enqueue success, add Head Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Head, 1) to assume that, if one process enqueue success && been killed before + add Head, other process can recorrect the Head Value; + one more thing the direction of Tail must been add-direction, so we using the condition (ring->Head - CurHead >0x80000000); + while many thread do enqueue at same time, Head may not correct,exp: + thread A get old head 10, thread A want set head to 11 + thread B get old head 10, thread B want set head to 12 + thread A do CAS && thread B do CAS at same time, thread A do CAS success; + the result of head is 11, but the correct Value should be 12; + + then thread C get old head 11, thread C will set head to 13[cause pos 12 already has value, thread C will skill 12], + the head will be recorrect by thread C. + if no thread C, thread A& B are the last enqueue thread; the head must recorrect by the deque function. + */ + tmpHead = ring->prod.head; + + if (0 == (CurHead & 0x03) && tmpHead - CurHead > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + CurHead + 1); + } + + break; + } + + /* + CurHead++ here; + may be cpu slice is end here; while re-sched CurHead < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurHead++ instead CurHead++ directly. + if using CurHead++ will amplify the probability of ABA problem + */ + /*CurHead++; */ + tmpHead = ring->prod.head; + CurHead = CurHead - tmpHead < mask - 1 ? CurHead + 1 : tmpHead; + } + while (1); + + return 1; +} + +/* + this is a single thread/process enqueue function + */ +int nsfw_shmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U texpectPostVal; + union RingData_U curVal; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int uisize = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + return -1; + } + + do + { + tmpTail = ring->cons.tail; + if (tmpTail + uisize - CurHead == 0) + { + /* + *here we give enqueue a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + texpectPostVal.data_l = + (((unsigned long long) (CurHead - uisize)) << VALUE_LEN); + + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + + if (ring->ring[CurHead & mask].data_l == texpectPostVal.data_l) + { + ring->ring[CurHead & mask].data_l = curVal.data_l; + ring->prod.head = CurHead + 1; + break; + } + + CurHead++; + } + while (1); + return 1; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +*/ +int nsfw_shmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + + CurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap(&ring-> + ring[CurTail & mask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + *box = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue success && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + while multi CAS done the result value of CurTail may not correct, but we don't care, it will be recorrect while next deque done. + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (CurTail & 0x03) && tmpTail - CurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + CurTail + 1); + } + break; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + CurTail = CurTail - tmpTail < mask - 1 ? CurTail + 1 : tmpTail; + } + while (1); + + return 1; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_shmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int uiCurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int uimask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int deqNum = 0; + uiCurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (uiCurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (deqNum == 0 && ring->ring[tmpHead & uimask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return deqNum; + } + } + + curNullVal.data_l = (((unsigned long long) uiCurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[uiCurTail & uimask]; + + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap(&ring-> + ring[uiCurTail & uimask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + box[deqNum] = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue success && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (uiCurTail & 0x03) && tmpTail - uiCurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + uiCurTail + 1); + } + + deqNum++; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + uiCurTail = + uiCurTail - tmpTail < uimask - 1 ? uiCurTail + 1 : tmpTail; + + } + while (n > deqNum); + + return deqNum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int nsfw_shmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int uitmpHead; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + uitmpHead = ring->prod.head; + if (CurTail == uitmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[uitmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, + uitmpHead, uitmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + *box = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + break; + } + + CurTail++; + } + while (1); + + return 1; +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_shmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int CurTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int usdeqNum = 0; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (usdeqNum == 0 && ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return usdeqNum; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + /* + the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + box[usdeqNum] = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + usdeqNum++; + } + + CurTail++; + } + while (n > usdeqNum); + + return usdeqNum; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + void *prmBox = NULL; + + /*if queue is full, just return 0 */ + if (ring->prod.head >= (ring->size + ring->cons.tail)) + { + return 0; + } + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + head = ring->prod.head; + ring->prod.head = head + 1; + ring->ring[head & ring->mask].data_s.ver = head; + ring->ring[head & ring->mask].data_s.val = + (char *) prmBox - (char *) ring->Addrbase; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + u32 tail = 0; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return 0; + } + + tail = ring->cons.tail; + *box = + ADDR_SHTOL((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + ring->cons.tail++; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return num; + } + + ring->cons.tail = tail + 1; + + box[num] = + ADDR_SHTOL((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + num++; + } + + return num; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h new file mode 100644 index 0000000..af7c30c --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h @@ -0,0 +1,60 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_RING_H_ +#define _NSFW_SHMEM_RING_H_ + +#include + +#include "common_func.h" + +struct nsfw_shmem_ring_head +{ + struct common_mem_memzone *mem_zone; + struct nsfw_shmem_ring_head *next; + unsigned int uireserv[4]; +}; + +void nsfw_shmem_ring_baseaddr_query(uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr); +struct nsfw_mem_ring *nsfw_shmem_pool_create(const char *name, + unsigned int n, + unsigned int elt_size, + int socket_id, + unsigned char flag); +struct nsfw_mem_ring *nsfw_shmem_ring_create(const char *name, + unsigned int n, int socket_id, + unsigned char flag); + +void nsfw_shmem_pool_free(struct nsfw_mem_ring *perfring_ptr); + +void nsfw_shmem_ring_reset(struct nsfw_mem_ring *ring, unsigned char flag); +int nsfw_shmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, + void *box); +int nsfw_shmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, + void **box); +int nsfw_shmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_SHMEM_RING_H_*/ diff --git a/stacks/lwip_stack/src/nStackMain/CMakeLists.txt b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt new file mode 100644 index 0000000..22bf8b8 --- /dev/null +++ b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt @@ -0,0 +1,66 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +FILE(GLOB_RECURSE MAIN *.c) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -pie") + +ADD_DEFINITIONS(-rdynamic -D__NSTACK_MAIN__) +ADD_EXECUTABLE(nStackMain ${MAIN}) +TARGET_LINK_LIBRARIES( + nStackMain + -Wl,--whole-archive + ${LIB_PATH_STATIC}/libjson-c.a + ${LIB_PATH_STATIC}/libglog.a + nStackFw + stacklwip + nStackHal + nStackAlarm + nTcpdump + nsfw_mem + -Wl,--no-whole-archive,-lstdc++ -ldl + -Wl,--no-as-needed + rte_eal + rte_ethdev + rte_mempool + rte_ring + rte_mbuf + rte_pmd_ixgbe + rte_pmd_virtio + rte_pmd_e1000 + rte_pmd_vmxnet3_uio + rte_pmd_bond + rte_kvargs + rte_cmdline +) + +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(nStackMain nStackAlarm stacklwip SECUREC) +else() +ADD_DEPENDENCIES(nStackMain nStackAlarm stacklwip) +endif() + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../alarm/ + ${CMAKE_CURRENT_LIST_DIR}/../maintain/ + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_shmem/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_nshmem/ +) diff --git a/stacks/lwip_stack/src/nStackMain/main.c b/stacks/lwip_stack/src/nStackMain/main.c new file mode 100644 index 0000000..6f58823 --- /dev/null +++ b/stacks/lwip_stack/src/nStackMain/main.c @@ -0,0 +1,457 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "nstack_securec.h" +#include "nstack_log.h" +#include "types.h" +#include "nsfw_init_api.h" +#include "alarm_api.h" + +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_recycle_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" +#include "nstack_dmm_adpt.h" + +#include "nsfw_mem_api.h" +#include "nsfw_mt_config.h" +#include "nsfw_shmem_mdesc.h" +#include "nsfw_nshmem_mdesc.h" + +#define GLOBAL_Stack_ARG "stack" +#define GlOBAL_HELP "--help" +#define GLOBAL_Dpdk_ARG "dpdk" +#define GLOBAL_STACK_PORT "-port" +#define NSTACK_MAIN_MAX_PARA 32 +#define NSTACK_MAIN_MIN_PARA 1 + +#define MAX_MASTER_OPEN_FD 1024 + +extern int uStackArgIndex; +extern void spl_tcpip_thread(void *arg); +extern int globalArgc; +extern char **gArgv; +extern int g_dpdk_argc; +extern char **g_dpdk_argv; +extern void print_call_stack(); +extern int adjust_mem_arg(int argc, char *argv[]); +extern struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM]; +extern int get_network_json_data(); +extern int get_ip_json_data(); +extern nsfw_ring_ops + g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX]; + +#ifdef SYS_MEM_RES_STAT +extern void get_resource_stat(); +#endif + +extern alarm_result ms_alarm_check_func(void *para); +int g_tcpip_thread_stat = 0; //this variable will be used at health check feature + +#if (DPDK_MODULE) +extern void pal_common_usage(void); +#endif + +typedef void (*pSignalFunc) (int); +int app_init(void); + +void helpInfo() +{ + NSPOL_LOGERR + ("-----------------------------------------------------------------" + "\nThe format of arg" + "\nbash:./nStackMain RTE-ARGS stack STACK-ARGS" + "\n RTE-ARGS=-c COREMASK -n NUM [-b ] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type ] [-- xen-dom0]" + "\n STACK-ARGS=-port PORTMASK [-c COREMASK] [-thread NUM]" + "\nUser examples:" + "\nTo make the DPDK run on core mask:0xf,Number of memory channels per processor socket in DPDK is 3 " + "\nTo make the stack run on eth coremask:f" + "\nbash: ./nStackMain -c 0xf -n 3 stack -port f" + "\nTo get more help info for stack:" "\n ./nStackMain --help stack" + "\nTo get more help info for dpdk:" "\n ./nStackMain --help dpdk" + "\n-----------------------------------------------------------------"); + +#ifndef FOR_NSTACK_UT + exit(0); +#endif + +} + +#define SIG_PTRACE __SIGRTMIN + 5 + +void signal_handler(int s) +{ + NSPOL_LOGERR("Received signal exiting.]s=%d", s); + if (s == SIGSEGV) /* add for gdb attach work */ + { + print_call_stack(); + } + + nstack_segment_error(s); + if ((SIG_PTRACE != s) && (SIG_PTRACE + 2 != s)) + { +#ifndef FOR_NSTACK_UT + exit(0); +#endif + } + + int i; + for (i = 0; i < MAX_THREAD; i++) + { + if (g_all_thread[i] != pthread_self() && 0 != g_all_thread[i]) + { + NSFW_LOGERR("send sig thread %d", g_all_thread[i]); + if (0 == pthread_kill(g_all_thread[i], SIG_PTRACE + 2)) + { + return; + } + } + g_all_thread[i] = 0; + } + + for (i = 0; i < MAX_THREAD; i++) + { + if (0 != g_all_thread[i]) + { + return; + } + } + +#ifndef FOR_NSTACK_UT + exit(0); +#endif + + //dpdk_signal_handler(); +} + +void register_signal_handler() +{ +/* donot catch SIGHUP SIGTERM */ + static const int s_need_handle_signals[] = { + SIGABRT, + SIGBUS, + SIGFPE, + SIGILL, + SIGIOT, + SIGQUIT, + SIGSEGV, + //SIGTRAP, + SIGXCPU, + SIGXFSZ, + //SIGALRM, + //SIGHUP, + SIGINT, + //SIGKILL, + SIGPIPE, + SIGPROF, + SIGSYS, + //SIGTERM, + SIGUSR1, + SIGUSR2, + //SIGVTALRM, + //SIGSTOP, + //SIGTSTP, + //SIGTTIN, + //SIGTTOU + }; + + /* here mask signal that will use in sigwait() */ + sigset_t waitset, oset; + + if (0 != sigemptyset(&waitset)) + { + NSPOL_LOGERR("sigemptyset failed."); + } + sigaddset(&waitset, SIGRTMIN); /* for timer */ + sigaddset(&waitset, SIGRTMIN + 2); + pthread_sigmask(SIG_BLOCK, &waitset, &oset); + unsigned int i = 0; + + struct sigaction s; + s.sa_handler = signal_handler; + if (0 != sigemptyset(&s.sa_mask)) + { + NSPOL_LOGERR("sigemptyset failed."); + } + + s.sa_flags = (int) SA_RESETHAND; + + /* register sig handler for more signals */ + for (i = 0; i < sizeof(s_need_handle_signals) / sizeof(int); i++) + { + if (sigaction(s_need_handle_signals[i], &s, NULL) != 0) + { + NSPOL_LOGERR("Could not register %d signal handler.", + s_need_handle_signals[i]); + } + + } + +} + +void checkArgs(int argc, char **argv) +{ + int uStackArg = 0; //mark the status whether need helpinfo and return + int i; + const unsigned int global_para_length = 5; //GLOBAL_Stack_ARG "stack" and GLOBAL_STACK_PORT "-port" string length, both are 5 + const unsigned int global_help_length = 6; //GlOBAL_HELP "--help" string length is 6 + const unsigned int global_dpdk_length = 4; //GLOBAL_Dpdk_ARG "dpdk" string length is 4 + + for (i = 0; i < argc; i++) + { + if (argc > 1) + { + if (strncmp(argv[i], GLOBAL_Stack_ARG, global_para_length) == 0) + { + if (i < 5) + { + NSPOL_LOGERR("Too less args"); + helpInfo(); + return; + } + + uStackArg = 1; + uStackArgIndex = i; + continue; + } + + if (strncmp(argv[i], GLOBAL_STACK_PORT, global_para_length) == 0) + { + continue; + } + + if (strncmp(argv[i], GlOBAL_HELP, global_help_length) == 0) + { + if (i == (argc - 1)) + { + helpInfo(); + return; + } + else if ((++i < argc) + && + (strncmp + (argv[i], GLOBAL_Dpdk_ARG, + global_dpdk_length) == 0)) + { +#if (DPDK_MODULE != 1) + //eal_common_usage(); +#else + pal_common_usage(); +#endif + return; + } + else + { + helpInfo(); + return; + } + } + } + else + { + NSPOL_LOGERR("Too less args"); + helpInfo(); + return; + } + } + + if (!uStackArg) + { + helpInfo(); + return; + } +} + +extern u64 timer_get_threadid(); + +#ifdef FOR_NSTACK_UT +int nstack_main(void) +{ + int argc; + + char *argv[NSTACK_MAIN_MAX_PARA]; + argv[0] = "nStackMain"; + argv[1] = "-c";; + argv[2] = "0xffffffff"; + argv[3] = "-n"; + argv[4] = "3"; + argv[5] = "stack"; + argv[6] = "-port"; + argv[7] = "288"; + argv[8] = "-c"; + argv[9] = "2"; + argc = 10; + +#else +int main(int argc, char *argv[]) +{ +#endif + fw_poc_type proc_type = NSFW_PROC_MAIN; + + /* although nStackMaster has set close on exec, here can't be removed. + * in upgrade senario, if Master is old which has not set close on exec, here, + * if new version Main not close, problem will reappear. Add Begin*/ + int i; + for (i = 4; i < MAX_MASTER_OPEN_FD; i++) + { + close(i); + } + + cfg_module_param config_para; + config_para.proc_type = proc_type; + config_para.argc = argc; + config_para.argv = (unsigned char **) argv; + config_module_init(&config_para); + + set_log_proc_type(LOG_PRO_NSTACK); + (void) nstack_log_init(); + +// nstack_tracing_enable(); + if (0 != nsfw_proc_start_with_lock(NSFW_PROC_MAIN)) + { + NSFW_LOGERR("another process is running!!"); + return 0; + } + + if (1 != mallopt(M_ARENA_MAX, 1)) + { + NSPOL_LOGERR("Error: mallopt fail, continue init"); + } + + /* Set different mem args to PAL and EAL */ + INITPOL_LOGINF("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + if (adjust_mem_arg(argc, argv)) + { + INITPOL_LOGERR("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + return -1; + } + INITPOL_LOGINF("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + checkArgs(globalArgc, gArgv); + register_signal_handler(); + + (void) signal(SIG_PTRACE, signal_handler); + (void) signal(SIG_PTRACE + 2, signal_handler); + + if (nsfw_mgr_comm_fd_init(NSFW_PROC_MAIN) < 0) + { + NSFW_LOGERR("nsfw_mgr_comm_fd_init failed"); + } + + (void) nsfw_reg_trace_thread(pthread_self()); + + nsfw_mem_para stinfo = { 0 }; + stinfo.iargsnum = uStackArgIndex; + stinfo.pargs = gArgv; + stinfo.enflag = proc_type; + (void) nstack_framework_set_module_param(NSFW_MEM_MGR_MODULE, &stinfo); + (void) nstack_framework_set_module_param(NSFW_MGR_COM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_TIMER_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_RECYCLE_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_LOG_CFG_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_VER_MGR_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(SPL_RES_MGR_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_SOFT_PARAM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_ALARM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(TCPDUMP_MODULE, + (void *) ((u64) proc_type)); + proc_type = NSFW_PROC_MASTER; + (void) nstack_framework_set_module_param(NSFW_PS_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_PS_MEM_MODULE, + (void *) ((u64) proc_type)); + + g_nsfw_mem_ops[NSFW_SHMEM].stmemop = &g_shmem_ops; + g_nsfw_mem_ops[NSFW_NSHMEM].stmemop = &g_nshmem_ops; + nsfw_ring_ops *ring_ops = (nsfw_ring_ops *) g_ring_ops_arry; + nsfw_ring_ops *temp_ring_ops = (nsfw_ring_ops *) g_ring_ops_arry_lwip; + for (i = 0; i < NSFW_MEM_TYPEMAX * NSFW_MPOOL_TYPEMAX; i++) + { + ring_ops[i] = *temp_ring_ops; + temp_ring_ops++; + } + + int init_ret = nstack_framework_init(); + if (init_ret < 0) + { + NSFW_LOGERR + ("######################init failed!!!!######################"); + return -1; + } + + ns_send_init_alarm(ALARM_EVENT_NSTACK_MAIN_ABNORMAL); + + while (!timer_get_threadid()) + { + (void) nsfw_thread_chk(); + sys_sleep_ns(0, 500000000); + } + (void) nsfw_thread_chk_unreg(); + NSFW_LOGINF("tcpip thread start!"); + (void) sleep(2); + + NSFW_LOGINF("read configuration!"); + if (0 != get_network_json_data()) + { + NSFW_LOGINF("get_network_json_data error"); + return -1; + } + + if (0 != get_ip_json_data()) + { + NSFW_LOGINF("get_ip_json_data error"); + return -1; + } + + int ep_thread = 0; + while (1) + { +#ifdef SYS_MEM_RES_STAT + get_resource_stat(); +#endif + (void) sleep(3); + ep_thread = nsfw_mgr_com_chk_hbt(1); + if (ep_thread > 0) + { + NSFW_LOGINF("force release lock"); + (void) nsfw_recycle_rechk_lock(); + } +#ifdef FOR_NSTACK_UT + return 0; +#endif + + } +} diff --git a/stacks/lwip_stack/src/sbr/CMakeLists.txt b/stacks/lwip_stack/src/sbr/CMakeLists.txt new file mode 100644 index 0000000..8bd5007 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/CMakeLists.txt @@ -0,0 +1,37 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +endif() + + +FILE(GLOB SBR *.c) +ADD_LIBRARY(lwip_dpdk SHARED ${SBR}) +TARGET_LINK_LIBRARIES(lwip_dpdk -Wl,--whole-archive socket nsfw_mem -Wl,--no-whole-archive rte_eal rte_mempool rte_ring rte_mbuf) +ADD_DEPENDENCIES(lwip_dpdk socket DPDK) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${PAL_H_DIRECTORIES} + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../stacks/lwip_stack/src/mem/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_shmem/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_nshmem/ +) diff --git a/stacks/lwip_stack/src/sbr/sbr_err.h b/stacks/lwip_stack/src/sbr/sbr_err.h new file mode 100644 index 0000000..96b5399 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_err.h @@ -0,0 +1,190 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SBR_ERR_H +#define SBR_ERR_H +#include + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifdef SBR_PROVIDE_ERRNO +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No stored locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#define ENSROK 0 +#define ENSRNODATA 160 +#define ENSRFORMERR 161 +#define ENSRSERVFAIL 162 +#define ENSRNOTFOUND 163 +#define ENSRNOTIMP 164 +#define ENSRREFUSED 165 +#define ENSRBADQUERY 166 +#define ENSRBADNAME 167 +#define ENSRBADFAMILY 168 +#define ENSRBADRESP 169 +#define ENSRCONNREFUSED 170 +#define ENSRTIMEOUT 171 +#define ENSROF 172 +#define ENSRFILE 173 +#define ENSRNOMEM 174 +#define ENSRDESTRUCTION 175 +#define ENSRQUERYDOMAINTOOLONG 176 +#define ENSRCNAMELOOP 177 +#define OPTION_DEG 200 + +#endif + +static inline void sbr_set_errno(int err) +{ + errno = err; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.c b/stacks/lwip_stack/src/sbr/sbr_index_ring.c new file mode 100644 index 0000000..b684918 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_index_ring.c @@ -0,0 +1,212 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "sbr_index_ring.h" +#include "nstack_securec.h" +#include "common_mem_common.h" +#include "common_func.h" + +/***************************************************************************** +* Prototype : sbr_init_index_ring +* Description : init index ring +* Input : sbr_index_ring* ring +* u32 num +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_init_index_ring(sbr_index_ring * ring, u32 num) +{ + u32 loop; + + ring->head = 0; + ring->tail = 0; + ring->num = num; + ring->mask = num - 1; + + for (loop = 0; loop < num; loop++) + { + ring->nodes[loop].ver = (loop - num); + ring->nodes[loop].val = 0; + } +} + +/***************************************************************************** +* Prototype : sbr_create_index_ring +* Description : create index ring +* Input : u32 num +* Output : None +* Return Value : sbr_index_ring* +* Calls : +* Called By : +* +*****************************************************************************/ +sbr_index_ring *sbr_create_index_ring(u32 num) +{ + num = common_mem_align32pow2(num + 1); + sbr_index_ring *ring = + (sbr_index_ring *) malloc(sizeof(sbr_index_ring) + + num * sizeof(sbr_index_node)); + if (!ring) + { + return NULL; + } + + sbr_init_index_ring(ring, num); + return ring; +} + +/***************************************************************************** +* Prototype : sbr_index_ring_enqueue +* Description : enqueue data,val != 0 +* Input : sbr_index_ring* ring +* i32 val +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_index_ring_enqueue(sbr_index_ring * ring, i32 val) +{ + if (0 == val) + { + return -1; + } + + sbr_index_node expect_node; + sbr_index_node cur_node; + u32 tmp_head; + u32 tmp_tail; + u32 cur_head = ring->head; + u32 mask = ring->mask; + u32 size = ring->num; + + do + { + tmp_tail = ring->tail; + if (tmp_tail + size - cur_head == 0) + { + if (ring->nodes[tmp_tail & mask].val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->tail, tmp_tail, + tmp_tail + 1); + } + else + { + return 0; + } + } + + expect_node.ver = cur_head - size; + expect_node.val = 0; + + cur_node.ver = cur_head; + cur_node.val = val; + + if ((ring->nodes[cur_head & mask].ver == expect_node.ver) + && __sync_bool_compare_and_swap(&ring-> + nodes[cur_head & mask].data, + expect_node.data, cur_node.data)) + { + tmp_head = ring->head; + if ((tmp_head - cur_head > 0x80000000) + && (0 == (cur_head & 0x11))) + { + (void) __sync_bool_compare_and_swap(&ring->head, tmp_head, + cur_head); + } + + break; + } + + tmp_head = ring->head; + cur_head = cur_head - tmp_head < mask - 1 ? cur_head + 1 : tmp_head; + } + while (1); + + return 1; +} + +/***************************************************************************** +* Prototype : sbr_index_ring_dequeue +* Description : dequeue +* Input : sbr_index_ring* ring +* i32* val +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_index_ring_dequeue(sbr_index_ring * ring, i32 * val) +{ + u32 cur_tail; + u32 tmp_tail; + u32 tmp_head; + u32 mask = ring->mask; + sbr_index_node null_node; + sbr_index_node expect_node; + + cur_tail = ring->tail; + do + { + tmp_head = ring->head; + if (cur_tail == tmp_head) + { + if (0 != (ring->nodes[tmp_head & mask].val)) + { + (void) __sync_bool_compare_and_swap(&ring->head, tmp_head, + tmp_head + 1); + } + else + { + return 0; + } + } + + null_node.ver = cur_tail; + null_node.val = 0; + expect_node = ring->nodes[cur_tail & mask]; + + if ((null_node.ver == expect_node.ver) && (expect_node.val) + && __sync_bool_compare_and_swap(&ring-> + nodes[cur_tail & mask].data, + expect_node.data, null_node.data)) + + { + *val = expect_node.val; + tmp_tail = ring->tail; + if ((tmp_tail - cur_tail > 0x80000000) + && (0 == (cur_tail & 0x11))) + { + (void) __sync_bool_compare_and_swap(&ring->tail, tmp_tail, + cur_tail); + } + + break; + } + + tmp_tail = ring->tail; + cur_tail = cur_tail - tmp_tail < mask - 1 ? cur_tail + 1 : tmp_tail; + } + while (1); + + return 1; +} diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.h b/stacks/lwip_stack/src/sbr/sbr_index_ring.h new file mode 100644 index 0000000..7a1e396 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_index_ring.h @@ -0,0 +1,61 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _SBR_INDEX_RING_H_ +#define _SBR_INDEX_RING_H_ + +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct +{ + union + { + struct + { + volatile u32 ver; + volatile u32 val; + }; + u64 data; + }; +} sbr_index_node; + +typedef struct +{ + volatile u32 head; + i8 cache_space[124]; + volatile u32 tail; + u32 num; + u32 mask; + sbr_index_node nodes[0]; +} sbr_index_ring; + +sbr_index_ring *sbr_create_index_ring(u32 num); +int sbr_index_ring_enqueue(sbr_index_ring * ring, i32 val); +int sbr_index_ring_dequeue(sbr_index_ring * ring, i32 * val); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/sbr/sbr_protocol_api.h b/stacks/lwip_stack/src/sbr/sbr_protocol_api.h new file mode 100644 index 0000000..16608bc --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_protocol_api.h @@ -0,0 +1,102 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SBR_PROTOCOL_API_H +#define SBR_PROTOCOL_API_H +#include +#include +#include +#include "sbr_err.h" +#include "nsfw_msg_api.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef SBR_MAX_INTEGER +#define SBR_MAX_INTEGER 0x7FFFFFFF +#endif + +#ifndef socklen_t +#define socklen_t u32 +#endif + +#define SBR_MAX_FD_NUM MAX_SOCKET_NUM + +typedef struct sbr_socket_s sbr_socket_t; +typedef struct +{ + int (*socket) (sbr_socket_t *, int, int, int); + int (*bind) (sbr_socket_t *, const struct sockaddr *, socklen_t); + int (*listen) (sbr_socket_t *, int); + int (*accept) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *, + socklen_t *); + int (*accept4) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *, + socklen_t *, int); + int (*connect) (sbr_socket_t *, const struct sockaddr *, socklen_t); + int (*shutdown) (sbr_socket_t *, int); + int (*getsockname) (sbr_socket_t *, struct sockaddr *, socklen_t *); + int (*getpeername) (sbr_socket_t *, struct sockaddr *, socklen_t *); + int (*getsockopt) (sbr_socket_t *, int, int, void *, socklen_t *); + int (*setsockopt) (sbr_socket_t *, int, int, const void *, socklen_t); + int (*recvfrom) (sbr_socket_t *, void *, size_t, int, struct sockaddr *, + socklen_t *); + int (*readv) (sbr_socket_t *, const struct iovec *, int); + int (*recvmsg) (sbr_socket_t *, struct msghdr *, int); + int (*send) (sbr_socket_t *, const void *, size_t, int); + int (*sendto) (sbr_socket_t *, const void *, size_t, int, + const struct sockaddr *, socklen_t); + int (*sendmsg) (sbr_socket_t *, const struct msghdr *, int); + int (*writev) (sbr_socket_t *, const struct iovec *, int); + int (*fcntl) (sbr_socket_t *, int, long); + int (*ioctl) (sbr_socket_t *, unsigned long, void *); + int (*close) (sbr_socket_t *); + int (*peak) (sbr_socket_t *); + void (*lock_common) (sbr_socket_t *); + void (*unlock_common) (sbr_socket_t *); + void (*fork_parent) (sbr_socket_t *, pid_t); + void (*fork_child) (sbr_socket_t *, pid_t, pid_t); + void (*(*ep_triggle) (sbr_socket_t *, int triggle_ops, void *, void *)); + int (*ep_getevt) (sbr_socket_t *); + void (*set_app_info) (sbr_socket_t *, void *appinfo); + void (*set_close_stat) (sbr_socket_t *, int flag); +} sbr_fdopt; + +struct sbr_socket_s +{ + int fd; + sbr_fdopt *fdopt; + void *stack_obj; + void *sk_obj; +}; + +int sbr_init_protocol(); +int sbr_fork_protocol(); +sbr_fdopt *sbr_get_fdopt(int domain, int type, int protocol); +void sbr_app_touch_in(void); /*app send its version info to nStackMain */ +int lwip_try_select(int fdsize, fd_set * fdread, fd_set * fdwrite, + fd_set * fderr, struct timeval *timeout); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/sbr/sbr_res_mgr.c b/stacks/lwip_stack/src/sbr/sbr_res_mgr.c new file mode 100644 index 0000000..3758084 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.c @@ -0,0 +1,87 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_securec.h" +#include "sbr_res_mgr.h" + +sbr_res_group g_res_group = { }; + +/***************************************************************************** +* Prototype : sbr_init_sk +* Description : init sock pool +* Input : None +* Output : None +* Return Value : static int +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC int sbr_init_sk() +{ + sbr_index_ring *ring = sbr_create_index_ring(SBR_MAX_FD_NUM - 1); + + if (!ring) + { + NSSBR_LOGERR("init ring failed"); + return -1; + } + + int i; + /*the queue can't accept value=0, so i begin with 1 */ + for (i = 1; i <= SBR_MAX_FD_NUM; ++i) + { + g_res_group.sk[i].fd = i; + if (sbr_index_ring_enqueue(ring, i) != 1) + { + NSSBR_LOGERR + ("sbr_index_ring_enqueue failed, this can not happen"); + free(ring); + return -1; + } + } + + g_res_group.sk_ring = ring; + return 0; +} + +/***************************************************************************** +* Prototype : sbr_init_res +* Description : init sbr res +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_init_res() +{ + if (sbr_init_sk() != 0) + { + return -1; + } + + NSSBR_LOGDBG("init socket ok"); + + if (sbr_init_protocol() != 0) + { + return -1; + } + + NSSBR_LOGDBG("init protocol ok"); + + return 0; +} diff --git a/stacks/lwip_stack/src/sbr/sbr_res_mgr.h b/stacks/lwip_stack/src/sbr/sbr_res_mgr.h new file mode 100644 index 0000000..d597ef7 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.h @@ -0,0 +1,155 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SBR_RES_MGR_H +#define SBR_RES_MGR_H +#include "sbr_protocol_api.h" +#include "sbr_index_ring.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct +{ + sbr_index_ring *sk_ring; + sbr_socket_t sk[SBR_MAX_FD_NUM + 1]; /* unuse index 0 */ +} sbr_res_group; + +extern sbr_res_group g_res_group; + +/***************************************************************************** +* Prototype : sbr_malloc_sk +* Description : malloc sock +* Input : None +* Output : None +* Return Value : static inline sbr_socket_t * +* Calls : +* Called By : +* +*****************************************************************************/ +static inline sbr_socket_t *sbr_malloc_sk() +{ + int fd; + + if (sbr_index_ring_dequeue(g_res_group.sk_ring, &fd) != 1) + { + NSSBR_LOGERR("malloc sk failed]"); + sbr_set_errno(EMFILE); + return NULL; + } + + NSSBR_LOGDBG("malloc sk ok]fd=%d", fd); + return &g_res_group.sk[fd]; +} + +/***************************************************************************** +* Prototype : sbr_free_sk +* Description : free sock +* Input : sbr_socket_t * sk +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_free_sk(sbr_socket_t * sk) +{ + sk->fdopt = NULL; + sk->sk_obj = NULL; + sk->stack_obj = NULL; + + if (sbr_index_ring_enqueue(g_res_group.sk_ring, sk->fd) != 1) + { + NSSBR_LOGERR("sbr_index_ring_enqueue failed, this can not happen"); + } + + NSSBR_LOGDBG("free sk ok]fd=%d", sk->fd); +} + +/***************************************************************************** +* Prototype : sbr_lookup_sk +* Description : lookup socket +* Input : int fd +* Output : None +* Return Value : static inline sbr_socket_t * +* Calls : +* Called By : +* +*****************************************************************************/ +static inline sbr_socket_t *sbr_lookup_sk(int fd) +{ + if ((fd < 1) || (fd > SBR_MAX_FD_NUM)) + { + NSSBR_LOGERR("fd is not ok]fd=%d", fd); + sbr_set_errno(EBADF); + return NULL; + } + + sbr_socket_t *sk = &g_res_group.sk[fd]; + if (!sk->sk_obj || !sk->stack_obj) + { + NSSBR_LOGERR + ("data in sk is error, this can not happen]fd=%d,sk_obj=%p,stack_obj=%p", + fd, sk->sk_obj, sk->stack_obj); + sbr_set_errno(EBADF); + return NULL; + } + + return sk; +} + +/***************************************************************************** +* Prototype : sbr_free_sk +* Description : free sock +* Input : sbr_socket_t * sk +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_free_fd(int fd) +{ + if ((fd < 1) || (fd > SBR_MAX_FD_NUM)) + { + NSSBR_LOGERR("fd is not ok]fd=%d", fd); + sbr_set_errno(EBADF); + return; + } + + sbr_socket_t *sk = &g_res_group.sk[fd]; + if (!sk->fdopt && !sk->sk_obj && !sk->stack_obj) + { + NSSBR_LOGERR + ("can't free empty fd] fd=%d, fdopt=%p, sk_obj=%p, stack_obj=%p", + fd, sk->fdopt, sk->sk_obj, sk->stack_obj); + return; + } + sbr_free_sk(sk); +} + +int sbr_init_res(); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/sbr/sbr_socket.c b/stacks/lwip_stack/src/sbr/sbr_socket.c new file mode 100644 index 0000000..27f3ad1 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_socket.c @@ -0,0 +1,1324 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include "sbr_protocol_api.h" +#include "sbr_res_mgr.h" +#include "nstack_log.h" +#include "nsfw_shmem_mdesc.h" +#include "nsfw_nshmem_mdesc.h" +#include "nstack_callback_ops.h" +#include "nstack_rd_data.h" + +#define SBR_INTERCEPT(ret, name, args) ret sbr_ ## name args +#define CALL_SBR_INTERCEPT(name, args) sbr_ ## name args +#define GET_SBR_INTERCEPT(name) sbr_ ## name + +void *lwip_rd_table = NULL; +extern nsfw_ring_ops + g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX]; + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : create socket +* Input : int +* socket +* (int domain +* int type +* int protocol) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, socket, (int domain, int type, int protocol)) +{ + NSSBR_LOGDBG("socket]domain=%d,type=%d,protocol=%d", domain, type, + protocol); + sbr_fdopt *fdopt = sbr_get_fdopt(domain, type, protocol); + + if (!fdopt) + { + return -1; + } + + sbr_socket_t *sk = sbr_malloc_sk(); + + if (!sk) + { + return -1; + } + + sk->fdopt = fdopt; + + int ret = sk->fdopt->socket(sk, domain, type, protocol); + + if (ret != 0) + { + sbr_free_sk(sk); + return ret; + } + + return sk->fd; +} + +/***************************************************************************** +* Prototype : sbr_check_addr +* Description : check addr +* Input : int s +* struct sockaddr * addr +* socklen_t * addrlen +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_check_addr(int s, struct sockaddr *addr, socklen_t * addrlen) +{ + if (addr) + { + if (!addrlen) + { + NSSBR_LOGERR("addrlen is null]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + if (0 > (int) (*addrlen)) + { + NSSBR_LOGERR("addrlen is negative]fd=%d,addrlen=%d", s, *addrlen); + sbr_set_errno(EINVAL); + return -1; + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : accept4 +* Input : int +* accept4 +* (int s +* struct sockaddr * addr +* socklen_t * addrlen +* int flags) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, accept4, + (int s, struct sockaddr * addr, socklen_t * addrlen, int flags)) +{ + NSSBR_LOGDBG("accept4]fd=%d,addr=%p,addrlen=%p,flags=%d", s, addr, + addrlen, flags); + int ret = sbr_check_addr(s, addr, addrlen); + + if (ret != 0) + { + return ret; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sbr_socket_t *new_sk = sbr_malloc_sk(); + if (!new_sk) + { + return -1; + } + + new_sk->fdopt = sk->fdopt; + + ret = sk->fdopt->accept4(sk, new_sk, addr, addrlen, flags); + if (-1 == ret) + { + sbr_free_sk(new_sk); + } + + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : accept +* Input : int +* accept +* (int s +* struct sockaddr * addr +* socklen_t * addrlen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, accept, + (int s, struct sockaddr * addr, socklen_t * addrlen)) +{ + NSSBR_LOGDBG("accept]fd=%d,addr=%p,addrlen=%p", s, addr, addrlen); + int ret = sbr_check_addr(s, addr, addrlen); + + if (ret != 0) + { + return ret; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sbr_socket_t *new_sk = sbr_malloc_sk(); + if (!new_sk) + { + return -1; + } + + new_sk->fdopt = sk->fdopt; + + ret = sk->fdopt->accept(sk, new_sk, addr, addrlen); + if (-1 == ret) + { + sbr_free_sk(new_sk); + } + + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : bind +* Input : int +* bind +* (int s +* const struct sockaddr * name +* socklen_t namelen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, bind, + (int s, const struct sockaddr * name, socklen_t namelen)) +{ + NSSBR_LOGDBG("bind]fd=%d,name=%p,namelen=%d", s, name, namelen); + if (!name) + { + NSSBR_LOGERR("name is not ok]fd=%d,name=%p", s, name); + sbr_set_errno(EFAULT); + return -1; + } + + if ((name->sa_family) != AF_INET) + { + NSSBR_LOGERR("domain is not AF_INET]fd=%d,name->sa_family=%u", s, + name->sa_family); + sbr_set_errno(EAFNOSUPPORT); + return -1; + } + + if (namelen != sizeof(struct sockaddr_in)) + { + NSSBR_LOGERR("namelen is invalid]fd=%d,namelen=%d", s, namelen); + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->bind(sk, name, namelen); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : listen +* Input : int +* listen +* (int s +* int backlog) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, listen, (int s, int backlog)) +{ + NSSBR_LOGDBG("listen]fd=%d,backlog=%d", s, backlog); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + /* limit the "backlog" parameter to fit in an u8_t */ + if (backlog < 0) + { + backlog = 0; + } + + if (backlog > 0xff) + { + backlog = 0xff; + } + + return sk->fdopt->listen(sk, backlog); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : connect +* Input : int +* connect +* (int s +* const struct sockaddr * name +* socklen_t namelen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, connect, + (int s, const struct sockaddr * name, socklen_t namelen)) +{ + NSSBR_LOGDBG("connect]fd=%d,name=%p,namelen=%d", s, name, namelen); + if (!name) + { + NSSBR_LOGERR("name is null]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + if (! + (namelen == sizeof(struct sockaddr_in) + && (name->sa_family == AF_INET))) + { + NSSBR_LOGERR("parameter invalid]fd=%d,domain=%u,namelen=%d", s, + name->sa_family, namelen); + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + NSSBR_LOGERR("get socket failed]fd=%d", s); + return -1; + } + + return sk->fdopt->connect(sk, name, namelen); +} + +/***************************************************************************** +* Prototype : sbr_check_sock_name +* Description : check name +* Input : int s +* struct sockaddr * name +* socklen_t * namelen +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int +sbr_check_sock_name(int s, struct sockaddr *name, socklen_t * namelen) +{ + if (!name || !namelen) + { + NSSBR_LOGERR("name or namelen is null]fd=%d", s); + sbr_set_errno(EINVAL); + return -1; + } + + if (*namelen & 0x80000000) + { + NSSBR_LOGERR("namelen is not ok]fd=%d,namelen=%d", s, *namelen); + sbr_set_errno(EINVAL); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : getpeername +* Input : int +* getpeername +* (int s +* struct sockaddr * name +* socklen_t * namelen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, getpeername, + (int s, struct sockaddr * name, socklen_t * namelen)) +{ + NSSBR_LOGDBG("getpeername]fd=%d", s); + int ret = sbr_check_sock_name(s, name, namelen); + + if (ret != 0) + { + return ret; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + ret = sk->fdopt->getpeername(sk, name, namelen); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : getsockname +* Input : int +* getsockname +* (int s +* struct sockaddr * name +* socklen_t * namelen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, getsockname, + (int s, struct sockaddr * name, socklen_t * namelen)) +{ + NSSBR_LOGDBG("getsockname]fd=%d", s); + int ret = sbr_check_sock_name(s, name, namelen); + + if (ret != 0) + { + return ret; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + ret = sk->fdopt->getsockname(sk, name, namelen); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : setsockopt +* Input : int +* setsockopt +* (int s +* int level +* int optname +* const void * optval +* socklen_t optlen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, setsockopt, + (int s, int level, int optname, const void *optval, + socklen_t optlen)) +{ + NSSBR_LOGDBG("setsockopt]fd=%d,level=%d,optname=%d,optval=%p,optlen=%d", + s, level, optname, optval, optlen); + if (!optval) + { + NSSBR_LOGERR("optval is null]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + int ret = sk->fdopt->setsockopt(sk, level, optname, optval, optlen); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : getsockopt +* Input : int +* getsockopt +* (int s +* int level +* int optname +* void * optval +* socklen_t * optlen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, getsockopt, + (int s, int level, int optname, void *optval, + socklen_t * optlen)) +{ + NSSBR_LOGDBG("getsockopt]fd=%d,level=%d,optname=%d,optval=%p,optlen=%p", + s, level, optname, optval, optlen); + if (!optval || !optlen) + { + NSSBR_LOGERR("optval or optlen is NULL]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + int ret = sk->fdopt->getsockopt(sk, level, optname, optval, optlen); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : ioctl +* Input : int +* ioctl +* (int s +* unsigned long cmd +* ...) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, ioctl, (int s, unsigned long cmd, ...)) +{ + NSSBR_LOGDBG("ioctl]fd=%d,cmd=%lu", s, cmd); + va_list va; + va_start(va, cmd); + void *arg = va_arg(va, void *); + va_end(va); + + if (!arg) + { + NSSBR_LOGERR("parameter is not ok]fd=%d", s); + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + int ret = sk->fdopt->ioctl(sk, cmd, arg); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : fcntl +* Input : int +* fcntl +* (int s +* int cmd +* ...) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, fcntl, (int s, int cmd, ...)) +{ + NSSBR_LOGDBG("fcntl]fd=%d,cmd=%d", s, cmd); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + va_list va; + va_start(va, cmd); + long arg = va_arg(va, long); + va_end(va); + + sk->fdopt->lock_common(sk); + int ret = sk->fdopt->fcntl(sk, cmd, arg); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : recvfrom +* Input : int +* recvfrom +* (int s +* void * mem +* size_t len +* int flags +* struct sockaddr * from +* socklen_t * fromlen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, recvfrom, + (int s, void *mem, size_t len, int flags, + struct sockaddr * from, socklen_t * fromlen)) +{ + NSSBR_LOGDBG("recvfrom]fd=%d,mem=%p,len=%d,flags=%d,from=%p,fromlen=%p", + s, mem, len, flags, from, fromlen); + + if (0 == len) + { + NSSBR_LOGDBG("len is zero]fd=%d,len=%u", s, (u32) len); + return 0; //return directly, don't change the last errno. + } + + if (!mem) + { + NSSBR_LOGERR("mem is NULL]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + if (fromlen && (*((int *) fromlen) < 0)) + { + NSSBR_LOGERR("fromlen is not ok]fd=%d,fromlen=%d", s, *fromlen); + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->recvfrom(sk, mem, len, flags, from, fromlen); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : read +* Input : int +* read +* (int s +* void * mem +* size_t len) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, read, (int s, void *mem, size_t len)) +{ + NSSBR_LOGDBG("read]fd=%d,mem=%p,len=%d", s, mem, len); + return CALL_SBR_INTERCEPT(recvfrom, (s, mem, len, 0, NULL, NULL)); +} + +/***************************************************************************** +* Prototype : sbr_check_iov +* Description : check iov +* Input : int s +* const struct iovec * iov +* int iovcnt +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int sbr_check_iov(int s, const struct iovec *iov, int iovcnt) +{ + if ((!iov) || (iovcnt <= 0)) + { + NSSBR_LOGERR("iov is NULL or iovcn <=0]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + int i; + for (i = 0; i < iovcnt; ++i) + { + if (!iov[i].iov_base && (iov[i].iov_len != 0)) + { + NSSBR_LOGERR("iov is not ok]fd=%d,iov_base=%p,iov_len=%d", s, + iov[i].iov_base, iov[i].iov_len); + sbr_set_errno(EFAULT); + return -1; + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : readv +* Input : int +* readv +* (int s +* const struct iovec * iov +* int iovcnt) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, readv, (int s, const struct iovec * iov, int iovcnt)) +{ + NSSBR_LOGDBG("readv]fd=%d,iov=%p,iovcnt=%d", s, iov, iovcnt); + + if (sbr_check_iov(s, iov, iovcnt) != 0) + { + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->readv(sk, iov, iovcnt); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : recv +* Input : int +* recv +* (int s +* void * mem +* size_t len +* int flags) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, recv, (int s, void *mem, size_t len, int flags)) +{ + NSSBR_LOGDBG("recv]fd=%d,mem=%p,len=%d,flags=%d", s, mem, len, flags); + return CALL_SBR_INTERCEPT(recvfrom, (s, mem, len, flags, NULL, NULL)); +} + +/***************************************************************************** +* Prototype : sbr_check_msg +* Description : check msg +* Input : int s +* const struct msghdr * msg +* Output : None +* Return Value : static inline int +* Calls : +* Called By : +* +*****************************************************************************/ +static inline int sbr_check_msg(int s, const struct msghdr *msg) +{ + if (!msg) + { + NSSBR_LOGERR("msg is NULL]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + if (msg->msg_name && ((int) msg->msg_namelen < 0)) + { + NSSBR_LOGERR("msg_namelen is not ok]fd=%d,msg_namelen=%d", s, + msg->msg_namelen); + sbr_set_errno(EINVAL); + return -1; + } + + return sbr_check_iov(s, msg->msg_iov, msg->msg_iovlen); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : recvmsg +* Input : int +* recvmsg +* (int s +* struct msghdr * msg +* int flags) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, recvmsg, (int s, struct msghdr * msg, int flags)) +{ + NSSBR_LOGDBG("recvmsg]fd=%d,msg=%p,flags=%d", s, msg, flags); + + if (sbr_check_msg(s, msg) != 0) + { + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->recvmsg(sk, msg, flags); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : send +* Input : int +* send +* (int s +* const void * data +* size_t size +* int flags) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, send, + (int s, const void *data, size_t size, int flags)) +{ + NSSBR_LOGDBG("send]fd=%d,data=%p,size=%zu,flags=%d", s, data, size, + flags); + if (!data) + { + NSSBR_LOGERR("data is NULL]fd=%d", s); + sbr_set_errno(EFAULT); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->send(sk, data, size, flags); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : sendmsg +* Input : int +* sendmsg +* (int s +* const struct msghdr * msg +* int flags) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, sendmsg, (int s, const struct msghdr * msg, int flags)) +{ + NSSBR_LOGDBG("sendmsg]fd=%d,msg=%p,flags=%d", s, msg, flags); + + if (sbr_check_msg(s, msg) != 0) + { + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->sendmsg(sk, msg, flags); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : sendto +* Input : int +* sendto +* (int s +* const void * data +* size_t size +* int flags +* const struct sockaddr * to +* socklen_t tolen) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, sendto, + (int s, const void *data, size_t size, int flags, + const struct sockaddr * to, socklen_t tolen)) +{ + NSSBR_LOGDBG("sendto]fd=%d,data=%p,size=%zu,flags=%d,to=%p,tolen=%d", s, + data, size, flags, to, tolen); + if ((data == NULL) || (flags < 0)) + { + NSSBR_LOGERR("parameter is not ok]fd=%d,data=%p,size=%zu,flags=%d", s, + data, size, flags); + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->sendto(sk, data, size, flags, to, tolen); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : write +* Input : int +* write +* (int s +* const void * data +* size_t size) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, write, (int s, const void *data, size_t size)) +{ + NSSBR_LOGDBG("write]fd=%d,data=%p,size=%zu", s, data, size); + return CALL_SBR_INTERCEPT(send, (s, data, size, 0)); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : writev +* Input : int +* writev +* (int s +* const struct iovec * iov +* int iovcnt) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(ssize_t, writev, (int s, const struct iovec * iov, int iovcnt)) +{ + NSSBR_LOGDBG("writev]fd=%d,iov=%p,iovcnt=%d", s, iov, iovcnt); + + if (sbr_check_iov(s, iov, iovcnt) != 0) + { + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->writev(sk, iov, iovcnt); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : shutdown +* Input : int +* shutdown +* (int s +* int how) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, shutdown, (int s, int how)) +{ + NSSBR_LOGDBG("shutdown]fd=%d,how=%d", s, how); + if ((how != SHUT_RD) && (how != SHUT_WR) && (how != SHUT_RDWR)) + { + sbr_set_errno(EINVAL); + return -1; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + sk->fdopt->lock_common(sk); + int ret = sk->fdopt->shutdown(sk, how); + sk->fdopt->unlock_common(sk); + return ret; +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : close +* Input : int +* close +* (int s) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(int, close, (int s)) +{ + NSSBR_LOGDBG("close]fd=%d", s); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + int ret = sk->fdopt->close(sk); + sbr_free_sk(sk); + return ret; +} + +SBR_INTERCEPT(int, select, + (int nfds, fd_set * readfd, fd_set * writefd, + fd_set * exceptfd, struct timeval * timeout)) +{ + return lwip_try_select(nfds, readfd, writefd, exceptfd, timeout); +} + +SBR_INTERCEPT(int, ep_getevt, (int profd)) +{ + NSSBR_LOGDBG("proFD=%d", profd); + sbr_socket_t *sk = sbr_lookup_sk(profd); + + if (!sk) + { + return -1; + } + + return sk->fdopt->ep_getevt(sk); +} + +SBR_INTERCEPT(void *, ep_triggle, + (int proFD, int triggle_ops, void *epinfo, void *epitem)) +{ + NSSBR_LOGDBG("proFD=%d,triggle_ops=%d,epinfo=%p,epi=%p", proFD, + triggle_ops, epinfo, epitem); + sbr_socket_t *sk = sbr_lookup_sk(proFD); + + if (!sk) + { + return NULL; + } + + return sk->fdopt->ep_triggle(sk, triggle_ops, epinfo, epitem); +} + +SBR_INTERCEPT(int, peak, (int s)) +{ + NSSBR_LOGDBG("]fd=%d", s); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return -1; + } + + return sk->fdopt->peak(sk); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : set_app_info +* Input : int +* set_app_info +* (int s +* void* app_info) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(void, set_app_info, (int s, void *app_info)) +{ + NSSBR_LOGDBG("set_app_info]fd=%d", s); + + if (!app_info) + { + NSSBR_LOGERR("invalid param, app_info is NULL]"); + return; + } + + sbr_socket_t *sk = sbr_lookup_sk(s); + if (!sk) + { + return; + } + + sk->fdopt->set_app_info(sk, app_info); +} + +/* app send its version info to nStackMain */ +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : sbr_app_touch +* Input : int +* sbr_app_touch +* () +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(void, app_touch, (void)) +{ + NSSBR_LOGDBG("sbr_app_touch() is called]"); + + sbr_app_touch_in(); +} + +/***************************************************************************** +* Prototype : SBR_INTERCEPT +* Description : set_close_status +* Input : void +* set_close_stat +* (int s +* int flag) +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +SBR_INTERCEPT(void, set_close_stat, (int s, int flag)) +{ + NSSBR_LOGDBG("]fd=%d", s); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return; + } + if (sk->fdopt->set_close_stat) + { + sk->fdopt->set_close_stat(sk, flag); + } + +} + +SBR_INTERCEPT(int, fd_alloc, ()) +{ + return sbr_socket(AF_INET, SOCK_STREAM, 0); +} + +SBR_INTERCEPT(int, fork_init_child, (pid_t p, pid_t c)) +{ + NSSBR_LOGDBG("fork_init_child() is called]"); + return sbr_fork_protocol(); +} + +SBR_INTERCEPT(void, fork_parent_fd, (int s, pid_t p)) +{ + NSSBR_LOGDBG("fork_parent_fd() is called]"); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return; + } + + sk->fdopt->fork_parent(sk, p); +} + +SBR_INTERCEPT(void, fork_child_fd, (int s, pid_t p, pid_t c)) +{ + NSSBR_LOGDBG("fork_child_fd() is called]"); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return; + } + + sk->fdopt->fork_child(sk, p, c); + +} + +SBR_INTERCEPT(void, fork_free_fd, (int s)) +{ + NSSBR_LOGDBG("fork_free_fd() is called]"); + sbr_free_fd(s); +} + +SBR_INTERCEPT(void *, get_ip_shmem, (void)) +{ + lwip_rd_table = nstack_rd_malloc("lwip_rd_table"); + + if (!lwip_rd_table) + { + NSSOC_LOGERR("lwip rd table create failed!"); + return NULL; + } + + if (nstack_rd_parse("lwip", lwip_rd_table)) + { + NSSOC_LOGWAR("lwip parse rd data failed, load default instead"); + } + + return lwip_rd_table; +} + +SBR_INTERCEPT(int, module_init_pre, + (void *op1, void *op2, int memtype, int pooltype)) +{ + int i; + nsfw_mem_attr *mem_ops = (nsfw_mem_attr *) op1; + nsfw_ring_ops *ring_ops = (nsfw_ring_ops *) op2; + nsfw_ring_ops *tmp_ring_ops; + + if (!mem_ops || !ring_ops) + { + return -1; + } + + mem_ops[NSFW_SHMEM].stmemop = &g_shmem_ops; + mem_ops[NSFW_NSHMEM].stmemop = &g_nshmem_ops; + + tmp_ring_ops = (nsfw_ring_ops *) g_ring_ops_arry_lwip; + for (i = 0; i < memtype * pooltype; i++) + { + ring_ops[i] = tmp_ring_ops[i]; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nstack_stack_register +* Description : reg api to nsocket +* Input : nstack_socket_ops* ops +* nstack_event_ops *val +* nstack_proc_ops *deal +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +lwip_stack_register(nstack_socket_ops * ops, nstack_event_ops * val, + nstack_proc_ops * deal) +{ + if (!ops || !val || !val->handle) + { + return -1; + } + +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) \ + ops->pf ## fn = (typeof(((nstack_socket_ops*)0)->pf ## fn))dlsym(val->handle, "sbr_" # fn); +#include "declare_syscalls.h.tmpl" + + deal->module_init = sbr_init_res; + deal->fork_init_child = GET_SBR_INTERCEPT(fork_init_child); + deal->fork_fd = GET_SBR_INTERCEPT(fork_child_fd); + deal->fork_free_fd = GET_SBR_INTERCEPT(fork_free_fd); + deal->ep_getEvt = GET_SBR_INTERCEPT(ep_getevt); + deal->ep_triggle = GET_SBR_INTERCEPT(ep_triggle); + deal->peak = GET_SBR_INTERCEPT(peak); + //deal->stack_alloc_fd = GET_SBR_INTERCEPT (fd_alloc); /*alloc a fd id for epoll */ + deal->fork_parent_fd = GET_SBR_INTERCEPT(fork_parent_fd); + deal->get_ip_shmem = GET_SBR_INTERCEPT(get_ip_shmem); + deal->module_init_pre = GET_SBR_INTERCEPT(module_init_pre); + return 0; +} diff --git a/stacks/lwip_stack/src/tools/CMakeLists.txt b/stacks/lwip_stack/src/tools/CMakeLists.txt new file mode 100644 index 0000000..018b338 --- /dev/null +++ b/stacks/lwip_stack/src/tools/CMakeLists.txt @@ -0,0 +1,26 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +FILE(GLOB_RECURSE Tcpdump *.c) +ADD_LIBRARY(nTcpdump STATIC ${Tcpdump}) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ +) +TARGET_LINK_LIBRARIES(nTcpdump nStackFw) diff --git a/stacks/lwip_stack/src/tools/dump_tool.c b/stacks/lwip_stack/src/tools/dump_tool.c new file mode 100644 index 0000000..7e6e67c --- /dev/null +++ b/stacks/lwip_stack/src/tools/dump_tool.c @@ -0,0 +1,611 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include + +#include "nsfw_init_api.h" +#include "nsfw_maintain_api.h" +#include "nsfw_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nstack_log.h" +#include "nstack_securec.h" + +#include "dump_tool.h" +#include "nstack_dmm_adpt.h" + +NSTACK_STATIC u32 g_dump_task_mask = 0; +NSTACK_STATIC dump_task_info g_dump_task[MAX_DUMP_TASK]; +static dump_timer_info g_dump_timer; + +static nsfw_mem_name g_dump_mem_ring_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_RING_NAME }; +static nsfw_mem_name g_dump_mem_pool_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_POOL_NAME }; + +NSTACK_STATIC inline void dump_task_init(dump_task_info * task) +{ + task->task_state = 0; + task->task_id = -1; + task->task_keep_time = 0; + task->task_pool = NULL; + task->task_queue = NULL; +} + +NSTACK_STATIC inline void clear_dump_task() +{ + int i = 0; + for (; i < MAX_DUMP_TASK; i++) + { + dump_task_init(&g_dump_task[i]); + } +} + +NSTACK_STATIC i16 get_dump_task(nsfw_tool_dump_msg * req) +{ + // base version just support 1 dump task + if (req->task_keep_time > MAX_DUMP_TIME + || req->task_keep_time < MIN_DUMP_TIME) + { + NSPOL_DUMP_LOGERR("task keep time invalid] time=%u.", + req->task_keep_time); + return -1; + } + + if (1 == g_dump_task[0].task_state) + { + NSPOL_DUMP_LOGERR + ("start tcpdump task failed, task still in work state] task id=%d.", + 0); + return -1; + } + + struct timespec cur_time; + GET_CUR_TIME(&cur_time); /*do not need return value */ + g_dump_task[0].task_start_sec = cur_time.tv_sec; + g_dump_task[0].last_hbt_sec = cur_time.tv_sec; + + g_dump_task[0].task_state = 1; + g_dump_task[0].task_id = 0; + g_dump_task[0].task_keep_time = req->task_keep_time; + + g_dump_task_mask |= (1 << g_dump_task[0].task_id); + NSPOL_DUMP_LOGINF("start tcpdump task success] task id=%d.", 0); + return 0; +} + +NSTACK_STATIC i16 close_dump_task(i16 task_id) +{ + if (task_id < 0 || task_id >= MAX_DUMP_TASK) + { + NSPOL_DUMP_LOGERR + ("receive invalid task id in close dump task req] task id=%d.", + task_id); + return -1; + } + + g_dump_task[task_id].task_state = 0; + + g_dump_task_mask &= ~(1 << task_id); + + NSPOL_DUMP_LOGINF("stop tcpdump task success] task id=%d.", 0); + + return task_id; +} + +NSTACK_STATIC void stop_expired_task(int idx, u32 now_sec) +{ + dump_task_info *ptask = &g_dump_task[idx]; + if (0 == ptask->task_state) + { + return; + } + + if (now_sec - ptask->task_start_sec > ptask->task_keep_time) + { + NSPOL_DUMP_LOGERR + ("stop dump task because task time expired] task id=%d, now_sec=%u, task start time=%u, dump time=%u.", + ptask->task_id, now_sec, ptask->task_start_sec, + ptask->task_keep_time); + close_dump_task(ptask->task_id); + return; + } + + if (now_sec - ptask->last_hbt_sec > DUMP_TASK_HBT_TIME_OUT) + { + NSPOL_DUMP_LOGERR + ("stop dump task because heart beat time out] task id=%d, now_sec=%u, last hbt time=%u, hbt timeout=%u.", + ptask->task_id, now_sec, ptask->last_hbt_sec, + DUMP_TASK_HBT_TIME_OUT); + close_dump_task(ptask->task_id); + } + + return; +} + +NSTACK_STATIC inline bool check_dump_alive(u32 timer_type, void *data) +{ + dump_timer_info *ptimer_info = (dump_timer_info *) data; + + struct timespec cur_time; + GET_CUR_TIME(&cur_time); /*do not need return value */ + + int i = 0; + for (; i < MAX_DUMP_TASK; i++) + { + stop_expired_task(i, cur_time.tv_sec); + } + + ptimer_info->ptimer = + nsfw_timer_reg_timer(1, ptimer_info, check_dump_alive, + *(struct timespec *) (ptimer_info->interval)); + + return true; +} + +NSTACK_STATIC bool dump_init_timer(dump_timer_info * ptimer_info) +{ + struct timespec *trigger_time = + (struct timespec *) malloc(sizeof(struct timespec)); + if (NULL == trigger_time) + { + NSPOL_DUMP_LOGERR("alloc memory for timer failed."); + return false; + } + + trigger_time->tv_sec = DUMP_HBT_CHK_INTERVAL; + trigger_time->tv_nsec = 0; + + ptimer_info->interval = trigger_time; + ptimer_info->ptimer = + nsfw_timer_reg_timer(1, ptimer_info, check_dump_alive, *trigger_time); + return true; +} + +NSTACK_STATIC inline u32 +copy_limit_buf(char *dst_buf, int dst_buf_len, char *src_buf, + u32 src_buf_len, u32 limit_len) +{ + if (src_buf_len < limit_len) + { + NSPOL_DUMP_LOGERR("message too short] len=%d", src_buf_len); + return 0; + } + + if (EOK != memcpy_s(dst_buf, dst_buf_len, src_buf, limit_len)) + { + NSPOL_DUMP_LOGERR("MEMCPY_S failed"); + return 0; + } + + return limit_len; +} + +NSTACK_STATIC inline u32 +get_packet_buf(char *dst_buf, int dst_buf_len, char *src_buf, + u32 src_buf_len, u32 eth_head_len) +{ +#define TCP_BUF_LEN (eth_head_len + IP_HEAD_LEN + TCP_HEAD_LEN) +#define UDP_BUF_LEN (eth_head_len + IP_HEAD_LEN + UDP_HEAD_LEN) +#define ICMP_BUF_LEN (eth_head_len + IP_HEAD_LEN + ICMP_HEAD_LEN) + + if (NULL == dst_buf || NULL == src_buf) + { + return 0; + } + + struct ip_hdr *ip_head = (struct ip_hdr *) (src_buf + eth_head_len); + if (ip_head->_proto == IP_PROTO_TCP) + { + return copy_limit_buf(dst_buf, dst_buf_len, src_buf, src_buf_len, + TCP_BUF_LEN); + } + + if (ip_head->_proto == IP_PROTO_UDP) + { + return copy_limit_buf(dst_buf, dst_buf_len, src_buf, src_buf_len, + UDP_BUF_LEN); + } + + if (ip_head->_proto == IP_PROTO_ICMP) + { + return copy_limit_buf(dst_buf, dst_buf_len, src_buf, src_buf_len, + ICMP_BUF_LEN); + } + + if (EOK != memcpy_s(dst_buf, dst_buf_len, src_buf, src_buf_len)) + { + NSPOL_DUMP_LOGERR("MEMCPY_S failed"); + return 0; + } + + return src_buf_len; +} + +NSTACK_STATIC int +pack_msg_inout(void *dump_buf, char *msg_buf, u32 len, u16 direction, + void *para) +{ + (void) para; + dump_msg_info *pmsg = (dump_msg_info *) dump_buf; + if (!pmsg) + { + return 0; + } + + pmsg->direction = direction; + struct timeval cur_time; + gettimeofday(&cur_time, NULL); + pmsg->dump_sec = cur_time.tv_sec; + pmsg->dump_usec = cur_time.tv_usec; + + /* msg content can not be captured */ + u32 real_len = + get_packet_buf(pmsg->buf, DUMP_MSG_SIZE, msg_buf, len, ETH_HEAD_LEN); + if (0 == real_len) + { + return 0; + } + + pmsg->len = real_len; + + return 1; +} + +NSTACK_STATIC int +pack_msg_loop(void *dump_buf, char *msg_buf, u32 len, u16 direction, + void *para) +{ + dump_msg_info *pmsg = (dump_msg_info *) dump_buf; + if (!pmsg) + { + return 0; + } + pmsg->direction = direction; + struct timeval cur_time; + gettimeofday(&cur_time, NULL); + pmsg->dump_sec = cur_time.tv_sec; + pmsg->dump_usec = cur_time.tv_usec; + + eth_head pack_eth_head; + int retVal = + memcpy_s(pack_eth_head.dest_mac, MAC_ADDR_LEN, para, MAC_ADDR_LEN); + if (EOK != retVal) + { + NSPOL_DUMP_LOGERR("MEMCPY_S failed]retVal=%d", retVal); + return 0; + } + retVal = + memcpy_s(pack_eth_head.src_mac, MAC_ADDR_LEN, para, MAC_ADDR_LEN); + if (EOK != retVal) + { + NSPOL_DUMP_LOGERR("MEMCPY_S failed]retVal=%d", retVal); + return 0; + } + pack_eth_head.eth_type = htons(PROTOCOL_IP); + + retVal = + memcpy_s(pmsg->buf, DUMP_MSG_SIZE, &pack_eth_head, sizeof(eth_head)); + if (EOK != retVal) + { + NSPOL_DUMP_LOGERR("MEMCPY_S failed]retVal=%d", retVal); + return 0; + } + + u32 buf_len = DUMP_MSG_SIZE - ETH_HEAD_LEN; + + /* msg content can not be captured- Begin */ + u32 real_len = + get_packet_buf(pmsg->buf + ETH_HEAD_LEN, buf_len, msg_buf, len, 0); + if (0 == real_len) + { + return 0; + } + + pmsg->len = real_len + ETH_HEAD_LEN; + + return 1; +} + +NSTACK_STATIC void +dump_enqueue(int task_idx, void *buf, u32 len, u16 direction, + pack_msg_fun pack_msg, void *para) +{ + mring_handle queue = (mring_handle *) g_dump_task[task_idx].task_queue; + mring_handle pool = (mring_handle *) g_dump_task[task_idx].task_pool; + + void *msg = NULL; + + if (nsfw_mem_ring_dequeue(pool, &msg) <= 0) + { + // such log may be too much if queue is empty + NSPOL_DUMP_LOGDBG("get msg node from mem pool failed] pool=%p.", + pool); + return; + } + + if (NULL == msg) + { + NSPOL_DUMP_LOGWAR("get NULL msg node from mem pool] pool=%p.", pool); + return; + } + + if (!pack_msg(msg, buf, len, direction, para)) + { + NSPOL_DUMP_LOGWAR("get dump msg failed"); + return; + } + + if (nsfw_mem_ring_enqueue(queue, msg) < 0) + { + NSPOL_DUMP_LOGWAR("dump mem ring enqueue failed] ring=%p.", queue); + } + + return; +} + +NSTACK_STATIC inline bool dump_enabled() +{ + return (0 != g_dump_task_mask); +} + +void ntcpdump(void *buf, u32 buf_len, u16 direction) +{ + u32 i; + if (!dump_enabled()) + { + return; + } + + /* fix Dead-code type Codedex issue here */ + for (i = 0; i < MAX_DUMP_TASK; i++) + { + if (g_dump_task[i].task_state) + { + dump_enqueue(i, buf, buf_len, direction, pack_msg_inout, NULL); + } + } +} + +void ntcpdump_loop(void *buf, u32 buf_len, u16 direction, void *eth_addr) +{ + u32 i; + + if (!dump_enabled()) + { + return; + } + + /* fix Dead-code type Codedex issue here */ + for (i = 0; i < MAX_DUMP_TASK; i++) + { + if (g_dump_task[i].task_state) + { + dump_enqueue(i, buf, buf_len, direction, pack_msg_loop, eth_addr); + } + } +} + +// called by nStackMain +bool dump_create_pool() +{ + nsfw_mem_sppool pool_info; + if (EOK != + memcpy_s(&pool_info.stname, sizeof(nsfw_mem_name), + &g_dump_mem_pool_info, sizeof(nsfw_mem_name))) + { + NSPOL_DUMP_LOGERR("create dump mem pool failed, MEMCPY_S failed."); + return false; + } + + pool_info.usnum = MAX_DUMP_MSG_NUM; + pool_info.useltsize = DUMP_MSG_SIZE + sizeof(dump_msg_info); + pool_info.isocket_id = NSFW_SOCKET_ANY; + pool_info.enmptype = NSFW_MRING_MPSC; + + mring_handle pool = nsfw_mem_sp_create(&pool_info); + if (NULL == pool) + { + NSPOL_DUMP_LOGERR("create dump mem pool failed, pool create failed."); + return false; + } + + g_dump_task[0].task_pool = pool; + + NSPOL_DUMP_LOGINF("dump pool create success] pool=%p.", pool); + + return true; +} + +bool dump_create_ring() +{ + nsfw_mem_mring ring_info; + if (EOK != + memcpy_s(&ring_info.stname, sizeof(nsfw_mem_name), + &g_dump_mem_ring_info, sizeof(nsfw_mem_name))) + { + NSPOL_DUMP_LOGERR("create dump mem ring failed, MEMCPY_S failed."); + return false; + } + + ring_info.usnum = MAX_DUMP_MSG_NUM; + ring_info.isocket_id = NSFW_SOCKET_ANY; + ring_info.enmptype = NSFW_MRING_MPSC; + + mring_handle ring = nsfw_mem_ring_create(&ring_info); + if (NULL == ring) + { + NSPOL_DUMP_LOGERR("create dump mem ring failed, ring create failed."); + return false; + } + + g_dump_task[0].task_queue = ring; + + NSPOL_DUMP_LOGINF("dump ring create success] ring=%p.", ring); + + return true; +} + +NSTACK_STATIC int on_dump_tool_req(nsfw_mgr_msg * req) +{ + i16 task_id = 0; + if (!req) + { + return -1; + } + if (req->src_proc_type != NSFW_PROC_TOOLS) + { + NSPOL_DUMP_LOGDBG + ("dump module receive invaild message] module type=%u.", + req->src_proc_type); + return -1; + } + + if (req->msg_type != MGR_MSG_TOOL_TCPDUMP_REQ) + { + NSPOL_DUMP_LOGDBG("dump module receive invaild message] msg type=%u.", + req->msg_type); + return -1; + } + + nsfw_tool_dump_msg *dump_msg_req = GET_USER_MSG(nsfw_tool_dump_msg, req); + + switch (dump_msg_req->op_type) + { + case START_DUMP_REQ: + task_id = get_dump_task(dump_msg_req); + break; + + case STOP_DUMP_REQ: + task_id = close_dump_task(dump_msg_req->task_id); + break; + + default: + task_id = -1; + } + + nsfw_mgr_msg *rsp = nsfw_mgr_rsp_msg_alloc(req); + if (NULL == rsp) + { + NSPOL_DUMP_LOGDBG("alloc response for dump request failed."); + return -1; + } + + nsfw_tool_dump_msg *dump_msg_rsp = GET_USER_MSG(nsfw_tool_dump_msg, rsp); + dump_msg_rsp->op_type = dump_msg_req->op_type + DUMP_MSG_TYPE_RSP; + dump_msg_rsp->task_id = task_id; + + nsfw_mgr_send_msg(rsp); + nsfw_mgr_msg_free(rsp); + return 0; + +} + +NSTACK_STATIC int on_dump_hbt_req(nsfw_mgr_msg * req) +{ + if (!req) + { + return -1; + } + if (req->src_proc_type != NSFW_PROC_TOOLS) + { + NSPOL_DUMP_LOGDBG + ("dump module receive invaild message] module type=%u.", + req->src_proc_type); + return -1; + } + + if (req->msg_type != MGR_MSG_TOOL_HEART_BEAT) + { + NSPOL_DUMP_LOGDBG("dump module receive invaild message] msg type=%u.", + req->msg_type); + return -1; + } + + nsfw_tool_hbt *dump_hbt_req = GET_USER_MSG(nsfw_tool_hbt, req); + + i16 task_id = dump_hbt_req->task_id; + if (task_id < 0 || task_id >= MAX_DUMP_TASK) + { + NSPOL_DUMP_LOGERR("dump heart beat with invalid task id] task id=%d.", + task_id); + return -1; + } + + if (0 == g_dump_task[task_id].task_state) + { + NSPOL_DUMP_LOGDBG + ("dump module receive heart beat but task not enabled] task id=%d.", + task_id); + return 0; + } + + struct timespec cur_time; + GET_CUR_TIME(&cur_time); /*no need return value */ + + // update task alive time + g_dump_task[task_id].last_hbt_seq = dump_hbt_req->seq; + g_dump_task[task_id].last_hbt_sec = cur_time.tv_sec; + + return 0; +} + +NSTACK_STATIC int dump_tool_init(void *param); +NSTACK_STATIC int dump_tool_init(void *param) +{ + u32 proc_type = (u32) ((long long) param); + NSPOL_DUMP_LOGINF("dump module init] proc type=%d", proc_type); + + switch (proc_type) + { + case NSFW_PROC_MAIN: + nsfw_mgr_reg_msg_fun(MGR_MSG_TOOL_TCPDUMP_REQ, on_dump_tool_req); + nsfw_mgr_reg_msg_fun(MGR_MSG_TOOL_HEART_BEAT, on_dump_hbt_req); + break; + default: + NSPOL_DUMP_LOGERR("dump init with unknow module] proc type=%d", + proc_type); + return -1; + } + + clear_dump_task(); + + if (!dump_create_ring()) + { + return -1; + } + + if (!dump_create_pool()) + { + return -1; + } + + if (!dump_init_timer(&g_dump_timer)) + { + return -1; + } + + NSPOL_DUMP_LOGINF("dump module init success."); + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (TCPDUMP_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS(NSFW_MEM_MGR_MODULE) +NSFW_MODULE_DEPENDS(NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS(NSFW_TIMER_MODULE) +NSFW_MODULE_INIT (dump_tool_init) +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/src/tools/dump_tool.h b/stacks/lwip_stack/src/tools/dump_tool.h new file mode 100644 index 0000000..7727bc1 --- /dev/null +++ b/stacks/lwip_stack/src/tools/dump_tool.h @@ -0,0 +1,81 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _DUMP_TOOL_H_ +#define _DUMP_TOOL_H_ + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef IP_HEAD_LEN +#define IP_HEAD_LEN 20 +#endif +#ifndef TCP_HEAD_LEN +#define TCP_HEAD_LEN 20 +#endif +#ifndef UDP_HEAD_LEN +#define UDP_HEAD_LEN 8 +#endif + +#ifndef ICMP_HEAD_LEN +#define ICMP_HEAD_LEN 8 +#endif + +typedef struct _dump_task_info +{ + u16 task_state; // 0:off, 1:on + i16 task_id; + u32 task_keep_time; + u32 task_start_sec; + u32 last_hbt_seq; + u32 last_hbt_sec; + void *task_queue; + void *task_pool; +} dump_task_info; + +typedef struct _dump_eth_head +{ + u8 dest_mac[MAC_ADDR_LEN]; + u8 src_mac[MAC_ADDR_LEN]; + u16 eth_type; +} eth_head; + +#define ETH_HEAD_LEN sizeof(eth_head) + +struct ip_hdr +{ + u16 _v_hl_tos; + u16 _len; + u16 _id; + u16 _offset; + u8 _ttl; + u8 _proto; + u16 _chksum; + u32 src; + u32 dest; +}; + +typedef int (*pack_msg_fun) (void *dump_buf, char *msg_buf, u32 len, + u16 direction, void *para); + +#endif diff --git a/stacks/lwip_stack/tools/CMakeLists.txt b/stacks/lwip_stack/tools/CMakeLists.txt new file mode 100644 index 0000000..cc8f408 --- /dev/null +++ b/stacks/lwip_stack/tools/CMakeLists.txt @@ -0,0 +1,95 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() +endif() +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${NSTACKTOOLS_PATH}) +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/platform/SecureC/include/) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIC -fPIE -pie -m64 -mssse3 -std=gnu89") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags,--rpath,.") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium") + +INCLUDE_DIRECTORIES( + ../src/include/ + ../../../thirdparty/glog/glog-0.3.5/src/ + ../../SecureC/include/ + ../../../src/include/ + ../../../src/framework/include/common/ + ../../../src/framework/include/ + ../../../src/framework/include/common/generic/ +) + +#ADD_EXECUTABLE(narp narp.c) +#ADD_EXECUTABLE(nnetstat nnetstat.c) + +ADD_EXECUTABLE(ntcpdump ntcpdump.c) +if(WITH_SECUREC_LIB) +TARGET_LINK_LIBRARIES( + ntcpdump + pthread + rt + securec + -Wl,--whole-archive + libjson-c.a + libglog.a + nStackFw + -Wl,--no-whole-archive,-lstdc++ -ldl + rte_eal + rte_mempool + rte_mbuf + rte_ring +) +else() +TARGET_LINK_LIBRARIES( + ntcpdump + pthread + rt + -Wl,--whole-archive + libjson-c.a + libglog.a + nStackFw + -Wl,--no-whole-archive,-lstdc++ -ldl + rte_eal + rte_mempool + rte_mbuf + rte_ring +) +endif() + +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(ntcpdump JSON GLOG SECUREC DPDK) +else() +ADD_DEPENDENCIES(ntcpdump JSON GLOG DPDK) +endif() + + +ADD_EXECUTABLE(nping nping.c) + +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(nping SECUREC DPDK) +else() +ADD_DEPENDENCIES(nping DPDK) +endif() + +if(WITH_SECUREC_LIB) +TARGET_LINK_LIBRARIES(nping libnStackAPI.so securec -Wl,-rpath=. -lpthread -lrt -ldl) +else() +TARGET_LINK_LIBRARIES(nping libnStackAPI.so -Wl,-rpath=. -lpthread -lrt -ldl) +endif() diff --git a/stacks/lwip_stack/tools/nping.c b/stacks/lwip_stack/tools/nping.c new file mode 100644 index 0000000..a75de85 --- /dev/null +++ b/stacks/lwip_stack/tools/nping.c @@ -0,0 +1,615 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nstack_securec.h" +#include "tool_common.h" + +/*======== for global variables =======*/ + +NSTACK_STATIC input_info g_input_info = { 0 }; +static stat_info g_stat_info = { 0 }; + +static char *g_nping_short_options = "c:r:I:"; + +int g_exit = 0; +void user_exit(int sig) +{ + g_exit = 1; +} + +NSTACK_STATIC inline double +get_cost_time(struct timespec *pstart, struct timespec *pend) +{ + double sec = (double) (pend->tv_sec - pstart->tv_sec); + double nsec = (double) (pend->tv_nsec - pstart->tv_nsec); + + return (sec * 1000 + (nsec / 1000000)); +} + +NSTACK_STATIC inline double +get_lost_rate(unsigned int lost_count, unsigned int send_count) +{ + if (0 == send_count) + { + return 0; + } + + return ((double) lost_count / send_count); +} + +void print_stat(stat_info * info, const char *remote_ip) +{ + unsigned int send_count = info->send_seq; + unsigned int recv_count = info->recv_ok; + unsigned int lost_count = send_count - recv_count; + double lost_rate = 100 * get_lost_rate(lost_count, send_count); + double cost_time = get_cost_time(&info->start_time, &info->end_time); + + printf("\n------ %s ping statistics ------\n", remote_ip); + + printf + ("%u packets transmitted, %u received, %.2f%% packet loss, time %.2fms\n", + send_count, recv_count, lost_rate, cost_time); + + if (0 != recv_count) + { + double min_interval = info->min_interval; + double max_interval = info->max_interval; + double avg_interval = info->all_interval / recv_count; + printf("rtt min/avg/max = %.3f/%.3f/%.3f ms\n", min_interval, + avg_interval, max_interval); + } +} + +NSTACK_STATIC inline u16 get_chksum(icmp_head * pmsg) +{ + int len = sizeof(icmp_head); + u32 sum = 0; + u16 *msg_stream = (u16 *) pmsg; + u16 check_sum = 0; + + while (len > 1) + { + sum += *msg_stream; + len -= 2; + msg_stream++; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + check_sum = ~sum; + + return check_sum; +} + +#ifndef MAX_SHORT +#define MAX_SHORT 0xFFFF +#endif + +NSTACK_STATIC inline void +code_icmp_req(icmp_head * pmsg, u32 send_seq, pid_t my_pid) +{ + struct timespec cur_time; + + pmsg->icmp_type = ICMP_ECHO; + pmsg->icmp_code = 0; + pmsg->icmp_cksum = 0; + pmsg->icmp_seq = send_seq % (MAX_SHORT + 1); + pmsg->icmp_id = my_pid; + pmsg->timestamp = 0; + + if (0 != clock_gettime(CLOCK_MONOTONIC, &cur_time)) + { + printf("Failed to get time, errno = %d\n", errno); + } + + pmsg->icmp_sec = cur_time.tv_sec; + pmsg->icmp_nsec = cur_time.tv_nsec; + + pmsg->icmp_cksum = get_chksum(pmsg); + return; +} + +NSTACK_STATIC int +send_icmp_req(int socket, pid_t my_pid, stat_info * stat, + struct sockaddr_in *remote_addr) +{ + int send_ret; + icmp_head icmp_req; + + stat->send_seq++; + code_icmp_req(&icmp_req, stat->send_seq, my_pid); + + send_ret = sendto(socket, &icmp_req, sizeof(icmp_head), 0, + (struct sockaddr *) remote_addr, + sizeof(struct sockaddr_in)); + + if (send_ret < 0) + { + printf("send icmp request failed.\n"); + return -1; + } + + return send_ret; +} + +NSTACK_STATIC inline double +cal_interval(struct timespec *psend, struct timespec *precv, stat_info * stat) +{ + double interval = get_cost_time(psend, precv); + + stat->all_interval += interval; + + if (interval < stat->min_interval) + { + stat->min_interval = interval; + } + + if (interval > stat->max_interval) + { + stat->max_interval = interval; + } + + return interval; +} + +NSTACK_STATIC inline void +print_info_on_reply(long send_sec, long send_usec, u32 send_seq, + stat_info * stat, struct sockaddr_in *dst_addr) +{ + struct timespec send_time; + struct timespec recv_time; + if (0 != clock_gettime(CLOCK_MONOTONIC, &recv_time)) + { + printf("Failed to get time, errno = %d\n", errno); + } + + send_time.tv_sec = send_sec; + send_time.tv_nsec = send_usec; + + double interval = cal_interval(&send_time, &recv_time, stat); + const char *remote_ip = inet_ntoa(dst_addr->sin_addr); + printf("%lu bytes from %s: icmp_seq=%u, time=%.3f ms\n", + sizeof(icmp_head), remote_ip, send_seq % (MAX_SHORT + 1), + interval); +} + +NSTACK_STATIC inline void +print_info_on_no_reply(u32 send_seq, const char *remote_ip) +{ + printf("No data from %s, icmp_seq=%u, Destination Host Unreachable\n", + remote_ip, send_seq); +} + +static inline int expect_addr(int expect, int addr) +{ + return (expect == addr); +} + +NSTACK_STATIC inline int +parse_icmp_reply(char *buf, unsigned int buf_len, u32 my_pid, u32 send_seq, + stat_info * stat, struct sockaddr_in *dst_addr) +{ + unsigned int ip_head_len; + ip_head *recv_ip_head; + icmp_head *recv_icmp_head; + + // parse all received ip package + while (buf_len > sizeof(ip_head)) + { + recv_ip_head = (ip_head *) buf; + + ip_head_len = recv_ip_head->ihl << 2; + recv_icmp_head = (icmp_head *) (buf + ip_head_len); + buf_len -= htons(recv_ip_head->tot_len); + + if (!expect_addr(dst_addr->sin_addr.s_addr, recv_ip_head->local_ip)) + { + return 0; + } + + if ((recv_icmp_head->icmp_type == ICMP_REPLY) + && (recv_icmp_head->icmp_id == my_pid) + && (recv_icmp_head->icmp_seq == send_seq % (MAX_SHORT + 1))) + { + print_info_on_reply(recv_icmp_head->icmp_sec, + recv_icmp_head->icmp_nsec, send_seq, stat, + dst_addr); + + return 1; + } + + buf += ip_head_len; + } + + return 0; +} + +NSTACK_STATIC inline int +recv_icmp_reply_ok(int socket, int my_pid, u32 send_seq, stat_info * stat, + struct sockaddr_in *dst_addr) +{ +#define MAX_RECV_BUFF_SIZE (200 * sizeof(icmp_head)) + + struct sockaddr_in remote_addr; + unsigned int addr_len = sizeof(remote_addr); + char recv_buf[MAX_RECV_BUFF_SIZE]; + + int recv_ret = recvfrom(socket, recv_buf, MAX_RECV_BUFF_SIZE, 0, + (struct sockaddr *) &remote_addr, &addr_len); + + if (recv_ret < 0) + { + return 0; + } + + if (!parse_icmp_reply + (recv_buf, (unsigned int) recv_ret, my_pid, send_seq, stat, dst_addr)) + { + return 0; + } + + return 1; +} + +// check recv msg in 2 us +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50811*/ +NSTACK_STATIC void +recv_icmp_reply(int socket, pid_t my_pid, input_info * input, + stat_info * stat, struct sockaddr_in *dst_addr) +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ +{ +#define MAX_SLEEP_TIME (2 * US_TO_NS) +#define MAX_WAIT_TIME (1000 * MS_TO_NS) + + int recv_ok = 0; + int retry = 0; + long sleep_all = 0; + long sleep_time = 0; + + u32 expect_seq = stat->send_seq; + + while (retry < input->retry_count) + { + if (recv_icmp_reply_ok(socket, my_pid, expect_seq, stat, dst_addr)) + { + recv_ok = 1; + stat->recv_ok++; + break; + } + + sleep_all += MAX_SLEEP_TIME; + sys_sleep_ns(0, MAX_SLEEP_TIME); + retry++; + } + + if (!recv_ok) + { + print_info_on_no_reply(expect_seq, input->dst_ip); + } + + if (sleep_all < MAX_WAIT_TIME) + { + sleep_time = MAX_WAIT_TIME - sleep_all; + sys_sleep_ns(0, sleep_time); + } +} + +NSTACK_STATIC inline int is_digit_nping(char *str) +{ + if (NULL == str || '\0' == str[0]) + { + return 0; + } + + while (*str) + { + if (*str > '9' || *str < '0') + { + return 0; + } + + str++; + } + + return 1; +} + +#define MIN_IP_LEN_NPING 7 //the length of string ip addr x.x.x.x is 7, 4 numbers + 3 dots = 7 +#define MAX_IP_LEN_NPING 15 //the length of string ip addr xxx.xxx.xxx.xxx is 15, 12 numbers + 3 dots = 15 + +NSTACK_STATIC inline int is_ip_addr_nping(char *param_addr) +{ + int ipseg1; + int ipseg2; + int ipseg3; + int ipseg4; + + if (NULL == param_addr) + { + return 0; + } + + size_t len = strlen(param_addr); + if (len < MIN_IP_LEN_NPING || len > MAX_IP_LEN_NPING) // valid ip MIN_IP_LEN=7, MAX_IP_LEN=15 + { + printf("Input IP format error.\n"); + return 0; + } + + if (sscanf_s + (param_addr, "%d.%d.%d.%d", &ipseg1, &ipseg2, &ipseg3, &ipseg4) != 4) + { + return 0; + } + + if ((ipseg1 & 0xffffff00) + || (ipseg2 & 0xffffff00) + || (ipseg3 & 0xffffff00) || (ipseg4 & 0xffffff00)) + { + return 0; + } + + return 1; +} + +NSTACK_STATIC inline bool check_nping_input_para(input_info * input) +{ + if (input->send_count < 1) + { + return false; + } + + if (input->retry_count < NPING_RETRY_COUNT + || input->retry_count > MAX_NPING_RETRY_COUNT) + { + return false; + } + + if (0 == input->src_ip[0] || 0 == input->dst_ip[0]) + { + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +get_nping_input_para(int argc, char **argv, input_info * input) +{ + int opt = 0; + bool arg_invalid = false; + + if (argc < 2) + { + return false; + } + + if (!is_ip_addr_nping(argv[1])) + { + return false; + } + + /* CID 36687 (#1 of 2): Unchecked return value (CHECKED_RETURN) */ + if (EOK != strcpy_s(input->dst_ip, sizeof(input->dst_ip), argv[1])) + { + printf("STRCPY_S failed.\n"); + return false; + } + + while (1) + { + opt = getopt(argc - 1, &argv[1], g_nping_short_options); + if (-1 == opt) + { + break; + } + + switch (opt) + { + // for short options + case 'c': + input->send_count = atoi(optarg); + break; + case 'r': + input->retry_count = atoi(optarg); + break; + case 'I': + /* CID 36687 (#2 of 2): Unchecked return value (CHECKED_RETURN) */ + if (!is_ip_addr_nping(optarg)) + { + return false; + } + if (EOK != + strcpy_s(input->src_ip, sizeof(input->src_ip), optarg)) + { + printf("STRCPY_S failed.\n"); + return false; + } + break; + default: + arg_invalid = true; + break; + } + + if (arg_invalid) + { + return false; + } + } + + if (!check_nping_input_para(input)) + { + return false; + } + + return true; +} + +void print_help_nping() +{ + printf + ("usage:nping destination [-c send_count -I src_addr -r retry_count]\n"); + printf("send count range:1-2147483647\n"); + printf("retry count range:1000-20000\n"); +} + +NSTACK_STATIC inline void init_input_info(input_info * input) +{ + if (EOK != memset_s(input, sizeof(input_info), 0, sizeof(input_info))) + { + printf("MEMSET_S failed.\n"); + return; + } + + input->send_count = 100000; + input->retry_count = NPING_RETRY_COUNT; +} + +NSTACK_STATIC inline void init_stat_info(stat_info * stat) +{ + stat->max_interval = 0; + stat->min_interval = 0xFFFFFFFF; +} + +#ifndef NSTACK_STATIC_CHECK +int main(int argc, char *argv[]) +#else +int nping_main(int argc, char *argv[]) +#endif +{ + struct sockaddr_in local_addr; + struct sockaddr_in remote_addr; + int send_ret; + int ret = -1; + int icmp_sock; + + pid_t my_pid; + + if (EOK != + memset_s(&local_addr, sizeof(local_addr), 0, sizeof(local_addr))) + { + printf("MEMSET_S failed.\n"); + return 0; + } + local_addr.sin_family = AF_INET; + + init_input_info(&g_input_info); + init_stat_info(&g_stat_info); + + if (!get_nping_input_para(argc, argv, &g_input_info)) + { + print_help_nping(); + return 0; + } + + if ((icmp_sock = socket(AF_INET, CUSTOM_SOCK_TYPE, IPPROTO_ICMP)) < 0) + { + printf("create socket failed.\n"); + return 0; + } + + local_addr.sin_addr.s_addr = inet_addr(g_input_info.src_ip); + + if (0 != + bind(icmp_sock, (struct sockaddr *) &local_addr, + sizeof(struct sockaddr))) + { + printf("bind failed, src ip %s\n", g_input_info.src_ip); + close(icmp_sock); + return 0; + } + + int opt = 1; + ret = ioctl(icmp_sock, FIONBIO, &opt); + if (-1 == ret) + { + printf("fcntl O_NONBLOCK fail\n"); + close(icmp_sock); + return 0; + } + + if (EOK != + memset_s(&remote_addr, sizeof(remote_addr), 0, sizeof(remote_addr))) + { + printf("MEMSET_S failed.\n"); + close(icmp_sock); + return 0; + } + + remote_addr.sin_family = AF_INET; + remote_addr.sin_addr.s_addr = inet_addr(g_input_info.dst_ip); + + my_pid = getpid(); + printf("nping %s %lu bytes of data, pid:%d.\n", g_input_info.dst_ip, + sizeof(icmp_head), my_pid); + + signal(SIGINT, user_exit); + + int loop_count = 0; + if (0 != clock_gettime(CLOCK_MONOTONIC, &g_stat_info.start_time)) + { + printf("Failed to get time, errno = %d\n", errno); + } + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50811*/ + i32 send_count = g_input_info.send_count; +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + while (!g_exit && (loop_count < send_count)) + { + send_ret = + send_icmp_req(icmp_sock, my_pid, &g_stat_info, &remote_addr); + if (send_ret < 0) + { + break; + } + + recv_icmp_reply(icmp_sock, my_pid, &g_input_info, &g_stat_info, + &remote_addr); + + loop_count++; + } + + close(icmp_sock); + + if (0 != clock_gettime(CLOCK_MONOTONIC, &g_stat_info.end_time)) + { + printf("Failed to get time, errno = %d\n", errno); + } + + print_stat(&g_stat_info, g_input_info.dst_ip); + + return 0; +} diff --git a/stacks/lwip_stack/tools/ntcpdump.c b/stacks/lwip_stack/tools/ntcpdump.c new file mode 100644 index 0000000..b2a3436 --- /dev/null +++ b/stacks/lwip_stack/tools/ntcpdump.c @@ -0,0 +1,1334 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "types.h" +#include "nsfw_init_api.h" +#include "nsfw_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" +#include "nstack_securec.h" + +#include "tool_common.h" + +NSTACK_STATIC struct option g_dump_long_options[] = { + {"host", 1, NULL, OPT_ARG_HOST}, + {"lhost", 1, NULL, OPT_ARG_LOCAL_HOST}, + {"rhost", 1, NULL, OPT_ARG_REMOTE_HOST}, + {"port", 1, NULL, OPT_ARG_PORT}, + {"lport", 1, NULL, OPT_ARG_LOCAL_PORT}, + {"rport", 1, NULL, OPT_ARG_REMOTE_PORT}, + {"mac", 1, NULL, OPT_ARG_MAC}, + {"lmac", 1, NULL, OPT_ARG_LOCAL_MAC}, + {"rmac", 1, NULL, OPT_ARG_REMOTE_MAC}, + {0, 0, 0, 0} +}; + +static char *g_dump_short_options = "c:s:w:y:G:P:T:"; + +NSTACK_STATIC FILE *g_dump_fp = NULL; +static u32 g_dumped_packet = 0; +NSTACK_STATIC u32 g_captured_packet = 0; +static u32 g_filtered_packet = 0; + +NSTACK_STATIC bool g_dump_exit = 0; + +static dump_timer_info g_dump_hbt_timer; +NSTACK_STATIC dump_condition g_dump_condition; +static nsfw_mem_name g_dump_mem_ring_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_RING_NAME }; +static nsfw_mem_name g_dump_mem_pool_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_POOL_NAME }; + +void dump_exit() +{ + g_dump_exit = 1; +} + +void print_help_ntcpdump() +{ + printf("usage:ntcpdump \n\ + -c count \n\ + -s len \n\ + -w file \n\ + -y l2_protocol \n\ + -T l3_protocol \n\ + -G dump_seconds \n\ + -P in/out/inout \n\ + --host/rhost/lhost ip_addr \n\ + --port/rport/lport port \n\ + --mac/rmac/lmac mac_addr\n"); +} + +bool is_digit_ntcpdump(char *str, size_t src_len) +{ + size_t count = 0; + + if (NULL == str || 0 == *str) + { + return FALSE; + } + + while (*str) + { + if (*str > '9' || *str < '0') + { + return false; + } + + str++; + count++; + } + + if (count > src_len) + { + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +is_ip_addr(const char *addr, ip_addr_bits * addr_info) +{ + u32 ip1; + u32 ip2; + u32 ip3; + u32 ip4; + + if (sscanf_s(addr, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) + { + return false; + } + + if ((ip1 & 0xffffff00) || (ip2 & 0xffffff00) || (ip3 & 0xffffff00) + || (ip4 & 0xffffff00)) + { + return false; + } + + addr_info->addr_bits1 = ip1; + addr_info->addr_bits2 = ip2; + addr_info->addr_bits3 = ip3; + addr_info->addr_bits4 = ip4; + + return true; +} + +NSTACK_STATIC inline bool get_ip_addr(const char *addr, u32 * ip_addr) +{ + ip_addr_bits addr_info; + if (!is_ip_addr(addr, &addr_info)) + { + return false; + } + + *ip_addr = ((addr_info.addr_bits1 & 0xFF) + | (addr_info.addr_bits2 & 0xFF) << 8 + | (addr_info.addr_bits3 & 0xFF) << 16 + | (addr_info.addr_bits4 & 0xFF) << 24); + + return true; +} + +NSTACK_STATIC inline bool get_dump_port(const char *pport, u16 * port) +{ + int user_port; + + if (!is_digit_ntcpdump((char *) pport, MAX_PORT_STR_LEN)) + { + return false; + } + + user_port = atoi(pport); + if (user_port < 1024 || user_port > 65535) + { + return false; + } + + *port = (unsigned short) user_port; + return true; +} + +NSTACK_STATIC inline bool get_dump_len(char *plen, u32 * limit_len) +{ + if (!is_digit_ntcpdump(plen, MAX_INTEGER_STR_LEN)) + { + return false; + } + + *limit_len = atoi(plen); + return true; +} + +NSTACK_STATIC inline bool get_mac_addr(const char *opt_value, char *mac_addr) +{ + /* avoid coredump when opt_value is NULL */ + if (NULL == opt_value) + { + return false; + } + + size_t org_len = strlen(opt_value); + if (org_len != MAC_ADDR_STR_LEN) + { + return false; + } + + u32 tmp_mac[MAC_ADDR_LEN]; + + if (6 != sscanf_s(opt_value, "%x:%x:%x:%x:%x:%x", + &tmp_mac[0], + &tmp_mac[1], + &tmp_mac[2], &tmp_mac[3], &tmp_mac[4], &tmp_mac[5])) + { + return false; + } + + int i = 0; + for (; i < MAC_ADDR_LEN; i++) + { + if (tmp_mac[i] > 0xFF) + { + // 01:02:03:04:5:1FF + return false; + } + + mac_addr[i] = tmp_mac[i]; + } + + return true; +} + +NSTACK_STATIC inline bool check_file_name(const char *file_name) +{ + if (0 == access(file_name, F_OK)) + { + printf("dump file exist, file name=%s.\n", file_name); + return false; + } + return true; +} + +NSTACK_STATIC inline u16 get_para_direction(const char *para) +{ + if (0 == strcasecmp(para, "out")) + { + return DUMP_SEND; + } + + if (0 == strcasecmp(para, "in")) + { + return DUMP_RECV; + } + + if (0 == strcasecmp(para, "inout")) + { + return DUMP_SEND_RECV; + } + + return INVALID_DIRECTION; +} + +NSTACK_STATIC inline u16 get_para_l2_protocol(const char *para) +{ + if (0 == strcasecmp(para, "arp")) + { + return PROTOCOL_ARP; + } + + if (0 == strcasecmp(para, "rarp")) + { + return PROTOCOL_RARP; + } + + if (0 == strcasecmp(para, "ip")) + { + return PROTOCOL_IP; + } + + if (0 == strcasecmp(para, "oam")) + { + return PROTOCOL_OAM_LACP; + } + + if (0 == strcasecmp(para, "lacp")) + { + return PROTOCOL_OAM_LACP; + } + + return INVALID_L2_PROTOCOL; +} + +NSTACK_STATIC inline u16 get_para_l3_protocol(const char *para) +{ + if (0 == strcasecmp(para, "tcp")) + { + return PROTOCOL_TCP; + } + + if (0 == strcasecmp(para, "udp")) + { + return PROTOCOL_UDP; + } + + if (0 == strcasecmp(para, "icmp")) + { + return PROTOCOL_ICMP; + } + + return INVALID_L3_PROTOCOL; +} + +NSTACK_STATIC bool +parse_long_options(int opt, const char *long_opt_arg, int optindex, + dump_condition * filter_info) +{ + switch (opt) + { + case OPT_ARG_HOST: + if (!get_ip_addr(long_opt_arg, &filter_info->ip_addr)) + { + printf("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_HOST: + if (!get_ip_addr(long_opt_arg, &filter_info->local_ip)) + { + printf("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_HOST: + if (!get_ip_addr(long_opt_arg, &filter_info->remote_ip)) + { + printf("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_REMOTE_SET; + break; + case OPT_ARG_PORT: + if (!get_dump_port(long_opt_arg, &filter_info->port)) + { + printf("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_PORT: + if (!get_dump_port(long_opt_arg, &filter_info->local_port)) + { + printf("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_PORT: + if (!get_dump_port(long_opt_arg, &filter_info->remote_port)) + { + printf("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_REMOTE_SET; + break; + case OPT_ARG_MAC: + if (!get_mac_addr(long_opt_arg, filter_info->mac_addr)) + { + printf("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_MAC: + if (!get_mac_addr(long_opt_arg, filter_info->local_mac)) + { + printf("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_MAC: + if (!get_mac_addr(long_opt_arg, filter_info->remote_mac)) + { + printf("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_REMOTE_SET; + break; + default: + printf("unknow arg, optindex=%d, arg=%s.\n", optindex, + long_opt_arg); + return false; + } + + return true; +} + +NSTACK_STATIC inline bool condition_valid(dump_condition * condition) +{ + // check direction + if (INVALID_DIRECTION == condition->direction) + { + printf("direction invalid.\n"); + return false; + } + + // check l2 protocol + if (INVALID_L2_PROTOCOL == condition->l2_protocol) + { + printf("L2 protocol invalid.\n"); + return false; + } + + // check l3 protocol + if (INVALID_L3_PROTOCOL == condition->l3_protocol) + { + printf("L3 protocol invalid.\n"); + return false; + } + + // check ip + if (condition->ip_set_flag > 0x4) + { + printf("IP options invalid.\n"); + return false; + } + + // check port + if (condition->port_set_flag > 0x4) + { + printf("Port options invalid.\n"); + return false; + } + + // check mac + if (condition->mac_set_flag > 0x4) + { + printf("MAC options invalid.\n"); + return false; + } + + if (condition->dump_time > MAX_DUMP_TIME + || condition->dump_time < MIN_DUMP_TIME) + { + printf("dump time invalid.\n"); + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +get_dump_condition(int argc, char **argv, dump_condition * filter_info) +{ + int opt = 0; + int opt_index = 0; + bool arg_invalid = false; + filter_info->has_condition = 0; + + if (argc < 2) + { + // dump all package + return true; + } + + while (1) + { + opt = + getopt_long(argc, argv, g_dump_short_options, g_dump_long_options, + &opt_index); + if (-1 == opt) + { + break; + } + + switch (opt) + { + // for short options + case 'c': + filter_info->dump_count = atoi(optarg); + break; + case 's': + if (!get_dump_len(optarg, &filter_info->limit_len)) + { + printf("length invalid, optindex=%d, arg=%s.\n", + opt_index, optarg); + arg_invalid = true; + } + break; + case 'w': + if (!check_file_name(optarg)) + { + printf("invalid file name, optindex=%d, arg=%s.\n", + opt_index, optarg); + arg_invalid = true; + } + else + { + filter_info->dump_file_name = optarg; + } + break; + case 'y': + filter_info->l2_protocol = get_para_l2_protocol(optarg); + break; + case 'G': + filter_info->dump_time = atoi(optarg); + break; + case 'P': + filter_info->direction = get_para_direction(optarg); + break; + case 'T': + filter_info->l3_protocol = get_para_l3_protocol(optarg); + break; + case '?': + arg_invalid = true; + break; + // for long options + default: + if (!parse_long_options(opt, optarg, opt_index, filter_info)) + { + arg_invalid = true; + } + break; + } + + if (arg_invalid) + { + print_help_ntcpdump(); + return false; + } + + filter_info->has_condition = 1; + } + + if (!condition_valid(filter_info)) + { + filter_info->has_condition = 0; + return false; + } + + return true; +} + +NSTACK_STATIC inline void open_file() +{ + if (NULL == g_dump_condition.dump_file_name) + { + return; + } + + g_dump_fp = fopen(g_dump_condition.dump_file_name, "w+"); + if (NULL == g_dump_fp) + { + printf("open file %s failed\n", g_dump_condition.dump_file_name); + } +} + +NSTACK_STATIC inline void close_file() +{ + if (NULL != g_dump_fp) + { + fclose(g_dump_fp); + g_dump_fp = NULL; + } +} + +NSTACK_STATIC inline void write_file_head(FILE * fp) +{ + dump_file_head file_head; + file_head.magic = 0xA1B2C3D4; + file_head.major_ver = 2; // 0x0200; + file_head.minor_ver = 4; // 0x0400; + file_head.area = 0; + file_head.time_stamp = 0; + file_head.max_pack_size = 0x0000FFFF; // 0xFFFF0000; + file_head.link_type = 1; //0x01000000; + + if (fwrite(&file_head, sizeof(dump_file_head), 1, fp) != 1) + { + return; + } + + fflush(fp); +} + +NSTACK_STATIC inline void write_packet(parse_msg_info * pmsg, FILE * fp) +{ + packet_head pack_head; + dump_msg_info *org_msg = (dump_msg_info *) pmsg->org_msg; + pack_head.sec = org_msg->dump_sec; + pack_head.usec = org_msg->dump_usec; + pack_head.save_len = + (u32) nstack_min(org_msg->len, g_dump_condition.limit_len); + pack_head.org_len = org_msg->len; + + if (fwrite(&pack_head, sizeof(packet_head), 1, fp) != 1) + { + // log error + return; + } + + if (fwrite(org_msg->buf, pack_head.save_len, 1, fp) != 1) + { + // log error + return; + } + + fflush(fp); + return; +} + +#define EMPTY(x) (0 == (x)) +#define EQUAL(x, y) ((x) == (y)) + +#define STR_EMPTY(str) (0 == str[0]) +#define STR_EQUAL(str1, str2, len) (0 == memcmp(str1, str2, len)) + +#define MATCH(cond, info, field) \ + (EQUAL(cond->field, info->field)) + +#define MATCH_MORE(cond, field, info, field1, field2) \ + (EQUAL(cond->field, info->field1) || EQUAL(cond->field, info->field2)) + +#define MATCH_STR(cond, info, field, len) \ + (STR_EQUAL(cond->field, info->field, len)) + +#define MATCH_STR_MORE(cond, field, info, field1, field2, len) \ + (STR_EQUAL(cond->field, info->field1, len) || STR_EQUAL(cond->field, info->field2, len)) + +NSTACK_STATIC inline bool +ip_match(dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->ip_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH(condition, msg_info, local_ip)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH(condition, msg_info, remote_ip)) + { + ret = true; + } + break; + case COND_AND_SET: + if (MATCH_MORE(condition, local_ip, msg_info, local_ip, remote_ip) + && MATCH_MORE(condition, remote_ip, msg_info, local_ip, + remote_ip)) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_MORE(condition, ip_addr, msg_info, local_ip, remote_ip)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +port_match(dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->port_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH(condition, msg_info, local_port)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH(condition, msg_info, remote_port)) + { + ret = true; + } + break; + case COND_AND_SET: + if (MATCH(condition, msg_info, local_port) + && MATCH(condition, msg_info, remote_port)) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_MORE + (condition, port, msg_info, local_port, remote_port)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +mac_match(dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->mac_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH_STR(condition, msg_info, local_mac, MAC_ADDR_LEN)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH_STR(condition, msg_info, remote_mac, MAC_ADDR_LEN)) + { + ret = true; + } + break; + case COND_AND_SET: + if ((MATCH_STR_MORE + (condition, local_mac, msg_info, local_mac, remote_mac, + MAC_ADDR_LEN) + && MATCH_STR_MORE(condition, remote_mac, msg_info, local_mac, + remote_mac, MAC_ADDR_LEN))) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_STR_MORE + (condition, mac_addr, msg_info, local_mac, remote_mac, + MAC_ADDR_LEN)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +filter_by_condition(dump_condition * condition, parse_msg_info * msg_info) +{ + dump_msg_info *org_msg = (dump_msg_info *) msg_info->org_msg; + if (0 == condition->has_condition) + { + return false; + } + + // direction + if (!(condition->direction & org_msg->direction)) + { + return true; + } + + // l2_protocol + if ((0 != condition->l2_protocol) + && !MATCH(condition, msg_info, l2_protocol)) + { + return true; + } + + // l3_protocol + if ((0 != condition->l3_protocol) + && !MATCH(condition, msg_info, l3_protocol)) + { + return true; + } + + // ip + if (!ip_match(condition, msg_info)) + { + return true; + } + + // port + if (!port_match(condition, msg_info)) + { + return true; + } + + // mac + if (!mac_match(condition, msg_info)) + { + return true; + } + + return false; +} + +NSTACK_STATIC inline char *get_l2_protocol_desc(u16 l2_protocol) +{ + switch (l2_protocol) + { + case PROTOCOL_IP: + return "IP"; + case PROTOCOL_ARP: + return "ARP"; + case PROTOCOL_RARP: + return "RARP"; + case PROTOCOL_OAM_LACP: + return "OAM/LACP"; + default: + return "unknown"; + } +} + +NSTACK_STATIC inline char *get_l3_protocol_desc(u16 l3_protocol) +{ + switch (l3_protocol) + { + case PROTOCOL_ICMP: + return "ICMP"; + case PROTOCOL_TCP: + return "TCP"; + case PROTOCOL_UDP: + return "UDP"; + default: + return "unknown"; + } +} + +NSTACK_STATIC inline void get_ip_str(char *pip_addr, u32 ip_addr_len, u32 ip) +{ + int retVal; + retVal = sprintf_s(pip_addr, ip_addr_len, "%d.%d.%d.%d", + ip & 0x000000FF, + (ip & 0x0000FF00) >> 8, + (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24); + if (-1 == retVal) + { + printf("get_ip_str:SPRINTF_S failed %d.\n", retVal); + } +} + +NSTACK_STATIC inline void print_packet(parse_msg_info * msg_info, u32 seq) +{ + char str_local_ip[IP_ADDR_LEN]; + char str_remote_ip[IP_ADDR_LEN]; + get_ip_str(str_local_ip, sizeof(str_local_ip), msg_info->local_ip); + get_ip_str(str_remote_ip, sizeof(str_remote_ip), msg_info->remote_ip); + + dump_msg_info *org_msg = (dump_msg_info *) msg_info->org_msg; + + printf("%-6d %-6d:%6d %-8s %-8s %-16s %-16s %-10d %-10d %-8d\n", + seq, + org_msg->dump_sec, org_msg->dump_usec, + get_l2_protocol_desc(msg_info->l2_protocol), + get_l3_protocol_desc(msg_info->l3_protocol), + str_local_ip, + str_remote_ip, + msg_info->local_port, msg_info->remote_port, org_msg->len); +} + +void print_head() +{ + if (NULL != g_dump_fp) + { + write_file_head(g_dump_fp); + } + else + { + printf("ntcpdump start listening:\n"); + printf("%-6s %-18s %-8s %-8s %-16s %-16s %-10s %-10s %-8s\n", + "Frame", "sec:usec", "L2", "L3", "Src IP", "Dest IP", + "Src Port", "Dest Port", "Length"); + } +} + +void register_dump_signal() +{ + signal(SIGINT, dump_exit); +} + +NSTACK_STATIC inline void init_parse_msg_info(parse_msg_info * info) +{ + int retVal = + memset_s(info, sizeof(parse_msg_info), 0, sizeof(parse_msg_info)); + if (EOK != retVal) + { + printf("MEMSET_S failed.\n"); + } +} + +NSTACK_STATIC inline void +parse_msg(dump_msg_info * msg, parse_msg_info * info) +{ + init_parse_msg_info(info); + + info->org_msg = msg; + + char *pmsg = msg->buf; + u32 len = msg->len; + /* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50886 */ + if (len < MAC_ADDR_LEN + MAC_ADDR_LEN + sizeof(u16)) + { + return; + } + /* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + // get mac addr + if (EOK != + memcpy_s(info->remote_mac, sizeof(info->remote_mac), pmsg, + MAC_ADDR_LEN)) + { + return; + } + + pmsg += MAC_ADDR_LEN; + len -= MAC_ADDR_LEN; + + if (EOK != + memcpy_s(info->local_mac, sizeof(info->local_mac), pmsg, + MAC_ADDR_LEN)) + { + return; + } + + pmsg += MAC_ADDR_LEN; + len -= MAC_ADDR_LEN; + + info->l2_protocol = htons(*(u16 *) pmsg); + pmsg += sizeof(u16); + len -= sizeof(u16); + + if (PROTOCOL_IP != info->l2_protocol) + { + return; + } + + ip_head *p_ip_head = (ip_head *) pmsg; + if (len < p_ip_head->ihl) + { + return; + } + + info->local_ip = p_ip_head->local_ip; + info->remote_ip = p_ip_head->remote_ip; + info->l3_protocol = p_ip_head->protocol; + + pmsg += p_ip_head->ihl * sizeof(u32); + + if (PROTOCOL_TCP == info->l3_protocol) + { + tcp_head *p_tcp_head = (tcp_head *) pmsg; + info->local_port = htons(p_tcp_head->src_port); + info->remote_port = htons(p_tcp_head->dst_port); + return; + } + + if (PROTOCOL_UDP == info->l3_protocol) + { + udp_head *p_udp_head = (udp_head *) pmsg; + info->local_port = htons(p_udp_head->src_port); + info->remote_port = htons(p_udp_head->dst_port); + return; + } + + return; +} + +NSTACK_STATIC inline bool +time_expired(struct timespec * start_time, u32 work_sec) +{ +#define TIME_EXPIRE_CHECK_COUNT 1000 + + static u32 loop_count = 0; + loop_count++; + + if (0 != loop_count % TIME_EXPIRE_CHECK_COUNT) + { + return false; + } + + struct timespec cur_time; + GET_CUR_TIME(&cur_time); + + if (cur_time.tv_sec - start_time->tv_sec > work_sec) + { + return true; + } + + return false; +} + +NSTACK_STATIC void dump_packet(parse_msg_info * msg) +{ + g_dumped_packet++; + if (!g_dump_fp) + { + print_packet(msg, g_dumped_packet); + return; + } + + write_packet(msg, g_dump_fp); +} + +NSTACK_STATIC void +dump_msg(mring_handle dump_ring, mring_handle dump_pool, + dump_condition * condition, struct timespec *start_time) +{ + u32 dump_count = 0; + open_file(); + + print_head(); + + void *msg = NULL; + while (!g_dump_exit + && (dump_count < condition->dump_count) + && !time_expired(start_time, condition->dump_time)) + { + if (nsfw_mem_ring_dequeue(dump_ring, &msg) <= 0) + { + sys_sleep_ns(0, 10000); + continue; + } + + if (NULL == msg) + { + continue; + } + + parse_msg_info msg_info; + parse_msg(msg, &msg_info); + + g_captured_packet++; + if (!condition->has_condition) + { + dump_packet(&msg_info); + dump_count++; + nsfw_mem_ring_enqueue(dump_pool, msg); + continue; + } + + if (filter_by_condition(condition, &msg_info)) + { + g_filtered_packet++; + nsfw_mem_ring_enqueue(dump_pool, msg); + continue; + } + + dump_packet(&msg_info); + dump_count++; + nsfw_mem_ring_enqueue(dump_pool, msg); + } + + close_file(); +} + +mring_handle dump_get_mem_ring() +{ + return nsfw_mem_ring_lookup(&g_dump_mem_ring_info); +} + +mring_handle dump_get_mem_pool() +{ + return nsfw_mem_sp_lookup(&g_dump_mem_pool_info); +} + +NSTACK_STATIC void dump_clear_mem(mring_handle ring, mring_handle pool) +{ + void *msg = NULL; + while (nsfw_mem_ring_dequeue(ring, &msg) > 0) + { + nsfw_mem_ring_enqueue(pool, msg); + sys_sleep_ns(0, 1000); + } +} + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50859*/ +i16 dump_send_req(u16 op_type, i16 task_id, u32 task_keep_time) +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ +{ + nsfw_mgr_msg *req = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc(MGR_MSG_TOOL_TCPDUMP_REQ, + NSFW_PROC_MAIN); + if (NULL == req) + { + printf("all message for getting instance id failed.\n"); + return -1; + } + + nsfw_tool_dump_msg *req_body = GET_USER_MSG(nsfw_tool_dump_msg, req); + req_body->op_type = op_type; + req_body->task_id = task_id; + req_body->task_keep_time = task_keep_time; + + nsfw_mgr_msg *rsp = nsfw_mgr_null_rspmsg_alloc(); + if (NULL == rsp) + { + printf("alloc rsp message for getting memory failed.\n"); + nsfw_mgr_msg_free(req); + return -1; + } + + if (!nsfw_mgr_send_req_wait_rsp(req, rsp)) + { + printf("request memory can not get response.\n"); + nsfw_mgr_msg_free(req); + nsfw_mgr_msg_free(rsp); + return -1; + } + + if (rsp->src_proc_type != NSFW_PROC_MAIN + || rsp->dst_proc_type != NSFW_PROC_TOOLS) + { + printf + ("dump get wrong response, src or dst proc type error,src proc type=%u, dst proc type=%u.\n", + rsp->src_proc_type, rsp->dst_proc_type); + nsfw_mgr_msg_free(req); + nsfw_mgr_msg_free(rsp); + return -1; + } + + if (rsp->msg_type != MGR_MSG_TOOL_TCPDUMP_RSP) + { + printf("dump get wrong response, msg type error, msg type=%d.\n", + rsp->msg_type); + nsfw_mgr_msg_free(req); + nsfw_mgr_msg_free(rsp); + return -1; + } + + nsfw_tool_dump_msg *rsp_body = GET_USER_MSG(nsfw_tool_dump_msg, rsp); + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50859*/ + i16 new_task_id = rsp_body->task_id; +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + nsfw_mgr_msg_free(req); + nsfw_mgr_msg_free(rsp); + + return new_task_id; +} + +i16 start_dump_task(u32 task_keep_time) +{ + return dump_send_req(START_DUMP_REQ, -1, task_keep_time); +} + +i16 stop_dump_task(i16 task_id) +{ + return dump_send_req(STOP_DUMP_REQ, task_id, 0); +} + +NSTACK_STATIC void init_dump_condition(dump_condition * condition) +{ + if (EOK != + memset_s(condition, sizeof(dump_condition), 0, + sizeof(dump_condition))) + { + printf("MEMSET_S failed.\n"); + } + condition->limit_len = DUMP_MSG_SIZE; + condition->dump_time = DEFAULT_DUMP_TIME; + condition->direction = 3; + condition->dump_count = DEFAULT_DUMP_COUNT; +} + +NSTACK_STATIC inline bool send_hbt_req(u32 seq, i16 task_id) +{ + nsfw_mgr_msg *req = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc(MGR_MSG_TOOL_HEART_BEAT, + NSFW_PROC_MAIN); + if (NULL == req) + { + printf("all message for getting instance id failed.\n"); + return false; + } + + nsfw_tool_hbt *req_body = GET_USER_MSG(nsfw_tool_hbt, req); + req_body->seq = seq; + req_body->task_id = task_id; + + if (!nsfw_mgr_send_msg(req)) + { + printf("request memory can not get response.\n"); + } + + nsfw_mgr_msg_free(req); + + return true; +} + +NSTACK_STATIC bool on_send_hbt_req(u32 timer_type, void *data) +{ + dump_timer_info *ptimer_info = (dump_timer_info *) data; + // send heartbeat + + send_hbt_req(ptimer_info->seq, ptimer_info->task_id); + ptimer_info->seq++; + + ptimer_info->ptimer = + nsfw_timer_reg_timer(DUMP_HBT_TIMER, ptimer_info, on_send_hbt_req, + *(struct timespec *) (ptimer_info->interval)); + return true; +} + +NSTACK_STATIC bool start_dump_hbt(dump_timer_info * ptimer_info, i16 task_id) +{ + struct timespec *time_interval = + (struct timespec *) malloc(sizeof(struct timespec)); + if (NULL == time_interval) + { + return false; + } + + time_interval->tv_sec = DUMP_HBT_INTERVAL; + time_interval->tv_nsec = 0; + + ptimer_info->interval = time_interval; + ptimer_info->seq = 1; + ptimer_info->task_id = task_id; + + ptimer_info->ptimer = + nsfw_timer_reg_timer(DUMP_HBT_TIMER, ptimer_info, on_send_hbt_req, + *time_interval); + + return true; +} + +NSTACK_STATIC bool stop_dump_hbt(dump_timer_info * ptimer_info) +{ + free(ptimer_info->interval); + /* fix "SET_NULL_AFTER_FREE" type codedex issue */ + ptimer_info->interval = NULL; + nsfw_timer_rmv_timer(ptimer_info->ptimer); + return true; +} + +#ifndef NSTACK_STATIC_CHECK +int main(int argc, char *argv[]) +#else +int ntcpdump_main(int argc, char *argv[]) +#endif +{ + register_dump_signal(); + + init_dump_condition(&g_dump_condition); + if (!get_dump_condition(argc, argv, &g_dump_condition)) + { + printf("dump exit because of input invalid.\n"); + return INPUT_INVALID; + } + + printf("parse filter condition ok.\n"); + + fw_poc_type proc_type = NSFW_PROC_TOOLS; + nsfw_mem_para stinfo = { 0 }; + stinfo.iargsnum = 0; + stinfo.pargs = NULL; + stinfo.enflag = proc_type; + nstack_framework_set_module_param(NSFW_MEM_MGR_MODULE, &stinfo); + nstack_framework_set_module_param(NSFW_MGR_COM_MODULE, + (void *) ((u64) proc_type)); + nstack_framework_set_module_param(NSFW_TIMER_MODULE, + (void *) ((u64) proc_type)); + + if (0 != nstack_framework_init()) + { + printf("dump init failed.\n"); + return FRAMEWORK_INIT_FAILED; + } + + mring_handle dump_mem_pool = dump_get_mem_pool(); + if (NULL == dump_mem_pool) + { + printf("dump init mem pool failed.\n"); + return MEMPOOL_INIT_FAILED; + } + + mring_handle dump_mem_ring = dump_get_mem_ring(); + if (NULL == dump_mem_ring) + { + printf("dump init mem ring failed.\n"); + return MEMRING_INIT_FAILED; + } + + // initialize queue first + dump_clear_mem(dump_mem_ring, dump_mem_pool); + + i16 task_id = start_dump_task(g_dump_condition.dump_time); + if (task_id < 0 || task_id > MAX_DUMP_TASK) + { + printf("start dump task failed.\n"); + return START_TASK_FAILED; + } + + if (!start_dump_hbt(&g_dump_hbt_timer, task_id)) + { + printf("start dump heart beat timer failed.\n"); + return START_TIMER_FAILED; + } + + struct timespec dump_start_time; + GET_CUR_TIME(&dump_start_time); + dump_msg(dump_mem_ring, dump_mem_pool, &g_dump_condition, + &dump_start_time); + + i16 new_task_id = stop_dump_task(task_id); + if (new_task_id != task_id) + { + printf("stop dump task failed.\n"); + } + /* modify deadcode type codedex issue */ + (void) stop_dump_hbt(&g_dump_hbt_timer); + + printf("dump complete.\n"); + printf("captured packets=%u.\n", g_captured_packet); + printf("dumped packets=%u.\n", g_dumped_packet); + printf("filtered packets=%u.\n", g_filtered_packet); + + return 0; +} diff --git a/stacks/lwip_stack/tools/tool_common.h b/stacks/lwip_stack/tools/tool_common.h new file mode 100644 index 0000000..5a302d1 --- /dev/null +++ b/stacks/lwip_stack/tools/tool_common.h @@ -0,0 +1,243 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _TOOL_COMMON_H_ +#define _TOOL_COMMON_H_ + +#include +#include "types.h" + +#ifndef NSTACK_STATIC +#ifndef NSTACK_STATIC_CHECK +#define NSTACK_STATIC static +#else +#define NSTACK_STATIC +#endif +#endif + +#ifndef IP_ADDR_LEN +#define IP_ADDR_LEN 16 +#endif + +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef MAC_ADDR_STR_LEN +#define MAC_ADDR_STR_LEN 17 +#endif + +#define ICMP_ECHO 8 +#define ICMP_REPLY 0 +#define MS_TO_NS 1000000 +#define US_TO_NS 1000 +#define NPING_RETRY_COUNT 1000 +#define MAX_NPING_RETRY_COUNT 20000 + +#define MAX_PORT_STR_LEN 5 +#define MAX_IP_STR_LEN 15 +#define MAX_INTEGER_STR_LEN 10 + +#define DUMP_HBT_TIMER 1 + +#define INVALID_DIRECTION 0xFFFF +#define DEFAULT_DUMP_COUNT 1000 + +#ifndef CUSTOM_SOCK_TYPE +#define CUSTOM_SOCK_TYPE 0xF001 +#endif + +enum DUMP_ERR_CODE +{ + RET_OK = 0, + INPUT_INVALID = 1, + FRAMEWORK_INIT_FAILED = 2, + MEMPOOL_INIT_FAILED = 3, + MEMRING_INIT_FAILED = 4, + START_TASK_FAILED = 5, + START_TIMER_FAILED = 6, + UNKNOW_ERR +}; + +enum COND_LOCAL_REMOTE_SET +{ + COND_NOT_SET = 0, + COND_REMOTE_SET = 0x1, + COND_LOCAL_SET = 0x2, + COND_AND_SET = 0x3, + COND_OR_SET = 0x4 +}; + +enum DUMP_OPT_ARG +{ + OPT_ARG_HOST = 256, + OPT_ARG_LOCAL_HOST, + OPT_ARG_REMOTE_HOST, + OPT_ARG_PORT, + OPT_ARG_LOCAL_PORT, + OPT_ARG_REMOTE_PORT, + OPT_ARG_MAC, + OPT_ARG_LOCAL_MAC, + OPT_ARG_REMOTE_MAC, + OPT_ARG_INVALID +}; + +typedef struct _ip_head +{ + u8 ihl:4; + u8 version:4; + u8 tos; + u16 tot_len; + u16 id; + u16 frag_off; + u8 ttl; + u8 protocol; + u16 chk_sum; + u32 local_ip; + u32 remote_ip; +} ip_head; + +typedef struct _tcp_head +{ + u16 src_port; + u16 dst_port; + u32 seq_no; + u32 ack_no; +} tcp_head; + +typedef struct _udp_head +{ + u16 src_port; + u16 dst_port; + u16 uhl; + u16 chk_sum; +} udp_head; + +typedef struct _dump_file_head +{ + u32 magic; + u16 major_ver; + u16 minor_ver; + u32 area; + u32 time_stamp; + u32 max_pack_size; + u32 link_type; +} dump_file_head; + +typedef struct _packet_head +{ + u32 sec; + u32 usec; + u32 save_len; + u32 org_len; +} packet_head; + +typedef struct _ip_addr_bits +{ + u32 addr_bits1; + u32 addr_bits2; + u32 addr_bits3; + u32 addr_bits4; +} ip_addr_bits; + +typedef struct _parse_msg_info +{ + u16 l2_protocol; // ARP/IP/OAM/LACP + u16 l3_protocol; // TCP/UDP/ICMP + u16 local_port; + u16 remote_port; + u32 local_ip; + u32 remote_ip; + char local_mac[MAC_ADDR_LEN + 1]; + char remote_mac[MAC_ADDR_LEN + 1]; + + void *org_msg; +} parse_msg_info; + +typedef struct _dump_condition +{ + bool has_condition; + u32 dump_count; + u32 dump_time; + u32 limit_len; + u16 direction; //1:send 2:recv 3:send-recv + u16 l2_protocol; // ARP/IP/OAM/LACP + u16 l3_protocol; // TCP/UDP/ICMP + u16 port_set_flag; + u16 port; + u16 local_port; + u16 remote_port; + u16 ip_set_flag; + u32 ip_addr; + u32 local_ip; + u32 remote_ip; + u16 mac_set_flag; + char mac_addr[MAC_ADDR_LEN + 1]; + char local_mac[MAC_ADDR_LEN + 1]; + char remote_mac[MAC_ADDR_LEN + 1]; + + char *dump_file_name; +} dump_condition; + +typedef struct _icmp_head +{ + u8 icmp_type; + u8 icmp_code; + u16 icmp_cksum; + u16 icmp_id; + u16 icmp_seq; + u32 timestamp; + + long icmp_sec; + long icmp_nsec; +} icmp_head; + +typedef struct _ning_input_info +{ + i32 send_count; // total send req + i32 retry_count; // retry count for 1 req + char src_ip[IP_ADDR_LEN]; + char dst_ip[IP_ADDR_LEN]; +} input_info; + +typedef struct _nping_stat_info +{ + u32 send_seq; + u32 recv_ok; + double all_interval; + double min_interval; + double max_interval; + struct timespec start_time; + struct timespec end_time; +} stat_info; + +#ifndef sys_sleep_ns +#define sys_sleep_ns(_s, _ns)\ +{ \ + if (_s >= 0 && _ns >= 0) \ + { \ + struct timespec delay, remain; \ + delay.tv_sec = _s; \ + delay.tv_nsec = _ns; \ + while (nanosleep(&delay, &remain) < 0) \ + { \ + delay = remain; \ + } \ + } \ +} +#endif + +#endif diff --git a/stacks/lwip_stack/vagrant/Vagrantfile b/stacks/lwip_stack/vagrant/Vagrantfile new file mode 100644 index 0000000..b3a31c1 --- /dev/null +++ b/stacks/lwip_stack/vagrant/Vagrantfile @@ -0,0 +1,65 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure(2) do |config| + + # Pick the right distro and bootstrap, default is ubuntu1604 + distro = ( ENV['DMM_VAGRANT_DISTRO'] || "ubuntu") + if distro == 'centos7' + config.vm.box = "puppetlabs/centos-7.2-64-nocm" + else + config.vm.box = "puppetlabs/ubuntu-16.04-64-nocm" + end + config.vm.box_check_update = false + + # Create DMM client and server VM's + config.vm.define "dmm-stackx-server" do |server| + server.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../scripts/install_prereq.sh") + server.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"build.sh"), :args => "/DMM vagrant" + server.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"start_nstackMain.sh"), :args => "/DMM vagrant" + end + config.vm.define "dmm-stackx-client" do |client| + client.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"../../../scripts/install_prereq.sh") + client.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"build.sh"), :args => "/DMM vagrant" + client.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"start_nstackMain.sh"), :args => "/DMM vagrant" + end + + + # vagrant-cachier caches apt/yum etc to speed subsequent + # vagrant up + # to enable, run + # vagrant plugin install vagrant-cachier + # + if Vagrant.has_plugin?("vagrant-cachier") + config.cache.scope = :box + end + + # Define some physical ports for your VMs to be used by DPDK + nics = (ENV['DMM_VAGRANT_NICS'] || "2").to_i(10) + for i in 1..nics + config.vm.network "private_network", type: "dhcp" + # config.vm.network "private_network", ip: "172.28.128.200" + # config.vm.network "private_network", ip: "172.28.128.201" + end + + # use http proxy if avaiable + if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf") + config.proxy.http = ENV['http_proxy'] + config.proxy.https = ENV['https_proxy'] + config.proxy.no_proxy = "localhost,127.0.0.1" + end + + vmcpu=(ENV['DMM_VAGRANT_VMCPU'] || 4) + vmram=(ENV['DMM_VAGRANT_VMRAM'] || 5120) + + config.ssh.forward_agent = true + config.ssh.forward_x11 = true + + config.vm.provider "virtualbox" do |vb| + vb.customize ["modifyvm", :id, "--ioapic", "on"] + vb.memory = "#{vmram}" + vb.cpus = "#{vmcpu}" + + config.vm.synced_folder "../../../", "/DMM", type: "rsync" + end +end diff --git a/stacks/lwip_stack/vagrant/build.sh b/stacks/lwip_stack/vagrant/build.sh new file mode 100644 index 0000000..a934eef --- /dev/null +++ b/stacks/lwip_stack/vagrant/build.sh @@ -0,0 +1,59 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S) +log_file="/tmp/build_log.txt-$TIMESTAMP" +exec 1> >(tee -a "$log_file") 2>&1 + +# Get Command Line arguements if present +if [ "$1" == "from-base-build" ]; then + WAS_DMM_BUILT="YES" +fi + +if [ "x$1" != "x" ] && [ "$1" != "from-base-build" ]; then + TEMP_DIR=$1 + DMM_BUILD_SCRIPT_DIR=${TEMP_DIR}/scripts + LWIP_BUILD_DIR=${TEMP_DIR}/stacks/lwip_stack/build/ +else + TEMP_DIR=`dirname $(readlink -f $0)`/.. + DMM_BUILD_SCRIPT_DIR=${TEMP_DIR}/../../scripts + LWIP_BUILD_DIR=${TEMP_DIR}/build/ +fi + +echo 0:$0 +echo 1:$1 +echo 2:$2 +echo TEMP_DIR: $TEMP_DIR +echo DMM_BUILD_SCRIPT_DIR: $DMM_BUILD_SCRIPT_DIR +echo LWIP_BUILD_DIR: $LWIP_BUILD_DIR + +if [ 'x$WAS_DMM_BUILT' != "xYES" ]; then + bash -x $DMM_BUILD_SCRIPT_DIR/build.sh +fi + +#===========build LWIP=========== +echo "LWIP build started....." +cd $LWIP_BUILD_DIR +cmake .. +make -j 8 +if [ $? -eq 0 ]; then + echo "LWIP build is SUCCESS" +else + echo "LWIP build has FAILED" + exit 1 +fi diff --git a/stacks/lwip_stack/vagrant/env.sh b/stacks/lwip_stack/vagrant/env.sh new file mode 100644 index 0000000..96ad346 --- /dev/null +++ b/stacks/lwip_stack/vagrant/env.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +#export DMM_VAGRANT_DISTRO="ubuntu1604" +export DMM_VAGRANT_DISTRO="centos7" +export DMM_VAGRANT_NICS=2 +export DMM_VAGRANT_VMCPU=4 +export DMM_VAGRANT_VMRAM=8192 diff --git a/stacks/lwip_stack/vagrant/start_nstackMain.sh b/stacks/lwip_stack/vagrant/start_nstackMain.sh new file mode 100644 index 0000000..d7016c7 --- /dev/null +++ b/stacks/lwip_stack/vagrant/start_nstackMain.sh @@ -0,0 +1,105 @@ +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash -x + +set -x + +DPDK_DOWNLOAD_PATH=/tmp/dpdk +ifname=enp0s8 + +if [ "x$1" != "x" ] && [ "$1" != "from-base-build" ]; then + TEMP_DIR=$1 + DMM_BUILD_SCRIPT_DIR=${TEMP_DIR}/scripts + LWIP_BUILD_DIR=${TEMP_DIR}/stacks/lwip_stack/build/ +else + TEMP_DIR=`dirname $(readlink -f $0)`/.. + DMM_BUILD_SCRIPT_DIR=${TEMP_DIR}/../../scripts + LWIP_BUILD_DIR=${TEMP_DIR}/build/ +fi + +LIB_PATH=$LWIP_BUILD_DIR/../release/lib64/ + +echo 0:$0 +echo 1:$1 +echo 2:$2 +echo TEMP_DIR: $TEMP_DIR +echo DMM_BUILD_SCRIPT_DIR: $DMM_BUILD_SCRIPT_DIR +echo LWIP_BUILD_DIR: $LWIP_BUILD_DIR +echo LIB_PATH: $LIB_PATH + +#===========check hugepages================= +source $DMM_BUILD_SCRIPT_DIR/check_hugepage.sh + +OS_ID=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') +if [ "$OS_ID" == "centos" ]; then + ifaddress1=$(ifconfig $ifname | grep 'inet' | cut -d: -f2 | awk '{print $2}') + echo $ifaddress1 + ifaddresscut=$(ifconfig $ifname | grep 'inet' | head -n 1 | awk -F " " '{print $2}' | awk -F "." '{print $1"."$2"."$3}') + echo $ifaddresscut + ifmac=$(ifconfig $ifname | grep 'ether' | awk -F " " '{print $2}') + echo $ifmac +elif [ "$OS_ID" == "ubuntu" ]; then + ifaddress1=$(ifconfig $ifname | grep 'inet' | head -n 1 | cut -d: -f2 | awk '{print $1}') + echo $ifaddress1 + ifaddresscut=$(ifconfig $ifname | grep 'inet' | head -n 1 | cut -d: -f2 | awk '{print $1}' | awk -F "." '{print $1"."$2"."$3}') + echo $ifaddresscut + ifmac=$(ifconfig $ifname | grep 'HWaddr' | awk -F " " '{print $5}') + echo $ifmac +fi + +cd $LWIP_BUILD_DIR/../ +cd release/script +sed -i 's!DPDK_INSTALL_PATH=.*!DPDK_INSTALL_PATH='$DPDK_DOWNLOAD_PATH'/dpdk-18.02!1' nstack_var.sh + +cd ../ +chmod 775 * +cp ./configure/*.json bin/ +cd bin + +sed -i 's!192.168.1.175!'$ifaddress1'!1' ip_data.json + +sed -i 's!192.168.1.1!'$ifaddresscut'.1!1' network_data_tonStack.json + +if [ "$OS_ID" == "centos" ]; then + sed -i 's!ens4!'$ifname'!1' network_data_tonStack.json +elif [ "$OS_ID" == "ubuntu" ]; then + sed -i 's!ens4!'$ifname'!1' network_data_tonStack.json +fi +sed -i 's!ens4!'$ifname'!1' network_data_tonStack.json + +cd $DMM_BUILD_SCRIPT_DIR/../release/bin +cp -r . ../../stacks/lwip_stack/app_test +cd $DMM_BUILD_SCRIPT_DIR/../stacks/lwip_stack/app_test +cp -r ../configure/*.json . + +sed -i 's!192.168.1.1!'$ifaddresscut'.1!1' rd_config.json + +sudo mkdir -p /var/run/ip_module/ +sudo mkdir -p /var/log/nStack/ip_module/ + +export LD_LIBRARY_PATH=$LIB_PATH +export NSTACK_LOG_ON=DBG + +cd $LWIP_BUILD_DIR/../release +bash -x ./stop_nstack.sh +bash -x ./start_nstack.sh +check_result=$(pgrep nStackMain) +if [ -z "$check_result" ]; then + echo "nStackMain execute failed" + exit 1 +else + echo "nStackMain execute successful" + exit 0 +fi diff --git a/stacks/vpp/adapt/dmm_vcl.h b/stacks/vpp/adapt/dmm_vcl.h new file mode 100644 index 0000000..448c225 --- /dev/null +++ b/stacks/vpp/adapt/dmm_vcl.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Huawei Technologies Co.,Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef included_dmm_vcl_h +#define included_dmm_vcl_h + +#include "nstack_epoll_api.h" +#include "nstack_callback_ops.h" + +#define DMM_VCL_ENV_DEBUG "DMM_VCL_DEBUG" +#define DMM_VCL_MAX_FD_VALUE 1024 + +typedef struct dmm_vcl +{ + int epfd; + long unsigned int epoll_threadid; + nstack_event_ops regVal; + int (*p_epoll_create) (int size); + unsigned int (*p_epoll_ctl) (int epFD, int proFD, int ctl_ops, + struct epoll_event * events); + unsigned int (*p_epoll_wait) (int epfd, struct epoll_event * events, + int maxevents, int timeout); + int (*p_close) (int fd); +} dmm_vcl_t; + +typedef struct dmm_vcl_event +{ + void *pdata; + int proFD; + int event_type; +} dmm_vcl_event_t; + +#endif /* included_dmm_vcl_h */ diff --git a/stacks/vpp/adapt/dmm_vcl_adpt.c b/stacks/vpp/adapt/dmm_vcl_adpt.c new file mode 100644 index 0000000..a91e6a4 --- /dev/null +++ b/stacks/vpp/adapt/dmm_vcl_adpt.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018 Huawei Technologies Co.,Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include "dmm_vcl.h" +#include "nstack_log.h" +#include "nstack_rd_api.h" + +#define DMM_VCL_ADPT_DEBUG dmm_vcl_debug +static unsigned int dmm_vcl_debug; + +dmm_vcl_t g_dmm_vcl; +dmm_vcl_event_t g_dmm_vcl_event[DMM_VCL_MAX_FD_VALUE] = { 0 }; + +void *vpprd_table = NULL; +void *vpp_get_ip_shmem() +{ + return vpprd_table; +} + +void *vpphs_ep_ctl_ops(int proFD, int ctl_ops, void *pdata, void *event) +{ + struct epoll_event tmpEvt; + int ret = 0; + int dmm_epfd; + g_dmm_vcl_event[proFD].pdata = pdata; + g_dmm_vcl_event[proFD].proFD = proFD; + + tmpEvt.data.ptr = &g_dmm_vcl_event[proFD]; + tmpEvt.events = *(int *) event; + tmpEvt.events |= (EPOLLIN | EPOLLOUT); + + if (DMM_VCL_ADPT_DEBUG > 0) + NSSOC_LOGINF("DMM VCL ADPT<%d>: fd=%d,ops=%d, events=%u", + getpid(), proFD, ctl_ops, event); + + dmm_epfd = g_dmm_vcl.epfd; + switch (ctl_ops) + { + case nstack_ep_triggle_add: + ret = + g_dmm_vcl.p_epoll_ctl(dmm_epfd, EPOLL_CTL_ADD, proFD, + &tmpEvt); + break; + case nstack_ep_triggle_mod: + ret = + g_dmm_vcl.p_epoll_ctl(dmm_epfd, EPOLL_CTL_MOD, proFD, + &tmpEvt); + break; + case nstack_ep_triggle_del: + ret = + g_dmm_vcl.p_epoll_ctl(dmm_epfd, EPOLL_CTL_DEL, proFD, + &tmpEvt); + break; + default: + ret = -1; + break; + } + if (ret == -1) + return NULL; + return pdata; +} + +#define DMM_VCL_MAX_EP_EVENT 1024 + +static void *dmm_vcl_epoll_thread(void *arg) +{ + int num, i; + + struct epoll_event events[DMM_VCL_MAX_EP_EVENT]; + dmm_vcl_event_t vcl_event = { 0 }; + while (1) + { + num = + g_dmm_vcl.p_epoll_wait(g_dmm_vcl.epfd, events, + DMM_VCL_MAX_EP_EVENT, 100); + + for (i = 0; i < num; ++i) + { + if (DMM_VCL_ADPT_DEBUG > 0) + NSSOC_LOGINF + ("DMM_VCL_ADPT<%d>: dmm_vcl_epoll i[%d] events=%u, epfd=%d, ptr=%d", + getpid(), i, events[i].events, events[i].data.fd, + events[i].data.ptr); + vcl_event = *(dmm_vcl_event_t *) (events[i].data.ptr); + g_dmm_vcl_event[vcl_event.proFD].event_type = events[i].events; + g_dmm_vcl.regVal.event_cb(vcl_event.pdata, events[i].events, + EVENT_INFORM_APP); + } + } + + return NULL; +} + +int dmm_vpphs_init() +{ + char *env_var_str; + int rv = 0; + + env_var_str = getenv(DMM_VCL_ENV_DEBUG); + if (env_var_str) + { + u32 tmp; + if (sscanf(env_var_str, "%u", &tmp) != 1) + { + NSSOC_LOGINF + ("DMM_VCL_ADPT<%d>: WARNING: Invalid debug level specified " + "in the environment variable " DMM_VCL_ENV_DEBUG " (%s)!\n", + getpid(), env_var_str); + } + else + { + dmm_vcl_debug = tmp; + if (DMM_VCL_ADPT_DEBUG > 0) + NSSOC_LOGINF + ("DMM_VCL_ADPT<%d>: configured DMM VCL ADPT debug (%u) from " + "DMM_VCL_ENV_DEBUG ", getpid(), dmm_vcl_debug); + } + } + + vpprd_table = nstack_local_rd_malloc(); + if (!vpprd_table) + { + NSSOC_LOGERR("vpp_hoststack rd table create failed!"); + return -1; + } + if (nstack_rd_parse("vpp_hoststack", vpprd_table)) + { + NSSOC_LOGWAR("no rd data got!"); + NSSOC_LOGWAR("rsocket parse rd data failed"); + nstack_rd_table_clear(vpprd_table); + return -1; + } + g_dmm_vcl.epfd = g_dmm_vcl.p_epoll_create(1000); + if (g_dmm_vcl.epfd < 0) + return g_dmm_vcl.epfd; + + rv = pthread_create(&g_dmm_vcl.epoll_threadid, NULL, dmm_vcl_epoll_thread, + NULL); + if (rv != 0) + { + NSSOC_LOGINF("dmm vcl epoll thread create fail, errno:%d!", errno); + g_dmm_vcl.p_close(g_dmm_vcl.epfd); + g_dmm_vcl.epfd = -1; + return rv; + } + + rv = pthread_setname_np(g_dmm_vcl.epoll_threadid, "dmm_vcl_epoll"); + if (rv != 0) + { + NSSOC_LOGINF + ("pthread_setname_np failed for dmm_vcl_epoll, rv=%d, errno:%d", + rv, errno); + } + + return rv; +} + +int vpp_getEvt(int fd) +{ + return g_dmm_vcl_event[fd].event_type; +} + +int +vpp_hoststack_stack_register(nstack_socket_ops * ops, nstack_event_ops * val, + nstack_proc_ops * fddeal) +{ + +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) \ + ops->pf ## fn = (typeof(((nstack_socket_ops*)0)->pf ## fn))dlsym(val->handle, # fn); +#include "declare_syscalls.h.tmpl" + ops->pfepoll_create = NULL; + + g_dmm_vcl.p_epoll_ctl = dlsym(val->handle, "epoll_ctl"); + g_dmm_vcl.p_epoll_create = dlsym(val->handle, "epoll_create1"); + g_dmm_vcl.p_epoll_wait = dlsym(val->handle, "epoll_wait"); + g_dmm_vcl.p_close = dlsym(val->handle, "close"); + g_dmm_vcl.regVal = *val; + + fddeal->module_init = dmm_vpphs_init; + fddeal->fork_init_child = dmm_vpphs_init; + fddeal->fork_free_fd = NULL; + fddeal->ep_triggle = vpphs_ep_ctl_ops; + fddeal->get_ip_shmem = vpp_get_ip_shmem; + fddeal->peak = NULL; + fddeal->ep_getEvt = vpp_getEvt; + + return 0; +} diff --git a/stacks/vpp/configure/module_config.json b/stacks/vpp/configure/module_config.json new file mode 100644 index 0000000..fb73574 --- /dev/null +++ b/stacks/vpp/configure/module_config.json @@ -0,0 +1,20 @@ +{ + "default_stack_name": "kernel", /*when rd can't be find maybe choose the defualt one*/ + "module_list": [ + { + "stack_name": "kernel", /*stack name*/ + "libname": "./", /*library name, if loadtype is static, this maybe + null, else must give a library name*/ + "deploytype": "1", /*deploy model type:model type1, model type2, + model type3. Indicating single or multi process + deployment. Used during shared memory initialization.*/ + "stackid": "0", /*stack id, this must be ordered and not be repeated*/ + }, + { + "stack_name": "vpp_hoststack", + "libname": "../lib64/libdmm_vcl.so", + "deploytype": "4", + "stackid": "1", + }, + ] +} diff --git a/stacks/vpp/configure/rd_config.json b/stacks/vpp/configure/rd_config.json new file mode 100644 index 0000000..166fbec --- /dev/null +++ b/stacks/vpp/configure/rd_config.json @@ -0,0 +1,26 @@ +{ + "ip_route": [ + { + "subnet": "192.168.1.1/24", + "stack_name": "vpp_hoststack", + }, + { + "subnet": "10.145.240.1/24", + "stack_name": "kernel", + }, + { + "subnet": "192.166.1.1/24", + "stack_name": "kernel", + } + ], + "prot_route": [ + { + "proto_type": "1", + "stack_name": "vpp_hoststack", + }, + { + "proto_type": "2", + "stack_name": "kernel", + } + ], +} diff --git a/stacks/vpp/configure/startup.conf b/stacks/vpp/configure/startup.conf new file mode 100644 index 0000000..ada7fdf --- /dev/null +++ b/stacks/vpp/configure/startup.conf @@ -0,0 +1,21 @@ +unix { + interactive + log /var/log/vpp/vpp.log + cli-listen localhost:5002 + full-coredump + exec /etc/vpp/vpp_config +} + +api-trace { + on +} + +cpu { + main-core 2 +} + +dpdk { + socket-mem 1024 + uio-driver igb_uio + dev 0000:00:09.0 +} diff --git a/stacks/vpp/configure/vpp_config b/stacks/vpp/configure/vpp_config new file mode 100644 index 0000000..56d80b5 --- /dev/null +++ b/stacks/vpp/configure/vpp_config @@ -0,0 +1,6 @@ +set int state GigabitEthernet0/9/0 up +set int ip addr GigabitEthernet0/9/0 192.168.1.1/24 +show version +show version verbose +show cpu +show int diff --git a/stacks/vpp/doc/README.md b/stacks/vpp/doc/README.md new file mode 100644 index 0000000..e09aefe --- /dev/null +++ b/stacks/vpp/doc/README.md @@ -0,0 +1,115 @@ +# 1. What is VPP Host Stack +VPP's host stack is a user space implementation of a number of transport, +session and application layer protocols that leverages VPP's existing +protocol stack. + +# 2. How to use VPP Host Stack + +## How to integrate VPP Host Stack into DMM +The file CMakeList.txt defined the compiling process, including downloading +the vpp code and patch it. The patch will modify the makefile to adapt dmm. + +Target 'libdmm_vcl' could not be get automatically unless you run +'make vpp-stack' manually. It will compile the adaption code and link the +libraries of vpp and finally generate the library of "libdmm_vcl.so". + + +## Compile +```sh + #cd dmm/build && cmake .. + #make vpp-statck +``` +Note: + After these processes, libdmm_vcl.so library would be generated in +vpp/build-root/install-vpp_debug-native/vpp/lib64/. + +##Start VPP Host Stack +- Steps 1: copy the plugins to /usr/lib/. +```sh + #cp -r vpp/build-root/install-vpp_debug-native/vpp/lib64/vpp_plugins /usr/lib/ +``` + +- Steps 2: load dpdk network card driver manually. +```sh + #cd dpdk-18.02/x86_64-native-linuxapp-gcc/kmod/ + #modprobe uio + #insmod igb_uio.ko +``` + +- Steps 3: choose a network card that is not in use and down it. +```sh + #ifconfig eth1 down +``` +- Steps 4: copy the config file and start vpp +```sh + #cp dmm/stacks/vpp/configure/startup.conf /etc/vpp/ + #cp dmm/stacks/vpp/configure/vpp_config /etc/vpp/ + #cd vpp/build-root/install-vpp_debug-native/vpp/bin + #./vpp -c /etc/vpp/startup.conf +``` +Note: + 1.modify the dev of dpdk in startup.conf. + 2.modify the interface name and ip in vpp_config. + +## Test app +Note: + Before testing, we should anotation the dmm code that "close (listenFd);" in + function process_server_accept_thread for server. Otherwize the app can + not send and recieve packets. + +- Steps 1: copy the libdmm_vcl.so to dmm/release/lib64/ +- Steps 2: copy the config file from dmm/stacks/vpp/configure/*.json to + dmm/release/bin and modify the rd_config.json. +```sh + #vim rd_config.json + //set "subnet": "192.168.21.1/24" +``` +Note: + Means dmm will hijack data from subnet 192.168.21.* + +- Steps 3: Communication test between machine A(as server) with machine B + (as client) + +##### Run in machine A +```sh + #cd dmm/release/bin/ + #./vs_epoll -p 20000 -d 192.168.21.180 -a 10000 -s 192.168.21.181 -l 1000 -t 500000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 50000 -e 10 -x 1 +``` +Note: + Means the current machine would be server, and it's +destination address is 192.168.21.180 (client address), +source address is 192.168.21.181(server address) + +##### Run in machine B +``` + #cd dmm/release/bin/ + #./vc_common -p 20000 -d 192.168.21.181 -a 10000 -s 192.168.21.180 -l 1000 -t 500000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 50000 -e 10 -x 1 +``` +Note: + Means the current machine would be client, and it's +destination address is 192.168.21.181 (server address), +source address is 192.168.21.180(client address) + +# 3. Document description + +(dmm/stacks/vpp/) + +## configure folder +##### module_config.json +- module_config.json is for configuring dmm protocol stack module + +##### rd_config.json +- rd_config.json is to choose which module is better to go through. It will go + through vpp host protocol stack when RD type is nstack-vpp + +## patch folder +- modify the makefile to compile the adapt code. + +## adapt folder +##### dmm_vcl_adpt.c && dmm_vcl.h +- vpp host stack adaptation code, including initialization and adaptation functions. + +# 4. More Information +- https://wiki.fd.io/view/DMM +- https://wiki.fd.io/view/VPP +- https://wiki.fd.io/view/VPP/HostStack diff --git a/stacks/vpp/patch/vpp.patch b/stacks/vpp/patch/vpp.patch new file mode 100644 index 0000000..a9b5427 --- /dev/null +++ b/stacks/vpp/patch/vpp.patch @@ -0,0 +1,104 @@ +diff --git a/src/vcl/CMakeLists.txt b/src/vcl/CMakeLists.txt +index 2578a37..21245e4 100644 +--- a/src/vcl/CMakeLists.txt ++++ b/src/vcl/CMakeLists.txt +@@ -38,6 +38,19 @@ add_vpp_library(vcl_ldpreload + vppinfra svm vlibmemoryclient rt pthread vppcom dl + ) + ++set(DMM_HEADERS_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../release/include/) ++include_directories(${DMM_HEADERS_DIR}) ++ ++add_vpp_library(dmm_vcl ++ SOURCES ++ dmm_vcl_adpt.c ++ ldp_socket_wrapper.c ++ ldp.c ++ ++ LINK_LIBRARIES ++ vppinfra svm vlibmemoryclient vppcom vcl_ldpreload pthread rt dl ++) ++ + add_vpp_headers(vcl + ldp.h + sock_test.h +diff --git a/src/vcl/ldp.c b/src/vcl/ldp.c +index 9e00d7e..2ba1099 100644 +--- a/src/vcl/ldp.c ++++ b/src/vcl/ldp.c +@@ -26,6 +26,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -672,6 +673,7 @@ ldp_pselect (int nfds, fd_set * __restrict readfds, + const __sigset_t * __restrict sigmask) + { + u32 minbits = clib_max (nfds, BITS (uword)), n_bytes; ++ vcl_set_worker_index(0); + ldp_worker_ctx_t *ldpw = ldp_worker_get_current (); + struct timespec libc_tspec = { 0 }; + f64 time_out, vcl_timeout = 0; +@@ -2170,6 +2172,7 @@ static inline int + ldp_epoll_pwait (int epfd, struct epoll_event *events, int maxevents, + int timeout, const sigset_t * sigmask) + { ++ vcl_set_worker_index(0); + ldp_worker_ctx_t *ldpw = ldp_worker_get_current (); + double time_to_wait = (double) 0, max_time; + int libc_epfd, rv = 0; +diff --git a/src/vcl/vcl_locked.c b/src/vcl/vcl_locked.c +index 5539191..528e331 100644 +--- a/src/vcl/vcl_locked.c ++++ b/src/vcl/vcl_locked.c +@@ -468,7 +468,7 @@ vls_mt_rel_locks (int locks_acq) + + #define vls_mt_guard(_vls, _op) \ + int _locks_acq = 0; \ +- if (PREDICT_FALSE (vcl_get_worker_index () == ~0)) \ ++ if (PREDICT_FALSE (vcl_get_worker_index () == ~0)); \ + vls_mt_add (); \ + if (PREDICT_FALSE (vlsl->vls_mt_n_threads > 1)) \ + vls_mt_acq_locks (_vls, _op, &_locks_acq); \ +@@ -779,8 +779,10 @@ vls_epoll_ctl (vls_handle_t ep_vlsh, int op, vls_handle_t vlsh, + vls_table_rlock (); + ep_vls = vls_get_and_lock (ep_vlsh); + vls = vls_get_and_lock (vlsh); ++ vls_mt_guard (0, VLS_MT_OP_XPOLL); + ep_sh = vls_to_sh (ep_vls); + sh = vls_to_sh (vls); ++ vls_mt_unguard (); + + if (PREDICT_FALSE (!vlsl->epoll_mp_check)) + vls_epoll_ctl_mp_checks (vls, op); +@@ -886,6 +888,7 @@ vls_unshare_vcl_worker_sessions (vcl_worker_t * wrk) + vls_table_wunlock (); + } + ++#if 0 + static void + vls_cleanup_vcl_worker (vcl_worker_t * wrk) + { +@@ -1043,7 +1046,7 @@ vls_app_fork_parent_handler (void) + while (vcm->forking) + ; + } +- ++#endif + void + vls_app_exit (void) + { +@@ -1061,8 +1064,8 @@ vls_app_create (char *app_name) + vlsm = clib_mem_alloc (sizeof (vls_main_t)); + clib_memset (vlsm, 0, sizeof (*vlsm)); + clib_rwlock_init (&vlsm->vls_table_lock); +- pthread_atfork (vls_app_pre_fork, vls_app_fork_parent_handler, +- vls_app_fork_child_handler); ++ /* pthread_atfork (vls_app_pre_fork, vls_app_fork_parent_handler, ++ vls_app_fork_child_handler);*/ + atexit (vls_app_exit); + vlsl->vls_wrk_index = vcl_get_worker_index (); + vls_mt_locks_init (); diff --git a/stacks/vpp/vagrant/Vagrantfile b/stacks/vpp/vagrant/Vagrantfile new file mode 100644 index 0000000..5cf102c --- /dev/null +++ b/stacks/vpp/vagrant/Vagrantfile @@ -0,0 +1,63 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure(2) do |config| + + # Pick the right distro and bootstrap, default is ubuntu1604 + distro = ( ENV['DMM_VAGRANT_DISTRO'] || "ubuntu") + if distro == 'centos7' + config.vm.box = "puppetlabs/centos-7.2-64-nocm" + else + config.vm.box = "puppetlabs/ubuntu-16.04-64-nocm" + end + config.vm.box_check_update = false + + # Create DMM client and server VM's + config.vm.define "dmm-vpp-server" do |server| + server.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"install_prereq.sh") + server.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"build.sh"), :args => "/dmm vagrant" + end + config.vm.define "dmm-vpp-client" do |client| + client.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"install_prereq.sh") + client.vm.provision :shell, :path => File.join(File.dirname(__FILE__),"build.sh"), :args => "/dmm vagrant" + end + + + # vagrant-cachier caches apt/yum etc to speed subsequent + # vagrant up + # to enable, run + # vagrant plugin install vagrant-cachier + # + if Vagrant.has_plugin?("vagrant-cachier") + config.cache.scope = :box + end + + # Define some physical ports for your VMs to be used by DPDK + nics = (ENV['DMM_VAGRANT_NICS'] || "2").to_i(10) + for i in 1..nics + config.vm.network "private_network", type: "dhcp" + # config.vm.network "private_network", ip: "172.28.128.200" + # config.vm.network "private_network", ip: "172.28.128.201" + end + + # use http proxy if avaiable + if ENV['http_proxy'] && Vagrant.has_plugin?("vagrant-proxyconf") + config.proxy.http = ENV['http_proxy'] + config.proxy.https = ENV['https_proxy'] + config.proxy.no_proxy = "localhost,127.0.0.1" + end + + vmcpu=(ENV['DMM_VAGRANT_VMCPU'] || 4) + vmram=(ENV['DMM_VAGRANT_VMRAM'] || 5120) + + config.ssh.forward_agent = true + config.ssh.forward_x11 = true + + config.vm.provider "virtualbox" do |vb| + vb.customize ["modifyvm", :id, "--ioapic", "on"] + vb.memory = "#{vmram}" + vb.cpus = "#{vmcpu}" + + config.vm.synced_folder "../../../", "/dmm", type: "rsync" + end +end diff --git a/stacks/vpp/vagrant/build.sh b/stacks/vpp/vagrant/build.sh new file mode 100644 index 0000000..1ed343b --- /dev/null +++ b/stacks/vpp/vagrant/build.sh @@ -0,0 +1,224 @@ +#!/bin/bash -x +######################################################################### +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +set -x + +TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S) +log_file="/tmp/build_log.txt-$TIMESTAMP" +exec 1> >(tee -a "$log_file") 2>&1 + +# Get Command Line arguements if present +TEMP_DIR=$1 +if [ "x$1" != "x" ]; then + TEMP_DIR=$1 + DMM_BUILD_DIR=${TEMP_DIR}/build + DPDK_BUILD_SCRIPT_DIR=${DMM_BUILD_DIR}/../scripts + VPP_BUILD_DIR=${TEMP_DIR}/stacks/vpp/vpp/ +else + TEMP_DIR=`dirname $(readlink -f $0)`/.. + DMM_BUILD_DIR=${TEMP_DIR}/../../build + DPDK_BUILD_SCRIPT_DIR=${DMM_BUILD_DIR}/../scripts + VPP_BUILD_DIR=${TEMP_DIR} +fi + +echo 0:$0 +echo 1:$1 +echo 2:$2 +echo TEMP_DIR: $TEMP_DIR +echo DMM_BUILD_DIR: $DMM_BUILD_DIR +echo DPDK_BUILD_SCRIPT_DIR: $DPDK_BUILD_SCRIPT_DIR +echo VPP_BUILD_DIR: $VPP_BUILD_DIR + +OS_ID=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') +OS_VERSION_ID=$(grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') +KERNEL_OS=`uname -o` +KERNEL_MACHINE=`uname -m` +KERNEL_RELEASE=`uname -r` +KERNEL_VERSION=`uname -v` + +echo KERNEL_OS: $KERNEL_OS +echo KERNEL_MACHINE: $KERNEL_MACHINE +echo KERNEL_RELEASE: $KERNEL_RELEASE +echo KERNEL_VERSION: $KERNEL_VERSION +echo OS_ID: $OS_ID +echo OS_VERSION_ID: $OS_ID + +#DPDK download path +DPDK_DOWNLOAD_PATH=/tmp/dpdk + +#dpdk installation path +DPDK_INSTALL_PATH=/usr + +#set and check the environment for Linux +if [ "$OS_ID" == "ubuntu" ]; then + export DEBIAN_FRONTEND=noninteractive + export DEBCONF_NONINTERACTIVE_SEEN=true + + APT_OPTS="--assume-yes --no-install-suggests --no-install-recommends -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\"" + sudo apt-get update ${APT_OPTS} + sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev vim ethtool unzip +elif [ "$OS_ID" == "debian" ]; then + echo "not tested for debian and exit" + exit 1 + export DEBIAN_FRONTEND=noninteractive + export DEBCONF_NONINTERACTIVE_SEEN=true + + APT_OPTS="--assume-yes --no-install-suggests --no-install-recommends -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\"" + sudo apt-get update ${APT_OPTS} + sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump libpcre3 libpcre3-dev zlibc zlib1g zlib1g-dev vim +elif [ "$OS_ID" == "centos" ]; then + sudo yum install -y git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump vim sudo yum-utils pcre-devel zlib-devel +elif [ "$OS_ID" == "opensuse" ]; then + echo "not tested for opensuse and exit" + exit 1 + sudo yum install -y git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump vim sudo yum-utils pcre-devel zlib-devel +fi + +#DPDK will be having dependancy on linux headers +if [ "$OS_ID" == "ubuntu" ]; then + sudo apt-get -y install git build-essential linux-headers-`uname -r` + sudo apt-get -y install libnuma-dev +elif [ "$OS_ID" == "debian" ]; then + sudo apt-get -y install git build-essential linux-headers-`uname -r` +elif [ "$OS_ID" == "centos" ]; then + sudo yum groupinstall -y "Development Tools" + sudo yum install -y kernel-headers + sudo yum install -y numactl-devel +elif [ "$OS_ID" == "opensuse" ]; then + sudo yum groupinstall -y "Development Tools" + sudo yum install -y kernel-headers +fi +#===========build DPDK================ + +if [ ! -d /usr/include/dpdk ] || [ ! -d /usr/share/dpdk ] || [ ! -d /usr/lib/modules/4.4.0-31-generic/extra/dpdk ]; then + mkdir -p $DPDK_DOWNLOAD_PATH + + cd $DPDK_DOWNLOAD_PATH + wget -N https://fast.dpdk.org/rel/dpdk-18.02.tar.xz --no-check-certificate + tar xvf dpdk-18.02.tar.xz + cd dpdk-18.02/ + + + sed -i 's!CONFIG_RTE_EXEC_ENV=.*!CONFIG_RTE_EXEC_ENV=y!1' config/common_base + sed -i 's!CONFIG_RTE_BUILD_SHARED_LIB=.*!CONFIG_RTE_BUILD_SHARED_LIB=y!1' config/common_base + sed -i 's!CONFIG_RTE_LIBRTE_EAL=.*!CONFIG_RTE_LIBRTE_EAL=y!1' config/common_base + sed -i 's!CONFIG_RTE_EAL_PMD_PATH=.*!CONFIG_RTE_EAL_PMD_PATH="/tmp/dpdk/drivers/"!1' config/common_base + + sudo make install T=x86_64-native-linuxapp-gcc DESTDIR=${DPDK_INSTALL_PATH} -j 4 + + mkdir -p /tmp/dpdk/drivers/ + cp -f /usr/lib/librte_mempool_ring.so /tmp/dpdk/drivers/ +fi + +#===========check running env ================= +hugepagesize=$(cat /proc/meminfo | grep Hugepagesize | awk -F " " {'print$2'}) +if [ "$hugepagesize" == "2048" ]; then + pages=2560 +elif [ "$hugepagesize" == "1048576" ]; then + pages=5 +fi +sudo sysctl -w vm.nr_hugepages=$pages +HUGEPAGES=`sysctl -n vm.nr_hugepages` +if [ $HUGEPAGES != $pages ]; then + echo "ERROR: Unable to get $pages hugepages, only got $HUGEPAGES. Cannot finish." + exit +fi + + +hugepageTotal=$(cat /proc/meminfo | grep -c "HugePages_Total: 0") +if [ $hugepageTotal -ne 0 ]; then + echo "HugePages_Total is zero" + exit +fi + +hugepageFree=$(cat /proc/meminfo | grep -c "HugePages_Free: 0") +if [ $hugepageFree -ne 0 ]; then + echo "HugePages_Free is zero" + exit +fi + +hugepageSize=$(cat /proc/meminfo | grep -c "Hugepagesize: 0 kB") +if [ $hugepageSize -ne 0 ]; then + echo "Hugepagesize is zero" + exit +fi + + +sudo mkdir /mnt/nstackhuge -p +if [ "$hugepagesize" == "2048" ]; then +sudo mount -t hugetlbfs -o pagesize=2M none /mnt/nstackhuge/ +elif [ "$hugepagesize" == "1048576" ]; then + sudo mount -t hugetlbfs -o pagesize=1G none /mnt/nstackhuge/ +fi + +#===========build DMM================= +echo "DMM build started....." + +cd $DMM_BUILD_DIR +ldconfig +rm -rf * +cmake .. +make -j 8 +if [ $? -eq 0 ]; then + echo "DMM build is SUCCESS" +else + echo "DMM build has FAILED" + exit 1 +fi +echo "DMM build finished....." + +git config --global http.sslVerify false +#===========build vpp=========== +echo "vpp build started....." +make vpp-stack +if [ $? -eq 0 ]; then + echo "vpp build is SUCCESS" +else + echo "vpp build has FAILED" + exit 1 +fi +echo "vpp build finished....." + +#===========set environment=========== +sudo mkdir -p /etc/vpp/ +cp /dmm/stacks/vpp/configure/startup.conf /etc/vpp/ +cp /dmm/stacks/vpp/configure/vpp_config /etc/vpp/ + +sudo cp -r /dmm/stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib64/vpp_plugins/ /usr/lib/ + +sudo modprobe uio +sudo insmod ${DPDK_DOWNLOAD_PATH}/dpdk-18.02/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko + +sudo ifconfig enp0s9 down + +if [ "$OS_ID" == "centos" ]; then + ifaddress1=$(ifconfig enp0s9 | grep 'inet' | cut -d: -f2 | awk '{print $2}') + echo $ifaddress1 + ifaddresscut=$(ifconfig enp0s9 | grep 'inet' | head -n 1 | awk -F " " '{print $2}' | awk -F "." '{print $1"."$2"."$3}') + echo $ifaddresscut +elif [ "$OS_ID" == "ubuntu" ]; then + ifaddress1=$(ifconfig enp0s9 | grep 'inet' | head -n 1 | cut -d: -f2 | awk '{print $1}') + echo $ifaddress1 +fi + +cd /etc/vpp/ + +sudo sed -i 's!192.168.1.1!'$ifaddress1'!1' vpp_config + +cd $DMM_BUILD_DIR/../release/bin +sudo cp ../../stacks/vpp/configure/*.json ./ +sudo cp ../../stacks/vpp/vpp/build-root/install-vpp_debug-native/vpp/lib64/libdmm_vcl.so ../lib64/ +sudo sed -i 's!192.168.1.1!'$ifaddresscut'.0!1' rd_config.json diff --git a/stacks/vpp/vagrant/env.sh b/stacks/vpp/vagrant/env.sh new file mode 100644 index 0000000..96ad346 --- /dev/null +++ b/stacks/vpp/vagrant/env.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +#export DMM_VAGRANT_DISTRO="ubuntu1604" +export DMM_VAGRANT_DISTRO="centos7" +export DMM_VAGRANT_NICS=2 +export DMM_VAGRANT_VMCPU=4 +export DMM_VAGRANT_VMRAM=8192 diff --git a/stacks/vpp/vagrant/install_prereq.sh b/stacks/vpp/vagrant/install_prereq.sh new file mode 100644 index 0000000..2e636c2 --- /dev/null +++ b/stacks/vpp/vagrant/install_prereq.sh @@ -0,0 +1,39 @@ +#!/bin/bash -x +log_file="/tmp/pre_install_log.txt-`date +'%Y-%m-%d_%H-%M-%S'`" +exec 1> >(tee -a "$log_file") 2>&1 + +if [ "$(uname)" <> "Darwin" ]; then + OS_ID=$(grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') + OS_VERSION_ID=$(grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') +fi + +if [ "$OS_ID" == "ubuntu" ]; then + # Standard update + upgrade dance + cat << EOF >> /etc/apt/sources.list + deb http://in.archive.ubuntu.com/ubuntu/ trusty main restricted + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty main restricted + deb http://in.archive.ubuntu.com/ubuntu/ trusty-updates main restricted + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty-updates main restricted + deb http://in.archive.ubuntu.com/ubuntu/ trusty universe + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty universe + deb http://in.archive.ubuntu.com/ubuntu/ trusty-updates universe + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty-updates universe + deb http://in.archive.ubuntu.com/ubuntu/ trusty multiverse + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty multiverse + deb http://in.archive.ubuntu.com/ubuntu/ trusty-updates multiverse + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty-updates multiverse + deb http://in.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse + deb-src http://in.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse + deb http://security.ubuntu.com/ubuntu trusty-security main restricted + deb-src http://security.ubuntu.com/ubuntu trusty-security main restricted + deb http://security.ubuntu.com/ubuntu trusty-security universe + deb-src http://security.ubuntu.com/ubuntu trusty-security universe + deb http://security.ubuntu.com/ubuntu trusty-security multiverse + deb-src http://security.ubuntu.com/ubuntu trusty-security multiverse + deb http://extras.ubuntu.com/ubuntu trusty main + deb-src http://extras.ubuntu.com/ubuntu trusty main +EOF +elif [ "$OS_ID" == "centos" ]; then + + echo centos +fi diff --git a/testcode/app_example/CMakeLists.txt b/testcode/app_example/CMakeLists.txt deleted file mode 100644 index ff25e1f..0000000 --- a/testcode/app_example/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -######################################################################### -# -# Copyright (c) 2018 Huawei Technologies Co.,Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -######################################################################### - -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11) -PROJECT(nStack) -SET(CMAKE_SKIP_RPATH TRUE) -SET(CMAKE_C_COMPILER "gcc") -SET(OS_RELEASE "" CACHE STRING "User-specified OS release.") - -SET(EXECUTABLE_PATH ${CMAKE_CURRENT_LIST_DIR}/release/bin) -SET(LIB_PATH_STATIC ${PROJECT_BINARY_DIR}) -SET(LIB_PATH_SHARED ${CMAKE_CURRENT_LIST_DIR}/../../release/lib64) - -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH_STATIC}) -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_PATH}) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB_PATH_SHARED}) -ADD_SUBDIRECTORY(perf-test) -ADD_SUBDIRECTORY(func-test) diff --git a/testcode/app_example/build/.gitkeep b/testcode/app_example/build/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/testcode/app_example/func-test/CMakeLists.txt b/testcode/app_example/func-test/CMakeLists.txt deleted file mode 100644 index 865eba5..0000000 --- a/testcode/app_example/func-test/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -######################################################################### -# -# Copyright (c) 2018 Huawei Technologies Co.,Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -######################################################################### - -ADD_SUBDIRECTORY(fork) -ADD_SUBDIRECTORY(file_transfer) diff --git a/testcode/app_example/func-test/file_transfer/CMakeLists.txt b/testcode/app_example/func-test/file_transfer/CMakeLists.txt deleted file mode 100644 index e4f653a..0000000 --- a/testcode/app_example/func-test/file_transfer/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -######################################################################### -# -# Copyright (c) 2018 Huawei Technologies Co.,Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -######################################################################### -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") - -LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) - -ADD_EXECUTABLE(vc_serv_file server_filetrans.c) -TARGET_LINK_LIBRARIES(vc_serv_file libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(vc_cli_file client_filetrans.c) -TARGET_LINK_LIBRARIES(vc_cli_file libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(kc_serv_file server_filetrans.c) -TARGET_LINK_LIBRARIES(kc_serv_file pthread) - -ADD_EXECUTABLE(kc_cli_file client_filetrans.c) -TARGET_LINK_LIBRARIES(kc_cli_file pthread) diff --git a/testcode/app_example/func-test/file_transfer/client_filetrans.c b/testcode/app_example/func-test/file_transfer/client_filetrans.c deleted file mode 100644 index f0e2a80..0000000 --- a/testcode/app_example/func-test/file_transfer/client_filetrans.c +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -char *END_FLAG = "=================END"; -#define HEXCONVERT_COLS 8 -#define HEX_CONVERT 1 -//#define DEBUG 1 -#define out(fmt, arg...) (void)printf(fmt, ##arg) - -#ifdef DEBUG -#define DBG(fmt, arg...) do { \ - out("[Debug] " fmt, ##arg); \ - } while (0) -#else -#define DBG(fmt, arg...) ((void)0) -#endif - -void error(const char *msg) -{ - perror(msg); - out("./client_tcp [server_ip_address] [port number] [filename] [client_ip_address]\n"); - exit(1); -} - -#if defined(HEX_CONVERT) && defined(DEBUG) -void hexconvert(void *mem, unsigned int len) -{ - unsigned int i; - - for (i = 0; - i < - len + - ((len % HEXCONVERT_COLS) ? (HEXCONVERT_COLS - - len % HEXCONVERT_COLS) : 0); i++) - { - /* print offset */ - if (i % HEXCONVERT_COLS == 0) - { - DBG("\n0x%06x: ", i); - } - - /*print hex data */ - if (i < len) - { - DBG("%02x ", 0xFF & ((char *) mem)[i]); - } - else /* end of block, just aligning for ASCII dump */ - { - DBG("\n"); - } - } -} -#endif - -void tcp(char **pArgv) -{ - - int sockfd, portno; - char buff[1024]; - - struct sockaddr_in serv_addr, cli_addr; - struct hostent *server; - - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - { - error("error in socket creation\n"); - } - out("socket create successful\n"); - - portno = atoi(pArgv[2]); - server = gethostbyname(pArgv[1]); - - if (server == NULL) - { - fprintf(stderr, "error no such host\n"); - } - - bzero((char *) &serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr, - server->h_length); - serv_addr.sin_port = htons(portno); - bzero((char *) &cli_addr, sizeof(serv_addr)); - - cli_addr.sin_family = AF_INET; - cli_addr.sin_addr.s_addr = inet_addr(pArgv[4]); - cli_addr.sin_port = htons(portno); - if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) - { - error("bind fail"); - } - out("Bind successful\n"); - - if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < - 0) - { - error("connection fail"); - } - out("connection done\n"); - - FILE *file; - int filebyte = 0; - int lsize, totalsize = 0; - - file = fopen(pArgv[3], "r"); - fseek(file, 0, SEEK_END); - lsize = ftell(file); - rewind(file); - out("Name of file: %s, Size of file : %d\n", pArgv[3], lsize); - if (write(sockfd, &lsize, sizeof(int)) == -1) - { - out("error executing write\n"); - } - if (write(sockfd, pArgv[3], 255) == -1) - { - out("error executing write\n"); - } - while (lsize > totalsize) - { - bzero(buff, 1024); - fseek(file, totalsize, SEEK_SET); - filebyte = fread(buff, 1, sizeof(buff), file); - if (filebyte == 0) - { - printf("file End of file\n"); - break; - } - - if (filebyte < 0) - error("error in reading file. \n"); -#if defined(HEX_CONVERT) && defined(DEBUG) - DBG("=========================================\n"); - hexconvert(buff, filebyte); - DBG("=========================================\n"); -#endif - - void *p = buff; - totalsize += filebyte; - - while (filebyte > 0) - { -#ifdef DEBUG - DBG("=========================================\n"); - puts((const char *) p); - DBG("=========================================\n"); -#endif - int bytes_written = write(sockfd, p, filebyte); - if (bytes_written <= 0) - { - error("error in Socket write.\n"); - } - - filebyte -= bytes_written; - p += bytes_written; -//#if DEBUG - DBG("Total size of file = %d, Total Bytes sent to socket = %d, bytes_written in each step = %d\n", lsize, totalsize, bytes_written); -//#endif - } - } - out("file has been sent successfully\n"); - out("Final Total size of file = %d, Total Bytes sent to socket = %d\n", - lsize, totalsize); - - fclose(file); - sleep(60); - close(sockfd); - return; -} - -void udp(char **pArgv) -{ - int sockfd, n, fd, sz, portno, MAXLINE; - FILE *fp; - struct sockaddr_in servaddr, cliaddr; - char *buf; - char *target, *path; - portno = atoi(pArgv[2]); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(portno); - servaddr.sin_addr.s_addr = inet_addr(pArgv[1]); - bzero(&cliaddr, sizeof(servaddr)); - cliaddr.sin_family = AF_INET; - cliaddr.sin_port = htons(portno); - cliaddr.sin_addr.s_addr = inet_addr(pArgv[3]); - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) - { - out("error in socket creation\n"); - } - out("socket create successful\n"); - - if (bind(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0) - { - out("bind fail"); - } - out("Bind successful\n"); - - path = pArgv[4]; - target = pArgv[5]; - MAXLINE = atoi(pArgv[6]); - buf = malloc(MAXLINE * sizeof(int)); - fp = fopen(path, "r"); - fseek(fp, 0L, SEEK_END); - sz = ftell(fp); - out("The size of the path file is %d", sz); - sendto(sockfd, target, strlen(target), 0, - (struct sockaddr *) &servaddr, sizeof(servaddr)); - n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, NULL); - if (!strncmp(buf, "ok", 2)) - { - out("Filename sent.\n"); - } - - fd = open(path, O_RDONLY); - while ((n = read(fd, buf, MAXLINE)) > 0) - { - sendto(sockfd, buf, n, 0, (struct sockaddr *) &servaddr, - sizeof(servaddr)); - } - sendto(sockfd, END_FLAG, strlen(END_FLAG), 0, - (struct sockaddr *) &servaddr, sizeof(servaddr)); - fclose(fp); - sleep(60); - close(sockfd); - return; -} - -int main(int argc, char *argv[]) -{ - int i; - char **pArgv, str[10]; - pArgv = (char **) malloc(sizeof(char *) * 10); - for (i = 0; i < 10; i++) - { - pArgv[i] = (char *) malloc(sizeof(char) * 20); - } - printf("%s", argv[1]); - - if (strcmp("tcp", argv[1]) == 0) - { - strcpy(pArgv[0], "tcp"); - printf("pArgv[0]=%s", pArgv[0]); - /* The arguments of tcp are [server_ip_address] [port number] [filename] [client_ip_address] */ - for (i = 1; i < 5; i++) - { - strcpy(pArgv[i], argv[i + 1]); - } - tcp(pArgv); - } - - else - { - strcpy(str, argv[1]); - if (strcmp("udp", str) == 0) - { - strcpy(pArgv[0], "udp"); - printf("pArgv[0]=%s", pArgv[0]); - /* The arguments of udp are [server_ip_address] [port number] [client_ip_address] [filename] [target_filename] [MAX_BUFFER_LENGTH] */ - for (i = 1; i < 7; i++) - { - strcpy(pArgv[i], argv[i + 1]); - } - udp(pArgv); - } - } - return 0; -} diff --git a/testcode/app_example/func-test/file_transfer/server_filetrans.c b/testcode/app_example/func-test/file_transfer/server_filetrans.c deleted file mode 100644 index 8b7e25f..0000000 --- a/testcode/app_example/func-test/file_transfer/server_filetrans.c +++ /dev/null @@ -1,336 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -char *END_FLAG = "=================END"; -#define HEXCONVERT_COLS 8 -#define HEX_CONVERT 1 -//#define DEBUG 1 -#define out(fmt, arg...) (void)printf(fmt, ##arg) - -#ifdef DEBUG -#define DBG(fmt, arg...) do { \ - out("[Debug] " fmt, ##arg); \ - } while (0) -#else -#define DBG(fmt, arg...) ((void)0) -#endif - -void error(const char *msg) -{ - perror(msg); - out("./server_tcp [server_ip_address] [port number]\n"); - exit(1); -} - -#if defined(HEX_CONVERT) && defined(DEBUG) -void hexconvert(void *mem, unsigned int len) -{ - unsigned int i; - - for (i = 0; - i < - len + - ((len % HEXCONVERT_COLS) ? (HEXCONVERT_COLS - - len % HEXCONVERT_COLS) : 0); i++) - { - /* print offset */ - if (i % HEXCONVERT_COLS == 0) - { - DBG("\n0x%06x: ", i); - } - - /*print hex data */ - if (i < len) - { - DBG("%02x ", 0xFF & ((char *) mem)[i]); - } - else /* end of block, just aligning for ASCII dump */ - { - DBG("\n"); - } - } -} -#endif -int compareFiles(FILE * fp1, FILE * fp2) -{ - - char ch1 = getc(fp1); - char ch2 = getc(fp2); - int error = 0, pos = 0, line = 1; - - while (ch1 != EOF && ch2 != EOF) - { - pos++; - if (ch1 == '\n' && ch2 == '\n') - { - line++; - pos = 0; - } - - if (ch1 != ch2) - { - error++; - DBG("Line Number : %d \tError" " Position :%d \n", line, pos); - } - - ch1 = getc(fp1); - ch2 = getc(fp2); - } - - //printf("Total Errors : %d\t", error); - return error; -} - -void tcp(char **pArgv) -{ - - int sockfd, newsockfd, portno; - char buff[1024], filename[255]; - - struct sockaddr_in serv_addr, cli_addr; - socklen_t clilen; - - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - { - error("error in socket creation"); - } - out("socket create successful\n"); - - bzero((char *) &serv_addr, sizeof(serv_addr)); - portno = atoi(pArgv[2]); - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = inet_addr(pArgv[1]); - serv_addr.sin_port = htons(portno); - - if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) - { - error("bind fail"); - } - out("Bind successful\n"); - listen(sockfd, 5); - clilen = sizeof(cli_addr); - - newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); - if (newsockfd < 0) - { - error("error in accept"); - } - out("socket accept succesful\n"); - bzero(buff, 1024); - - FILE *fp; - int lSize = 0, totallSize = 0; - - bzero(filename, 255); - - fclose(fopen("receive_file.txt", "w")); - if (system("chmod +x *") == -1) - { - out(" incorrect use of system\n"); - } - fp = fopen("receive_file.txt", "a"); - - if (read(newsockfd, &lSize, sizeof(int)) == -1) - { - out("error executing read\n"); - } - if (read(newsockfd, filename, sizeof(filename)) == -1) - { - out("error executing read\n"); - } - - while (lSize > totallSize) - { - int bytes_read = 0; - bzero(buff, 1024); - - bytes_read = read(newsockfd, buff, 1024); - - if (bytes_read == 0) - { - break; - } - - if (bytes_read < 0) - { - error("error in Socket read.\n"); - } - -#if defined(HEX_CONVERT) && defined(DEBUG) - DBG("=========================================\n"); - hexconvert(buff, bytes_read); - DBG("=========================================\n"); -#endif -#ifdef DEBUG - DBG("=========================================\n"); - puts((const char *) buff); - DBG("=========================================\n"); -#endif - totallSize += bytes_read; - - if (fwrite(buff, 1, bytes_read, fp) == -1) - { - error("error in file write\n"); - } -//#if DEBUG - DBG("Total size of file = %d, Total Bytes sent to socket = %d, bytes_read in each step = %d\n", lSize, totallSize, bytes_read); -//#endif - } - out("file name = %s\n", filename); - out("Final total size of file = %d, total read from socket = %d\n", lSize, - totallSize); - out("copy complete\n"); - fclose(fp); - - FILE *fp1 = fopen("receive_file.txt", "r"); - FILE *fp2 = fopen(filename, "r"); - - fseek(fp2, 0L, SEEK_END); - int lfile_size = ftell(fp2); - rewind(fp2); - if (lfile_size != lSize) - { - out("Size unmatch...\n"); - } - else - { - out("Size match...\n"); - } - - if (compareFiles(fp1, fp2) > 0) - { - out("file unmatch...\n"); - } - else - { - out("file match...\n"); - } - - close(newsockfd); - close(sockfd); - return; -} - -void -run(int sockfd, struct sockaddr *cliaddr, socklen_t clilen, char *res_buf, - int MAXLINE) -{ - int n, fd; - socklen_t len; - char *buf, *buf2; - FILE *fp1, *fp2; - buf = malloc(MAXLINE + 1); - len = clilen; - n = recvfrom(sockfd, buf, MAXLINE, 0, cliaddr, &len); - buf[n] = 0; - out("Received from client:[%s] \n", buf); - buf2 = malloc(MAXLINE); - strcpy(buf2, buf); - sendto(sockfd, "ok", strlen("ok"), 0, cliaddr, len); - fd = open(buf, O_RDWR | O_CREAT, 0666); - while ((n = recvfrom(sockfd, buf, MAXLINE, 0, cliaddr, &len))) - { - buf[n] = 0; - //out("%s", buf); - if (!(strcmp(buf, END_FLAG))) - { - break; - } - if (write(fd, buf, n) == -1) - { - out("error in executing write\n"); - } - } - fp1 = fopen(buf2, "r"); - fp2 = fopen(res_buf, "r"); - - if (compareFiles(fp1, fp2) == 0) - { - out("\nPass:The contents of the files are same"); - } - else - { - out("\nFail:The contents of the files are different"); - } - close(fd); -} - -void udp(char **pArgv) -{ - int sockfd, portno, MAXLINE; - struct sockaddr_in servaddr, cliaddr; - char *res_buf; - res_buf = pArgv[3]; - - portno = atoi(pArgv[2]); - MAXLINE = atoi(pArgv[4]); - sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) - { - out("error in socket creation\n"); - } - out("socket create successful\n"); - - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = inet_addr(pArgv[1]); - servaddr.sin_port = htons(portno); - - if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) - { - out("bind fail"); - } - out("Binded successfully\n"); - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(sockfd, &read_fds); - int fdmax = sockfd; - if (FD_ISSET(sockfd, &read_fds)) - { - run(fdmax, (struct sockaddr *) &cliaddr, sizeof(cliaddr), res_buf, - MAXLINE); - } - return; -} - -int main(int argc, char *argv[]) -{ - int i, j; - char **pArgv; - pArgv = (char **) malloc(sizeof(char *) * 10); - for (i = 0; i < 10; i++) - { - pArgv[i] = (char *) malloc(sizeof(char) * 20); - } - if (strcmp("tcp", argv[1]) == 0) - { - strcpy(pArgv[0], "tcp"); - /* The arguments of tcp are [server_ip_address] [port number] */ - for (i = 1; i < 3; i++) - { - strcpy(pArgv[i], argv[i + 1]); - } - tcp(pArgv); - } - else if (strcmp("udp", argv[1]) == 0) - { - strcpy(pArgv[0], "udp"); - /* The arguments of udp are [server_ip_address] [port number] [filename] [MAX_BUFFER_LENGTH] */ - for (i = 1; i < 5; i++) - { - strcpy(pArgv[i], argv[i + 1]); - } - udp(pArgv); - } - - return 0; -} diff --git a/testcode/app_example/func-test/fork/CMakeLists.txt b/testcode/app_example/func-test/fork/CMakeLists.txt deleted file mode 100644 index a78f617..0000000 --- a/testcode/app_example/func-test/fork/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -######################################################################### -# -# Copyright (c) 2018 Huawei Technologies Co.,Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -######################################################################### -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") - -LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) - -ADD_EXECUTABLE(vtcp_fork_server tcpserver.c) -TARGET_LINK_LIBRARIES(vtcp_fork_server libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(vtcp_client tcpclient.c) -TARGET_LINK_LIBRARIES(vtcp_client libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(ktcp_fork_server tcpserver.c) -TARGET_LINK_LIBRARIES(ktcp_fork_server pthread) - -ADD_EXECUTABLE(ktcp_client tcpclient.c) -TARGET_LINK_LIBRARIES(ktcp_client pthread) diff --git a/testcode/app_example/func-test/fork/tcpclient.c b/testcode/app_example/func-test/fork/tcpclient.c deleted file mode 100644 index 8023b34..0000000 --- a/testcode/app_example/func-test/fork/tcpclient.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG - -#ifdef DEBUG -#define DBG(fmt, arg...) do { \ - printf(fmt, ##arg); \ -} while(0) -#else -#define DBG(fmt, arg...) ((void)0) -#endif - -static struct sockaddr_in g_dest; -static struct sockaddr_in g_src; -int srcPort = 0; -int destPort = 0; -int times = 0; - -void random_str(char *str, const int len) -{ - static const char alphaNum[] = - "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i = 0; - - for (i = 0; i < len; i++) - { - str[i] = alphaNum[rand() % (sizeof(alphaNum) - 1)]; - } - - str[len] = 0; -} - -static void setArgsDefault() -{ - - memset(&g_dest, 0, sizeof(g_dest)); - g_dest.sin_family = AF_INET; - g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - g_dest.sin_port = htons(12345); - bzero(&(g_dest.sin_zero), 8); - - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - times = 1; -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "p:d:s:a:t:"; - - if (argc < 5) - { - DBG("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -t times; \n"); - return -1; - } - setArgsDefault(); - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 'p': - g_dest.sin_port = htons(atoi(optarg)); - break; - case 'd': - g_dest.sin_addr.s_addr = inet_addr(optarg); - break; - case 's': - g_src.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - g_src.sin_port = htons(atoi(optarg)); - break; - case 't': - times = atoi(optarg); - break; - } - } - return 0; -} - -int main(int argc, char *argv[]) -{ - - int clientSocket, ret, i; - char sndbuffer[1024]; - char rcvbuffer[1024]; - int result = 0; - - /* - * check command line arguments - */ - if (0 != process_arg(argc, argv)) - { - DBG("Error in argument.%d\n", argc); - exit(1); - } - - clientSocket = socket(AF_INET, SOCK_STREAM, 0); - if (clientSocket < 0) - { - DBG("Error in connection.\n"); - exit(1); - } - DBG("[INFO]Client Socket is created.\n"); - - ret = bind(clientSocket, (struct sockaddr *) &g_src, sizeof(g_src)); - if (ret < 0) - { - DBG("Error in binding.errno=%d\n", errno); - exit(1); - } - - DBG("[INFO]Bind to client aaddress port 0\n"); - - ret = connect(clientSocket, (struct sockaddr *) &g_dest, sizeof(g_dest)); - if (ret < 0) - { - DBG("Error in connection.\n"); - exit(1); - } - DBG("[INFO]Connected to Server.\n"); - - memset(sndbuffer, '\0', 1024 * sizeof(char)); - memset(rcvbuffer, '\0', 1024 * sizeof(char)); - - for (i = 1; i <= times; i++) - { - //DBG ("Client: \t"); - random_str(sndbuffer, 50); - send(clientSocket, sndbuffer, strlen(sndbuffer), 0); - - if (recv(clientSocket, rcvbuffer, 1024, 0) < 0) - { - DBG("Error in receiving data.\n"); - } - else - { - //DBG ("Server: \t%s\n", rcvbuffer); - } - if (0 != strcmp(sndbuffer, rcvbuffer)) - { - result = -1; - break; - } - } - - /* Send exit message to server */ - strcpy(sndbuffer, "#exit"); - send(clientSocket, sndbuffer, strlen(sndbuffer), 0); - - DBG("Result = %s\n", (result == 0) ? "Success" : "Fail"); - close(clientSocket); - DBG("Disconnecting from server.\n"); - return 0; -} diff --git a/testcode/app_example/func-test/fork/tcpserver.c b/testcode/app_example/func-test/fork/tcpserver.c deleted file mode 100644 index af11832..0000000 --- a/testcode/app_example/func-test/fork/tcpserver.c +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct sockaddr_in g_src; -int srcPort = 0; -int destPort = 0; -int times = 0; - -#ifdef DEBUG -#define DBG(fmt, arg...) do { \ - DBG(fmt, ##arg); \ -} while(0) -#else -#define DBG(fmt, arg...) ((void)0) -#endif - -static void setArgsDefault() -{ - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - times = 1; -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "s:a:t:"; - - if (argc < 5) - { - DBG("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -t times; \n"); - return -1; - } - setArgsDefault(); - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 's': - g_src.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - g_src.sin_port = htons(atoi(optarg)); - break; - case 't': - times = atoi(optarg); - break; - } - } - return 0; -} - -int main(int argc, char *argv[]) -{ - - int sockfd, ret; - int newSocket; - socklen_t addr_size; - static struct sockaddr_in accept_addr; - char buffer[1024]; - pid_t childpid; - - /* - * check command line arguments - */ - if (0 != process_arg(argc, argv)) - { - DBG("Error in argument.%d\n", argc); - exit(1); - } - - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - { - DBG("Error in connection.\n"); - exit(1); - } - DBG("Server Socket is created. %d\n", sockfd); - - ret = bind(sockfd, (struct sockaddr *) &g_src, sizeof(g_src)); - if (ret < 0) - { - DBG("Error in binding.errno=%d\n", errno); - exit(1); - } - - DBG("Bind sucess port %d\n", g_src.sin_port); - - if (listen(sockfd, 10) == 0) - { - DBG("Listening on %s....\n", inet_ntoa(g_src.sin_addr)); - } - else - { - DBG("Error in binding.\n"); - } - - while (1) - { - newSocket = - accept(sockfd, (struct sockaddr *) &accept_addr, &addr_size); - if (newSocket < 0) - { - DBG("Error: Exiting here pid %d", getpid()); - exit(1); - } - - DBG("Connection accepted from %s:%d fd %d\n", - inet_ntoa(accept_addr.sin_addr), - ntohs(accept_addr.sin_port), newSocket); - if ((childpid = fork()) == 0) - { - DBG("[ PID %d] Child process Created. Pid %d \r\n", getpid(), - getpid()); - DBG("[ PID %d] Closing fd %d\n", getpid(), sockfd); - close(sockfd); - - while (1) - { - memset(buffer, '\0', 1024 * sizeof(char)); - recv(newSocket, buffer, 1024, 0); - if (strcmp(buffer, "#exit") == 0) - { - DBG("Disconnected from %s:%d\n", - inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port)); - break; - } - else - { - DBG("[PID %d]Client: %s\n", getpid(), buffer); - send(newSocket, buffer, strlen(buffer), 0); - bzero(buffer, sizeof(buffer)); - } - } - - DBG("[PID %d]Closing socket %d\r\n", getpid(), newSocket); - close(newSocket); - } - - } - - DBG("[PID %d]Process exiting... %d\r\n", getpid(), getpid()); - return 0; -} diff --git a/testcode/app_example/module_config.json b/testcode/app_example/module_config.json deleted file mode 100644 index fd4b47a..0000000 --- a/testcode/app_example/module_config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "default_stack_name": "kernel", /*when rd can't be find maybe choose the defualt one*/ - "module_list": [ - { - "stack_name": "kernel", /*stack name*/ - "function_name": "kernel_stack_register", - "libname": "./", /*library name, if loadtype is static, this maybe - null, else must give a library name*/ - "deploytype": "1", /*deploy model type:model type1, model type2, - model type3. Indicating single or multi process - deployment. Used during shared memory initialization.*/ - "stackid": "0", /*stack id, this must be ordered and not be repeated*/ - }, - ] -} diff --git a/testcode/app_example/perf-test/CMakeLists.txt b/testcode/app_example/perf-test/CMakeLists.txt deleted file mode 100644 index dbef0f2..0000000 --- a/testcode/app_example/perf-test/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -######################################################################### -# -# Copyright (c) 2018 Huawei Technologies Co.,Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -######################################################################### -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIC -m64 -mssse3 -std=gnu89") - -LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) - -ADD_EXECUTABLE(vc_common multi_tcp_common_app_Cli.c) -TARGET_LINK_LIBRARIES(vc_common libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(vs_epoll multi_tcp_epoll_app_Ser.c) -TARGET_LINK_LIBRARIES(vs_epoll libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(vs_select multi_tcp_select_app_Ser.c) -TARGET_LINK_LIBRARIES(vs_select libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(kc_common multi_tcp_common_app_Cli.c) -TARGET_LINK_LIBRARIES(kc_common pthread) - -ADD_EXECUTABLE(ks_epoll multi_tcp_epoll_app_Ser.c) -TARGET_LINK_LIBRARIES(ks_epoll pthread) - -ADD_EXECUTABLE(ks_select multi_tcp_select_app_Ser.c) -TARGET_LINK_LIBRARIES(ks_select pthread) - -ADD_EXECUTABLE(vs_common multi_tcp_common_Ser.c) -TARGET_LINK_LIBRARIES(vs_common libnStackAPI.so -lpthread -lrt) - -ADD_EXECUTABLE(ks_common multi_tcp_common_Ser.c) -TARGET_LINK_LIBRARIES(ks_common pthread) - diff --git a/testcode/app_example/perf-test/multi_tcp_common_Ser.c b/testcode/app_example/perf-test/multi_tcp_common_Ser.c deleted file mode 100644 index 27d44ae..0000000 --- a/testcode/app_example/perf-test/multi_tcp_common_Ser.c +++ /dev/null @@ -1,538 +0,0 @@ -/* -* -* Copyright (c) 2018 Huawei Technologies Co.,Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define __USE_GNU -#include -#include -#include -#include -#include - -#define _BIND bind -#define _LISTEN listen -#define _SOCKET socket -#define _ACCEPT accept -#define _SEND send -#define _RECV recv -#define _CLOSE close -#define _CONNECT connect -#define _PROTOCOL IPPROTO_TCP - -#define MAX_TEST_TIME 1000 -#define MSG_LENGTH 256 -#define CORE_NUM 8 -#define START_CPU_ID 2 -#define MAX_CONN_LIMIT 256 -#define MAX_PORT_NUM 65535 -//1:A-B ;0:A-B-A -#define SEND_RECV_MODE 1 -#define MAX_EVENTS 1000 -#define Default_PortID 12345 -#define Default_SleepCnt 10000 -#define Default_SleepTime 1000000 -#define Flag_Print 1 -#define Fd_Number 1 - -static struct sockaddr_in g_dest; -static struct sockaddr_in g_src; -static struct sockaddr_in g_recv; - -int times = MAX_TEST_TIME; -int msg_length = MSG_LENGTH; -int coreNum = CORE_NUM; -int startCPUId = START_CPU_ID; -int connectNum = MAX_CONN_LIMIT; -int msgMode = SEND_RECV_MODE; -int sleepCnt = Default_SleepCnt; -int sleepTime = Default_SleepTime; //us -int fdNumber = Fd_Number; -int flagPrint = Flag_Print; -int unitPrint = 0; -int waitTime = 0; - -int srcPort = Default_PortID; -int destPort = 0; -int recvPort = 0; -char sendarr[256] = ""; -char recvarr[256] = ""; -char destarr[256] = ""; - -static void setArgsDefault() -{ - - memset(&g_dest, 0, sizeof(g_dest)); - g_dest.sin_family = AF_INET; - g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - g_dest.sin_port = htons(12345); - bzero(&(g_dest.sin_zero), 8); - - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - memset(&g_recv, 0, sizeof(g_recv)); - g_recv.sin_family = AF_INET; - g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_recv.sin_port = htons(7895); - bzero(&(g_recv.sin_zero), 8); - -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; - int rw_mark = 0; - - if (argc < 4) - { - printf - ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); - printf - ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); - return 0; - } - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 'p': - destPort = atoi(optarg); - g_dest.sin_port = htons(atoi(optarg)); - break; - case 'd': - stpcpy(destarr, optarg); - g_dest.sin_addr.s_addr = inet_addr(optarg); - break; - case 's': - stpcpy(sendarr, optarg); - g_src.sin_addr.s_addr = inet_addr(optarg); - g_recv.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - //g_src.sin_port = htons(atoi(optarg)); - srcPort = atoi(optarg); - break; - case 'l': - msg_length = atoi(optarg); - break; - case 't': - times = atoi(optarg); - break; - case 'e': - sleepCnt = atoi(optarg); - break; - case 'i': - sleepTime = atoi(optarg); - break; - case 'f': - fdNumber = atoi(optarg); - break; - case 'r': - recvPort = atoi(optarg); - g_recv.sin_port = htons(atoi(optarg)); - break; - case 'n': - connectNum = atoi(optarg); - break; - case 'w': - waitTime = atoi(optarg); - break; - case 'u': - unitPrint = atoi(optarg); - break; - case 'x': - flagPrint = atoi(optarg); - break; - - } - } - return 1; -} - -void process_client(void) -{ - int sendLen = 0; - int i = 0, t = 0, p = 0, optval = 0, ret = 0; - char send_buf[1000] = ""; - int c_socketfd[100] = { 0 }; - int errbind[1000] = { 0 }; - int errconn[1000] = { 0 }; - - int send_count[1000] = { 0 }; - int pps = 0; - long pps_time = 0; - - struct timespec startTime, endTime; - struct timespec countStart; - struct timespec countEnd; - - memset(&countStart, 0, sizeof(countStart)); - memset(&countEnd, 0, sizeof(countEnd)); - - for (i = 0; i < fdNumber; i++) - { - c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); - if (0 > c_socketfd[i]) - { - printf("client %d failed,err %d\n", i, errno); - } - else - { - printf("client %d created success\n", i); - } - } - - for (i = 0; i < fdNumber; i++) - { - optval = 1; - ret = - setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, - (void *) &optval, sizeof(optval)); - if (ret == -1) - { - printf("Couldn't setsockopt(SO_REUSEADDR)\n"); - break; - } - } - - for (i = 0; i < fdNumber; i++) - { - g_src.sin_port = htons(srcPort + i); - errbind[i] = - _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); - if (errbind[i] < 0) - { - printf("client %d bind Failed %d\n", i, errno); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d bind Success port:%d IP:%s\n", i, - ntohs(g_src.sin_port), - inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); - } - } - for (i = 0; i < fdNumber; i++) - { - if (errbind[i] >= 0) - { - errconn[i] = - _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, - sizeof(g_dest)); - if (errconn[i] < 0) - { - printf("client %d Connect Failed %d\n", i, errno); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d Connect Success port:%d, IP:%s\n", i, - ntohs(g_dest.sin_port), - inet_ntoa(* - ((struct in_addr *) - &(g_dest.sin_addr.s_addr)))); - } - } - } - - sleep(1); - - clock_gettime(CLOCK_MONOTONIC, &startTime); - clock_gettime(CLOCK_MONOTONIC, &countStart); - - for (t = 0; t < times; t++) - { - for (i = 0; i < fdNumber; i++) - { - if (c_socketfd[i] < 0) - { - continue; - } - do - { - sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); - } - while (sendLen <= 0); - send_count[i]++; - } - - if (0 != sleepTime) - { - if ((t % sleepCnt) == 0) - { - usleep(sleepTime); - } - } - - if ((send_count[0] % unitPrint) == 0) - { - clock_gettime(CLOCK_MONOTONIC, &countEnd); - - pps_time = - (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + - countEnd.tv_nsec - countStart.tv_nsec; - pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; - if ((flagPrint != 0)) - { - printf(" sendcount %d, time: %ld ns\n", - send_count[0] * fdNumber, pps_time); - } - printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); - clock_gettime(CLOCK_MONOTONIC, &countStart); - } - } - - clock_gettime(CLOCK_MONOTONIC, &endTime); - - for (i = 0; i < fdNumber; i++) - { - printf("client %d send %d , sendtime :%ld s %ld ns\n", i, - send_count[i], endTime.tv_sec - startTime.tv_sec, - endTime.tv_nsec - startTime.tv_nsec); - } - - for (i = 0; i < fdNumber; i++) - { - printf("client %d close!\n", i); - if (c_socketfd[i] > 0) - _CLOSE(c_socketfd[i]); - } - - pthread_exit(NULL); -} - -/* - using this thread to do recv msg; -*/ -void *process_server_msg_thread(void *pArgv) -{ - int recvLen = 0, recvLen2 = 0; - char send_buf[1000]; - char recv_buf[1000]; - int recv_count = 0; - long recv_ppstime = 0; - int recv_pps = 0; - int ret; - struct timespec recvStart; - struct timespec recvEnd; - memset(&recvStart, 0, sizeof(recvStart)); - memset(&recvEnd, 0, sizeof(recvEnd)); - - pthread_detach(pthread_self()); - - int msgFd = *(int *) pArgv; - clock_gettime(CLOCK_MONOTONIC, &recvStart); - while (recv_count < times) - { - recvLen = 0; - recvLen2 = 0; - while (1) - { - recvLen2 = - recv(msgFd, recv_buf + recvLen, msg_length - recvLen, 0); - if (recvLen2 <= 0) - { - break; - } - else if (recvLen2 == msg_length - recvLen) - { - recvLen = 0; - recv_count++; - if (msg_length != send(msgFd, send_buf, msg_length, 0)) - { - printf("send failed!====, need exit\n"); - } - - } - else if (recvLen2 < msg_length - recvLen) - { - recvLen += recvLen2; - } - if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) - { - clock_gettime(CLOCK_MONOTONIC, &recvEnd); - recv_ppstime = - (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + - recvEnd.tv_nsec - recvStart.tv_nsec; - recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint; - printf("receive count:%d, receive time: %ld ns\n", recv_count, - recv_ppstime); - printf("receive pps = %d\n", recv_pps); - clock_gettime(CLOCK_MONOTONIC, &recvStart); - } - } - } - close(msgFd); -} - -/* - using this thread to do accept connect -*/ -void *process_server_accept_thread(void *pArgv) -{ - int listenFd = 0; - int x, optval, ret, m = 0; - int acpt_socketfd[1000] = { 0 }; - - listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (0 > listenFd) - { - printf("ERROR:socket failed,errno [%d]\n", errno); - return; - } - else - { - printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); - } - - if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) - { - printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); - close(listenFd); - } - - optval = 1; - ret = - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, - sizeof(optval)); - if (ret == -1) - { - printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, - errno); - close(listenFd); - return; - } - - if (0 != - bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) - { - printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); - printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - close(listenFd); - exit(-1); - } - else - { - printf("Info Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - } - - if (0 != listen(listenFd, 100)) - { - printf("server socket listen failed. err %d\n", errno); - close(listenFd); - return; - } - printf("Listen Success\n"); - - int timeout = -1; - int accpedNum = 0; - while (accpedNum < connectNum) - { - while (1) - { - acpt_socketfd[accpedNum] = - accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); - if (acpt_socketfd[accpedNum] < 0) - { - break; - } - - fcntl(acpt_socketfd[accpedNum], F_SETFL, 0); - - /*add new accptFd to MsgEpFD */ - pthread_t ser_rcv_thread_id; - if (pthread_create - (&ser_rcv_thread_id, NULL, process_server_msg_thread, - (void *) &acpt_socketfd[accpedNum]) == -1) - { - printf("create process_server_msg_thread fail\n"); - break; - } - - printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, - acpt_socketfd[accpedNum]); - accpedNum++; - } - } - close(listenFd); - while (1) - { - sleep(10); - } - - pthread_exit(NULL); -} - -void main(int argc, char *argv[]) -{ - socklen_t addrlen = sizeof(struct sockaddr); - int err = 0, result = 0, ret = 0; - int i = 0, j = 0, optval = 0, z = 0, x, listenfd; - cpu_set_t mask; - - setArgsDefault(); - ret = process_arg(argc, argv); - if (ret != 1) - { - printf("The param error\n"); - return; - } - - pthread_t server_thread_id; - - if (pthread_create - (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) - { - printf("create process_server_accept_thread fail\n"); - return; - } - - printf("create process_server_accept_thread success\n"); - - if (server_thread_id != 0) - { - printf("Server Thread join\n"); - pthread_join(server_thread_id, NULL); - } - - while (1) - { - sleep(10); - } - - return; -} diff --git a/testcode/app_example/perf-test/multi_tcp_common_app_Cli.c b/testcode/app_example/perf-test/multi_tcp_common_app_Cli.c deleted file mode 100644 index 02991bd..0000000 --- a/testcode/app_example/perf-test/multi_tcp_common_app_Cli.c +++ /dev/null @@ -1,392 +0,0 @@ -/* -* -* Copyright (c) 2018 Huawei Technologies Co.,Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _BIND bind -#define _LISTEN listen -#define _SOCKET socket -#define _ACCEPT accept -#define _SEND send -#define _RECV recv -#define _CLOSE close -#define _CONNECT connect -#define _PROTOCOL IPPROTO_TCP - -#define MAX_TEST_TIME 1000 -#define MSG_LENGTH 256 -#define CORE_NUM 8 -#define START_CPU_ID 2 -#define MAX_CONN_LIMIT 256 -#define MAX_PORT_NUM 65535 -//1:A-B ;0:A-B-A -#define SEND_RECV_MODE 1 -#define MAX_EVENTS 1000 -#define Default_PortID 12345 -#define Default_SleepCnt 10000 -#define Default_SleepTime 1000000 -#define Flag_Print 1 -#define Fd_Number 1 - -static struct sockaddr_in g_dest; -static struct sockaddr_in g_src; -static struct sockaddr_in g_recv; - -int times = MAX_TEST_TIME; -int msg_length = MSG_LENGTH; -int coreNum = CORE_NUM; -int startCPUId = START_CPU_ID; -int connectNum = MAX_CONN_LIMIT; -int msgMode = SEND_RECV_MODE; -int sleepCnt = Default_SleepCnt; -int sleepTime = Default_SleepTime; //us -int fdNumber = Fd_Number; -int flagPrint = Flag_Print; -int unitPrint = 0; -int waitTime = 0; - -int srcPort = Default_PortID; -int destPort = 0; -int recvPort = 0; -char sendarr[256] = ""; -char recvarr[256] = ""; -char destarr[256] = ""; - -static void setArgsDefault() -{ - - memset(&g_dest, 0, sizeof(g_dest)); - g_dest.sin_family = AF_INET; - g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - g_dest.sin_port = htons(12345); - bzero(&(g_dest.sin_zero), 8); - - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - memset(&g_recv, 0, sizeof(g_recv)); - g_recv.sin_family = AF_INET; - g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_recv.sin_port = htons(7895); - bzero(&(g_recv.sin_zero), 8); - -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; - int rw_mark = 0; - - if (argc < 4) - { - printf - ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); - printf - ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); - return 0; - } - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 'p': - destPort = atoi(optarg); - g_dest.sin_port = htons(atoi(optarg)); - break; - case 'd': - stpcpy(destarr, optarg); - g_dest.sin_addr.s_addr = inet_addr(optarg); - break; - case 's': - stpcpy(sendarr, optarg); - g_src.sin_addr.s_addr = inet_addr(optarg); - g_recv.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - //g_src.sin_port = htons(atoi(optarg)); - srcPort = atoi(optarg); - break; - case 'l': - msg_length = atoi(optarg); - break; - case 't': - times = atoi(optarg); - break; - case 'e': - sleepCnt = atoi(optarg); - break; - case 'i': - sleepTime = atoi(optarg); - break; - case 'f': - fdNumber = atoi(optarg); - break; - case 'r': - recvPort = atoi(optarg); - g_recv.sin_port = htons(atoi(optarg)); - break; - case 'n': - connectNum = atoi(optarg); - break; - case 'w': - waitTime = atoi(optarg); - break; - case 'u': - unitPrint = atoi(optarg); - break; - case 'x': - flagPrint = atoi(optarg); - break; - - } - } - return 1; -} - -void process_client(void) -{ - int sendLen = 0; - int i = 0, t = 0, p = 0, optval = 0, ret = 0; - char send_buf[1000] = ""; - char recv_buf[1000] = ""; - int c_socketfd[100] = { 0 }; - int errbind[1000] = { 0 }; - int errconn[1000] = { 0 }; - - int send_count[1000] = { 0 }; - int pps = 0; - long pps_time = 0; - - struct timespec startTime, endTime; - struct timespec countStart; - struct timespec countEnd; - memset(&countStart, 0, sizeof(countStart)); - memset(&countEnd, 0, sizeof(countEnd)); - - for (i = 0; i < fdNumber; i++) - { - c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); - if (0 > c_socketfd[i]) - { - printf("client %d failed,err %d\n", i, errno); - } - else - { - printf("client %d created success\n", i); - } - } - - for (i = 0; i < fdNumber; i++) - { - optval = 1; - ret = - setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, - (void *) &optval, sizeof(optval)); - if (ret == -1) - { - printf("Couldn't setsockopt(SO_REUSEADDR)\n"); - break; - } - } - - for (i = 0; i < fdNumber; i++) - { - g_src.sin_port = htons(srcPort + i); - errbind[i] = - _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); - if (errbind[i] < 0) - { - printf("client %d bind Failed %d\n", i, errno); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d bind Success port:%d IP:%s\n", i, - ntohs(g_src.sin_port), - inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); - } - } - for (i = 0; i < fdNumber; i++) - { - if (errbind[i] >= 0) - { - errconn[i] = - _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, - sizeof(g_dest)); - if (errconn[i] < 0) - { - printf("client %d Connect Failed %s\n", i, strerror(errno)); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d Connect Success port:%d, IP:%s\n", i, - ntohs(g_dest.sin_port), - inet_ntoa(* - ((struct in_addr *) - &(g_dest.sin_addr.s_addr)))); - } - } - } - - sleep(1); - - clock_gettime(CLOCK_MONOTONIC, &startTime); - clock_gettime(CLOCK_MONOTONIC, &countStart); - - int recvLen2, recvLen; - for (t = 0; t < times; t++) - { - for (i = 0; i < fdNumber; i++) - { - if (c_socketfd[i] < 0) - { - continue; - } - do - { - sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); - } - while (sendLen <= 0); - send_count[i]++; - recvLen = 0; - do - { - recvLen2 = - recv(c_socketfd[i], recv_buf + recvLen, - msg_length - recvLen, 0); - if (recvLen2 <= 0) - { - continue; - } - else if (recvLen2 == msg_length - recvLen) - { - recvLen = 0; - break; - } - else if (recvLen2 < msg_length - recvLen) - { - recvLen += recvLen2; - } - } - while (1); - } - - if (0 != sleepTime) - { - if ((t % sleepCnt) == 0) - { - usleep(sleepTime); - } - } - - if ((send_count[0] % unitPrint) == 0 && send_count[0] > 0) - { - clock_gettime(CLOCK_MONOTONIC, &countEnd); - - pps_time = - (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + - countEnd.tv_nsec - countStart.tv_nsec; - pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; - if ((flagPrint != 0)) - { - printf(" sendcount %d, time: %ld ns\n", - send_count[0] * fdNumber, pps_time); - } - printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); - clock_gettime(CLOCK_MONOTONIC, &countStart); - } - } - - clock_gettime(CLOCK_MONOTONIC, &endTime); - - for (i = 0; i < fdNumber; i++) - { - printf("client %d send %d , sendtime :%ld s %ld ns\n", i, - send_count[i], endTime.tv_sec - startTime.tv_sec, - endTime.tv_nsec - startTime.tv_nsec); - } - - for (i = 0; i < fdNumber; i++) - { - printf("client %d close!\n", i); - if (c_socketfd[i] > 0) - _CLOSE(c_socketfd[i]); - } - - pthread_exit(NULL); -} - -void main(int argc, char *argv[]) -{ - socklen_t addrlen = sizeof(struct sockaddr); - int err = 0, result = 0, ret = 0; - int i = 0, j = 0, optval = 0, z = 0, x, listenfd; - cpu_set_t mask; - - setArgsDefault(); - ret = process_arg(argc, argv); - if (ret != 1) - { - printf("The param error\n"); - return; - } - - pthread_t client_thread_id; - - if (pthread_create - (&client_thread_id, NULL, (void *) (&process_client), NULL) == -1) - { - printf("create client thread fail\n"); - return; - } - - printf("create client thread success\n"); - - if (client_thread_id != 0) - { - printf("Client Thread join\n"); - pthread_join(client_thread_id, NULL); - } - - return; -} diff --git a/testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c b/testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c deleted file mode 100644 index b37a9c3..0000000 --- a/testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c +++ /dev/null @@ -1,627 +0,0 @@ -/* -* -* Copyright (c) 2018 Huawei Technologies Co.,Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _BIND bind -#define _LISTEN listen -#define _SOCKET socket -#define _ACCEPT accept -#define _SEND send -#define _RECV recv -#define _CLOSE close -#define _CONNECT connect -#define _PROTOCOL IPPROTO_TCP - -#define MAX_TEST_TIME 1000 -#define MSG_LENGTH 256 -#define CORE_NUM 8 -#define START_CPU_ID 2 -#define MAX_CONN_LIMIT 256 -#define MAX_PORT_NUM 65535 -//1:A-B ;0:A-B-A -#define SEND_RECV_MODE 1 -#define MAX_EVENTS 1000 -#define Default_PortID 12345 -#define Default_SleepCnt 10000 -#define Default_SleepTime 1000000 -#define Flag_Print 1 -#define Fd_Number 1 - -static struct sockaddr_in g_dest; -static struct sockaddr_in g_src; -static struct sockaddr_in g_recv; - -int times = MAX_TEST_TIME; -int msg_length = MSG_LENGTH; -int coreNum = CORE_NUM; -int startCPUId = START_CPU_ID; -int connectNum = MAX_CONN_LIMIT; -int msgMode = SEND_RECV_MODE; -int sleepCnt = Default_SleepCnt; -int sleepTime = Default_SleepTime; //us -int fdNumber = Fd_Number; -int flagPrint = Flag_Print; -int unitPrint = 0; -int waitTime = 0; - -int srcPort = Default_PortID; -int destPort = 0; -int recvPort = 0; -char sendarr[256] = ""; -char recvarr[256] = ""; -char destarr[256] = ""; - -static void setArgsDefault() -{ - - memset(&g_dest, 0, sizeof(g_dest)); - g_dest.sin_family = AF_INET; - g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - g_dest.sin_port = htons(12345); - bzero(&(g_dest.sin_zero), 8); - - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - memset(&g_recv, 0, sizeof(g_recv)); - g_recv.sin_family = AF_INET; - g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_recv.sin_port = htons(7895); - bzero(&(g_recv.sin_zero), 8); - -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; - int rw_mark = 0; - - if (argc < 4) - { - printf - ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); - printf - ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); - return 0; - } - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 'p': - destPort = atoi(optarg); - g_dest.sin_port = htons(atoi(optarg)); - break; - case 'd': - stpcpy(destarr, optarg); - g_dest.sin_addr.s_addr = inet_addr(optarg); - break; - case 's': - stpcpy(sendarr, optarg); - g_src.sin_addr.s_addr = inet_addr(optarg); - g_recv.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - //g_src.sin_port = htons(atoi(optarg)); - srcPort = atoi(optarg); - break; - case 'l': - msg_length = atoi(optarg); - break; - case 't': - times = atoi(optarg); - break; - case 'e': - sleepCnt = atoi(optarg); - break; - case 'i': - sleepTime = atoi(optarg); - break; - case 'f': - fdNumber = atoi(optarg); - break; - case 'r': - recvPort = atoi(optarg); - g_recv.sin_port = htons(atoi(optarg)); - break; - case 'n': - connectNum = atoi(optarg); - break; - case 'w': - waitTime = atoi(optarg); - break; - case 'u': - unitPrint = atoi(optarg); - break; - case 'x': - flagPrint = atoi(optarg); - break; - - } - } - return 1; -} - -void process_client(void) -{ - int sendLen = 0; - int i = 0, t = 0, p = 0, optval = 0, ret = 0; - char send_buf[1000] = ""; - int c_socketfd[100] = { 0 }; - int errbind[1000] = { 0 }; - int errconn[1000] = { 0 }; - - int send_count[1000] = { 0 }; - int pps = 0; - long pps_time = 0; - - struct timespec startTime, endTime; - struct timespec countStart; - struct timespec countEnd; - memset(&countStart, 0, sizeof(countStart)); - memset(&countEnd, 0, sizeof(countEnd)); - - for (i = 0; i < fdNumber; i++) - { - c_socketfd[i] = _SOCKET(PF_INET, SOCK_STREAM, _PROTOCOL); - if (0 > c_socketfd[i]) - { - printf("client %d failed,err %d\n", i, errno); - } - else - { - printf("client %d created success\n", i); - } - } - - for (i = 0; i < fdNumber; i++) - { - optval = 1; - ret = - setsockopt(c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, - (void *) &optval, sizeof(optval)); - if (ret == -1) - { - printf("Couldn't setsockopt(SO_REUSEADDR)\n"); - break; - } - } - - for (i = 0; i < fdNumber; i++) - { - g_src.sin_port = htons(srcPort + i); - errbind[i] = - _BIND(c_socketfd[i], (struct sockaddr *) &g_src, sizeof(g_src)); - if (errbind[i] < 0) - { - printf("client %d bind Failed %d\n", i, errno); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d bind Success port:%d IP:%s\n", i, - ntohs(g_src.sin_port), - inet_ntoa(*((struct in_addr *) &(g_src.sin_addr.s_addr)))); - } - } - for (i = 0; i < fdNumber; i++) - { - if (errbind[i] >= 0) - { - errconn[i] = - _CONNECT(c_socketfd[i], (struct sockaddr *) &g_dest, - sizeof(g_dest)); - if (errconn[i] < 0) - { - printf("client %d Connect Failed %d\n", i, errno); - _CLOSE(c_socketfd[i]); - c_socketfd[i] = -1; - continue; - } - else - { - printf("client %d Connect Success port:%d, IP:%s\n", i, - ntohs(g_dest.sin_port), - inet_ntoa(* - ((struct in_addr *) - &(g_dest.sin_addr.s_addr)))); - } - } - } - - sleep(1); - - clock_gettime(CLOCK_MONOTONIC, &startTime); - clock_gettime(CLOCK_MONOTONIC, &countStart); - - for (t = 0; t < times; t++) - { - for (i = 0; i < fdNumber; i++) - { - if (c_socketfd[i] < 0) - { - continue; - } - do - { - sendLen = _SEND(c_socketfd[i], send_buf, msg_length, 0); - } - while (sendLen <= 0); - send_count[i]++; - } - - if (0 != sleepTime) - { - if ((t % sleepCnt) == 0) - { - usleep(sleepTime); - } - } - - if ((send_count[0] % unitPrint) == 0) - { - clock_gettime(CLOCK_MONOTONIC, &countEnd); - - pps_time = - (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + - countEnd.tv_nsec - countStart.tv_nsec; - pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; - if ((flagPrint != 0)) - { - printf(" sendcount %d, time: %ld ns\n", - send_count[0] * fdNumber, pps_time); - } - printf("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); - clock_gettime(CLOCK_MONOTONIC, &countStart); - } - - } - - clock_gettime(CLOCK_MONOTONIC, &endTime); - - for (i = 0; i < fdNumber; i++) - { - printf("client %d send %d , sendtime :%ld s %ld ns\n", i, - send_count[i], endTime.tv_sec - startTime.tv_sec, - endTime.tv_nsec - startTime.tv_nsec); - } - - for (i = 0; i < fdNumber; i++) - { - printf("client %d close!\n", i); - if (c_socketfd[i] > 0) - _CLOSE(c_socketfd[i]); - } - - pthread_exit(NULL); -} - -/* - using this thread to do recv msg; -*/ -void *process_server_msg_thread(void *pArgv) -{ - int recvLen = 0, recvLen2 = 0; - char send_buf[1000]; - char recv_buf[1000]; - int recv_count = 0; - long recv_ppstime = 0; - int recv_pps = 0; - int ret; - struct epoll_event event; - - struct epoll_event eventList[MAX_EVENTS]; - - struct timespec recvStart; - struct timespec recvEnd; - memset(&recvStart, 0, sizeof(recvStart)); - memset(&recvEnd, 0, sizeof(recvEnd)); - - pthread_detach(pthread_self()); - - int msgEpFd = epoll_create(100); - int msgFd = *(int *) pArgv; - - event.events = EPOLLIN | EPOLLET; - event.data.fd = msgFd; - if (epoll_ctl(msgEpFd, EPOLL_CTL_ADD, msgFd, &event) < 0) - { - printf("epoll add fd[%d] to msgEpfd:[%d] failed\n", msgFd, msgEpFd); - close(msgEpFd); - close(msgFd); - return NULL; - } - - clock_gettime(CLOCK_MONOTONIC, &recvStart); - while (1) - { - int timeout = -1; - int m; - int sock; - ret = epoll_wait(msgEpFd, eventList, MAX_EVENTS, timeout); - if (ret == 0) - continue; - - for (m = 0; m < ret; m++) - { - if ((eventList[m].events & EPOLLERR) - || (eventList[m].events & EPOLLHUP) - || !(eventList[m].events & EPOLLIN)) - { - printf("fd %d epoll error event:%d\n", eventList[m].data.fd, - eventList[m].events); - close(eventList[m].data.fd); - continue; - } - else - { - recvLen = 0; - recvLen2 = 0; - sock = eventList[m].data.fd; - - do - { - recvLen2 = - recv(sock, recv_buf + recvLen, msg_length - recvLen, - 0); - if (recvLen2 <= 0) - { - break; - } - else if (recvLen2 == msg_length - recvLen) - { - recvLen = 0; - recv_count++; - if (msg_length != send(sock, send_buf, msg_length, 0)) - { - printf("send failed!====, need exit\n"); - } - } - else if (recvLen2 < msg_length - recvLen) - { - recvLen += recvLen2; - } - if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) - { - clock_gettime(CLOCK_MONOTONIC, &recvEnd); - recv_ppstime = - (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + - recvEnd.tv_nsec - recvStart.tv_nsec; - recv_pps = - ((float) 1000000000 / recv_ppstime) * unitPrint; - printf("receive count:%d, receive time: %ld ns\n", - recv_count, recv_ppstime); - printf("receive pps = %d\n", recv_pps); - clock_gettime(CLOCK_MONOTONIC, &recvStart); - } - } - while (1); - } - - } - - if (recv_count == times) - { - break; - } - } - close(msgFd); - close(msgEpFd); -} - -/* - using this thread to do accept connect -*/ -void *process_server_accept_thread(void *pArgv) -{ - int listenFd = 0; - int x, optval, ret = 0; - int acpt_socketfd[1000] = { 0 }; - - listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (0 > listenFd) - { - printf("ERROR:socket failed,errno [%d]\n", errno); - return NULL; - } - else - { - printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); - } - - if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) - { - printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); - close(listenFd); - } - - optval = 1; - ret = - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, - sizeof(optval)); - if (ret == -1) - { - printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, - errno); - close(listenFd); - return NULL; - } - - if (0 != - bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) - { - printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); - printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - close(listenFd); - //return NULL; - exit(-1); - } - else - { - printf("INFO:Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - } - - if (0 != listen(listenFd, 100)) - { - printf("server socket listen failed. err %d\n", errno); - close(listenFd); - return NULL; - } - printf("Listen Success\n"); - - int accEpFd; - struct epoll_event eventList[100]; - accEpFd = epoll_create(100); - struct epoll_event event; - event.events = EPOLLIN | EPOLLET; - event.data.fd = listenFd; - - if (epoll_ctl(accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0) - { - printf("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd); - exit(-1); - } - - int timeout = -1; - int accpedNum = 0; - while (accpedNum < connectNum) - { - ret = epoll_wait(accEpFd, eventList, connectNum, timeout); - - if (ret < 0) - { - printf("accept_thread epoll_wait error, epfd[%d], errno[%d]\n", - accEpFd, errno); - continue; - } - else if (ret == 0) - continue; - - /*loop done ever Event */ - for (x = 0; x < ret; x++) - { - printf("event:%d; ret:%d\n", eventList[x].events, ret); - if ((eventList[x].events & EPOLLERR) - || !(eventList[x].events & EPOLLIN)) - { - printf("epoll fd %d error\n", eventList[x].data.fd); - close(eventList[x].data.fd); - continue; - } - - while (1) - { - acpt_socketfd[accpedNum] = - accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); - if (acpt_socketfd[accpedNum] < 0) - { - printf("no more connect\n"); - break; - } - /*add new accptFd to MsgEpFD */ - pthread_t ser_rcv_thread_id; - if (pthread_create - (&ser_rcv_thread_id, NULL, process_server_msg_thread, - (void *) &acpt_socketfd[accpedNum]) == -1) - { - printf("create process_server_msg_thread fail\n"); - break; - } - - printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, - acpt_socketfd[accpedNum]); - accpedNum++; - } - } - } - - close(listenFd); - close(accEpFd); - - while (1) - { - sleep(10); - } - - pthread_exit(NULL); -} - -void main(int argc, char *argv[]) -{ - socklen_t addrlen = sizeof(struct sockaddr); - int err = 0, result = 0, ret = 0; - int i = 0, j = 0, optval = 0, z = 0, x, listenfd; - cpu_set_t mask; - - setArgsDefault(); - ret = process_arg(argc, argv); - if (ret != 1) - { - printf("The param error\n"); - return; - } - - pthread_t server_thread_id; - - if (pthread_create - (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) - { - printf("create process_server_accept_thread fail\n"); - return; - } - - printf("create process_server_accept_thread success\n"); - - if (server_thread_id != 0) - { - printf("Server Thread join\n"); - pthread_join(server_thread_id, NULL); - } - - while (1) - { - sleep(10); - } - - return; -} diff --git a/testcode/app_example/perf-test/multi_tcp_select_app_Ser.c b/testcode/app_example/perf-test/multi_tcp_select_app_Ser.c deleted file mode 100644 index 56b9c5d..0000000 --- a/testcode/app_example/perf-test/multi_tcp_select_app_Ser.c +++ /dev/null @@ -1,431 +0,0 @@ -/* -* -* Copyright (c) 2018 Huawei Technologies Co.,Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at: -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _BIND bind -#define _LISTEN listen -#define _SOCKET socket -#define _ACCEPT accept -#define _SEND send -#define _RECV recv -#define _CLOSE close -#define _CONNECT connect -#define _PROTOCOL IPPROTO_TCP - -#define MAX_TEST_TIME 1000 -#define MSG_LENGTH 256 -#define CORE_NUM 8 -#define START_CPU_ID 2 -#define MAX_CONN_LIMIT 256 -#define MAX_PORT_NUM 65535 -//1:A-B ;0:A-B-A -#define SEND_RECV_MODE 1 -#define MAX_EVENTS 1000 -#define Default_PortID 12345 -#define Default_SleepCnt 10000 -#define Default_SleepTime 1000000 -#define Flag_Print 1 -#define Fd_Number 1 - -static struct sockaddr_in g_dest; -static struct sockaddr_in g_src; -static struct sockaddr_in g_recv; - -int times = MAX_TEST_TIME; -int msg_length = MSG_LENGTH; -int coreNum = CORE_NUM; -int startCPUId = START_CPU_ID; -int connectNum = MAX_CONN_LIMIT; -int msgMode = SEND_RECV_MODE; -int sleepCnt = Default_SleepCnt; -int sleepTime = Default_SleepTime; //us -int fdNumber = Fd_Number; -int flagPrint = Flag_Print; -int unitPrint = 0; -int waitTime = 0; - -int srcPort = Default_PortID; -int destPort = 0; -int recvPort = 0; -char sendarr[256] = ""; -char recvarr[256] = ""; -char destarr[256] = ""; - -static void setArgsDefault() -{ - - memset(&g_dest, 0, sizeof(g_dest)); - g_dest.sin_family = AF_INET; - g_dest.sin_addr.s_addr = inet_addr("127.0.0.1"); - g_dest.sin_port = htons(12345); - bzero(&(g_dest.sin_zero), 8); - - memset(&g_src, 0, sizeof(g_src)); - g_src.sin_family = AF_INET; - g_src.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_src.sin_port = htons(7895); - bzero(&(g_src.sin_zero), 8); - - memset(&g_recv, 0, sizeof(g_recv)); - g_recv.sin_family = AF_INET; - g_recv.sin_addr.s_addr = inet_addr("0.0.0.0"); - g_recv.sin_port = htons(7895); - bzero(&(g_recv.sin_zero), 8); - -} - -static int process_arg(int argc, char *argv[]) -{ - int opt = 0; - int error = 0; - const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; - int rw_mark = 0; - - if (argc < 4) - { - printf - ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); - printf - ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); - return 0; - } - while ((opt = getopt(argc, argv, optstring)) != -1) - { - switch (opt) - { - case 'p': - destPort = atoi(optarg); - g_dest.sin_port = htons(atoi(optarg)); - break; - case 'd': - stpcpy(destarr, optarg); - g_dest.sin_addr.s_addr = inet_addr(optarg); - break; - case 's': - stpcpy(sendarr, optarg); - g_src.sin_addr.s_addr = inet_addr(optarg); - g_recv.sin_addr.s_addr = inet_addr(optarg); - break; - case 'a': - //g_src.sin_port = htons(atoi(optarg)); - srcPort = atoi(optarg); - break; - case 'l': - msg_length = atoi(optarg); - break; - case 't': - times = atoi(optarg); - break; - case 'e': - sleepCnt = atoi(optarg); - break; - case 'i': - sleepTime = atoi(optarg); - break; - case 'f': - fdNumber = atoi(optarg); - break; - case 'r': - recvPort = atoi(optarg); - g_recv.sin_port = htons(atoi(optarg)); - break; - case 'n': - connectNum = atoi(optarg); - break; - case 'w': - waitTime = atoi(optarg); - break; - case 'u': - unitPrint = atoi(optarg); - break; - case 'x': - flagPrint = atoi(optarg); - break; - - } - } - return 1; -} - -/* - using this thread to do recv msg; -*/ -void *process_server_msg_thread(void *pArgv) -{ - int recvLen = 0, recvLen2 = 0; - char send_buf[1000]; - char recv_buf[1000]; - int recv_count = 0; - long recv_ppstime = 0; - int recv_pps = 0; - int ret; - struct timeval timeout; - fd_set rfds; - int maxfd; - - struct timespec recvStart; - struct timespec recvEnd; - memset(&recvStart, 0, sizeof(recvStart)); - memset(&recvEnd, 0, sizeof(recvEnd)); - - pthread_detach(pthread_self()); - - int msgFd = *(int *) pArgv; - - clock_gettime(CLOCK_MONOTONIC, &recvStart); - while (1) - { - FD_ZERO(&rfds); - FD_SET(msgFd, &rfds); - maxfd = msgFd + 1; - timeout.tv_sec = 10; - timeout.tv_usec = 0; - ret = select(maxfd, &rfds, NULL, NULL, &timeout); - - if (ret <= 0) - { - continue; - } - - if (FD_ISSET(msgFd, &rfds) == 0) - { - continue; - } - - recvLen = 0; - recvLen2 = 0; - - do - { - recvLen2 = - recv(msgFd, recv_buf + recvLen, msg_length - recvLen, 0); - if (recvLen2 <= 0) - { - break; - } - else if (recvLen2 == msg_length - recvLen) - { - recvLen = 0; - recv_count++; - if (msg_length != send(msgFd, send_buf, msg_length, 0)) - { - printf("send failed!====, need exit\n"); - } - } - else if (recvLen2 < msg_length - recvLen) - { - recvLen += recvLen2; - } - if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) - { - clock_gettime(CLOCK_MONOTONIC, &recvEnd); - recv_ppstime = - (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + - recvEnd.tv_nsec - recvStart.tv_nsec; - recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint; - printf("receive count:%d, receive time: %ld ns\n", - recv_count, recv_ppstime); - printf("receive pps = %d\n", recv_pps); - clock_gettime(CLOCK_MONOTONIC, &recvStart); - } - } - while (1); - - if (recv_count == times) - { - break; - } - } - close(msgFd); -} - -/* - using this thread to do accept connect -*/ -void *process_server_accept_thread(void *pArgv) -{ - int listenFd = 0; - int x, optval, ret, m = 0; - int acpt_socketfd[1000] = { 0 }; - struct timeval timeout; - fd_set rfds; - int maxfd; - - listenFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (0 > listenFd) - { - printf("ERROR:socket failed,errno [%d]\n", errno); - return NULL; - } - else - { - printf("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); - } - - if (0 > fcntl(listenFd, F_SETFL, O_NONBLOCK)) - { - printf("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); - close(listenFd); - } - - optval = 1; - ret = - setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, - sizeof(optval)); - if (ret == -1) - { - printf("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, - errno); - close(listenFd); - return NULL; - } - - if (0 != - bind(listenFd, (struct sockaddr *) &g_recv, sizeof(struct sockaddr))) - { - printf("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); - printf("INFO:Bind Failed, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - close(listenFd); - //return NULL; - exit(-1); - } - else - { - printf("INFO:Bind Success, port %d IP:%s\n", ntohs(g_recv.sin_port), - inet_ntoa(*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); - } - - if (0 != listen(listenFd, 100)) - { - printf("server socket listen failed. err %d\n", errno); - close(listenFd); - return NULL; - } - printf("Listen Success\n"); - - int accpedNum = 0; - while (accpedNum < connectNum) - { - FD_ZERO(&rfds); - FD_SET(listenFd, &rfds); - maxfd = listenFd + 1; - timeout.tv_sec = 10; - timeout.tv_usec = 0; - ret = select(maxfd, &rfds, NULL, NULL, &timeout); - - if (ret <= 0) - { - continue; - } - - if (FD_ISSET(listenFd, &rfds) == 0) - { - continue; - } - - while (1) - { - acpt_socketfd[accpedNum] = - accept4(listenFd, NULL, NULL, SOCK_NONBLOCK); - if (acpt_socketfd[accpedNum] < 0) - { - printf("no more connect\n"); - break; - } - /*add new accptFd to MsgEpFD */ - pthread_t ser_rcv_thread_id; - if (pthread_create - (&ser_rcv_thread_id, NULL, process_server_msg_thread, - (void *) &acpt_socketfd[accpedNum]) == -1) - { - printf("create process_server_msg_thread fail\n"); - break; - } - - printf("accept cnt [%d], cur accept fd [%d]\n", accpedNum, - acpt_socketfd[accpedNum]); - accpedNum++; - } - } - - close(listenFd); - - while (1) - { - sleep(10); - } - - pthread_exit(NULL); -} - -void main(int argc, char *argv[]) -{ - socklen_t addrlen = sizeof(struct sockaddr); - int err = 0, result = 0, ret = 0; - int i = 0, j = 0, optval = 0, z = 0, x, listenfd; - cpu_set_t mask; - - setArgsDefault(); - ret = process_arg(argc, argv); - if (ret != 1) - { - printf("The param error\n"); - return; - } - - pthread_t server_thread_id; - - if (pthread_create - (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) - { - printf("create process_server_accept_thread fail\n"); - return; - } - - printf("create process_server_accept_thread success\n"); - - if (server_thread_id != 0) - { - printf("Server Thread join\n"); - pthread_join(server_thread_id, NULL); - } - - while (1) - { - sleep(10); - } - - return; -} diff --git a/testcode/app_example/rd_config.json b/testcode/app_example/rd_config.json deleted file mode 100644 index 26abef6..0000000 --- a/testcode/app_example/rd_config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "modules": [ - { - "name": "kernel", - "ip_route": [ - "127.0.0.1/24" - ], - "type_route": [ - ], - "protocol_route": [ - ] - } - ] -} -- cgit 1.2.3-korg