summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsharath reddy <bs.reddy@huawei.com>2019-06-04 11:53:49 +0530
committersharath reddy <bs.reddy@huawei.com>2019-06-04 20:38:30 +0530
commit2a42ad20b9730706ad371ae3787d4597c4e42276 (patch)
treefa01cd312586ea007468e7233f94c0ce53d75873
parenta826fe833d3f2a8fe2673fa05811fe1a22baf045 (diff)
Feature: 19.04 part-2DMM-2
Change-Id: I0b52a6bb67c25c7955d58e29eb81a3cc9efea9e9 Signed-off-by: sharath reddy <bs.reddy@huawei.com>
-rw-r--r--CMakeLists.txt5
-rw-r--r--app_example/CMakeLists.txt (renamed from testcode/app_example/CMakeLists.txt)13
-rw-r--r--app_example/func-test/CMakeLists.txt (renamed from testcode/app_example/func-test/CMakeLists.txt)0
-rw-r--r--app_example/func-test/file_transfer/CMakeLists.txt (renamed from testcode/app_example/func-test/file_transfer/CMakeLists.txt)4
-rw-r--r--app_example/func-test/file_transfer/client_filetrans.c (renamed from testcode/app_example/func-test/file_transfer/client_filetrans.c)0
-rw-r--r--app_example/func-test/file_transfer/server_filetrans.c (renamed from testcode/app_example/func-test/file_transfer/server_filetrans.c)0
-rw-r--r--app_example/func-test/fork/CMakeLists.txt (renamed from testcode/app_example/func-test/fork/CMakeLists.txt)4
-rw-r--r--app_example/func-test/fork/tcpclient.c (renamed from testcode/app_example/func-test/fork/tcpclient.c)7
-rw-r--r--app_example/func-test/fork/tcpserver.c (renamed from testcode/app_example/func-test/fork/tcpserver.c)2
-rw-r--r--app_example/perf-test/CMakeLists.txt (renamed from testcode/app_example/perf-test/CMakeLists.txt)4
-rw-r--r--app_example/perf-test/multi_tcp_common_Ser.c (renamed from testcode/app_example/perf-test/multi_tcp_common_Ser.c)0
-rw-r--r--app_example/perf-test/multi_tcp_common_app_Cli.c (renamed from testcode/app_example/perf-test/multi_tcp_common_app_Cli.c)0
-rw-r--r--app_example/perf-test/multi_tcp_epoll_app_Ser.c (renamed from testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c)0
-rw-r--r--app_example/perf-test/multi_tcp_select_app_Ser.c (renamed from testcode/app_example/perf-test/multi_tcp_select_app_Ser.c)0
-rw-r--r--demo/nginx_proxy/README.md24
-rw-r--r--demo/nginx_proxy/demo-1/Vagrantfile98
-rw-r--r--demo/nginx_proxy/demo-1/adjust_hugepage.sh14
-rwxr-xr-xdemo/nginx_proxy/demo-1/apply_patch.sh9
-rw-r--r--demo/nginx_proxy/demo-1/demo_2stack.patch15
-rw-r--r--demo/nginx_proxy/demo-1/module_config.json26
-rw-r--r--demo/nginx_proxy/demo-1/proxy_nginx.conf81
-rw-r--r--demo/nginx_proxy/demo-1/rd_config.json42
-rw-r--r--demo/nginx_proxy/demo-1/setup_proxy.sh54
-rw-r--r--demo/nginx_proxy/demo-1/setup_upstream.sh45
-rw-r--r--demo/nginx_proxy/demo-1/startup.conf20
-rw-r--r--demo/nginx_proxy/demo-1/upstream_nginx.conf80
-rw-r--r--demo/nginx_proxy/demo-1/vpp_config6
-rw-r--r--demo/nginx_proxy/demo-2/README.md69
-rw-r--r--demo/nginx_proxy/demo-2/Vagrantfile116
-rw-r--r--demo/nginx_proxy/demo-2/adjust_hugepage.sh14
-rwxr-xr-xdemo/nginx_proxy/demo-2/apply_patch.sh9
-rw-r--r--demo/nginx_proxy/demo-2/dem-2-topo.pngbin0 -> 32437 bytes
-rw-r--r--demo/nginx_proxy/demo-2/demo-2.pngbin0 -> 125156 bytes
-rw-r--r--demo/nginx_proxy/demo-2/demo_2stack.patch15
-rw-r--r--demo/nginx_proxy/demo-2/module_config.json26
-rw-r--r--demo/nginx_proxy/demo-2/proxy_nginx.conf33
-rw-r--r--demo/nginx_proxy/demo-2/rd_config.json43
-rw-r--r--demo/nginx_proxy/demo-2/setup_client.sh25
-rw-r--r--demo/nginx_proxy/demo-2/setup_proxy.sh54
-rw-r--r--demo/nginx_proxy/demo-2/setup_udpserver.sh25
-rw-r--r--demo/nginx_proxy/demo-2/setup_upstream.sh44
-rw-r--r--demo/nginx_proxy/demo-2/startup.conf20
-rw-r--r--demo/nginx_proxy/demo-2/udpclient.c49
-rw-r--r--demo/nginx_proxy/demo-2/udpserver.c54
-rw-r--r--demo/nginx_proxy/demo-2/upstream_nginx.conf80
-rw-r--r--demo/nginx_proxy/demo-2/vpp_config6
-rw-r--r--demo/nginx_proxy/demo-3/NGINX_with_DMM_Demo.md26
-rw-r--r--demo/nginx_proxy/demo-3/proxy_nginx.conf81
-rw-r--r--demo/nginx_proxy/demo-3/rd_config.json23
-rw-r--r--demo/nginx_proxy/demo-3/rsocket.pngbin0 -> 10614 bytes
-rw-r--r--demo/nginx_proxy/demo-3/server/index.html31
-rw-r--r--demo/nginx_proxy/demo-3/server/test.c315
-rw-r--r--pkg/deb/control13
-rw-r--r--pkg/rpm/dmm.spec50
-rw-r--r--release/configure/module_config.json (renamed from testcode/app_example/module_config.json)10
-rw-r--r--release/configure/rd_config.json (renamed from testcode/app_example/rd_config.json)8
-rwxr-xr-xscripts/build.sh4
-rwxr-xr-xscripts/build_dmm_dep.sh4
-rwxr-xr-xscripts/build_vpp.sh4
-rwxr-xr-xscripts/prep_app_test.sh37
-rw-r--r--src/include/nstack_callback_ops.h1
-rw-r--r--src/nSocket/nstack/nstack_fd_mng.c23
-rw-r--r--src/nSocket/nstack/nstack_fd_mng.h1
-rw-r--r--src/nSocket/nstack/nstack_socket.c1
-rw-r--r--stacks/lwip_stack/CMakeLists.txt111
-rw-r--r--stacks/lwip_stack/build/.gitkeep (renamed from testcode/app_example/build/.gitkeep)0
-rw-r--r--stacks/lwip_stack/configure/module_config.json26
-rw-r--r--stacks/lwip_stack/configure/nStackConfig.json32
-rw-r--r--stacks/lwip_stack/configure/rd_config.json24
-rw-r--r--stacks/lwip_stack/doc/README.md125
-rw-r--r--stacks/lwip_stack/doc/dmm_lwip.pngbin0 -> 52940 bytes
-rw-r--r--stacks/lwip_stack/lwip_src/CMakeLists.txt106
-rw-r--r--stacks/lwip_stack/lwip_src/api/nsfw_msg.c23
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api.c50
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api_msg.c3320
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netbuf.c57
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netifapi.c279
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_sbr.c477
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_tcpip.c1531
-rw-r--r--stacks/lwip_stack/lwip_src/common/rb_tree.c389
-rw-r--r--stacks/lwip_stack/lwip_src/common/rb_tree.h110
-rw-r--r--stacks/lwip_stack/lwip_src/common/spl_def.h138
-rw-r--r--stacks/lwip_stack/lwip_src/common/spl_opt.h329
-rw-r--r--stacks/lwip_stack/lwip_src/common/spl_rti.c91
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_app_res.c951
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_app_res.h103
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common.c351
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common.h44
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common_opt.h147
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_debug.h70
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_err.h68
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c276
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h82
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h145
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_netbuf.h43
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf.c220
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf.h80
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h109
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h241
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_share.c192
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_share.h444
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h42
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tx_box.c62
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tx_box.h39
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_types.h68
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackxopts.h53
-rw-r--r--stacks/lwip_stack/lwip_src/core/global_tick.c48
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_pbuf.c605
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_timers.c599
-rw-r--r--stacks/lwip_stack/lwip_src/core/unmatch_version.c59
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/config_common.h64
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h26
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h39
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h223
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/network.h36
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h77
-rw-r--r--stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h162
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/common.h227
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/kni_proc.h103
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h79
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h149
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/spl_hal.h112
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h90
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_api.h276
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h128
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_err.h40
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h30
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h52
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h174
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h33
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h252
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h80
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h108
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h91
-rw-r--r--stacks/lwip_stack/lwip_src/instance/spl_instance.c47
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c1039
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/container_ip.c1117
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c356
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/network.c1093
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c563
-rw-r--r--stacks/lwip_stack/lwip_src/maintain/spl_mt_config.c778
-rw-r--r--stacks/lwip_stack/lwip_src/maintain/spl_res_mgr.c392
-rw-r--r--stacks/lwip_stack/lwip_src/netif/ethernetif.c164
-rw-r--r--stacks/lwip_stack/lwip_src/netif/sc_dpdk.c563
-rw-r--r--stacks/lwip_stack/lwip_src/netif/spl_hal.c1755
-rw-r--r--stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c666
-rw-r--r--stacks/lwip_stack/lwip_src/socket/CMakeLists.txt75
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_cfg.h54
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c329
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c143
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h46
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.c175
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.h46
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_macro.h24
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c766
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h78
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c670
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h159
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c109
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c271
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h67
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_socket.h138
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_tcp.c1682
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_udp.c1149
-rw-r--r--stacks/lwip_stack/patch/.gitkeep0
-rw-r--r--stacks/lwip_stack/release/configure/ip_data.json8
-rw-r--r--stacks/lwip_stack/release/configure/nStackConfig.json32
-rw-r--r--stacks/lwip_stack/release/configure/network_data_tonStack.json16
-rw-r--r--stacks/lwip_stack/release/include/nstack_custom_api.h42
-rw-r--r--stacks/lwip_stack/release/lib64/.gitkeep0
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/arch/queue.c120
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/arch/sys_arch.c303
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/core/memp.c495
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/core/timeouts.c527
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/download_lwip.sh36
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/include/lwipopts.h39
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/include/opt.h2875
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/include/sys.h455
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/include/timeouts.h134
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/lwip/arch/atomic_32.h53
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/lwip/arch/cc.h82
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/lwip/arch/queue.h30
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/lwip/arch/sys_arch.h29
-rw-r--r--stacks/lwip_stack/release/lwip_helper_files/lwip/arch/win_minmax.h120
-rwxr-xr-xstacks/lwip_stack/release/script/nstack_fun.sh591
-rwxr-xr-xstacks/lwip_stack/release/script/nstack_var.sh65
-rwxr-xr-xstacks/lwip_stack/release/script/run_nstack_main.sh27
-rwxr-xr-xstacks/lwip_stack/release/script/run_nstack_master.sh29
-rwxr-xr-xstacks/lwip_stack/release/send_alarm.sh17
-rwxr-xr-xstacks/lwip_stack/release/start_nstack.sh149
-rwxr-xr-xstacks/lwip_stack/release/stop_nstack.sh51
-rwxr-xr-xstacks/lwip_stack/release/uninstall.sh34
-rw-r--r--stacks/lwip_stack/release_tar.sh86
-rw-r--r--stacks/lwip_stack/run_stackx.txt49
-rw-r--r--stacks/lwip_stack/src/CMakeLists.txt61
-rw-r--r--stacks/lwip_stack/src/alarm/CMakeLists.txt38
-rw-r--r--stacks/lwip_stack/src/alarm/alarm.c857
-rw-r--r--stacks/lwip_stack/src/alarm/alarm.h80
-rw-r--r--stacks/lwip_stack/src/alarm/alarm_api.h107
-rw-r--r--stacks/lwip_stack/src/include/common_func.h140
-rw-r--r--stacks/lwip_stack/src/include/common_mem_api.h134
-rw-r--r--stacks/lwip_stack/src/include/common_mem_base_type.h85
-rw-r--r--stacks/lwip_stack/src/include/common_mem_buf.h78
-rw-r--r--stacks/lwip_stack/src/include/common_mem_common.h25
-rw-r--r--stacks/lwip_stack/src/include/common_mem_mbuf.h40
-rw-r--r--stacks/lwip_stack/src/include/common_mem_mempool.h25
-rw-r--r--stacks/lwip_stack/src/include/common_mem_pal_memconfig.h26
-rw-r--r--stacks/lwip_stack/src/include/common_mem_rwlock.h25
-rw-r--r--stacks/lwip_stack/src/include/common_mem_spinlock.h38
-rw-r--r--stacks/lwip_stack/src/include/nsfw_msg.h201
-rw-r--r--stacks/lwip_stack/src/include/nsfw_msg_api.h305
-rw-r--r--stacks/lwip_stack/src/include/nsfw_mt_config.h63
-rw-r--r--stacks/lwip_stack/src/include/nsfw_rti.h49
-rw-r--r--stacks/lwip_stack/src/include/nstack_dmm_adpt.h64
-rw-r--r--stacks/lwip_stack/src/io_adpt/CMakeLists.txt41
-rw-r--r--stacks/lwip_stack/src/io_adpt/dpdk.c2499
-rw-r--r--stacks/lwip_stack/src/mem/CMakeLists.txt36
-rw-r--r--stacks/lwip_stack/src/mem/include/common_mem_memzone.h25
-rw-r--r--stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h204
-rw-r--r--stacks/lwip_stack/src/mem/include/common_sys_config.h46
-rw-r--r--stacks/lwip_stack/src/mem/lib_common_mem/common_api.c163
-rw-r--r--stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c299
-rw-r--r--stacks/lwip_stack/src/mem/lib_common_mem/common_func.c211
-rw-r--r--stacks/lwip_stack/src/mem/lwip_mem_api.c86
-rw-r--r--stacks/lwip_stack/src/mem/lwip_mem_desc.c80
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c44
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h22
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c529
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h70
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c434
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h38
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c989
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h51
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c48
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h22
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c800
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h135
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c843
-rw-r--r--stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h60
-rw-r--r--stacks/lwip_stack/src/nStackMain/CMakeLists.txt66
-rw-r--r--stacks/lwip_stack/src/nStackMain/main.c457
-rw-r--r--stacks/lwip_stack/src/sbr/CMakeLists.txt37
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_err.h190
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_index_ring.c212
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_index_ring.h61
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_protocol_api.h102
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_res_mgr.c87
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_res_mgr.h155
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_socket.c1324
-rw-r--r--stacks/lwip_stack/src/tools/CMakeLists.txt26
-rw-r--r--stacks/lwip_stack/src/tools/dump_tool.c611
-rw-r--r--stacks/lwip_stack/src/tools/dump_tool.h81
-rw-r--r--stacks/lwip_stack/tools/CMakeLists.txt95
-rw-r--r--stacks/lwip_stack/tools/nping.c615
-rw-r--r--stacks/lwip_stack/tools/ntcpdump.c1334
-rw-r--r--stacks/lwip_stack/tools/tool_common.h243
-rw-r--r--stacks/lwip_stack/vagrant/Vagrantfile65
-rw-r--r--stacks/lwip_stack/vagrant/build.sh59
-rw-r--r--stacks/lwip_stack/vagrant/env.sh7
-rw-r--r--stacks/lwip_stack/vagrant/start_nstackMain.sh105
-rw-r--r--stacks/vpp/adapt/dmm_vcl.h45
-rw-r--r--stacks/vpp/adapt/dmm_vcl_adpt.c205
-rw-r--r--stacks/vpp/configure/module_config.json20
-rw-r--r--stacks/vpp/configure/rd_config.json26
-rw-r--r--stacks/vpp/configure/startup.conf21
-rw-r--r--stacks/vpp/configure/vpp_config6
-rw-r--r--stacks/vpp/doc/README.md115
-rw-r--r--stacks/vpp/patch/vpp.patch104
-rw-r--r--stacks/vpp/vagrant/Vagrantfile63
-rw-r--r--stacks/vpp/vagrant/build.sh224
-rw-r--r--stacks/vpp/vagrant/env.sh7
-rw-r--r--stacks/vpp/vagrant/install_prereq.sh39
272 files changed, 54862 insertions, 46 deletions
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/testcode/app_example/CMakeLists.txt b/app_example/CMakeLists.txt
index ff25e1f..a82c752 100644
--- a/testcode/app_example/CMakeLists.txt
+++ b/app_example/CMakeLists.txt
@@ -14,18 +14,5 @@
# 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/func-test/CMakeLists.txt b/app_example/func-test/CMakeLists.txt
index 865eba5..865eba5 100644
--- a/testcode/app_example/func-test/CMakeLists.txt
+++ b/app_example/func-test/CMakeLists.txt
diff --git a/testcode/app_example/func-test/file_transfer/CMakeLists.txt b/app_example/func-test/file_transfer/CMakeLists.txt
index e4f653a..408fc7a 100644
--- a/testcode/app_example/func-test/file_transfer/CMakeLists.txt
+++ b/app_example/func-test/file_transfer/CMakeLists.txt
@@ -18,13 +18,15 @@ 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)
+TARGET_LINK_LIBRARIES(kc_cli_file pthread) \ No newline at end of file
diff --git a/testcode/app_example/func-test/file_transfer/client_filetrans.c b/app_example/func-test/file_transfer/client_filetrans.c
index f0e2a80..f0e2a80 100644
--- a/testcode/app_example/func-test/file_transfer/client_filetrans.c
+++ b/app_example/func-test/file_transfer/client_filetrans.c
diff --git a/testcode/app_example/func-test/file_transfer/server_filetrans.c b/app_example/func-test/file_transfer/server_filetrans.c
index 8b7e25f..8b7e25f 100644
--- a/testcode/app_example/func-test/file_transfer/server_filetrans.c
+++ b/app_example/func-test/file_transfer/server_filetrans.c
diff --git a/testcode/app_example/func-test/fork/CMakeLists.txt b/app_example/func-test/fork/CMakeLists.txt
index a78f617..f37dae7 100644
--- a/testcode/app_example/func-test/fork/CMakeLists.txt
+++ b/app_example/func-test/fork/CMakeLists.txt
@@ -18,13 +18,15 @@ 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)
+TARGET_LINK_LIBRARIES(ktcp_client pthread) \ No newline at end of file
diff --git a/testcode/app_example/func-test/fork/tcpclient.c b/app_example/func-test/fork/tcpclient.c
index 8023b34..1a48e86 100644
--- a/testcode/app_example/func-test/fork/tcpclient.c
+++ b/app_example/func-test/fork/tcpclient.c
@@ -6,7 +6,6 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include <errno.h>
#define DEBUG
@@ -121,7 +120,7 @@ int main(int argc, char *argv[])
ret = bind(clientSocket, (struct sockaddr *) &g_src, sizeof(g_src));
if (ret < 0)
{
- DBG("Error in binding.errno=%d\n", errno);
+ DBG("Error in binding.\n");
exit(1);
}
@@ -140,7 +139,7 @@ int main(int argc, char *argv[])
for (i = 1; i <= times; i++)
{
- //DBG ("Client: \t");
+ DBG("Client: \t");
random_str(sndbuffer, 50);
send(clientSocket, sndbuffer, strlen(sndbuffer), 0);
@@ -150,7 +149,7 @@ int main(int argc, char *argv[])
}
else
{
- //DBG ("Server: \t%s\n", rcvbuffer);
+ DBG("Server: \t%s\n", rcvbuffer);
}
if (0 != strcmp(sndbuffer, rcvbuffer))
{
diff --git a/testcode/app_example/func-test/fork/tcpserver.c b/app_example/func-test/fork/tcpserver.c
index af11832..73c053a 100644
--- a/testcode/app_example/func-test/fork/tcpserver.c
+++ b/app_example/func-test/fork/tcpserver.c
@@ -92,7 +92,7 @@ int main(int argc, char *argv[])
ret = bind(sockfd, (struct sockaddr *) &g_src, sizeof(g_src));
if (ret < 0)
{
- DBG("Error in binding.errno=%d\n", errno);
+ DBG("Error in binding.\n");
exit(1);
}
diff --git a/testcode/app_example/perf-test/CMakeLists.txt b/app_example/perf-test/CMakeLists.txt
index dbef0f2..7f05b84 100644
--- a/testcode/app_example/perf-test/CMakeLists.txt
+++ b/app_example/perf-test/CMakeLists.txt
@@ -18,12 +18,15 @@ 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)
@@ -36,6 +39,7 @@ 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)
diff --git a/testcode/app_example/perf-test/multi_tcp_common_Ser.c b/app_example/perf-test/multi_tcp_common_Ser.c
index 27d44ae..27d44ae 100644
--- a/testcode/app_example/perf-test/multi_tcp_common_Ser.c
+++ b/app_example/perf-test/multi_tcp_common_Ser.c
diff --git a/testcode/app_example/perf-test/multi_tcp_common_app_Cli.c b/app_example/perf-test/multi_tcp_common_app_Cli.c
index 02991bd..02991bd 100644
--- a/testcode/app_example/perf-test/multi_tcp_common_app_Cli.c
+++ b/app_example/perf-test/multi_tcp_common_app_Cli.c
diff --git a/testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c b/app_example/perf-test/multi_tcp_epoll_app_Ser.c
index b37a9c3..b37a9c3 100644
--- a/testcode/app_example/perf-test/multi_tcp_epoll_app_Ser.c
+++ b/app_example/perf-test/multi_tcp_epoll_app_Ser.c
diff --git a/testcode/app_example/perf-test/multi_tcp_select_app_Ser.c b/app_example/perf-test/multi_tcp_select_app_Ser.c
index 56b9c5d..56b9c5d 100644
--- a/testcode/app_example/perf-test/multi_tcp_select_app_Ser.c
+++ b/app_example/perf-test/multi_tcp_select_app_Ser.c
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 <vm-name>
+```
+
+####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_bind<NSSOC>fd addr Select module]fd=18,addr=192.168.50.20,module=lwip
+...
+nstack_bind<NSSOC>fd addr Select module]fd=22,addr=172.167.50.20,module=vpp_hoststack
+...
+nstack_bind<NSSOC>fd 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
--- /dev/null
+++ b/demo/nginx_proxy/demo-2/dem-2-topo.png
Binary files 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
--- /dev/null
+++ b/demo/nginx_proxy/demo-2/demo-2.png
Binary files 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#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
--- /dev/null
+++ b/demo/nginx_proxy/demo-3/rsocket.png
Binary files 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 @@
+<!DOCTYPE html>
+
+<!--
+Copyright 2015 Google Inc.
+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.
+-->
+
+<html>
+
+<head>
+ <title>Hello, world</title>
+ <link rel="stylesheet" href="/style.css">
+ <script src="/script.js"></script>
+</head>
+
+<body>
+ <h1>Hello, world</h1>
+
+ <button onclick="fetchMessage()">Fetch Message</button>
+ <p id="message">Click on the button to fetch the message.</p>
+</body>
+
+</html>
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 <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/mman.h>
+
+#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/testcode/app_example/module_config.json b/release/configure/module_config.json
index fd4b47a..03f0940 100644
--- a/testcode/app_example/module_config.json
+++ b/release/configure/module_config.json
@@ -11,5 +11,15 @@
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/testcode/app_example/rd_config.json b/release/configure/rd_config.json
index 26abef6..697067e 100644
--- a/testcode/app_example/rd_config.json
+++ b/release/configure/rd_config.json
@@ -3,12 +3,16 @@
{
"name": "kernel",
"ip_route": [
- "127.0.0.1/24"
+ "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/testcode/app_example/build/.gitkeep b/stacks/lwip_stack/build/.gitkeep
index e69de29..e69de29 100644
--- a/testcode/app_example/build/.gitkeep
+++ b/stacks/lwip_stack/build/.gitkeep
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
--- /dev/null
+++ b/stacks/lwip_stack/doc/dmm_lwip.png
Binary files 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 <netinet/in.h>
+
+#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 <netinet/in.h>
+#include <errno.h>
+#include <netinet/tcp.h>
+
+#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 <adam@sics.se>
+ *
+ */
+//#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 <sys/socket.h>
+//#include <netinet/in.h>
+
+#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 <inet.h>
+
+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 <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include "memp.h"
+#include "mem.h"
+#include "spl_pbuf.h"
+//#include "sockets.h"
+//#include <netinet/in.h>
+
+#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 <stdint.h>
+#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 <stdlib.h>
+#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 <stdarg.h>
+#include <stddef.h>
+#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(&param);
+ 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(&param);
+ 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(&param, 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(&param);
+ 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(&param, 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(&param);
+ 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(&param, 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(&param, 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(&param);
+ 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 <sys/ioctl.h>
+
+#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 <pthread.h>
+
+#include <sys/syscall.h>
+
+#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 <stdint.h>
+#include <stddef.h>
+#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 <sys/socket.h>
+#include <netinet/tcp.h>
+
+#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 <sys/types.h>
+#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 <errno.h>
+
+#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 <sys/time.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 <common_mem_mbuf.h>
+
+#include <string.h>
+#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 <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 <time.h>
+#include <signal.h>
+#include <pthread.h>
+#include <syscall.h>
+#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 <semaphore.h>
+#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 <stddef.h> /* 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 <rte_kni.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+
+#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 <pbuf.h>
+#include <sharedmemory.h>
+
+#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 <sys/types.h>
+#include <semaphore.h>
+//#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 <arch/sys_arch.h>
+#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 <stddef.h> /* 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 <stddef.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+
+#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 <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#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 <errno.h>
+#include <stddef.h> /* for size_t */
+#include "arch/sys_arch.h"
+#include "sys/socket.h"
+#include <errno.h>
+#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 <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#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 <stdlib.h>
+#include <string.h>
+#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 <stdio.h>
+#include <sys/socket.h>
+#include <string.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <stdlib.h>
+#include <pthread.h>
+#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 <stdlib.h>
+#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 <stackx/stats.h>
+//#include "sockets.h"
+#include <netinet/in.h>
+
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+#include "lwip/etharp.h"
+
+#include <sc_dpdk.h>
+#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, &eth_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 <netinet/in.h>
+
+#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 <netinet/in.h>
+#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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#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 <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#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 <stdlib.h>
+#include <string.h>
+#include <time.h>
+#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 <netinet/in.h>
+#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
--- /dev/null
+++ b/stacks/lwip_stack/patch/.gitkeep
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
--- /dev/null
+++ b/stacks/lwip_stack/release/lib64/.gitkeep
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 <pthread.h>
+#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 <netif/sc_dpdk.h>
+
+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 <sys/queue.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+#include <linux/sched.h>
+
+#include <asm/unistd.h>
+#include <linux/unistd.h>
+#include <syscall.h>
+
+#include <lwip/sys.h>
+#include <cc.h>
+#include <arch/sys_arch.h>
+#include <arch/queue.h>
+#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 <netif/sc_dpdk.h>
+#include <netif/sharedmemory.h>
+
+#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, &param);
+ 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, &param);
+ (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 <adam@sics.se>
+ *
+ */
+
+#include "lwip/opt.h"
+
+#include "lwip/memp.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+
+#include <string.h>
+
+/* 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 <adam@sics.se>
+ * 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 <errno.h>
+#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 <adam@sics.se>
+ *
+ */
+
+/*
+ * 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:
+ * - &lt;0: Packet shall not contain VLAN header.
+ * - 0 &lt;= return value &lt;= 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 <adam@sics.se>
+ */
+
+#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 <adam@sics.se>
+ * 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 <sys/time.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 <sys/types.h>
+#include <semaphore.h>
+
+#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<time.h>
+#include<sys/time.h>
+#include "nsfw_init_api.h"
+#include "nstack_log.h"
+#include "json.h"
+#include "nstack_securec.h"
+#include <stdlib.h>
+#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 <stdint.h>
+#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 <sys/types.h>
+#include <unistd.h>
+#include <semaphore.h>
+
+#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 <stdint.h>
+#include <sched.h>
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <pwd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fnmatch.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+
+#include <rte_config.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+#include <rte_eth_bond.h>
+#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 <rte_ethdev_driver.h>
+
+#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, &eth_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(&eth_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, &eth_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, &eth_addr);
+
+ ret = rte_eth_bond_mac_address_set((uint8_t) port, &eth_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 <string.h>
+#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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/queue.h>
+
+#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 <sys/types.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#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 <sys/types.h>
+#include <unistd.h>
+#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 <stdlib.h>
+#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 <string.h>
+#include <sched.h>
+#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 <stdint.h>
+#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 <stdint.h>
+#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 <string.h>
+#include <common_sys_config.h>
+
+#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 <stdint.h>
+
+#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 <signal.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <malloc.h>
+#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 <domain:bus:devid.func>] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type <primary|secondary|auto>] [-- 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 <errno.h>
+
+#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 <string.h>
+#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 <sys/uio.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#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 <dlfcn.h>
+#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 <arpa/inet.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <strings.h>
+#include <limits.h>
+#include <getopt.h>
+#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 <arpa/inet.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <unistd.h>
+#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 <time.h>
+#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 <pthread.h>
+#include <dlfcn.h>
+#include <sys/epoll.h>
+#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 <vcl/ldp.h>
+ #include <sys/time.h>
+
++#include <vcl/vcl_private.h>
+ #include <vcl/vcl_locked.h>
+ #include <vppinfra/time.h>
+ #include <vppinfra/bitmap.h>
+@@ -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