Repository: kmesh-net/kmesh

Issue:
[lfx-mentorship-2025-Mar-May] Kmesh eBPF unit test
- Description: As the community features continue to expand, the number of eBPF programs in the data plane has increased. Due to the inherent limitations of eBPF (third-state encoding, neither user space nor kernel space, running in a kernel virtual machine with a dedicated instruction set), Kmesh implements complex governance logic through features like tail call and map-in-map, which poses challenges for data plane quality protection.
eBPF, a recently introduced programmable technology in the kernel, currently has an immature ecosystem. The industry is actively exploring eBPF testing capabilities (e.g., Unit Testing eBPF). This project aims to develop an eBPF UT testing framework in conjunction with the Kmesh project to ensure the quality of the Kmesh data plane.
- Expected Outcome:
  - Export Kmesh eBPF programs to support UT test case.
  - Export design documentation for eBPF UT tests
- Recommended Skills: C, eBPF,  (go)
- Mentor(s): @bitcoffeeiux ([liuxin350@huawei.com](mailto:liuxin350@huawei.com))
- Useful Link:
  - https://github.com/kmesh-net/kmesh/blob/main/docs/proposal/unit_test_framework_zh.md
  - https://github.com/kmesh-net/kmesh/blob/main/test/unittest/workload

Hints from issue comments:
@Dhiren-Mhatre: Hello @LiZhenCheng9527 and @bitcoffeeiux,
I am very interested in contributing to the "[lfx-mentorship-2025-Mar-May] Kmesh eBPF Unit Test" project. With a strong background in Golang, I have previously contributed to open-source projects such as Prometheus and the Palisadoes Foundation, where I gained valuable experience in building scalable and efficient systems.
The project's focus on developing an eBPF unit testing framework for Kmesh aligns perfectly with my interests in low-level programming and kernel technologies. I am eager to apply my skills in C and Golang while learning more about eBPF's capabilities and challenges.
I look forward to the opportunity to collaborate with the team and contribute to ensuring the quality of Kmesh's data plane.
@btwshivam: Hello @bitcoffeeiux I’m Shivam, i have experience in eBPF testing and kernel-level development. I recently worked on unit testing for Inspektor Gadget, focusing on running eBPF gadget tests across different kernel versions.

I’m very interested in contributing to the Kmesh eBPF Unit Test Project and helping build a robust testing framework. I’ve gone through the documentation and would love to discuss the current testing challenges and possible approaches.@btwshivam: Hey, @LiZhenCheng9527 I’d like to pick a small task, such as writing a basic eBPF unit test. Could you suggest a good starting point or any existing gaps in the test suite that I can work on?@bdharsan04: hey @btwshivam, i guess [this](https://who.ldelossa.is/posts/unit-testing-ebpf/) is a good place to start regarding writing a basic eBPF unit test 

Solution patch:
diff --git a/README.md b/README.md
index 404ab174..38fc45d1 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ Kmesh also provide a Dual-Engine Mode, which makes use of eBPF and waypoint to p
 
 ## Quick Start
 
-Please refer to [quick start](https://kmesh.net/en/docs/setup/quickstart/) and [user guide](docs/kmesh_demo.md) to try Kmesh quickly.
+Please refer to [quick start](https://kmesh.net/en/docs/setup/quick-start/) and [user guide](docs/kmesh_demo.md) to try Kmesh quickly.
 
 ## Performance
 
diff --git a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfeb.go b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfeb.go
index 27cc98f9..e8c642f4 100644
--- a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfeb.go
+++ b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfeb.go
@@ -130,8 +130,9 @@ type KmeshCgroupSkbMapSpecs struct {
 //
 // It can be passed ebpf.CollectionSpec.Assign.
 type KmeshCgroupSkbVariableSpecs struct {
-	BpfLogLevel      *ebpf.VariableSpec `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.VariableSpec `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.VariableSpec `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbObjects contains all objects after they have been loaded into the kernel.
@@ -201,8 +202,9 @@ func (m *KmeshCgroupSkbMaps) Close() error {
 //
 // It can be passed to LoadKmeshCgroupSkbObjects or ebpf.CollectionSpec.LoadAndAssign.
 type KmeshCgroupSkbVariables struct {
-	BpfLogLevel      *ebpf.Variable `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.Variable `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.Variable `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.Variable `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.Variable `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbPrograms contains all programs after they have been loaded into the kernel.
diff --git a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfel.go b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfel.go
index f242a80f..72c31aac 100644
--- a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfel.go
+++ b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskb_bpfel.go
@@ -130,8 +130,9 @@ type KmeshCgroupSkbMapSpecs struct {
 //
 // It can be passed ebpf.CollectionSpec.Assign.
 type KmeshCgroupSkbVariableSpecs struct {
-	BpfLogLevel      *ebpf.VariableSpec `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.VariableSpec `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.VariableSpec `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbObjects contains all objects after they have been loaded into the kernel.
@@ -201,8 +202,9 @@ func (m *KmeshCgroupSkbMaps) Close() error {
 //
 // It can be passed to LoadKmeshCgroupSkbObjects or ebpf.CollectionSpec.LoadAndAssign.
 type KmeshCgroupSkbVariables struct {
-	BpfLogLevel      *ebpf.Variable `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.Variable `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.Variable `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.Variable `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.Variable `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbPrograms contains all programs after they have been loaded into the kernel.
diff --git a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfeb.go b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfeb.go
index 54f8b5e9..df82fc22 100644
--- a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfeb.go
+++ b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfeb.go
@@ -130,8 +130,9 @@ type KmeshCgroupSkbCompatMapSpecs struct {
 //
 // It can be passed ebpf.CollectionSpec.Assign.
 type KmeshCgroupSkbCompatVariableSpecs struct {
-	BpfLogLevel      *ebpf.VariableSpec `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.VariableSpec `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.VariableSpec `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbCompatObjects contains all objects after they have been loaded into the kernel.
@@ -201,8 +202,9 @@ func (m *KmeshCgroupSkbCompatMaps) Close() error {
 //
 // It can be passed to LoadKmeshCgroupSkbCompatObjects or ebpf.CollectionSpec.LoadAndAssign.
 type KmeshCgroupSkbCompatVariables struct {
-	BpfLogLevel      *ebpf.Variable `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.Variable `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.Variable `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.Variable `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.Variable `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbCompatPrograms contains all programs after they have been loaded into the kernel.
diff --git a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfel.go b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfel.go
index 7a0a905a..e144c525 100644
--- a/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfel.go
+++ b/bpf/kmesh/bpf2go/dualengine/kmeshcgroupskbcompat_bpfel.go
@@ -130,8 +130,9 @@ type KmeshCgroupSkbCompatMapSpecs struct {
 //
 // It can be passed ebpf.CollectionSpec.Assign.
 type KmeshCgroupSkbCompatVariableSpecs struct {
-	BpfLogLevel      *ebpf.VariableSpec `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.VariableSpec `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.VariableSpec `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.VariableSpec `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbCompatObjects contains all objects after they have been loaded into the kernel.
@@ -201,8 +202,9 @@ func (m *KmeshCgroupSkbCompatMaps) Close() error {
 //
 // It can be passed to LoadKmeshCgroupSkbCompatObjects or ebpf.CollectionSpec.LoadAndAssign.
 type KmeshCgroupSkbCompatVariables struct {
-	BpfLogLevel      *ebpf.Variable `ebpf:"bpf_log_level"`
-	EnableMonitoring *ebpf.Variable `ebpf:"enable_monitoring"`
+	BpfLogLevel          *ebpf.Variable `ebpf:"bpf_log_level"`
+	EnableMonitoring     *ebpf.Variable `ebpf:"enable_monitoring"`
+	EnablePeriodicReport *ebpf.Variable `ebpf:"enable_periodic_report"`
 }
 
 // KmeshCgroupSkbCompatPrograms contains all programs after they have been loaded into the kernel.
diff --git a/bpf/kmesh/workload/cgroup_skb.c b/bpf/kmesh/workload/cgroup_skb.c
index 192c15df..9cb9662b 100644
--- a/bpf/kmesh/workload/cgroup_skb.c
+++ b/bpf/kmesh/workload/cgroup_skb.c
@@ -11,10 +11,17 @@
 #include "probe.h"
 #include "config.h"
 
+volatile __u32 enable_periodic_report = 0;
+
+static inline bool is__periodic_report_enable()
+{
+    return enable_periodic_report == 1;
+}
+
 SEC("cgroup_skb/ingress")
 int cgroup_skb_ingress_prog(struct __sk_buff *skb)
 {
-    if (!is_monitoring_enable()) {
+    if (!is_monitoring_enable() || !is__periodic_report_enable()) {
         return SK_PASS;
     }
     if (skb->family != AF_INET && skb->family != AF_INET6)
@@ -38,7 +45,7 @@ int cgroup_skb_ingress_prog(struct __sk_buff *skb)
 SEC("cgroup_skb/egress")
 int cgroup_skb_egress_prog(struct __sk_buff *skb)
 {
-    if (!is_monitoring_enable()) {
+    if (!is_monitoring_enable() || !is__periodic_report_enable()) {
         return SK_PASS;
     }
     if (skb->family != AF_INET && skb->family != AF_INET6)
diff --git a/build.sh b/build.sh
index ed9c5dea..1d40a7b3 100755
--- a/build.sh
+++ b/build.sh
@@ -3,65 +3,65 @@ ROOT_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
 source ./kmesh_compile_env_pre.sh
 
 function install() {
-    mkdir -p /etc/kmesh
-    chmod 700 /etc/kmesh
+	mkdir -p /etc/kmesh
+	chmod 700 /etc/kmesh
 
-    cp $ROOT_DIR/build/kmesh-start-pre.sh /usr/bin
-    chmod 500 /usr/bin/kmesh-start-pre.sh
-    cp $ROOT_DIR/build/kmesh-stop-post.sh /usr/bin
-    chmod 500 /usr/bin/kmesh-stop-post.sh
+	cp $ROOT_DIR/build/kmesh-start-pre.sh /usr/bin
+	chmod 500 /usr/bin/kmesh-start-pre.sh
+	cp $ROOT_DIR/build/kmesh-stop-post.sh /usr/bin
+	chmod 500 /usr/bin/kmesh-stop-post.sh
 
-    mkdir -p /etc/oncn-mda
-    chmod 700 /etc/oncn-mda
-    cp $ROOT_DIR/oncn-mda/etc/oncn-mda.conf /etc/oncn-mda/
-    chmod 600 /etc/oncn-mda/oncn-mda.conf
+	mkdir -p /etc/oncn-mda
+	chmod 700 /etc/oncn-mda
+	cp $ROOT_DIR/oncn-mda/etc/oncn-mda.conf /etc/oncn-mda/
+	chmod 600 /etc/oncn-mda/oncn-mda.conf
 }
 
 function uninstall() {
-    rm -rf /etc/kmesh
-    rm -rf /usr/bin/kmesh-start-pre.sh
-    rm -rf /usr/bin/kmesh-stop-post.sh
-    rm -rf /etc/oncn-mda
-    rm -rf /usr/share/oncn-mda
+	rm -rf /etc/kmesh
+	rm -rf /usr/bin/kmesh-start-pre.sh
+	rm -rf /usr/bin/kmesh-stop-post.sh
+	rm -rf /etc/oncn-mda
+	rm -rf /usr/share/oncn-mda
 }
 
 function clean() {
-    rm -rf /etc/kmesh
-    rm -rf /usr/bin/kmesh-start-pre.sh
-    rm -rf /usr/bin/kmesh-stop-post.sh
+	rm -rf /etc/kmesh
+	rm -rf /usr/bin/kmesh-start-pre.sh
+	rm -rf /usr/bin/kmesh-stop-post.sh
 }
 
 set_enhanced_kernel_env
 
-if [ "$1" == "-h"  -o  "$1" == "--help" ]; then
-    echo build.sh -h/--help : Help.
-    echo build.sh -b/--build: Build Kmesh.
-    echo build.sh -i/--install: Install Kmesh.
-    echo build.sh -c/--clean: Clean the built binary.
-    echo build.sh -u/--uninstall: Uninstall Kmesh.
-    exit
+if [ "$1" == "-h" -o "$1" == "--help" ]; then
+	echo build.sh -h/--help : Help.
+	echo build.sh -b/--build: Build Kmesh.
+	echo build.sh -i/--install: Install Kmesh.
+	echo build.sh -c/--clean: Clean the built binary.
+	echo build.sh -u/--uninstall: Uninstall Kmesh.
+	exit
 fi
 
-if [ -z "$1" -o "$1" == "-b"  -o  "$1" == "--build" ]; then
-    prepare
-    make
-    exit
+if [ -z "$1" -o "$1" == "-b" -o "$1" == "--build" ]; then
+	prepare
+	make
+	exit
 fi
 
-if [ "$1" == "-i"  -o  "$1" == "--install" ]; then
-    make install
-    install
-    exit
+if [ "$1" == "-i" -o "$1" == "--install" ]; then
+	make install
+	install
+	exit
 fi
 
-if [ "$1" == "-u"  -o  "$1" == "--uninstall" ]; then
-    make uninstall
-    uninstall
-    exit
+if [ "$1" == "-u" -o "$1" == "--uninstall" ]; then
+	make uninstall
+	uninstall
+	exit
 fi
 
-if [ "$1" == "-c"  -o  "$1" == "--clean" ]; then
-    make clean
-    clean
-    exit
+if [ "$1" == "-c" -o "$1" == "--clean" ]; then
+	make clean
+	clean
+	exit
 fi
diff --git a/build/docker/start_kmesh.sh b/build/docker/start_kmesh.sh
index f528236b..0a7ac3c7 100755
--- a/build/docker/start_kmesh.sh
+++ b/build/docker/start_kmesh.sh
@@ -1,21 +1,21 @@
 #!/bin/sh
 
-# docker image compile online, if not compile online, the following lines also have no effect 
+# docker image compile online, if not compile online, the following lines also have no effect
 
-lsmod | grep kmesh > /dev/null
+lsmod | grep kmesh >/dev/null
 if [ $? -ne 0 ] && [ -f kmesh.ko ]; then
 	cp kmesh.ko /lib/modules/$(uname -r)
-        depmod -a
-        modprobe kmesh
+	depmod -a
+	modprobe kmesh
 fi
 
 mount | grep /mnt/kmesh_cgroup2
 if [ $? -ne 0 ]; then
-        mkdir -p /mnt/kmesh_cgroup2
-        mount -t cgroup2 none /mnt/kmesh_cgroup2/
-        if [ $? -ne 0 ]; then
-                echo "mount cgroup2 failed"
-        fi
+	mkdir -p /mnt/kmesh_cgroup2
+	mount -t cgroup2 none /mnt/kmesh_cgroup2/
+	if [ $? -ne 0 ]; then
+		echo "mount cgroup2 failed"
+	fi
 fi
 
 mount | grep "type bpf"
@@ -31,24 +31,24 @@ pid=$!
 
 # pass SIGTERM to kmesh process
 function stop_kmesh() {
-        echo "received SIGTERM, stopping kmesh"
-        kill $pid
+	echo "received SIGTERM, stopping kmesh"
+	kill $pid
 }
 
-function cleanup(){
-          lsmod | grep kmesh > /dev/null
-          if [ $? == 0 ]; then
-                  rmmod kmesh
-          fi
+function cleanup() {
+	lsmod | grep kmesh >/dev/null
+	if [ $? == 0 ]; then
+		rmmod kmesh
+	fi
 
-        echo "kmesh exit"
+	echo "kmesh exit"
 }
 
 trap 'stop_kmesh' SIGTERM
 
 # wait for kmesh process to exit, cannot use wait $pid here, because the script received SIGTERM, wait will return immediately
 while kill -0 $pid 2>/dev/null; do
-  sleep 1
+	sleep 1
 done
 
 kmesh-daemon uninstall $@
diff --git a/build/kmesh-start-pre.sh b/build/kmesh-start-pre.sh
index 52120a88..3767b1f1 100755
--- a/build/kmesh-start-pre.sh
+++ b/build/kmesh-start-pre.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-lsmod | grep kmesh > /dev/null
+lsmod | grep kmesh >/dev/null
 if [ $? == 0 ]; then
 	rmmod kmesh
 	depmod -a
diff --git a/build/kmesh-stop-post.sh b/build/kmesh-stop-post.sh
index 57d0718c..59126207 100755
--- a/build/kmesh-stop-post.sh
+++ b/build/kmesh-stop-post.sh
@@ -1,9 +1,9 @@
 #!/bin/sh
-lsmod | grep kmesh > /dev/null
+lsmod | grep kmesh >/dev/null
 if [ $? == 0 ]; then
 	rmmod kmesh
 fi
 
 umount -t cgroup2 /mnt/kmesh_cgroup2/
-rm -rf /mnt/kmesh_cgroup2 > /dev/null
+rm -rf /mnt/kmesh_cgroup2 >/dev/null
 rm -rf /sys/fs/bpf/bpf_kmesh
diff --git a/hack/copyright-check.sh b/hack/copyright-check.sh
index c171f41f..dcbf0146 100755
--- a/hack/copyright-check.sh
+++ b/hack/copyright-check.sh
@@ -8,133 +8,133 @@ c_copyright_path1=$ROOT_DIR/hack/copyright/BSDandGPL1.txt
 c_copyright_path2=$ROOT_DIR/hack/copyright/BSDandGPL2.txt
 
 function check_go_copyright() {
-    target_file=$1
-    copyright_file=$go_copyright_path
-
-    if [ ! -f "$target_file" ]; then
-        echo "Target file $target_file does not exist."
-        exit 1
-    fi
-
-    if [ ! -f "$copyright_file" ]; then
-        echo "Copyright file $copyright_file does not exist."
-        exit 1
-    fi
-
-    all_lines_present=true
-    while IFS= read -r line; do
-        if ! grep -qF -- "$line" "$target_file"; then
-            all_lines_present=false
-            break
-        fi
-    done < "$copyright_file"
-
-    if [ "$all_lines_present" != true ]; then
-        echo "The target file does not contain all lines from the copyright file."
-        echo $target_file
-    fi
+	target_file=$1
+	copyright_file=$go_copyright_path
+
+	if [ ! -f "$target_file" ]; then
+		echo "Target file $target_file does not exist."
+		exit 1
+	fi
+
+	if [ ! -f "$copyright_file" ]; then
+		echo "Copyright file $copyright_file does not exist."
+		exit 1
+	fi
+
+	all_lines_present=true
+	while IFS= read -r line; do
+		if ! grep -qF -- "$line" "$target_file"; then
+			all_lines_present=false
+			break
+		fi
+	done <"$copyright_file"
+
+	if [ "$all_lines_present" != true ]; then
+		echo "The target file does not contain all lines from the copyright file."
+		echo $target_file
+	fi
 }
 
 function check_c_copyright() {
-    target_file=$1
-    copyright_file1=$c_copyright_path1
-    copyright_file2=$c_copyright_path2
-
-    if [ ! -f "$target_file" ]; then
-        echo "Target file $target_file does not exist."
-        exit 1
-    fi
-
-    if [ ! -f "$copyright_file1" ]; then
-        echo "Copyright file $copyright_file1 does not exist."
-        exit 1
-    fi
-
-    if [ ! -f "$copyright_file2" ]; then
-        echo "Copyright file $copyright_file2 does not exist."
-        exit 1
-    fi
-
-    all_lines_present1=true
-    while IFS= read -r line; do
-        if ! grep -qF -- "$line" "$target_file"; then
-            all_lines_present1=false
-            break
-        fi
-    done < "$copyright_file1"
-
-    all_lines_present2=true
-    while IFS= read -r line; do
-        if ! grep -qF -- "$line" "$target_file"; then
-            all_lines_present2=false
-            break
-        fi
-    done < "$copyright_file2"
-
-    if [ "$all_lines_present1" != true ] && [ "$all_lines_present2" != true ]; then
-        echo "The target file does not contain all lines from the copyright file."
-        echo $target_file
-    fi  
+	target_file=$1
+	copyright_file1=$c_copyright_path1
+	copyright_file2=$c_copyright_path2
+
+	if [ ! -f "$target_file" ]; then
+		echo "Target file $target_file does not exist."
+		exit 1
+	fi
+
+	if [ ! -f "$copyright_file1" ]; then
+		echo "Copyright file $copyright_file1 does not exist."
+		exit 1
+	fi
+
+	if [ ! -f "$copyright_file2" ]; then
+		echo "Copyright file $copyright_file2 does not exist."
+		exit 1
+	fi
+
+	all_lines_present1=true
+	while IFS= read -r line; do
+		if ! grep -qF -- "$line" "$target_file"; then
+			all_lines_present1=false
+			break
+		fi
+	done <"$copyright_file1"
+
+	all_lines_present2=true
+	while IFS= read -r line; do
+		if ! grep -qF -- "$line" "$target_file"; then
+			all_lines_present2=false
+			break
+		fi
+	done <"$copyright_file2"
+
+	if [ "$all_lines_present1" != true ] && [ "$all_lines_present2" != true ]; then
+		echo "The target file does not contain all lines from the copyright file."
+		echo $target_file
+	fi
 }
 
 function go_check_dir() {
-    dir=$1
-    find $dir -type f -name "*.go" | while read file; do
-        # echo $file
-        exclude_dirs=$(jq -r '.exclude_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
-        exclude_files=$(jq -r '.exclude_files[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
-        if ! echo $ROOT_DIR$exclude_dirs | grep -q $(dirname $file); then
-            if ! echo $ROOT_DIR$exclude_files | grep -q "$file"; then
-                check_go_copyright $file
-            else
-                echo "Skipping exclude file: $file"
-            fi
-        fi 
-    done
+	dir=$1
+	find $dir -type f -name "*.go" | while read file; do
+		# echo $file
+		exclude_dirs=$(jq -r '.exclude_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+		exclude_files=$(jq -r '.exclude_files[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+		if ! echo $ROOT_DIR$exclude_dirs | grep -q $(dirname $file); then
+			if ! echo $ROOT_DIR$exclude_files | grep -q "$file"; then
+				check_go_copyright $file
+			else
+				echo "Skipping exclude file: $file"
+			fi
+		fi
+	done
 }
 
 function c_check_dir() {
-    dir=$1
-    find $dir -type f -name "*.c" -o -name "*.h" | while read file; do
-        # echo $file
-        exclude_dirs=$(jq -r '.exclude_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
-        exclude_files=$(jq -r '.exclude_files[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
-        if ! echo $ROOT_DIR$exclude_dirs | grep -q $(dirname $file); then
-            if ! echo $ROOT_DIR$exclude_files | grep -q "$file"; then
-                check_c_copyright $file
-            else
-                echo "Skipping exclude file: $file"
-            fi
-        fi 
-    done
+	dir=$1
+	find $dir -type f -name "*.c" -o -name "*.h" | while read file; do
+		# echo $file
+		exclude_dirs=$(jq -r '.exclude_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+		exclude_files=$(jq -r '.exclude_files[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+		if ! echo $ROOT_DIR$exclude_dirs | grep -q $(dirname $file); then
+			if ! echo $ROOT_DIR$exclude_files | grep -q "$file"; then
+				check_c_copyright $file
+			else
+				echo "Skipping exclude file: $file"
+			fi
+		fi
+	done
 }
 
 function copyright_check() {
 
-    go_dirs=$(jq -r '.go_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
-    c_dirs=$(jq -r '.c_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+	go_dirs=$(jq -r '.go_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
+	c_dirs=$(jq -r '.c_dirs[]' $ROOT_DIR/hack/copyright/copyright_scan_dir.json)
 
-    for dir in ${go_dirs}; do
-        go_check_dir "$ROOT_DIR$dir"
-    done
+	for dir in ${go_dirs}; do
+		go_check_dir "$ROOT_DIR$dir"
+	done
 
-    for dir in ${c_dirs}; do
-        c_check_dir "$ROOT_DIR$dir"
-    done
+	for dir in ${c_dirs}; do
+		c_check_dir "$ROOT_DIR$dir"
+	done
 }
 
 # Confirmation of whether there are files with wrong copyright
 if [ -z "$1" -o "$1" == "-c" -o "$1" == "--check" ]; then
-    result=$(copyright_check | grep -c 'not contain')
-    if [ "$result" != 0 ]; then
-        echo "ERROR: Some files need to be update copyright, please run "./hack/copyright-check.sh -g" and update and include any changed files in your PR"
-        exit 1
-    else
-        echo "pass copyright check"
-    fi
+	result=$(copyright_check | grep -c 'not contain')
+	if [ "$result" != 0 ]; then
+		echo "ERROR: Some files need to be update copyright, please run "./hack/copyright-check.sh -g" and update and include any changed files in your PR"
+		exit 1
+	else
+		echo "pass copyright check"
+	fi
 fi
 
 # Obtaining the name of a file that with wrong copyright
 if [ "$1" == "-g" -o "$1" == "--get" ]; then
-    copyright_check
+	copyright_check
 fi
diff --git a/hack/format.sh b/hack/format.sh
index fdc47ead..4db93d42 100755
--- a/hack/format.sh
+++ b/hack/format.sh
@@ -1,26 +1,33 @@
 #!/bin/bash
 
+function install_tool() {
+	tool=${1}
+	if command -v apt >/dev/null; then
+		sudo apt-get install -y $tool
+	elif command -v yum >/dev/null; then
+		# yum install
+		sudo yum install -y $tool
+	fi
+}
 
-function install_tool () {
-    tool=${1}
-    if command -v apt > /dev/null; then
-	    sudo apt-get install -y $tool
-    elif command -v yum > /dev/null; then
-	    # yum install
-	    sudo yum install -y $tool
-    fi
+function install_clang_format() {
+	if command -v clang-format >/dev/null; then
+		echo "clang-format already installed"
+	else
+		install_tool clang-format
+	fi
 }
 
-function install_clang_format () {
-    if command -v clang-format > /dev/null; then
-        echo "clang-format already installed"
-    else
-        install_tool clang-format
-    fi
+function install_shell_format() {
+	go install mvdan.cc/sh/v3/cmd/shfmt@v3.11.0
 }
 
 install_clang_format
 
-find ./ -name "*.[ch]" |grep -v pb-c |xargs clang-format -i
+find ./ -name "*.[ch]" | grep -v pb-c | xargs clang-format -i
+
+gofmt -w -s ../
+
+install_shell_format
 
-gofmt -w -s ../
\ No newline at end of file
+shfmt -w -s -ln=bash ../
diff --git a/hack/gen-check.sh b/hack/gen-check.sh
index e48f58c9..d86f84a8 100755
--- a/hack/gen-check.sh
+++ b/hack/gen-check.sh
@@ -1,8 +1,8 @@
 #!/bin/bash
 
 if [[ -n $(git status --porcelain) ]]; then
-  git status
-  git diff
-  echo "ERROR: Some files need to be updated, please run 'make gen' and include any changed files in your PR"
-  exit 1
+	git status
+	git diff
+	echo "ERROR: Some files need to be updated, please run 'make gen' and include any changed files in your PR"
+	exit 1
 fi
diff --git a/hack/gen_bpf2go.sh b/hack/gen_bpf2go.sh
index 7f20dea1..5ccd5c00 100755
--- a/hack/gen_bpf2go.sh
+++ b/hack/gen_bpf2go.sh
@@ -5,14 +5,12 @@ ROOT_DIR=$(git rev-parse --show-toplevel)
 . $ROOT_DIR/kmesh_compile_env_pre.sh
 
 function build_kmesh_bpf2go() {
-    local container_id=$1
-    docker exec $container_id git config --global --add safe.directory /kmesh
-    docker exec -e VERSION=$VERSION $container_id ./hack/gen_bpf2go_exec.sh
+	local container_id=$1
+	docker exec $container_id git config --global --add safe.directory /kmesh
+	docker exec -e VERSION=$VERSION $container_id ./hack/gen_bpf2go_exec.sh
 }
 
-
 container_id=$(run_docker_container)
 build_kmesh_bpf2go $container_id
 clean_container $container_id
 make clean
-
diff --git a/hack/gen_bpf2go_exec.sh b/hack/gen_bpf2go_exec.sh
index 666aee34..a2dfd779 100755
--- a/hack/gen_bpf2go_exec.sh
+++ b/hack/gen_bpf2go_exec.sh
@@ -4,10 +4,9 @@ ROOT_DIR=$(git rev-parse --show-toplevel)
 . $ROOT_DIR/hack/utils.sh
 . $ROOT_DIR/kmesh_compile_env_pre.sh
 
-
-kmesh_exec(){
-    set_enhanced_kernel_env
-    prepare
-    go generate bpf/kmesh/bpf2go/bpf2go.go
+kmesh_exec() {
+	set_enhanced_kernel_env
+	prepare
+	go generate bpf/kmesh/bpf2go/bpf2go.go
 }
 kmesh_exec
diff --git a/hack/gen_protoc.sh b/hack/gen_protoc.sh
index e43f9b0b..e2f1e468 100644
--- a/hack/gen_protoc.sh
+++ b/hack/gen_protoc.sh
@@ -8,13 +8,13 @@ PROTO_SRC=$@
 
 # if protoc-c is 1.4.x
 if protoc-c --version | grep -q -E "protobuf-c 1\.4\.[0-9]"; then
-    protoc-c --proto_path=$PROTO_PATH --c_out=. $PROTO_SRC
+	protoc-c --proto_path=$PROTO_PATH --c_out=. $PROTO_SRC
 else
-    echo "Generate proto files in docker"
-    docker run --rm \
-        -v $ROOT_DIR:/kmesh \
-        --name kmesh-build \
-        --user $(id -u):$(id -g) \
-        ghcr.io/kmesh-net/kmesh-build:latest \
-        sh -c "cd /kmesh/api && protoc-c --proto_path=$PROTO_PATH --c_out=. $PROTO_SRC"
+	echo "Generate proto files in docker"
+	docker run --rm \
+		-v $ROOT_DIR:/kmesh \
+		--name kmesh-build \
+		--user $(id -u):$(id -g) \
+		ghcr.io/kmesh-net/kmesh-build:latest \
+		sh -c "cd /kmesh/api && protoc-c --proto_path=$PROTO_PATH --c_out=. $PROTO_SRC"
 fi
diff --git a/hack/golangci-lint-prepare.sh b/hack/golangci-lint-prepare.sh
index c602f41e..4d3b8458 100755
--- a/hack/golangci-lint-prepare.sh
+++ b/hack/golangci-lint-prepare.sh
@@ -4,17 +4,16 @@ ROOT_DIR=$(git rev-parse --show-toplevel)
 TARGET_DIR="$ROOT_DIR/bpf/kmesh/bpf2go/kernelnative/enhanced"
 
 FILES=(
-    "kmeshsockops_bpfel.o"
-    "kmeshsockops_bpfeb.o"
-    "kmeshsockopscompat_bpfeb.o"
-    "kmeshsockopscompat_bpfel.o"
+	"kmeshsockops_bpfel.o"
+	"kmeshsockops_bpfeb.o"
+	"kmeshsockopscompat_bpfeb.o"
+	"kmeshsockopscompat_bpfel.o"
 )
 
 mkdir -p "$TARGET_DIR"
 
 for FILE in "${FILES[@]}"; do
-    touch "$TARGET_DIR/$FILE"
+	touch "$TARGET_DIR/$FILE"
 done
 
 echo "All files have been created in $TARGET_DIR."
-
diff --git a/hack/install-proto.sh b/hack/install-proto.sh
index 1b89be85..c2ea1356 100755
--- a/hack/install-proto.sh
+++ b/hack/install-proto.sh
@@ -1,97 +1,97 @@
 #!/bin/bash
 
 function install_tool() {
-    tool=${1}
-    if command -v apt >/dev/null; then
-        sudo apt-get update
-        sudo apt-get install -y $tool
-    elif command -v yum >/dev/null; then
-        # yum install
-        sudo yum install -y $tool
-    fi
+	tool=${1}
+	if command -v apt >/dev/null; then
+		sudo apt-get update
+		sudo apt-get install -y $tool
+	elif command -v yum >/dev/null; then
+		# yum install
+		sudo yum install -y $tool
+	fi
 }
 
 function install_protoc_binary() {
-    local version="$1"
-    local arch_suffix="$2"
-    local url="$3"
+	local version="$1"
+	local arch_suffix="$2"
+	local url="$3"
 
-    wget "$url" -O "protoc-${version}-linux-${arch_suffix}.zip"
-    unzip "protoc-${version}-linux-${arch_suffix}.zip" -d "protoc-${version}"
-    sudo mv "protoc-${version}/bin/protoc" /usr/local/bin/
-    rm -rf "protoc-${version}-linux-${arch_suffix}.zip" "protoc-${version}"
+	wget "$url" -O "protoc-${version}-linux-${arch_suffix}.zip"
+	unzip "protoc-${version}-linux-${arch_suffix}.zip" -d "protoc-${version}"
+	sudo mv "protoc-${version}/bin/protoc" /usr/local/bin/
+	rm -rf "protoc-${version}-linux-${arch_suffix}.zip" "protoc-${version}"
 }
 
 function install_protoc() {
-    local arch
-    local arch_suffix
-    local download_url
-    local installed_version
-    local desired_version="28.1"
+	local arch
+	local arch_suffix
+	local download_url
+	local installed_version
+	local desired_version="28.1"
 
-    # check the architecture
-    arch=$(uname -m)
-    case "$arch" in
-        x86_64)
-            arch_suffix="x86_64"
-            ;;
-        aarch64)
-            arch_suffix="aarch_64"
-            ;;
-        *)
-            echo "Unsupported architecture: $arch"
-            exit 1
-            ;;
-    esac
+	# check the architecture
+	arch=$(uname -m)
+	case "$arch" in
+	x86_64)
+		arch_suffix="x86_64"
+		;;
+	aarch64)
+		arch_suffix="aarch_64"
+		;;
+	*)
+		echo "Unsupported architecture: $arch"
+		exit 1
+		;;
+	esac
 
-    download_url="https://github.com/protocolbuffers/protobuf/releases/download/v${desired_version}/protoc-${desired_version}-linux-${arch_suffix}.zip"
+	download_url="https://github.com/protocolbuffers/protobuf/releases/download/v${desired_version}/protoc-${desired_version}-linux-${arch_suffix}.zip"
 
-    # Check if protoc is installed
-    if command -v protoc >/dev/null 2>&1; then
-        installed_version=$(protoc --version | awk '{print $2}')
-        echo "Installed protoc version: $installed_version"
-    else
-        installed_version="none"
-        echo "protoc is not installed."
-    fi
+	# Check if protoc is installed
+	if command -v protoc >/dev/null 2>&1; then
+		installed_version=$(protoc --version | awk '{print $2}')
+		echo "Installed protoc version: $installed_version"
+	else
+		installed_version="none"
+		echo "protoc is not installed."
+	fi
 
-    if [[ "$installed_version" != "$desired_version" ]]; then
-        echo "Installing protoc version ${desired_version}..."
-        install_protoc_binary "$desired_version" "$arch_suffix" "$download_url"
-    else
-        echo "protoc is up-to-date."
-    fi
+	if [[ $installed_version != "$desired_version" ]]; then
+		echo "Installing protoc version ${desired_version}..."
+		install_protoc_binary "$desired_version" "$arch_suffix" "$download_url"
+	else
+		echo "protoc is up-to-date."
+	fi
 
-    tools=()
+	tools=()
 
-    if command -v protoc >/dev/null; then
-        echo "protoc already installed"
-    else
-        tools+=(protobuf-compiler)
-    fi
+	if command -v protoc >/dev/null; then
+		echo "protoc already installed"
+	else
+		tools+=(protobuf-compiler)
+	fi
 
-    if command -v protoc-c >/dev/null; then
-        echo "protoc-c already installed"
-    else
-        tools+=(protobuf-c-compiler)
-    fi
+	if command -v protoc-c >/dev/null; then
+		echo "protoc-c already installed"
+	else
+		tools+=(protobuf-c-compiler)
+	fi
 
-    if [ ${#tools[@]} -gt 0 ]; then
-        for element in "${tools[@]}"; do
-            install_tool $element
-        done
-    fi
+	if [ ${#tools[@]} -gt 0 ]; then
+		for element in "${tools[@]}"; do
+			install_tool $element
+		done
+	fi
 
-    if command -v protoc-gen-go >/dev/null; then
-        installed_version=$(protoc-gen-go --version | awk '{print $2}')
-        if [[ "$installed_version" == "v1.34.2" ]]; then
-            echo "Installed protoc-gen-go version matches the desired version."
-        else
-            go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
-        fi
-    else
-        go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
-    fi
+	if command -v protoc-gen-go >/dev/null; then
+		installed_version=$(protoc-gen-go --version | awk '{print $2}')
+		if [[ $installed_version == "v1.34.2" ]]; then
+			echo "Installed protoc-gen-go version matches the desired version."
+		else
+			go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
+		fi
+	else
+		go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2
+	fi
 }
 
 install_protoc
diff --git a/hack/run-ebpf-ut.sh b/hack/run-ebpf-ut.sh
index f468524d..df5c0c13 100755
--- a/hack/run-ebpf-ut.sh
+++ b/hack/run-ebpf-ut.sh
@@ -4,66 +4,66 @@ ROOT_DIR=$(git rev-parse --show-toplevel)
 
 . $ROOT_DIR/hack/utils.sh
 
-DOCKER_EBPF_TEST_COMMAND="make -C /kmesh/test/bpf_ut run"
-LOCAL_EBPF_TEST_COMMAND="make -C $ROOT_DIR/test/bpf_ut run"
+DOCKER_EBPF_TEST_COMMAND="make -C /kmesh/test/bpf_ut clean;make -C /kmesh/test/bpf_ut run"
+LOCAL_EBPF_TEST_COMMAND="make -C $ROOT_DIR/test/bpf_ut clean;make -C $ROOT_DIR/test/bpf_ut run"
 
 function docker_run_ebpf_ut() {
-    local container_id=$1
+	local container_id=$1
 
-    docker exec $container_id bash -c "$DOCKER_EBPF_TEST_COMMAND"
-    
-    exit_code=$?
-    return $exit_code
+	docker exec $container_id bash -c "$DOCKER_EBPF_TEST_COMMAND"
+
+	exit_code=$?
+	return $exit_code
 }
 
 function run_ebpf_ut_local() {
-    bash $ROOT_DIR/build.sh
-    export PKG_CONFIG_PATH=$ROOT_DIR/mk
-    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOT_DIR/api/v2-c:$ROOT_DIR/bpf/deserialization_to_bpf_map
-    eval "$LOCAL_EBPF_TEST_COMMAND"  
+	bash $ROOT_DIR/build.sh
+	export PKG_CONFIG_PATH=$ROOT_DIR/mk
+	export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOT_DIR/api/v2-c:$ROOT_DIR/bpf/deserialization_to_bpf_map
+	eval "$LOCAL_EBPF_TEST_COMMAND"
 }
 
 function run_ebpf_ut_in_docker() {
-    container_id=$(run_docker_container)
-    build_kmesh $container_id
-    docker_run_ebpf_ut $container_id
-    ut_exit_code=$?
-    clean_container $container_id
-    exit $ut_exit_code
+	container_id=$(run_docker_container)
+	build_kmesh $container_id
+	docker_run_ebpf_ut $container_id
+	ut_exit_code=$?
+	clean_container $container_id
+	exit $ut_exit_code
 }
 
 function clean() {
-    make clean $ROOT_DIR
+	make clean $ROOT_DIR
 }
 
 TEST_FLAGS=""
 
-if [[ "$*" == *"-v"* ]] || [[ "$*" == *"--verbose"* ]]; then
-    TEST_FLAGS="$TEST_FLAGS V=1"
+if [[ $* == *"-v"* ]] || [[ $* == *"--verbose"* ]]; then
+	TEST_FLAGS="$TEST_FLAGS V=1"
 fi
 
 DOCKER_EBPF_TEST_COMMAND="$DOCKER_EBPF_TEST_COMMAND $TEST_FLAGS"
 LOCAL_EBPF_TEST_COMMAND="$LOCAL_EBPF_TEST_COMMAND $TEST_FLAGS"
 
 # Running ebpf ut with docker by default
-if [ -z "$1" -o "$1" == "-d"  -o  "$1" == "--docker" ]; then
-    run_ebpf_ut_in_docker
-    exit
+if [ -z "$1" -o "$1" == "-d" -o "$1" == "--docker" ]; then
+	run_ebpf_ut_in_docker
+	exit
 fi
 
-if [ "$1" == "-l"  -o  "$1" == "--local" ]; then
-    run_ebpf_ut_local
-    exit
+if [ "$1" == "-l" -o "$1" == "--local" ]; then
+	run_ebpf_ut_local
+	exit
 fi
 
-if [ "$1" == "-h"  -o  "$1" == "--help" ]; then
-    echo run-ebpf-ut.sh -h/--help : Help.
-    echo run-ebpf-ut.sh -d/--docker: run ebpf unit test in docker.
-    echo run-ebpf-ut.sh -l/--local: run ebpf unit test locally.
-    exit
+if [ "$1" == "-h" -o "$1" == "--help" ]; then
+	echo run-ebpf-ut.sh -h/--help : Help.
+	echo run-ebpf-ut.sh -d/--docker: run ebpf unit test in docker.
+	echo run-ebpf-ut.sh -l/--local: run ebpf unit test locally.
+	exit
 fi
 
-if [ "$1" == "-c"  -o  "$1" == "--clean" ]; then
-    clean
-    exit
-fi 
+if [ "$1" == "-c" -o "$1" == "--clean" ]; then
+	clean
+	exit
+fi
diff --git a/hack/run-ut.sh b/hack/run-ut.sh
index 1153b60f..7b503f23 100755
--- a/hack/run-ut.sh
+++ b/hack/run-ut.sh
@@ -5,65 +5,65 @@ ROOT_DIR=$(git rev-parse --show-toplevel)
 . $ROOT_DIR/hack/utils.sh
 
 function get_go_test_command() {
-    if [ -z "$TEST_PKG" ]; then
-        TEST_PKG="./pkg/..."
-    fi
+	if [ -z "$TEST_PKG" ]; then
+		TEST_PKG="./pkg/..."
+	fi
 
-    if [ -z "$TEST_TARGET" ]; then
-        echo "go test -p 1 -v -race -vet=off $TEST_PKG"
-    else
-        echo "go test -p 1 -v -race -vet=off -run $TEST_TARGET $TEST_PKG"
-    fi
+	if [ -z "$TEST_TARGET" ]; then
+		echo "go test -p 1 -v -race -vet=off $TEST_PKG"
+	else
+		echo "go test -p 1 -v -race -vet=off -run $TEST_TARGET $TEST_PKG"
+	fi
 }
 
 go_test_command=$(get_go_test_command)
 
 function docker_run_go_ut() {
-    local container_id=$1
-    docker exec $container_id $go_test_command
-    exit_code=$?
-    return $exit_code
+	local container_id=$1
+	docker exec $container_id $go_test_command
+	exit_code=$?
+	return $exit_code
 }
 
 function run_go_ut_local() {
-    bash $ROOT_DIR/build.sh
-    export PKG_CONFIG_PATH=$ROOT_DIR/mk
-    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOT_DIR/api/v2-c:$ROOT_DIR/bpf/deserialization_to_bpf_map
-    eval "$go_test_command"  
+	bash $ROOT_DIR/build.sh
+	export PKG_CONFIG_PATH=$ROOT_DIR/mk
+	export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOT_DIR/api/v2-c:$ROOT_DIR/bpf/deserialization_to_bpf_map
+	eval "$go_test_command"
 }
 
 function run_go_ut_in_docker() {
-    container_id=$(run_docker_container)
-    build_kmesh $container_id
-    docker_run_go_ut $container_id
-    ut_exit_code=$?
-    clean_container $container_id
-    exit $ut_exit_code
+	container_id=$(run_docker_container)
+	build_kmesh $container_id
+	docker_run_go_ut $container_id
+	ut_exit_code=$?
+	clean_container $container_id
+	exit $ut_exit_code
 }
 
 function clean() {
-    make clean $ROOT_DIR
+	make clean $ROOT_DIR
 }
 
 # Running go ut with docker by default
-if [ -z "$1" -o "$1" == "-d"  -o  "$1" == "--docker" ]; then
-    run_go_ut_in_docker
-    exit
+if [ -z "$1" -o "$1" == "-d" -o "$1" == "--docker" ]; then
+	run_go_ut_in_docker
+	exit
 fi
 
-if [ "$1" == "-l"  -o  "$1" == "--local" ]; then
-    run_go_ut_local
-    exit
+if [ "$1" == "-l" -o "$1" == "--local" ]; then
+	run_go_ut_local
+	exit
 fi
 
-if [ "$1" == "-h"  -o  "$1" == "--help" ]; then
-    echo run-ut.sh -h/--help : Help.
-    echo run-ut.sh -d/--docker: run go unit test in docker.
-    echo run-ut.sh -l/--local: run go unit test locally.
-    exit
+if [ "$1" == "-h" -o "$1" == "--help" ]; then
+	echo run-ut.sh -h/--help : Help.
+	echo run-ut.sh -d/--docker: run go unit test in docker.
+	echo run-ut.sh -l/--local: run go unit test locally.
+	exit
 fi
 
-if [ "$1" == "-c"  -o  "$1" == "--clean" ]; then
-    clean
-    exit
-fi 
+if [ "$1" == "-c" -o "$1" == "--clean" ]; then
+	clean
+	exit
+fi
diff --git a/hack/update-version.sh b/hack/update-version.sh
index 2901c8c3..54b99f04 100755
--- a/hack/update-version.sh
+++ b/hack/update-version.sh
@@ -2,14 +2,14 @@
 
 # Check if a Makefile exists in the current directory
 if [ ! -f "Makefile" ]; then
-  echo "Error: Makefile not found in the current directory."
-  exit 1
+	echo "Error: Makefile not found in the current directory."
+	exit 1
 fi
 
 # Check if the VERSION argument is provided
 if [ -z "$1" ]; then
-  echo "Usage: $0 VERSION=<value>"
-  exit 1
+	echo "Usage: $0 VERSION=<value>"
+	exit 1
 fi
 
 # Extract the VERSION value from the argument
diff --git a/hack/utils.sh b/hack/utils.sh
index c1a7e74c..54f66ee8 100644
--- a/hack/utils.sh
+++ b/hack/utils.sh
@@ -1,60 +1,60 @@
 #!/bin/bash
 
 function run_docker_container() {
-    local container_id
-    container_id=$(docker run --rm -itd --privileged=true \
-        -v /usr/src:/usr/src \
-        -v /usr/include/linux/bpf.h:/kmesh/config/linux-bpf.h \
-        -v /etc/cni/net.d:/etc/cni/net.d \
-        -v /opt/cni/bin:/opt/cni/bin \
-        -v /mnt:/mnt \
-        -v /sys/fs/bpf:/sys/fs/bpf \
-        -v /lib/modules:/lib/modules \
-        -v "$(pwd)":/kmesh \
-        -v "$(go env GOCACHE)":/root/.cache/go-build \
-        -v "$(go env GOMODCACHE)":/go/pkg/mod \
-        -e PKG_CONFIG_PATH=/kmesh/mk \
-        --name kmesh-build "ghcr.io/kmesh-net/kmesh-build:latest")
+	local container_id
+	container_id=$(docker run --rm -itd --privileged=true \
+		-v /usr/src:/usr/src \
+		-v /usr/include/linux/bpf.h:/kmesh/config/linux-bpf.h \
+		-v /etc/cni/net.d:/etc/cni/net.d \
+		-v /opt/cni/bin:/opt/cni/bin \
+		-v /mnt:/mnt \
+		-v /sys/fs/bpf:/sys/fs/bpf \
+		-v /lib/modules:/lib/modules \
+		-v "$(pwd)":/kmesh \
+		-v "$(go env GOCACHE)":/root/.cache/go-build \
+		-v "$(go env GOMODCACHE)":/go/pkg/mod \
+		-e PKG_CONFIG_PATH=/kmesh/mk \
+		--name kmesh-build "ghcr.io/kmesh-net/kmesh-build:latest")
 
-    echo "$container_id"
+	echo "$container_id"
 }
 
 function get_arch() {
-    if [ "$(arch)" == "x86_64" ]; then
-        echo "x86"
-    else
-        echo "arm"
-    fi
+	if [ "$(arch)" == "x86_64" ]; then
+		echo "x86"
+	else
+		echo "arm"
+	fi
 }
 
 function build_kmesh() {
-    local container_id=$1
-    docker exec $container_id git config --global --add safe.directory /kmesh
-    docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh
-    docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh -i
-    docker exec $container_id sh -c "$(declare -f copy_to_host); copy_to_host"
+	local container_id=$1
+	docker exec $container_id git config --global --add safe.directory /kmesh
+	docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh
+	docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh -i
+	docker exec $container_id sh -c "$(declare -f copy_to_host); copy_to_host"
 }
 
 function copy_to_host() {
-    mkdir -p "./out/ko"
+	mkdir -p "./out/ko"
 
-    cp /usr/lib64/libkmesh_api_v2_c.so out/
-    cp /usr/lib64/libkmesh_deserial.so out/
-    cp /usr/lib64/libboundscheck.so out/
-    cp oncn-mda/build/ebpf_src/CMakeFiles/sock_redirect.dir/sock_redirect.c.o out/
-    cp oncn-mda/etc/oncn-mda.conf out/
-    cp oncn-mda/build/ebpf_src/CMakeFiles/sock_ops.dir/sock_ops.c.o out/
-    find /usr/lib64 -name 'libbpf.so*' -exec cp {} out/ \;
-    find /usr/lib64 -name 'libprotobuf-c.so*' -exec cp {} out/ \;
-    cp /usr/bin/kmesh-daemon out/
-    cp /usr/bin/kmesh-cni out/
-    cp /usr/bin/mdacore out/
-    if [ -f "/lib/modules/kmesh/kmesh.ko" ]; then
-        cp /lib/modules/kmesh/kmesh.ko out/ko
-    fi
+	cp /usr/lib64/libkmesh_api_v2_c.so out/
+	cp /usr/lib64/libkmesh_deserial.so out/
+	cp /usr/lib64/libboundscheck.so out/
+	cp oncn-mda/build/ebpf_src/CMakeFiles/sock_redirect.dir/sock_redirect.c.o out/
+	cp oncn-mda/etc/oncn-mda.conf out/
+	cp oncn-mda/build/ebpf_src/CMakeFiles/sock_ops.dir/sock_ops.c.o out/
+	find /usr/lib64 -name 'libbpf.so*' -exec cp {} out/ \;
+	find /usr/lib64 -name 'libprotobuf-c.so*' -exec cp {} out/ \;
+	cp /usr/bin/kmesh-daemon out/
+	cp /usr/bin/kmesh-cni out/
+	cp /usr/bin/mdacore out/
+	if [ -f "/lib/modules/kmesh/kmesh.ko" ]; then
+		cp /lib/modules/kmesh/kmesh.ko out/ko
+	fi
 }
 
 function clean_container() {
-    local container_id=$1
-    docker rm -f $container_id
+	local container_id=$1
+	docker rm -f $container_id
 }
diff --git a/kmesh_bpf_env.sh b/kmesh_bpf_env.sh
index 248b4fcf..0d8255ee 100644
--- a/kmesh_bpf_env.sh
+++ b/kmesh_bpf_env.sh
@@ -12,11 +12,11 @@ helper_name=(
 	parse_header_msg
 )
 
-base_line=`grep -nr "FN(unspec)" $KERNEL_HEADER_LINUX_BPF | awk -F ":" {'print $1'}`
+base_line=$(grep -nr "FN(unspec)" $KERNEL_HEADER_LINUX_BPF | awk -F ":" {'print $1'})
 for name in ${helper_name[@]}; do
-	current_line=`grep -nr "FN($name)" $KERNEL_HEADER_LINUX_BPF | awk -F ":" {'print $1'}`
+	current_line=$(grep -nr "FN($name)" $KERNEL_HEADER_LINUX_BPF | awk -F ":" {'print $1'})
 	if [ -n "$current_line" ]; then
-		helper_id=`expr $current_line - $base_line`
+		helper_id=$(expr $current_line - $base_line)
 		sed -Ei "/${name}_num/s/([0-9]+)[^0-9]*$/$helper_id/" $ROOT_DIR/bpf/include/bpf_helper_defs_ext.h
 	fi
 done
diff --git a/kmesh_compile_env_pre.sh b/kmesh_compile_env_pre.sh
index 8e6f548e..8723cd1e 100644
--- a/kmesh_compile_env_pre.sh
+++ b/kmesh_compile_env_pre.sh
@@ -1,143 +1,139 @@
 # libboundscheck is not available in some environments, install by source
 function install_libboundscheck() {
-    if [ ! -f /usr/local/lib/libboundscheck.so ]; then
-	    git clone https://github.com/openeuler-mirror/libboundscheck.git
-	    cd libboundscheck
-	    make CC=gcc
-	    cp lib/libboundscheck.so /usr/local/lib
-	    cp include/* /usr/include
-	    cd ../
-	    rm -rf libboundscheck
-    fi
+	if [ ! -f /usr/local/lib/libboundscheck.so ]; then
+		git clone https://github.com/openeuler-mirror/libboundscheck.git
+		cd libboundscheck
+		make CC=gcc
+		cp lib/libboundscheck.so /usr/local/lib
+		cp include/* /usr/include
+		cd ../
+		rm -rf libboundscheck
+	fi
 }
 
 function dependency_pkg_install() {
-    
-    if command -v apt > /dev/null; then
-        echo "Checking for required packages on a Debian-based system..."
-
-      
-        packages=(git make clang libbpf-dev llvm linux-tools-generic protobuf-compiler libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler cmake pkg-config gcc-multilib)
-
-       
-        update_needed=false
-        for pkg in "${packages[@]}"; do
-            if ! dpkg -s "$pkg" >/dev/null 2>&1; then
-                update_needed=true
-                break
-            fi
-        done
-
-       
-        if [ "$update_needed" = true ]; then
-            apt-get update
-        fi
-
-        # Install each missing package
-        for pkg in "${packages[@]}"; do
-            if ! dpkg -s "$pkg" >/dev/null 2>&1; then
-                echo "Installing $pkg..."
-                apt-get install -y "$pkg"
-            else
-                echo "$pkg is already installed."
-            fi
-        done
-
-        # Install libboundscheck if it’s not already present
-        install_libboundscheck
-
-    # Check if running on a Red Hat-based system (yum)
-    elif command -v yum > /dev/null; then
-        echo "Checking for required packages on a Red Hat-based system..."
-
-        # List of required packages
-        packages=(git make clang llvm libboundscheck protobuf protobuf-c protobuf-c-devel bpftool libbpf libbpf-devel cmake pkg-config glibc-devel libstdc++-devel)
-
-        # Install each missing package
-        for pkg in "${packages[@]}"; do
-            if ! rpm -q "$pkg" >/dev/null 2>&1; then
-                echo "Installing $pkg..."
-                yum install -y "$pkg"
-            else
-                echo "$pkg is already installed."
-            fi
-        done
-    fi
-}
 
+	if command -v apt >/dev/null; then
+		echo "Checking for required packages on a Debian-based system..."
+
+		packages=(git make clang libbpf-dev llvm linux-tools-generic protobuf-compiler libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler cmake pkg-config gcc-multilib)
+
+		update_needed=false
+		for pkg in "${packages[@]}"; do
+			if ! dpkg -s "$pkg" >/dev/null 2>&1; then
+				update_needed=true
+				break
+			fi
+		done
+
+		if [ "$update_needed" = true ]; then
+			apt-get update
+		fi
+
+		# Install each missing package
+		for pkg in "${packages[@]}"; do
+			if ! dpkg -s "$pkg" >/dev/null 2>&1; then
+				echo "Installing $pkg..."
+				apt-get install -y "$pkg"
+			else
+				echo "$pkg is already installed."
+			fi
+		done
+
+		# Install libboundscheck if it’s not already present
+		install_libboundscheck
+
+	# Check if running on a Red Hat-based system (yum)
+	elif command -v yum >/dev/null; then
+		echo "Checking for required packages on a Red Hat-based system..."
+
+		# List of required packages
+		packages=(git make clang llvm libboundscheck protobuf protobuf-c protobuf-c-devel bpftool libbpf libbpf-devel cmake pkg-config glibc-devel libstdc++-devel)
+
+		# Install each missing package
+		for pkg in "${packages[@]}"; do
+			if ! rpm -q "$pkg" >/dev/null 2>&1; then
+				echo "Installing $pkg..."
+				yum install -y "$pkg"
+			else
+				echo "$pkg is already installed."
+			fi
+		done
+	fi
+}
 
 # fix bug in libbpf
 function fix_libbpf_bug() {
-    if ! grep -iq "#define SEC(name) __attribute__((section(name), used))" /usr/include/bpf/bpf_helpers.h; then
-	    LINENUMBER=$(grep -n '#define SEC(name)' /usr/include/bpf/bpf_helpers.h | cut -f1 -d:)
-	    if [[ ! -z "$LINENUMBER" ]]; then
-		    sed -i "${LINENUMBER} i #if __GNUC__ && !__clang__\n#define SEC(name) __attribute__((section(name), used))\n#else" /usr/include/bpf/bpf_helpers.h
-		    LINENUMBER=$((LINENUMBER+8))
-		    sed -i "${LINENUMBER} a \\#endif" /usr/include/bpf/bpf_helpers.h
-	    fi
-    fi
+	if ! grep -iq "#define SEC(name) __attribute__((section(name), used))" /usr/include/bpf/bpf_helpers.h; then
+		LINENUMBER=$(grep -n '#define SEC(name)' /usr/include/bpf/bpf_helpers.h | cut -f1 -d:)
+		if [[ -n $LINENUMBER ]]; then
+			sed -i "${LINENUMBER} i #if __GNUC__ && !__clang__\n#define SEC(name) __attribute__((section(name), used))\n#else" /usr/include/bpf/bpf_helpers.h
+			LINENUMBER=$((LINENUMBER + 8))
+			sed -i "${LINENUMBER} a \\#endif" /usr/include/bpf/bpf_helpers.h
+		fi
+	fi
 }
 
 function adapt_low_version_kernel() {
-    # adapt less insn in kernel 4.19, only 4096, so modify KMESH_PER_ENDPOINT_NUM into 15
-    if [ "$(uname -r | cut -d '.' -f 1)" -le 4 ]; then
-            sed -i 's/\(KMESH_PER_ENDPOINT_NUM\).*/\1 15/g' bpf/kmesh/ads/include/config.h
-    fi
+	# adapt less insn in kernel 4.19, only 4096, so modify KMESH_PER_ENDPOINT_NUM into 15
+	if [ "$(uname -r | cut -d '.' -f 1)" -le 4 ]; then
+		sed -i 's/\(KMESH_PER_ENDPOINT_NUM\).*/\1 15/g' bpf/kmesh/ads/include/config.h
+	fi
 }
 
-# Special case: 
-# There is a structure that is only defined in certain environments and is 
-# only used during the compilation stage. Therefore, the definition of this 
-# structure in the include directory is dynamically adjusted according to 
+# Special case:
+# There is a structure that is only defined in certain environments and is
+# only used during the compilation stage. Therefore, the definition of this
+# structure in the include directory is dynamically adjusted according to
 # the current compilation environment during compilation.
 function adapt_include_env {
-    if grep -q "struct bpf_mem_ptr {" /usr/include/linux/bpf.h; then
-        sed -i '/bpf_mem_ptr/{N;N;N;N;d;}' bpf/kmesh/ads/include/kmesh_common.h
-    fi
+	if grep -q "struct bpf_mem_ptr {" /usr/include/linux/bpf.h; then
+		sed -i '/bpf_mem_ptr/{N;N;N;N;d;}' bpf/kmesh/ads/include/kmesh_common.h
+	fi
 }
 
-function kmesh_set_env(){
-    if [ "$(arch)" == "x86_64" ]; then
-            export EXTRA_CDEFINE="-D__x86_64__"
-            export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu:$C_INCLUDE_PATH
-    fi
-
-    if [ "$(arch)" == "aarch64" ]; then
-            export C_INCLUDE_PATH=/usr/include/aarch64-linux-gnu:$C_INCLUDE_PATH
-    fi
-    export EXTRA_GOFLAGS="-gcflags=\"-N -l\" -buildmode=pie"
-    export EXTRA_CFLAGS="-O0 -g"
+function kmesh_set_env() {
+	if [ "$(arch)" == "x86_64" ]; then
+		export EXTRA_CDEFINE="-D__x86_64__"
+		export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu:$C_INCLUDE_PATH
+	fi
+
+	if [ "$(arch)" == "aarch64" ]; then
+		export C_INCLUDE_PATH=/usr/include/aarch64-linux-gnu:$C_INCLUDE_PATH
+	fi
+	export EXTRA_GOFLAGS='-gcflags="-N -l" -buildmode=pie'
+	export EXTRA_CFLAGS="-O0 -g"
 }
 
 function set_enhanced_kernel_env() {
-    # we use /usr/include/linux/bpf.h to determine the runtime environment’s
-    # support for kmesh. Considering the case of online image compilation, a
-    # variable KERNEL_HEADER_LINUX_BPF is used here to specify the path of the
-    # source of macro definition.
-    # When using an online compiled image, /usr/include/linux/bpf.h in host
-    # machine  will be mounted to config/linux-bpf.h.
-    # Otherwise, /usr/include/linux/bpf.h from the current compilation
-    # environment will be obtained
-    export KERNEL_HEADER_LINUX_BPF=$ROOT_DIR/config/linux-bpf.h
-    if [ ! -f "$KERNEL_HEADER_LINUX_BPF" ]; then
-            export KERNEL_HEADER_LINUX_BPF=/usr/include/linux/bpf.h
-    fi
-
-    if grep -q "FN(parse_header_msg)" $KERNEL_HEADER_LINUX_BPF; then
-            export ENHANCED_KERNEL="enhanced"
-    else
-            export ENHANCED_KERNEL="normal"
-    fi
+	# we use /usr/include/linux/bpf.h to determine the runtime environment’s
+	# support for kmesh. Considering the case of online image compilation, a
+	# variable KERNEL_HEADER_LINUX_BPF is used here to specify the path of the
+	# source of macro definition.
+	# When using an online compiled image, /usr/include/linux/bpf.h in host
+	# machine  will be mounted to config/linux-bpf.h.
+	# Otherwise, /usr/include/linux/bpf.h from the current compilation
+	# environment will be obtained
+	export KERNEL_HEADER_LINUX_BPF=$ROOT_DIR/config/linux-bpf.h
+	if [ ! -f "$KERNEL_HEADER_LINUX_BPF" ]; then
+		export KERNEL_HEADER_LINUX_BPF=/usr/include/linux/bpf.h
+	fi
+
+	if grep -q "FN(parse_header_msg)" $KERNEL_HEADER_LINUX_BPF; then
+		export ENHANCED_KERNEL="enhanced"
+	else
+		export ENHANCED_KERNEL="normal"
+	fi
 }
 
 function prepare() {
-    if [ "${SKIP_DEPENDENCY_INSTALL}" != "true" ]; then
-        dependency_pkg_install
-    fi
-    fix_libbpf_bug
-    adapt_low_version_kernel
-    adapt_include_env
-    kmesh_set_env
-    bash kmesh_macros_env.sh
-    bash kmesh_bpf_env.sh
+	if [ "${SKIP_DEPENDENCY_INSTALL}" != "true" ]; then
+		dependency_pkg_install
+	fi
+	fix_libbpf_bug
+	adapt_low_version_kernel
+	adapt_include_env
+	kmesh_set_env
+	bash kmesh_macros_env.sh
+	bash kmesh_bpf_env.sh
 }
diff --git a/kmesh_macros_env.sh b/kmesh_macros_env.sh
index 2f7a9476..9c5cd060 100644
--- a/kmesh_macros_env.sh
+++ b/kmesh_macros_env.sh
@@ -1,10 +1,10 @@
 #!/bin/bash
-  
+
 VERSION=$(uname -r | cut -d '.' -f 1)
 KERNEL_VERSION=$(uname -r | cut -d '-' -f 1)
 
 function set_config() {
-    sed -i -r -e "s/($1)([ \t]*)([0-9]+)/\1\2$2/" config/kmesh_marcos_def.h
+	sed -i -r -e "s/($1)([ \t]*)([0-9]+)/\1\2$2/" config/kmesh_marcos_def.h
 }
 
 # MDA_LOOPBACK_ADDR
@@ -50,13 +50,13 @@ else
 fi
 
 # Determine libbpf version
-if command -v apt > /dev/null; then
+if command -v apt >/dev/null; then
 	LIBBPF_VERSION=$(ls /usr/lib/x86_64-linux-gnu | grep -P 'libbpf\.so\.\d+\.\d+\.\d+$' | sed -n -e 's/^.*libbpf.so.\(.*\)$/\1/p')
 else
 	LIBBPF_VERSION=$(ls /usr/lib64 | grep -P 'libbpf\.so\.\d+\.\d+\.\d+$' | sed -n -e 's/^.*libbpf.so.\(.*\)$/\1/p')
 fi
 
-if [[ "$LIBBPF_VERSION" < "0.6.0" ]]; then
+if [[ $LIBBPF_VERSION < "0.6.0" ]]; then
 	set_config LIBBPF_HIGHER_0_6_0_VERSION 0
 else
 	set_config LIBBPF_HIGHER_0_6_0_VERSION 1
diff --git a/kmesh_macros_env_kernel.sh b/kmesh_macros_env_kernel.sh
index 2a489182..3bc70ce6 100755
--- a/kmesh_macros_env_kernel.sh
+++ b/kmesh_macros_env_kernel.sh
@@ -1,11 +1,11 @@
 #!/bin/bash
-  
+
 VERSION=$(uname -r | cut -d '.' -f 1)
 KERNEL_VERSION=$(uname -r | cut -d '-' -f 1)
 KERNEL_HEADER_LINUX_BPF=/usr/include/linux/bpf.h
 
 function set_config() {
-    sed -i -r -e "s/($1)([ \t]*)([0-9]+)/\1\2$2/" config/kmesh_marcos_def.h
+	sed -i -r -e "s/($1)([ \t]*)([0-9]+)/\1\2$2/" config/kmesh_marcos_def.h
 }
 
 # MDA_LOOPBACK_ADDR
@@ -49,4 +49,4 @@ if [ "$VERSION" -ge 6 ]; then
 	set_config KERNEL_KFUNC 1
 else
 	set_config KERNEL_KFUNC 0
-fi
\ No newline at end of file
+fi
diff --git a/pkg/bpf/bpf.go b/pkg/bpf/bpf.go
index 0d184245..79038569 100644
--- a/pkg/bpf/bpf.go
+++ b/pkg/bpf/bpf.go
@@ -512,6 +512,15 @@ func (l *BpfLoader) GetEnableMonitoring() uint32 {
 	return 0
 }
 
+func (l *BpfLoader) UpdateEnablePeriodicReport(EnablePeriodicReport uint32) error {
+	if l.workloadObj != nil {
+		if err := l.workloadObj.CgroupSkb.EnablePeriodicReport.Set(EnablePeriodicReport); err != nil {
+			return fmt.Errorf("set CgroupSkb enable periodic report failed %w", err)
+		}
+	}
+	return nil
+}
+
 func closeMap(m *ebpf.Map) {
 	if m == nil {
 		return
diff --git a/pkg/kube/clean.sh b/pkg/kube/clean.sh
index c7ca03f9..e14e84c6 100644
--- a/pkg/kube/clean.sh
+++ b/pkg/kube/clean.sh
@@ -3,4 +3,4 @@ rm -rf ../../deploy/yaml/crd/kmesh.net_kmeshnodeinfoes.yaml
 rm -rf apis/kmeshnodeinfo/v1alpha1/zz_generated.deepcopy.go
 rm -rf nodeinfo/clientset
 rm -rf nodeinfo/informers
-rm -rf nodeinfo/listers
\ No newline at end of file
+rm -rf nodeinfo/listers
diff --git a/pkg/kube/generate.sh b/pkg/kube/generate.sh
index 06e68cc2..dba3e2c7 100644
--- a/pkg/kube/generate.sh
+++ b/pkg/kube/generate.sh
@@ -7,7 +7,10 @@ set -o nounset
 set -o pipefail
 
 SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../
-CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../../../code-generator)}
+CODEGEN_PKG=${CODEGEN_PKG:-$(
+	cd "${SCRIPT_ROOT}"
+	ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../../../code-generator
+)}
 KUBE_VERBOSE=9
 
 source "${CODEGEN_PKG}/kube_codegen.sh"
@@ -15,12 +18,12 @@ source "${CODEGEN_PKG}/kube_codegen.sh"
 THIS_PKG="kmesh.net/kmesh"
 
 kube::codegen::gen_helpers \
-    --boilerplate "${SCRIPT_ROOT}/pkg/kube/boilerplate.go.txt" \
-    "${SCRIPT_ROOT}/pkg/kube/apis"
+	--boilerplate "${SCRIPT_ROOT}/pkg/kube/boilerplate.go.txt" \
+	"${SCRIPT_ROOT}/pkg/kube/apis"
 
 kube::codegen::gen_client \
-    --with-watch \
-    --output-dir "${SCRIPT_ROOT}/pkg/kube/nodeinfo" \
-    --output-pkg "${THIS_PKG}/pkg/kube/nodeinfo" \
-    --boilerplate "${SCRIPT_ROOT}/pkg/kube/boilerplate.go.txt" \
-    "${SCRIPT_ROOT}/pkg/kube/apis"
\ No newline at end of file
+	--with-watch \
+	--output-dir "${SCRIPT_ROOT}/pkg/kube/nodeinfo" \
+	--output-pkg "${THIS_PKG}/pkg/kube/nodeinfo" \
+	--boilerplate "${SCRIPT_ROOT}/pkg/kube/boilerplate.go.txt" \
+	"${SCRIPT_ROOT}/pkg/kube/apis"
diff --git a/pkg/status/status_server.go b/pkg/status/status_server.go
index fc73cb09..62568e8f 100644
--- a/pkg/status/status_server.go
+++ b/pkg/status/status_server.go
@@ -313,6 +313,15 @@ func (s *Server) connectionMetricHandler(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
+	enablePeriodicReport := constants.DISABLED
+	if enabled {
+		enablePeriodicReport = constants.ENABLED
+	}
+	if err := s.loader.UpdateEnablePeriodicReport(enablePeriodicReport); err != nil {
+		http.Error(w, fmt.Sprintf("update enable periodic report failed: %v", err), http.StatusBadRequest)
+		return
+	}
+
 	s.xdsClient.WorkloadController.SetConnectionMetricTrigger(enabled)
 	w.WriteHeader(http.StatusOK)
 }



Test patch:
diff --git a/test/bpf_ut/Makefile b/test/bpf_ut/Makefile
index 4efad7a9..89aff078 100644
--- a/test/bpf_ut/Makefile
+++ b/test/bpf_ut/Makefile
@@ -26,14 +26,15 @@ CLANG_FLAGS += -MD
 
 .PHONY: all clean run
 
-TEST_OBJECTS = xdp_shutdown_in_userspace_test.o xdp_authz_offload_test.o
+all: xdp_shutdown_in_userspace_test.o xdp_authz_offload_test.o workload_sockops_test.o
 
 XDP_FLAGS = -I$(ROOT_DIR)/bpf/kmesh/ -I$(ROOT_DIR)/bpf/kmesh/workload/include -I$(ROOT_DIR)/api/v2-c
-xdp_%.o: xdp_%.c clean
+xdp_%.o: xdp_%.c
 	$(QUIET) $(CLANG) $(CLANG_FLAGS) $(XDP_FLAGS) -c $< -o $@
 
-
-all: $(TEST_OBJECTS)
+WORKLOAD_SOCKOPS_FLAGS = -I$(ROOT_DIR)/bpf/kmesh/ -I$(ROOT_DIR)/bpf/kmesh/probes -I$(ROOT_DIR)/bpf/kmesh/workload/include -I$(ROOT_DIR)/api/v2-c
+workload_sockops_test.o: workload_sockops_test.c
+	$(QUIET) $(CLANG) $(CLANG_FLAGS) $(WORKLOAD_SOCKOPS_FLAGS) -c $< -o $@
 
 clean:
 	$(QUIET) rm -f $(wildcard *.o)
@@ -70,7 +71,6 @@ ifdef BPF_TEST_FILE
 endif
 
 run: all
-	$(QUIET)echo "rebuild and run bpf tests"
 	$(GO) test ./bpftest -bpf-ut-path $(ROOT_DIR)/test/bpf_ut $(BPF_TEST_FLAGS)
 
 -include $(TEST_OBJECTS:.o=.d)
diff --git a/test/bpf_ut/bpftest/bpf_test.go b/test/bpf_ut/bpftest/bpf_test.go
index cc12fb24..b8e60399 100644
--- a/test/bpf_ut/bpftest/bpf_test.go
+++ b/test/bpf_ut/bpftest/bpf_test.go
@@ -38,6 +38,7 @@ import (
 	"google.golang.org/protobuf/proto"
 
 	"kmesh.net/kmesh/pkg/bpf/factory"
+	"kmesh.net/kmesh/pkg/constants"
 	"kmesh.net/kmesh/pkg/logger"
 	"kmesh.net/kmesh/pkg/utils"
 )
@@ -47,17 +48,21 @@ var (
 	dumpCtx  = flag.Bool("dump-ctx", false, "If set, the program context will be dumped after a CHECK and SETUP run.")
 )
 
-type unitTest struct {
+type IunitTest interface {
+	run() func(t *testing.T)
+}
+
+type unitTest_BPF_PROG_TEST_RUN struct {
 	name             string
 	setupInUserSpace func(t *testing.T, coll *ebpf.Collection) // Builds test environment in user space, used for operations that cannot be completed in kernel space (e.g., cannot pass the eBPF verifier)
 }
 
-type unitTests struct {
+type unitTests_BPF_PROG_TEST_RUN struct {
 	objFilename string
-	uts         []unitTest
+	uts         []unitTest_BPF_PROG_TEST_RUN
 }
 
-func (uts *unitTests) run() func(t *testing.T) {
+func (uts *unitTests_BPF_PROG_TEST_RUN) run() func(t *testing.T) {
 	return func(t *testing.T) {
 		for _, ut := range uts.uts {
 			t.Run(ut.name, func(t *testing.T) {
@@ -67,6 +72,27 @@ func (uts *unitTests) run() func(t *testing.T) {
 	}
 }
 
+type unitTest_BUILD_CONTEXT struct {
+	name     string
+	workFunc func(t *testing.T, cgroupPath, elfPath string)
+}
+
+type unitTests_BUILD_CONTEXT struct {
+	objFilename string
+	uts         []unitTest_BUILD_CONTEXT
+}
+
+func (uts *unitTests_BUILD_CONTEXT) run() func(t *testing.T) {
+	return func(t *testing.T) {
+		for _, ut := range uts.uts {
+			t.Run(ut.name, func(t *testing.T) {
+				if ut.workFunc != nil {
+					ut.workFunc(t, constants.Cgroup2Path, uts.objFilename)
+				}
+			})
+		}
+	}
+}
 func TestBPF(t *testing.T) {
 	if testPath == nil || *testPath == "" {
 		t.Skip("Set -bpf-ut-path to run BPF tests")
@@ -81,7 +107,7 @@ func TestBPF(t *testing.T) {
 
 // common functions
 
-func loadAndRunSpec(t *testing.T, objFilename string, tt *unitTest) {
+func loadAndRunSpec(t *testing.T, objFilename string, tt *unitTest_BPF_PROG_TEST_RUN) {
 	elfPath := path.Join(*testPath, objFilename)
 	t.Logf("Running test %s", elfPath)
 
@@ -130,7 +156,7 @@ func loadAndRunSpec(t *testing.T, objFilename string, tt *unitTest) {
 	}
 
 	// Ensure test that has a jump program also has a check program
-	if programs.checkProg == nil {
+	if programs.jumpProg != nil && programs.checkProg == nil {
 		t.Fatalf(
 			"File '%s' contains a jump program in section '%s' but no check program.",
 			elfPath,
@@ -138,10 +164,8 @@ func loadAndRunSpec(t *testing.T, objFilename string, tt *unitTest) {
 		)
 	}
 
-	if !utils.KernelVersionLowerThan5_13() {
-		// TODO: use t.Context() instead of context.Background() when go 1.24 is required
-		logger.StartLogReader(context.Background(), coll.Maps["km_log_event"])
-	}
+	startLogReader(coll)
+
 	if tt.setupInUserSpace != nil {
 		tt.setupInUserSpace(t, coll)
 	}
@@ -150,6 +174,13 @@ func loadAndRunSpec(t *testing.T, objFilename string, tt *unitTest) {
 	subTest(t, programs, coll.Maps[suiteResultMap])
 }
 
+func startLogReader(coll *ebpf.Collection) {
+	if !utils.KernelVersionLowerThan5_13() {
+		// TODO: use t.Context() instead of context.Background() when go 1.24 is required
+		logger.StartLogReader(context.Background(), coll.Maps["km_log_event"])
+	}
+}
+
 // loadAndPrepSpec loads an eBPF Collection Specification from the provided ELF file
 // and prepares it for testing. It disables pinning for all maps to avoid interference
 // between tests. Additionally, it filters out programs that don't support BPF_PROG_RUN,
@@ -177,7 +208,7 @@ func loadAndPrepSpec(t *testing.T, elfPath string) *ebpf.CollectionSpec {
 	for n, p := range spec.Programs {
 		switch p.Type {
 		// https://docs.ebpf.io/linux/syscall/BPF_PROG_TEST_RUN/
-		case ebpf.XDP, ebpf.SchedACT, ebpf.SchedCLS, ebpf.SocketFilter, ebpf.CGroupSKB:
+		case ebpf.XDP, ebpf.SchedACT, ebpf.SchedCLS, ebpf.SocketFilter, ebpf.CGroupSKB, ebpf.SockOps:
 			continue
 		}
 
@@ -192,11 +223,15 @@ func loadAndPrepSpec(t *testing.T, elfPath string) *ebpf.CollectionSpec {
 // based on the provided GlobalBpfConfig. It sets the log level and authorization
 // offload settings.
 func setBpfConfig(t *testing.T, coll *ebpf.Collection, config *factory.GlobalBpfConfig) {
-	if err := coll.Variables["bpf_log_level"].Set(&config.BpfLogLevel); err != nil {
-		t.Fatalf("failed to set bpf_log_level: %v", err)
+	if v, ok := coll.Variables["bpf_log_level"]; ok {
+		if err := v.Set(&config.BpfLogLevel); err != nil {
+			t.Fatalf("failed to set bpf_log_level: %v", err)
+		}
 	}
-	if err := coll.Variables["authz_offload"].Set(&config.AuthzOffload); err != nil {
-		t.Fatalf("failed to set authz_offload: %v", err)
+	if v, ok := coll.Variables["authz_offload"]; ok {
+		if err := v.Set(&config.AuthzOffload); err != nil {
+			t.Fatalf("failed to set authz_offload: %v", err)
+		}
 	}
 }
 
diff --git a/test/bpf_ut/bpftest/workload_test.go b/test/bpf_ut/bpftest/workload_test.go
index b96d349f..c029c9c7 100644
--- a/test/bpf_ut/bpftest/workload_test.go
+++ b/test/bpf_ut/bpftest/workload_test.go
@@ -19,13 +19,27 @@
 package bpftests
 
 import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"log"
+	"net"
+	"os"
+	"path"
+	"strconv"
+	"strings"
+	"syscall"
 	"testing"
+	"time"
 
 	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/link"
+	"github.com/cilium/ebpf/ringbuf"
 
 	"kmesh.net/kmesh/api/v2/workloadapi/security"
 	bpf2go "kmesh.net/kmesh/bpf/kmesh/bpf2go/dualengine"
 	"kmesh.net/kmesh/daemon/options"
+	"kmesh.net/kmesh/pkg/auth"
 	"kmesh.net/kmesh/pkg/bpf/factory"
 	bpfUtils "kmesh.net/kmesh/pkg/bpf/utils"
 	bpfWorkload "kmesh.net/kmesh/pkg/bpf/workload"
@@ -37,13 +51,14 @@ import (
 
 func testWorkload(t *testing.T) {
 	t.Run("XDP", testXDP)
+	t.Run("SockOps", testSockOps)
 }
 
 func testXDP(t *testing.T) {
-	XDPtests := []unitTests{
+	XDPtests := []unitTests_BPF_PROG_TEST_RUN{
 		{
 			objFilename: "xdp_shutdown_in_userspace_test.o",
-			uts: []unitTest{
+			uts: []unitTest_BPF_PROG_TEST_RUN{
 				{
 					name: "1_shutdown_in_userspace__should_shutdown",
 					setupInUserSpace: func(t *testing.T, coll *ebpf.Collection) {
@@ -68,7 +83,7 @@ func testXDP(t *testing.T) {
 		},
 		{
 			objFilename: "xdp_authz_offload_test.o",
-			uts: []unitTest{
+			uts: []unitTest_BPF_PROG_TEST_RUN{
 				{
 					name: "3_deny_policy_matched",
 					setupInUserSpace: func(t *testing.T, coll *ebpf.Collection) {
@@ -279,3 +294,476 @@ func workload_setMapsEnv(t *testing.T, coll *ebpf.Collection) {
 		t.Fatalf("SetEnvByBpfMapId failed: %v", err)
 	}
 }
+
+func testSockOps(t *testing.T) {
+	tests := []unitTests_BUILD_CONTEXT{
+		{
+			objFilename: "workload_sockops_test.o",
+			uts: []unitTest_BUILD_CONTEXT{
+				{
+					name: "BPF_SOCK_OPS_TCP_CONNECT_CB__modify_kmesh_managed_ip",
+					workFunc: func(t *testing.T, cgroupPath, objFilePath string) {
+						// mount cgroup2
+						mount_cgroup2(t, cgroupPath)
+						defer syscall.Unmount(cgroupPath, 0)
+
+						// load the eBPF program
+						coll, lk := load_bpf_2_cgroup(t, objFilePath, cgroupPath)
+						defer coll.Close()
+						defer lk.Close()
+
+						// Set the BPF configuration
+						setBpfConfig(t, coll, &factory.GlobalBpfConfig{
+							BpfLogLevel:  constants.BPF_LOG_DEBUG,
+							AuthzOffload: constants.DISABLED,
+						})
+						startLogReader(coll)
+
+						// record_kmesh_managed_ip
+						enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
+						net.DialTimeout("tcp4", enableAddr, 2*time.Second)
+
+						// Execute bpftool map dump and log the results (optional, for debugging)
+						// cmd := exec.Command("bpftool", "map", "dump", "name", "km_manage")
+						// output, err := cmd.CombinedOutput()
+						// if err != nil {
+						// 	t.Logf("Failed to execute bpftool command: %v", err)
+						// } else {
+						// 	// Log the raw output from bpftool for comparison
+						// 	t.Logf("bpftool map dump name km_manage output:\n%s", string(output))
+						// }
+
+						// Get the km_manage map from the collection
+						kmManageMap := coll.Maps["km_manage"]
+						if kmManageMap == nil {
+							t.Fatal("Failed to get km_manage map from collection")
+						}
+
+						var (
+							keyBytes [16]byte // sizeof(struct manager_key)
+							value    uint32
+							count    uint32
+							iter     *ebpf.MapIterator
+						)
+
+						iter = kmManageMap.Iterate()
+						for iter.Next(&keyBytes, &value) {
+							ip4HostOrder := binary.LittleEndian.Uint32(keyBytes[0:4])
+							ipStr := net.IPv4(
+								byte(ip4HostOrder),
+								byte(ip4HostOrder>>8),
+								byte(ip4HostOrder>>16),
+								byte(ip4HostOrder>>24)).String()
+							t.Logf("km_manage[%s] = %d", ipStr, value)
+							count++
+						}
+
+						if err := iter.Err(); err != nil {
+							t.Fatalf("Map iteration failed: %v", err)
+						}
+
+						if count != 1 {
+							t.Fatalf("Expected 1 entry in km_manage map, but got %d", count)
+						}
+
+						// remove_kmesh_managed_ip
+						disableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperDisableControl))
+						net.DialTimeout("tcp4", disableAddr, 2*time.Second)
+
+						iter = kmManageMap.Iterate()
+						count = 0
+						for iter.Next(&keyBytes, &value) {
+							count++
+						}
+
+						if err := iter.Err(); err != nil {
+							t.Fatalf("Map iteration failed: %v", err)
+						}
+
+						if count != 0 {
+							t.Fatalf("Expected 0 entry in km_manage map, but got %d", count)
+						}
+					},
+				},
+				{
+					name: "BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB__enable_encoding_metadata",
+					workFunc: func(t *testing.T, cgroupPath, objFilePath string) {
+						localIP := get_local_ipv4(t)
+						clientPort := 12345
+						serverPort := 54321
+						serverSocket := localIP + ":" + strconv.Itoa(serverPort)
+
+						// mount cgroup2
+						mount_cgroup2(t, cgroupPath)
+						defer syscall.Unmount(cgroupPath, 0)
+
+						// load the eBPF program
+						coll, lk := load_bpf_2_cgroup(t, objFilePath, cgroupPath)
+						defer coll.Close()
+						defer lk.Close()
+
+						// Set the BPF configuration
+						setBpfConfig(t, coll, &factory.GlobalBpfConfig{
+							BpfLogLevel:  constants.BPF_LOG_DEBUG,
+							AuthzOffload: constants.DISABLED,
+						})
+						startLogReader(coll)
+
+						// record_kmesh_managed_ip
+						enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
+						(&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", enableAddr)
+
+						// Create a TCP server listener
+						listener, err := net.Listen("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to start TCP server: %v", err)
+						}
+						defer listener.Close()
+
+						// try to connect to the server using the specified client port
+						conn, err := (&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to connect to server: %v", err)
+						} else {
+							t.Logf("Connect success: %s:%d -> %s:%d", localIP, clientPort, localIP, serverPort)
+						}
+						defer conn.Close()
+
+						// Now, the TCP connection between localIP:12345(client) and localIP:54321(server) has been established
+						time.Sleep(1 * time.Second)
+
+						// Get the km_socket map from the collection
+						kmSocketMap, ok := coll.Maps["km_socket"]
+						if !ok {
+							t.Fatal("Failed to get km_socket map from collection")
+						}
+						var (
+							key   [36]byte // sizeof(struct bpf_sock_tuple)
+							value uint32
+						)
+						binary.BigEndian.PutUint32(key[0:4], binary.BigEndian.Uint32(net.ParseIP(localIP).To4())) // __be32 saddr;
+						binary.BigEndian.PutUint32(key[4:8], binary.BigEndian.Uint32(net.ParseIP(localIP).To4())) // __be32 daddr;
+						binary.BigEndian.PutUint16(key[8:10], uint16(clientPort))                                 // __be16 sport;
+						binary.BigEndian.PutUint16(key[10:12], uint16(serverPort))                                // __be16 dport;
+
+						err = kmSocketMap.Lookup(key, &value)
+						if err != nil && !strings.Contains(err.Error(), "no space left on device") {
+							t.Fatalf("Failed to lookup km_socket map: %v", err)
+						}
+						t.Logf("km_socket get key[%s:%d->%s:%d], test success.", localIP, clientPort, localIP, serverPort)
+					},
+				},
+				{
+					name: "BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB__auth_ip_tuple",
+					workFunc: func(t *testing.T, cgroupPath, objFilePath string) {
+						localIP := get_local_ipv4(t)
+						clientPort := 12345
+						serverPort := 54321
+						serverSocket := localIP + ":" + strconv.Itoa(serverPort)
+
+						// mount cgroup2
+						mount_cgroup2(t, cgroupPath)
+						defer syscall.Unmount(cgroupPath, 0)
+
+						// load the eBPF program
+						coll, lk := load_bpf_2_cgroup(t, objFilePath, cgroupPath)
+						defer coll.Close()
+						defer lk.Close()
+
+						// Set the BPF configuration
+						setBpfConfig(t, coll, &factory.GlobalBpfConfig{
+							BpfLogLevel:  constants.BPF_LOG_DEBUG,
+							AuthzOffload: constants.DISABLED,
+						})
+						startLogReader(coll)
+
+						// record_kmesh_managed_ip
+						enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
+						(&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", enableAddr)
+
+						// Create a TCP server listener
+						listener, err := net.Listen("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to start TCP server: %v", err)
+						}
+						defer listener.Close()
+
+						// try to connect to the server using the specified client port
+						conn, err := (&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to connect to server: %v", err)
+						} else {
+							t.Logf("Connect success: %s:%d -> %s:%d", localIP, clientPort, localIP, serverPort)
+						}
+						defer conn.Close()
+
+						// Now, the TCP connection between localIP:12345(client) and localIP:54321(server) has been established
+						time.Sleep(1 * time.Second)
+
+						// Check the contents of ringbuf km_auth_req
+						kmAuthReqMap := coll.Maps["km_auth_req"]
+						if kmAuthReqMap == nil {
+							t.Fatal("Failed to get km_auth_req map from collection")
+						}
+						rd, err := ringbuf.NewReader(kmAuthReqMap)
+						if err != nil {
+							t.Fatalf("Failed to create ringbuf reader: %v", err)
+						}
+						defer rd.Close()
+
+						var event [40]byte // sizeof(struct ringbuf_msg_type)
+						record, err := rd.Read()
+						if err != nil {
+							t.Fatalf("Failed to read from ringbuf: %v", err)
+						}
+						if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.LittleEndian, &event); err != nil {
+							log.Printf("parsing ringbuf event: %s", err)
+						}
+						protoType := binary.LittleEndian.Uint32(event[0:4])
+						srcIP := net.IPv4(event[4], event[5], event[6], event[7])
+						dstIP := net.IPv4(event[8], event[9], event[10], event[11])
+						srcPort := binary.BigEndian.Uint16(event[12:14])
+						dstPort := binary.BigEndian.Uint16(event[14:16])
+						t.Logf("Received km_auth_req ringbuf_msg: type=%d, src=%s:%d, dst=%s:%d", protoType, srcIP, srcPort, dstIP, dstPort)
+
+						// Check
+						if protoType != constants.MSG_TYPE_IPV4 ||
+							srcIP.String() != localIP || int(srcPort) != clientPort ||
+							dstIP.String() != localIP || int(dstPort) != serverPort {
+							t.Fatalf("Expected {protoType: %d, srcIP: %s, srcPort: %d, dstIP: %s, dstPort: %d}, but got {protoType: %d, srcIP: %s, srcPort: %d, dstIP: %s, dstPort: %d}",
+								constants.MSG_TYPE_IPV4, localIP, clientPort, localIP, serverPort,
+								protoType, srcIP, srcPort, dstIP, dstPort)
+						}
+					},
+				},
+				{
+					name: "BPF_SOCK_OPS_STATE_CB__clean_auth_map",
+					workFunc: func(t *testing.T, cgroupPath, objFilePath string) {
+						localIP := get_local_ipv4(t)
+						clientPort := 12345
+						serverPort := 54321
+						serverSocket := localIP + ":" + strconv.Itoa(serverPort)
+
+						// mount cgroup2
+						mount_cgroup2(t, cgroupPath)
+						defer syscall.Unmount(cgroupPath, 0)
+
+						// load the eBPF program
+						coll, lk := load_bpf_2_cgroup(t, objFilePath, cgroupPath)
+						defer coll.Close()
+						defer lk.Close()
+
+						// Set the BPF configuration
+						setBpfConfig(t, coll, &factory.GlobalBpfConfig{
+							BpfLogLevel:  constants.BPF_LOG_DEBUG,
+							AuthzOffload: constants.DISABLED,
+						})
+						startLogReader(coll)
+
+						// update km_auth_res map
+						mapOfAuth, ok := coll.Maps["km_auth_res"]
+						if !ok {
+							t.Fatal("Failed to get km_auth_res map from collection")
+						}
+						key := make([]byte, auth.TUPLE_LEN)                                                       // struct ipv4
+						binary.BigEndian.PutUint32(key[0:4], binary.BigEndian.Uint32(net.ParseIP(localIP).To4())) // __be32 saddr;
+						binary.BigEndian.PutUint32(key[4:8], binary.BigEndian.Uint32(net.ParseIP(localIP).To4())) // __be32 daddr;
+						binary.BigEndian.PutUint16(key[8:10], uint16(serverPort))                                 // __be16 sport;
+						binary.BigEndian.PutUint16(key[10:12], uint16(clientPort))                                // __be16 dport;
+						for i := auth.IPV4_TUPLE_LENGTH; i < len(key); i++ {
+							key[i] = 0
+						}
+						if err := mapOfAuth.Update(key, uint32(1), ebpf.UpdateAny); err != nil {
+							t.Fatalf("Failed to update km_auth_res map: %v", err)
+						}
+
+						// record_kmesh_managed_ip
+						enableAddr := constants.ControlCommandIp4 + ":" + strconv.Itoa(int(constants.OperEnableControl))
+						(&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", enableAddr)
+
+						// Create a TCP server listener
+						listener, err := net.Listen("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to start TCP server: %v", err)
+						}
+						defer listener.Close()
+
+						// try to connect to the server using the specified client port
+						conn, err := (&net.Dialer{
+							LocalAddr: &net.TCPAddr{
+								IP:   net.ParseIP(localIP),
+								Port: clientPort,
+							},
+							Timeout: 2 * time.Second,
+						}).Dial("tcp4", serverSocket)
+						if err != nil {
+							t.Fatalf("Failed to connect to server: %v", err)
+						} else {
+							t.Logf("Connect success: %s:%d -> %s:%d", localIP, clientPort, localIP, serverPort)
+						}
+						conn.Close()
+
+						// Now, the TCP connection between between localIP:12345(client) and localIP:54321(server) has been established and closed
+						time.Sleep(1 * time.Second)
+
+						// Check if the entry was deleted from km_auth_res map
+						// The same key we inserted earlier should no longer exist in the map
+						var value uint32
+						err = mapOfAuth.Lookup(key, &value)
+						if err == nil {
+							t.Fatalf("km_auth_res map entry was not deleted as expected")
+						} else if !errors.Is(err, ebpf.ErrKeyNotExist) {
+							t.Fatalf("Unexpected error when looking up km_auth_res map: %v", err)
+						} else {
+							t.Logf("km_auth_res map entry was successfully cleaned up")
+						}
+					},
+				},
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.objFilename, tt.run())
+	}
+}
+
+// mount_cgroup2 mounts a cgroup v2 filesystem at the specified path.
+// It creates the directory at cgroupPath if it doesn't exist, then attempts
+// to mount a cgroup2 filesystem at that location.
+//
+// If the cgroup is already mounted (EBUSY error), it logs a message and continues.
+// For other mount failures, it fails the test with an error message.
+//
+// This function requires root privileges to succeed, as mounting filesystems
+// is a privileged operation.
+//
+// Parameters:
+//   - t: Testing context for logging and failure reporting
+//   - cgroupPath: Directory path where cgroup2 should be mounted
+func mount_cgroup2(t *testing.T, cgroupPath string) {
+	var err error
+
+	// mount cgroup2
+	if err = os.MkdirAll(cgroupPath, 0755); err != nil {
+		t.Logf("Failed to create cgroup directory %s (might already exist): %v", cgroupPath, err)
+	}
+	err = syscall.Mount("none", cgroupPath, "cgroup2", 0, "")
+	if err != nil {
+		errno, ok := err.(syscall.Errno)
+		if ok && errno == syscall.EBUSY {
+			t.Logf("Cgroup v2 already mounted at %s", cgroupPath)
+		} else {
+			t.Fatalf("Failed to mount cgroup2 at %s: %v. Ensure test is run with sudo.", cgroupPath, err)
+		}
+	}
+}
+
+// load_bpf_2_cgroup loads an eBPF program from a specified object file and attaches it to the given cgroup path.
+// The function loads the eBPF collection into the kernel and specifically attaches the "sockops_prog" program
+// from the collection to the cgroup.
+//
+// Parameters:
+//   - t: Testing context for reporting failures
+//   - objFilename: Name of the eBPF object file to load (must not be empty)
+//   - cgroupPath: Path to the cgroup where the program will be attached (must not be empty)
+//
+// Returns:
+//   - *ebpf.Collection: The loaded eBPF collection containing programs and maps
+//   - link.Link: The link representing the attachment to the cgroup
+//
+// The function will call t.Fatal if any error occurs during loading or attachment.
+func load_bpf_2_cgroup(t *testing.T, objFilename string, cgroupPath string) (*ebpf.Collection, link.Link) {
+	if cgroupPath == "" {
+		t.Fatal("cgroupPath is empty")
+	}
+	if objFilename == "" {
+		t.Fatal("objFilename is empty")
+	}
+
+	// load the eBPF program
+	spec := loadAndPrepSpec(t, path.Join(*testPath, objFilename))
+	var (
+		coll *ebpf.Collection
+		err  error
+	)
+
+	// Load the eBPF collection into the kernel
+	coll, err = ebpf.NewCollection(spec)
+	if err != nil {
+		var ve *ebpf.VerifierError
+		if errors.As(err, &ve) {
+			t.Fatalf("verifier error: %+v", ve)
+		} else {
+			t.Fatal("loading collection:", err)
+		}
+	}
+
+	lk, err := link.AttachCgroup(link.CgroupOptions{
+		Path:    constants.Cgroup2Path,
+		Attach:  spec.Programs["sockops_prog"].AttachType,
+		Program: coll.Programs["sockops_prog"],
+	})
+	if err != nil {
+		coll.Close()
+		t.Fatalf("Failed to attach cgroup: %v", err)
+	}
+	return coll, lk
+}
+
+// get_local_ipv4 returns the local IPv4 address of the machine by establishing
+// a connection to an external server (8.8.8.8:53, Google's DNS).
+// This method determines which network interface is used for external communication.
+//
+// The function fails the test if:
+// - It cannot establish a connection to the external server
+// - It cannot extract the host part from the local address
+//
+// Parameters:
+//   - t *testing.T: The testing object for reporting test failures
+//
+// Returns:
+//   - string: The local IPv4 address (without port)
+func get_local_ipv4(t *testing.T) string {
+	testConn, testErr := net.Dial("tcp4", "8.8.8.8:53")
+	if testErr != nil {
+		t.Fatalf("Failed to create test connection: %v", testErr)
+	}
+	defer testConn.Close()
+
+	localAddr, _, err := net.SplitHostPort(testConn.LocalAddr().String())
+	if err != nil {
+		t.Fatalf("Failed to extract host from address: %v", err)
+	}
+	return localAddr
+}
diff --git a/test/bpf_ut/workload_sockops_test.c b/test/bpf_ut/workload_sockops_test.c
new file mode 100644
index 00000000..37ba4a00
--- /dev/null
+++ b/test/bpf_ut/workload_sockops_test.c
@@ -0,0 +1,23 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_log.h"
+#include "bpf_common.h"
+
+// mock bpf_sk_storage_get
+struct sock_storage_data mock_storage = {
+    .via_waypoint = 1,
+};
+
+static void *mock_bpf_sk_storage_get(void *map, void *sk, void *value, __u64 flags)
+{
+    void *storage = NULL;
+    storage = bpf_sk_storage_get(map, sk, value, flags);
+    if (!storage && map == &map_of_sock_storage) {
+        storage = &mock_storage;
+    }
+    return storage;
+}
+
+#define bpf_sk_storage_get mock_bpf_sk_storage_get
+
+#include "workload/sockops.c"
\ No newline at end of file
diff --git a/test/e2e/run_test.sh b/test/e2e/run_test.sh
index 78e362aa..6089d5bb 100755
--- a/test/e2e/run_test.sh
+++ b/test/e2e/run_test.sh
@@ -23,20 +23,20 @@ export PATH="$PATH:$TMPBIN"
 
 # Provision a kind clustr for testing.
 function setup_kind_cluster() {
-    local NAME="${1:-kmesh-testing}"
-    local IMAGE="${2:-"${DEFAULT_KIND_IMAGE}"}"
+	local NAME="${1:-kmesh-testing}"
+	local IMAGE="${2:-"${DEFAULT_KIND_IMAGE}"}"
 
-    # Delete any previous KinD cluster.
-    echo "Deleting previous KinD cluster with name=${NAME}"
-    if ! (kind delete cluster --name="${NAME}" -v9) > /dev/null; then
-        echo "No existing kind cluster with name ${NAME}. Continue..."
-    fi
+	# Delete any previous KinD cluster.
+	echo "Deleting previous KinD cluster with name=${NAME}"
+	if ! (kind delete cluster --name="${NAME}" -v9) >/dev/null; then
+		echo "No existing kind cluster with name ${NAME}. Continue..."
+	fi
 
-    # Create KinD cluster.
+	# Create KinD cluster.
 
-    if [[ -n "${IPV6:-}" ]]; then
-        # Create IPv6 KinD cluster
-        cat <<EOF | kind create cluster --name="${NAME}" -v4 --retain --image "${IMAGE}" --config=-
+	if [[ -n ${IPV6:-} ]]; then
+		# Create IPv6 KinD cluster
+		cat <<EOF | kind create cluster --name="${NAME}" -v4 --retain --image "${IMAGE}" --config=-
 kind: Cluster
 apiVersion: kind.x-k8s.io/v1alpha4
 networking:
@@ -49,9 +49,9 @@ containerdConfigPatches:
   [plugins."io.containerd.grpc.v1.cri".registry]
     config_path = "/etc/containerd/certs.d"
 EOF
-    else
-        # Create default IPv4 KinD cluster
-        cat <<EOF | kind create cluster --name="${NAME}" -v4 --retain --image "${IMAGE}" --config=-
+	else
+		# Create default IPv4 KinD cluster
+		cat <<EOF | kind create cluster --name="${NAME}" -v4 --retain --image "${IMAGE}" --config=-
 kind: Cluster
 apiVersion: kind.x-k8s.io/v1alpha4
 nodes:
@@ -62,35 +62,35 @@ containerdConfigPatches:
   [plugins."io.containerd.grpc.v1.cri".registry]
     config_path = "/etc/containerd/certs.d"
 EOF
-    fi
-
-    status=$?
-    if [ $status -ne 0 ]; then
-        echo "Could not setup KinD environment. Something wrong with KinD setup. Exporting logs."
-    fi
-
-    # Add the registry config to the nodes
-    #
-    # This is necessary because localhost resolves to loopback addresses that are network-namespace local.
-    # In other words: localhost in the container is not localhost on the host.
-    #
-    # We want a consistent name that works from both ends, so we tell containerd to alias localhost:${reg_port}
-    # to the registry container when pulling images
-    REGISTRY_DIR="/etc/containerd/certs.d/localhost:${KIND_REGISTRY_PORT}"
-    for node in $(kind get nodes --name="${NAME}"); do
-        docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
-        cat << EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
+	fi
+
+	status=$?
+	if [ $status -ne 0 ]; then
+		echo "Could not setup KinD environment. Something wrong with KinD setup. Exporting logs."
+	fi
+
+	# Add the registry config to the nodes
+	#
+	# This is necessary because localhost resolves to loopback addresses that are network-namespace local.
+	# In other words: localhost in the container is not localhost on the host.
+	#
+	# We want a consistent name that works from both ends, so we tell containerd to alias localhost:${reg_port}
+	# to the registry container when pulling images
+	REGISTRY_DIR="/etc/containerd/certs.d/localhost:${KIND_REGISTRY_PORT}"
+	for node in $(kind get nodes --name="${NAME}"); do
+		docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
+		cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
 [host."http://${KIND_REGISTRY_NAME}:5000"]
 EOF
-    done
+	done
 
-    # For KinD environment we need to mount bpf for each node, ref: https://github.com/kmesh-net/kmesh/issues/662
-    for node in $(kind get nodes --name="${NAME}"); do
-        docker exec "${node}" sh -c "mount -t bpf none /sys/fs/bpf"
-    done
+	# For KinD environment we need to mount bpf for each node, ref: https://github.com/kmesh-net/kmesh/issues/662
+	for node in $(kind get nodes --name="${NAME}"); do
+		docker exec "${node}" sh -c "mount -t bpf none /sys/fs/bpf"
+	done
 
-    # Document the local registry
-    cat <<EOF | kubectl apply -f -
+	# Document the local registry
+	cat <<EOF | kubectl apply -f -
 apiVersion: v1
 kind: ConfigMap
 metadata:
@@ -104,39 +104,39 @@ EOF
 }
 
 function setup_istio() {
-    echo "install istio $ISTIO_VERSION"
-    kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
-        { kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.1.0" | kubectl apply -f -; }
+	echo "install istio $ISTIO_VERSION"
+	kubectl get crd gateways.gateway.networking.k8s.io &>/dev/null ||
+		{ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd/experimental?ref=v1.1.0" | kubectl apply -f -; }
 
-    istioctl install --set profile=ambient --set meshConfig.accessLogFile="/dev/stdout" --set components.ingressGateways[0].enabled=true --set components.ingressGateways[0].name=istio-ingressgateway --skip-confirmation
+	istioctl install --set profile=ambient --set meshConfig.accessLogFile="/dev/stdout" --set components.ingressGateways[0].enabled=true --set components.ingressGateways[0].name=istio-ingressgateway --skip-confirmation
 }
 
 function setup_kmesh() {
-    helm install kmesh $ROOT_DIR/deploy/charts/kmesh-helm -n kmesh-system --create-namespace --set deploy.kmesh.image.repository=localhost:5000/kmesh \
-    --set deploy.kmesh.containers.kmeshDaemonArgs="--mode=dual-engine --enable-bypass=false --monitoring=true"
-
-    # Wait for all Kmesh pods to be ready.
-    while true; do
-        pod_statuses=$(kubectl get pods -n kmesh-system -l app=kmesh -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.phase}{"\n"}{end}')
-
-        running_pods=0
-        total_pods=0
-
-        while read -r pod_name pod_status; do
-            total_pods=$((total_pods + 1))
-            if [ "$pod_status" = "Running" ]; then
-                running_pods=$((running_pods + 1))
-            fi
-        done <<< "$pod_statuses"
-
-        if [ "$running_pods" -eq "$total_pods" ]; then
-            echo "All pods of Kmesh daemon are in Running state."
-            break
-        fi
-
-        echo "Waiting for pods of Kmesh daemon to enter Running state..."
-        sleep 1
-    done
+	helm install kmesh $ROOT_DIR/deploy/charts/kmesh-helm -n kmesh-system --create-namespace --set deploy.kmesh.image.repository=localhost:5000/kmesh \
+		--set deploy.kmesh.containers.kmeshDaemonArgs="--mode=dual-engine --enable-bypass=false --monitoring=true"
+
+	# Wait for all Kmesh pods to be ready.
+	while true; do
+		pod_statuses=$(kubectl get pods -n kmesh-system -l app=kmesh -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.phase}{"\n"}{end}')
+
+		running_pods=0
+		total_pods=0
+
+		while read -r pod_name pod_status; do
+			total_pods=$((total_pods + 1))
+			if [ "$pod_status" = "Running" ]; then
+				running_pods=$((running_pods + 1))
+			fi
+		done <<<"$pod_statuses"
+
+		if [ "$running_pods" -eq "$total_pods" ]; then
+			echo "All pods of Kmesh daemon are in Running state."
+			break
+		fi
+
+		echo "Waiting for pods of Kmesh daemon to enter Running state..."
+		sleep 1
+	done
 }
 
 export KIND_REGISTRY_NAME="kind-registry"
@@ -146,156 +146,153 @@ export KIND_REGISTRY="localhost:${KIND_REGISTRY_PORT}"
 # Provision a local docker registry, so KinD nodes could pull images from.
 # https://kind.sigs.k8s.io/docs/user/local-registry/
 function setup_kind_registry() {
-    running="$(docker inspect -f '{{.State.Running}}' "${KIND_REGISTRY_NAME}" 2>/dev/null || true)"
-    if [[ "${running}" != 'true' ]]; then
-        docker run \
-            -d --restart=always -p "${KIND_REGISTRY_PORT}:5000" --name "${KIND_REGISTRY_NAME}" \
-            gcr.io/istio-testing/registry:2
-        
-        # Allow kind nodes to reach the registry
-        docker network connect "kind" "${KIND_REGISTRY_NAME}"
-    fi
+	running="$(docker inspect -f '{{.State.Running}}' "${KIND_REGISTRY_NAME}" 2>/dev/null || true)"
+	if [[ ${running} != 'true' ]]; then
+		docker run \
+			-d --restart=always -p "${KIND_REGISTRY_PORT}:5000" --name "${KIND_REGISTRY_NAME}" \
+			gcr.io/istio-testing/registry:2
+
+		# Allow kind nodes to reach the registry
+		docker network connect "kind" "${KIND_REGISTRY_NAME}"
+	fi
 }
 
 function build_and_push_images() {
-    HUB="${KIND_REGISTRY}" TAG="latest" make docker.push
+	HUB="${KIND_REGISTRY}" TAG="latest" make docker.push
 }
 
 function install_dependencies() {
-    # 1. Install kind.
-    if ! which kind &> /dev/null
-    then
-        echo "install kind"
+	# 1. Install kind.
+	if ! which kind &>/dev/null; then
+		echo "install kind"
 
-        go install sigs.k8s.io/kind@v0.23.0
-    else
-        echo "kind is already installed"
-    fi
-    
-    # 2. Install helm.
-    if ! which helm &> /dev/null
-    then
-        echo "install helm"
+		go install sigs.k8s.io/kind@v0.23.0
+	else
+		echo "kind is already installed"
+	fi
 
-        curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
+	# 2. Install helm.
+	if ! which helm &>/dev/null; then
+		echo "install helm"
 
-        chmod 700 get_helm.sh
+		curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
 
-        ./get_helm.sh
+		chmod 700 get_helm.sh
 
-        rm get_helm.sh
-    else
-        echo "helm is already installed"
-    fi
+		./get_helm.sh
 
-    # 3. Install istioctl
-    curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} TARGET_ARCH=x86_64 sh -
+		rm get_helm.sh
+	else
+		echo "helm is already installed"
+	fi
 
-    cp istio-${ISTIO_VERSION}/bin/istioctl $TMPBIN
+	# 3. Install istioctl
+	curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} TARGET_ARCH=x86_64 sh -
 
-    rm -rf istio-${ISTIO_VERSION}
+	cp istio-${ISTIO_VERSION}/bin/istioctl $TMPBIN
+
+	rm -rf istio-${ISTIO_VERSION}
 }
 
 function cleanup_kind_cluster() {
-    local NAME="${1:-kmesh-testing}"
-    echo "Deleting KinD cluster with name=${NAME}"
-    kind delete cluster --name="${NAME}"
-    echo "KinD cluster ${NAME} cleaned up"
+	local NAME="${1:-kmesh-testing}"
+	echo "Deleting KinD cluster with name=${NAME}"
+	kind delete cluster --name="${NAME}"
+	echo "KinD cluster ${NAME} cleaned up"
 }
 
 function cleanup_docker_registry() {
-    echo "Stopping Docker registry named '${KIND_REGISTRY_NAME}'..."
-    docker stop "${KIND_REGISTRY_NAME}" || echo "Failed to stop or no such registry '${KIND_REGISTRY_NAME}'."
+	echo "Stopping Docker registry named '${KIND_REGISTRY_NAME}'..."
+	docker stop "${KIND_REGISTRY_NAME}" || echo "Failed to stop or no such registry '${KIND_REGISTRY_NAME}'."
 
-    echo "Removing Docker registry named '${KIND_REGISTRY_NAME}'..."
-    docker rm "${KIND_REGISTRY_NAME}" || echo "Failed to remove or no such registry '${KIND_REGISTRY_NAME}'."
+	echo "Removing Docker registry named '${KIND_REGISTRY_NAME}'..."
+	docker rm "${KIND_REGISTRY_NAME}" || echo "Failed to remove or no such registry '${KIND_REGISTRY_NAME}'."
 }
 
 PARAMS=()
 
-while (( "$#" )); do
-    case "$1" in
-    --skip-install-dep)
-      SKIP_INSTALL_DEPENDENCIES=true
-      shift
-    ;;
-    --skip-setup)
-      SKIP_SETUP=true
-      shift
-    ;;
-    --skip-build)
-      SKIP_BUILD=true
-      shift
-    ;;
-    --only-run-tests)
-      SKIP_INSTALL_DEPENDENCIES=true
-      SKIP_SETUP=true
-      SKIP_BUILD=true
-      shift
-    ;;
-    --cluster)
-      NAME="$2"
-      if ! kind get clusters | grep -qw "$NAME"; then
-        echo "Error: Cluster '$NAME' does not exist."
-        exit 1
-      fi
-      shift 2
-    ;;
-    --ipv6)
-      IPV6=true
-      shift
-    ;;
-    --cleanup)
-      CLEANUP_KIND=true
-      CLEANUP_REGISTRY=true
-      shift
-    ;;
-    --skip-cleanup-apps)
-      PARAMS+=("-istio.test.nocleanup")
-      shift
-    ;;
-    *)
-      PARAMS+=("$1")
-      shift
-    ;;
-    esac
+while (("$#")); do
+	case "$1" in
+	--skip-install-dep)
+		SKIP_INSTALL_DEPENDENCIES=true
+		shift
+		;;
+	--skip-setup)
+		SKIP_SETUP=true
+		shift
+		;;
+	--skip-build)
+		SKIP_BUILD=true
+		shift
+		;;
+	--only-run-tests)
+		SKIP_INSTALL_DEPENDENCIES=true
+		SKIP_SETUP=true
+		SKIP_BUILD=true
+		shift
+		;;
+	--cluster)
+		NAME="$2"
+		if ! kind get clusters | grep -qw "$NAME"; then
+			echo "Error: Cluster '$NAME' does not exist."
+			exit 1
+		fi
+		shift 2
+		;;
+	--ipv6)
+		IPV6=true
+		shift
+		;;
+	--cleanup)
+		CLEANUP_KIND=true
+		CLEANUP_REGISTRY=true
+		shift
+		;;
+	--skip-cleanup-apps)
+		PARAMS+=("-istio.test.nocleanup")
+		shift
+		;;
+	*)
+		PARAMS+=("$1")
+		shift
+		;;
+	esac
 done
 
 NAME="${NAME:-kmesh-testing}"
 
-if [[ -z "${SKIP_INSTALL_DEPENDENCIES:-}" ]]; then
-    install_dependencies
+if [[ -z ${SKIP_INSTALL_DEPENDENCIES:-} ]]; then
+	install_dependencies
 fi
 
-if [[ -z "${SKIP_SETUP:-}" ]]; then
-    setup_kind_cluster "$NAME"
+if [[ -z ${SKIP_SETUP:-} ]]; then
+	setup_kind_cluster "$NAME"
 fi
 
-if [[ -z "${SKIP_BUILD:-}" ]]; then
-    setup_kind_registry
-    build_and_push_images
+if [[ -z ${SKIP_BUILD:-} ]]; then
+	setup_kind_registry
+	build_and_push_images
 fi
 
 kubectl config use-context "kind-$NAME"
 echo "Running tests in cluster '$NAME'"
 
-
 # make sure the Kmesh local image is ready.
-if [[ -z "${SKIP_SETUP:-}" ]]; then
-    setup_istio
-    setup_kmesh
+if [[ -z ${SKIP_SETUP:-} ]]; then
+	setup_istio
+	setup_kmesh
 fi
 
 cmd="go test -v -tags=integ $ROOT_DIR/test/e2e/... -istio.test.kube.loadbalancer=false ${PARAMS[*]}"
 
 bash -c "$cmd"
 
-if [[ -n "${CLEANUP_KIND}" ]]; then
-    cleanup_kind_cluster
+if [[ -n ${CLEANUP_KIND} ]]; then
+	cleanup_kind_cluster
 fi
 
-if [[ -n "${CLEANUP_REGISTRY}" ]]; then
-    cleanup_docker_registry
+if [[ -n ${CLEANUP_REGISTRY} ]]; then
+	cleanup_docker_registry
 fi
 
 rm -rf "${TMP}"
diff --git a/test/performance/big_small_test/shell/test_big_small.sh b/test/performance/big_small_test/shell/test_big_small.sh
index 8ec4bedb..4dc49aa7 100644
--- a/test/performance/big_small_test/shell/test_big_small.sh
+++ b/test/performance/big_small_test/shell/test_big_small.sh
@@ -1,10 +1,10 @@
 #!/bin/bash
 
 namespace=default
-client_address_small=`kubectl get pod -n $namespace | grep fortio-client-small | grep Running | awk {'print $1'}`
-server_address_small=`kubectl get svc -n $namespace | grep fortio-server-small | awk {'print $3'}`:80
-client_address_big=`kubectl get pod -n $namespace | grep fortio-client-big | grep Running | awk {'print $1'}`
-server_address_big=`kubectl get svc -n $namespace | grep fortio-server-big | awk {'print $3'}`:80
+client_address_small=$(kubectl get pod -n $namespace | grep fortio-client-small | grep Running | awk {'print $1'})
+server_address_small=$(kubectl get svc -n $namespace | grep fortio-server-small | awk {'print $3'}):80
+client_address_big=$(kubectl get pod -n $namespace | grep fortio-client-big | grep Running | awk {'print $1'})
+server_address_big=$(kubectl get svc -n $namespace | grep fortio-server-big | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -18,19 +18,19 @@ qps=5000
 
 echo "test starting..."
 echo "test only small client run..."
-dstat -cmtn 5s > ${log_path}/dstat.log &
+dstat -cmtn 5s >${log_path}/dstat.log &
 
-echo "kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small}" > ${log_path}/only_small_client_run.log
-kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small} >> ${log_path}/only_small_client_run.log
+echo "kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small}" >${log_path}/only_small_client_run.log
+kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small} >>${log_path}/only_small_client_run.log
 
 sleep 10
 echo "test small and big run..."
 
 for theadnum in 1 10 20 30 40 50 60 70 80 90 100; do
-	echo "kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small}" > ${log_path}/both_small_run_${theadnum}.log
-	nohup kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small} >> ${log_path}/both_small_run_${theadnum}.log &
-	echo "kubectl exec -it ${client_address_big} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address_big}" > ${log_path}/both_big_run_${theadnum}.log
-	nohup kubectl exec -it ${client_address_big} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address_big} >> ${log_path}/both_big_run_${theadnum}.log &
+	echo "kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small}" >${log_path}/both_small_run_${theadnum}.log
+	nohup kubectl exec -it ${client_address_small} -n $namespace -- fortio load -quiet -c ${base_theadnum} -t ${runtime}s -keepalive=true -qps ${qps} ${server_address_small} >>${log_path}/both_small_run_${theadnum}.log &
+	echo "kubectl exec -it ${client_address_big} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address_big}" >${log_path}/both_big_run_${theadnum}.log
+	nohup kubectl exec -it ${client_address_big} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address_big} >>${log_path}/both_big_run_${theadnum}.log &
 	sleep ${runtime}
 	sleep 10
 done
@@ -38,4 +38,3 @@ done
 echo "stop dstat"
 ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 echo "test stop..."
-
diff --git a/test/performance/bookinfo_test/shell/bookinfo.sh b/test/performance/bookinfo_test/shell/bookinfo.sh
index 960e8da2..76ac7cd4 100644
--- a/test/performance/bookinfo_test/shell/bookinfo.sh
+++ b/test/performance/bookinfo_test/shell/bookinfo.sh
@@ -1,8 +1,8 @@
 #!/bin/bash
 
 namespace=default
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep productpage | awk {'print $3'}`:9080/productpage 
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep productpage | awk {'print $3'}):9080/productpage
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -10,11 +10,11 @@ log_path=long_connection/$time
 mkdir -p ${log_path}
 
 for i in {1..20}; do
-	theadnum=$[i*10]
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address}" > ${log_path}/test_${theadnum}.log
-	dstat -cmt 5s >> ${log_path}/test_${theadnum}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address} >> ${log_path}/test_${theadnum}.log
+	theadnum=$((i * 10))
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address}" >${log_path}/test_${theadnum}.log
+	dstat -cmt 5s >>${log_path}/test_${theadnum}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address} >>${log_path}/test_${theadnum}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
-	
+
 done
diff --git a/test/performance/density_test/shell/density_test.sh b/test/performance/density_test/shell/density_test.sh
index db5d5e01..565387c1 100644
--- a/test/performance/density_test/shell/density_test.sh
+++ b/test/performance/density_test/shell/density_test.sh
@@ -1,8 +1,8 @@
 #!/bin/bash
 
 namespace=default
-client_address_list=`kubectl get pod -n $namespace | grep fortio-client |grep Running| awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
+client_address_list=$(kubectl get pod -n $namespace | grep fortio-client | grep Running | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -13,11 +13,11 @@ theadnum=1
 runtime=60
 
 echo "test starting..."
-dstat -cmt >> ${log_path}/dstat.log &
+dstat -cmt >>${log_path}/dstat.log &
 for client_address in $client_address_list; do
 	cmd="kubectl exec ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address}"
-	echo $cmd > ${log_path}/${client_address}.log
-	nohup kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address} >> ${log_path}/${client_address}.log &
+	echo $cmd >${log_path}/${client_address}.log
+	nohup kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t ${runtime}s -keepalive=true -qps 0 ${server_address} >>${log_path}/${client_address}.log &
 	echo "exec $client_address success..."
 done
 echo "sleep $runtime ..."
@@ -26,4 +26,3 @@ sleep 10
 echo "wake up"
 ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 echo "test stop..."
-
diff --git a/test/performance/long_test/shell/long_test.sh b/test/performance/long_test/shell/long_test.sh
index b7add2aa..ef884060 100644
--- a/test/performance/long_test/shell/long_test.sh
+++ b/test/performance/long_test/shell/long_test.sh
@@ -2,8 +2,8 @@
 
 mode=${1:-}
 namespace=default
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -12,9 +12,9 @@ mkdir -p ${log_path}
 
 for theadnum in 1 2 4 8 16 32 64 128; do
 	echo "run $theadnum..."
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address}" > ${log_path}/test_${theadnum}.log
-	dstat -cmtn 5s >> ${log_path}/test_${theadnum}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address} >> ${log_path}/test_${theadnum}.log
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address}" >${log_path}/test_${theadnum}.log
+	dstat -cmtn 5s >>${log_path}/test_${theadnum}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=true -qps 0 ${server_address} >>${log_path}/test_${theadnum}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 done
diff --git a/test/performance/multiple_test/config/yaml/get_nginx_svc_address.sh b/test/performance/multiple_test/config/yaml/get_nginx_svc_address.sh
index e680dedb..89bae6cd 100644
--- a/test/performance/multiple_test/config/yaml/get_nginx_svc_address.sh
+++ b/test/performance/multiple_test/config/yaml/get_nginx_svc_address.sh
@@ -2,60 +2,58 @@
 relaNginxConfigPath=${1:-../nginx_config/}
 nginxnum=${2:-8}
 
-getClusterIPAddr()
-{
-    name=$1
-    clusterIP=`kubectl get svc -nnginx | grep $name | awk '{print $3}'`
-    echo $clusterIP
+getClusterIPAddr() {
+	name=$1
+	clusterIP=$(kubectl get svc -nnginx | grep $name | awk '{print $3}')
+	echo $clusterIP
 }
 
-setClusterIPAddr()
-{
-    clusterIP=$1
-    file=$2
-    sed -i "19c \\\t\tserver ${clusterIP}:80;" $file
-    echo "set $file success, clusterip:$clusterIP"
+setClusterIPAddr() {
+	clusterIP=$1
+	file=$2
+	sed -i "19c \\\t\tserver ${clusterIP}:80;" $file
+	echo "set $file success, clusterip:$clusterIP"
 }
 
 errVal=false
 for i in '1' '2' '3' '4' '5' '6' '7' '8'; do
 	if [ ${i} == $nginxnum ]; then
-		errVal=true	
+		errVal=true
 	fi
 done
 
-if [ $errVal == false ];then
+if [ $errVal == false ]; then
 	echo 'input num need >0 and <=8'
 	exit
 fi
 
 fortioSvc=$(getClusterIPAddr fortio-server-nginx)
 setClusterIPAddr $fortioSvc $relaNginxConfigPath/proxypass1/nginx.conf
-if [ x$nginxnum == 'x1' ];then	exit;fi
+if [ x$nginxnum == 'x1' ]; then exit; fi
 
 nginx1=$(getClusterIPAddr nginx-service1)
 setClusterIPAddr $nginx1 $relaNginxConfigPath/proxypass2/nginx.conf
-if [ x$nginxnum == 'x2' ];then	exit;fi
+if [ x$nginxnum == 'x2' ]; then exit; fi
 
 nginx2=$(getClusterIPAddr nginx-service2)
 setClusterIPAddr $nginx2 $relaNginxConfigPath/proxypass3/nginx.conf
-if [ x$nginxnum == 'x3' ];then	exit;fi
+if [ x$nginxnum == 'x3' ]; then exit; fi
 
 nginx3=$(getClusterIPAddr nginx-service3)
 setClusterIPAddr $nginx3 $relaNginxConfigPath/proxypass4/nginx.conf
-if [ x$nginxnum == 'x4' ];then	exit;fi
+if [ x$nginxnum == 'x4' ]; then exit; fi
 
 nginx4=$(getClusterIPAddr nginx-service4)
 setClusterIPAddr $nginx4 $relaNginxConfigPath/proxypass5/nginx.conf
-if [ x$nginxnum == 'x5' ];then	exit;fi
+if [ x$nginxnum == 'x5' ]; then exit; fi
 
 nginx5=$(getClusterIPAddr nginx-service5)
 setClusterIPAddr $nginx5 $relaNginxConfigPath/proxypass6/nginx.conf
-if [ x$nginxnum == 'x6' ];then	exit;fi
+if [ x$nginxnum == 'x6' ]; then exit; fi
 
 nginx6=$(getClusterIPAddr nginx-service6)
 setClusterIPAddr $nginx6 $relaNginxConfigPath/proxypass7/nginx.conf
-if [ x$nginxnum == 'x7' ];then	exit;fi
+if [ x$nginxnum == 'x7' ]; then exit; fi
 
 nginx7=$(getClusterIPAddr nginx-service7)
 setClusterIPAddr $nginx7 $relaNginxConfigPath/proxypass8/nginx.conf
diff --git a/test/performance/multiple_test/config/yaml/install.sh b/test/performance/multiple_test/config/yaml/install.sh
index ca5aea32..328b165e 100644
--- a/test/performance/multiple_test/config/yaml/install.sh
+++ b/test/performance/multiple_test/config/yaml/install.sh
@@ -5,4 +5,4 @@ sh get_nginx_svc_address.sh
 kubectl apply -f fortio-client.yaml
 kubectl apply -f fortio-server.yaml
 kubectl apply -f deployment.yaml
-kubectl apply -f cilium_policy.yaml 
+kubectl apply -f cilium_policy.yaml
diff --git a/test/performance/multiple_test/config/yaml/uninstall.sh b/test/performance/multiple_test/config/yaml/uninstall.sh
index 5d906dbc..5dab016e 100644
--- a/test/performance/multiple_test/config/yaml/uninstall.sh
+++ b/test/performance/multiple_test/config/yaml/uninstall.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-kubectl delete -f cilium_policy.yaml 
+kubectl delete -f cilium_policy.yaml
 kubectl delete -f deployment.yaml
 kubectl delete -f fortio-server.yaml
 kubectl delete -f fortio-client.yaml
diff --git a/test/performance/multiple_test/shell/test_nginx.sh b/test/performance/multiple_test/shell/test_nginx.sh
index ca848478..dd5855b4 100644
--- a/test/performance/multiple_test/shell/test_nginx.sh
+++ b/test/performance/multiple_test/shell/test_nginx.sh
@@ -1,12 +1,12 @@
 #!/bin/bash
 
 namespace=nginx
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
 #server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
 #server_address=http://`kubectl get svc -n $namespace | grep nginx-service2 | awk {'print $3'}`:80
 #server_address=http://`kubectl get svc -n $namespace | grep nginx-service4 | awk {'print $3'}`:80
 #server_address=http://`kubectl get svc -n $namespace | grep nginx-service6 | awk {'print $3'}`:80
-server_address=http://`kubectl get svc -n $namespace | grep nginx-service8 | awk {'print $3'}`:80
+server_address=http://$(kubectl get svc -n $namespace | grep nginx-service8 | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -14,11 +14,11 @@ log_path=nginx_multiple_test/$time
 mkdir -p ${log_path}
 
 for i in {1..20}; do
-	theadnum=$[i*10]
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 60s -keepalive=true -qps 0 ${server_address}" > ${log_path}/test_${theadnum}.log
-	dstat -cmt 60s >> ${log_path}/test_${theadnum}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 60s -keepalive=true -qps 0 ${server_address} >> ${log_path}/test_${theadnum}.log
+	theadnum=$((i * 10))
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 60s -keepalive=true -qps 0 ${server_address}" >${log_path}/test_${theadnum}.log
+	dstat -cmt 60s >>${log_path}/test_${theadnum}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 60s -keepalive=true -qps 0 ${server_address} >>${log_path}/test_${theadnum}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
-	
+
 done
diff --git a/test/performance/packsize_test/shell/packsize_test.sh b/test/performance/packsize_test/shell/packsize_test.sh
index 9c29595e..7177f044 100644
--- a/test/performance/packsize_test/shell/packsize_test.sh
+++ b/test/performance/packsize_test/shell/packsize_test.sh
@@ -2,8 +2,8 @@
 
 mode=${1:-}
 namespace=default
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -12,9 +12,9 @@ mkdir -p ${log_path}
 
 for packagesize in 0 50 100 300 500 1000 2000 3000 4000; do
 	echo "run $packagesize..."
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 16 -t 30s -keepalive=true -payload-size=$packagesize -qps 0 ${server_address}" > ${log_path}/test_${packagesize}.log
-	dstat -cmtn 5s >> ${log_path}/test_${packagesize}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 16 -t 30s -keepalive=true -payload-size=$packagesize -qps 0 ${server_address} >> ${log_path}/test_${packagesize}.log
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 16 -t 30s -keepalive=true -payload-size=$packagesize -qps 0 ${server_address}" >${log_path}/test_${packagesize}.log
+	dstat -cmtn 5s >>${log_path}/test_${packagesize}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 16 -t 30s -keepalive=true -payload-size=$packagesize -qps 0 ${server_address} >>${log_path}/test_${packagesize}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 done
diff --git a/test/performance/qps_test/shell/qps_test.sh b/test/performance/qps_test/shell/qps_test.sh
index 332ea02d..c538033a 100644
--- a/test/performance/qps_test/shell/qps_test.sh
+++ b/test/performance/qps_test/shell/qps_test.sh
@@ -2,8 +2,8 @@
 
 mode=${1:-}
 namespace=default
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -12,9 +12,9 @@ mkdir -p ${log_path}
 
 for qps in 10000 30000 60000 100000 200000 300000 400000 500000 600000; do
 	echo "run qps $qps..."
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 100 -qps ${qps} -t 30s -keepalive=true ${server_address}" > ${log_path}/test_qps_${qps}.log
-	dstat -cmtn 5s >> ${log_path}/test_qps_${qps}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 100 -t 30s -keepalive=true -qps ${qps} ${server_address} >> ${log_path}/test_qps_${qps}.log
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 100 -qps ${qps} -t 30s -keepalive=true ${server_address}" >${log_path}/test_qps_${qps}.log
+	dstat -cmtn 5s >>${log_path}/test_qps_${qps}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c 100 -t 30s -keepalive=true -qps ${qps} ${server_address} >>${log_path}/test_qps_${qps}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 done
diff --git a/test/performance/short_test/shell/short_test.sh b/test/performance/short_test/shell/short_test.sh
index e36bb407..29a231a5 100644
--- a/test/performance/short_test/shell/short_test.sh
+++ b/test/performance/short_test/shell/short_test.sh
@@ -2,8 +2,8 @@
 
 mode=${1:-}
 namespace=default
-client_address=`kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'}`
-server_address=http://`kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}`:80
+client_address=$(kubectl get pod -n $namespace | grep fortio-client | awk {'print $1'})
+server_address=http://$(kubectl get svc -n $namespace | grep fortio-server | awk {'print $3'}):80
 
 time=$(date "+%Y%m%d%H%M%S")
 
@@ -12,9 +12,9 @@ mkdir -p ${log_path}
 
 for theadnum in 1 2 4 8 16 32 64 128; do
 	echo "run $theadnum..."
-	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=false -qps 0 ${server_address}" > ${log_path}/test_${theadnum}.log
-	dstat -cmtn 5s >> ${log_path}/test_${theadnum}.log &
-	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=false -qps 0 ${server_address} >> ${log_path}/test_${theadnum}.log
+	echo "kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=false -qps 0 ${server_address}" >${log_path}/test_${theadnum}.log
+	dstat -cmtn 5s >>${log_path}/test_${theadnum}.log &
+	kubectl exec -it ${client_address} -n $namespace -- fortio load -quiet -c ${theadnum} -t 30s -keepalive=false -qps 0 ${server_address} >>${log_path}/test_${theadnum}.log
 	sleep 10
 	ps -ef | grep dstat | grep -v grep | awk {'print $2'} | xargs kill
 done
diff --git a/test/runtest.sh b/test/runtest.sh
index 5e454503..b20d4505 100755
--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -9,62 +9,62 @@ PORT=${5-22}
 CURRENT_PATH=$(pwd)
 
 function code_compile() {
-    cd $CURRENT_PATH/../
-    ./build.sh -u
-    ./build.sh -b
-    ./build.sh -i
+	cd $CURRENT_PATH/../
+	./build.sh -u
+	./build.sh -b
+	./build.sh -i
 }
 
 function env_reset() {
-    cd $CURRENT_PATH/../
-    ./build.sh -u
+	cd $CURRENT_PATH/../
+	./build.sh -u
 }
 
 function packages_install() {
-    yum install -y make golang clang libbpf-devel llvm libboundscheck protobuf protobuf-c protobuf-c-devel bpftool rpm-build rpmdevtools
+	yum install -y make golang clang libbpf-devel llvm libboundscheck protobuf protobuf-c protobuf-c-devel bpftool rpm-build rpmdevtools
 }
 
 function runtest() {
-    cd $CURRENT_PATH
+	cd $CURRENT_PATH
 
-    rm -rf mugen-master
-    unzip testframe/mugen-master.zip > /dev/null
-    cp -rf testcases/kmesh mugen-master/testcases/smoke-test/
-    cp -rf testcases/kmesh.json mugen-master/suite2cases/
+	rm -rf mugen-master
+	unzip testframe/mugen-master.zip >/dev/null
+	cp -rf testcases/kmesh mugen-master/testcases/smoke-test/
+	cp -rf testcases/kmesh.json mugen-master/suite2cases/
 
-    cd mugen-master
-    bash dep_install.sh
-    bash mugen.sh -c --ip $IPADDR --password $PASSWD --user $USER --port $PORT
+	cd mugen-master
+	bash dep_install.sh
+	bash mugen.sh -c --ip $IPADDR --password $PASSWD --user $USER --port $PORT
 
-    if [ $TESTCASE == 'ALL' ]; then
-	    bash mugen.sh -f kmesh -x
-    else
-	    bash mugen.sh -f kmesh -r $TESTCASE -x
-    fi
+	if [ $TESTCASE == 'ALL' ]; then
+		bash mugen.sh -f kmesh -x
+	else
+		bash mugen.sh -f kmesh -r $TESTCASE -x
+	fi
 
-    if [ -d results/kmesh ]; then
-        if [ -d results/kmesh/succeed ]; then
-            ls results/kmesh/succeed/ > succeed.log
-            echo "The following test cases run success"
-            echo "--------------------------------------->"
-            cat succeed.log
-            echo "<---------------------------------------"
-        fi
+	if [ -d results/kmesh ]; then
+		if [ -d results/kmesh/succeed ]; then
+			ls results/kmesh/succeed/ >succeed.log
+			echo "The following test cases run success"
+			echo "--------------------------------------->"
+			cat succeed.log
+			echo "<---------------------------------------"
+		fi
 
-        if [ -d results/kmesh/failed ]; then
-            ls results/kmesh/failed/ > failed.log
-            echo "The following test cases run failed"
-            echo "--------------------------------------->"
-            cat failed.log
-            echo "<---------------------------------------"
-        fi
-            
-        echo "****************************************"
-        echo "NOTICE:The test cases execution log is recorded in mugen-master/logs/kmesh/"
-        echo "****************************************"
-    else
-        echo "ERROR:test cases not run!"
-    fi
+		if [ -d results/kmesh/failed ]; then
+			ls results/kmesh/failed/ >failed.log
+			echo "The following test cases run failed"
+			echo "--------------------------------------->"
+			cat failed.log
+			echo "<---------------------------------------"
+		fi
+
+		echo "****************************************"
+		echo "NOTICE:The test cases execution log is recorded in mugen-master/logs/kmesh/"
+		echo "****************************************"
+	else
+		echo "ERROR:test cases not run!"
+	fi
 }
 
 packages_install
diff --git a/test/testcases/kmesh/libs/common.sh b/test/testcases/kmesh/libs/common.sh
index cccaa87d..8dbe31d8 100644
--- a/test/testcases/kmesh/libs/common.sh
+++ b/test/testcases/kmesh/libs/common.sh
@@ -2,92 +2,84 @@
 source ${OET_PATH}/libs/locallibs/common_lib.sh
 
 # environment preparation
-function env_init()
-{
-    mkdir /mnt/kmesh_cgroup2
-    mount -t cgroup2 none /mnt/kmesh_cgroup2/
+function env_init() {
+	mkdir /mnt/kmesh_cgroup2
+	mount -t cgroup2 none /mnt/kmesh_cgroup2/
 
-    cd $CURRENT_PATH
-    cd ../pkg
-    yum localinstall -y fortio-*$(arch).rpm
-    cd $CURRENT_PATH
+	cd $CURRENT_PATH
+	cd ../pkg
+	yum localinstall -y fortio-*$(arch).rpm
+	cd $CURRENT_PATH
 
-    cd /sys/fs/cgroup/net_cls && mkdir -p kmesh_test && cd kmesh_test
-    echo 0x1000 >> net_cls.classid
-    echo $$ >> tasks
-    cd $CURRENT_PATH
+	cd /sys/fs/cgroup/net_cls && mkdir -p kmesh_test && cd kmesh_test
+	echo 0x1000 >>net_cls.classid
+	echo $$ >>tasks
+	cd $CURRENT_PATH
 
-    insmod /lib/modules/kmesh/kmesh.ko
-    lsmod | grep kmesh
-    if [ $? -ne 0 ]; then
-        echo "insmod kmesh.ko failed"
-    fi
+	insmod /lib/modules/kmesh/kmesh.ko
+	lsmod | grep kmesh
+	if [ $? -ne 0 ]; then
+		echo "insmod kmesh.ko failed"
+	fi
 }
 
 # start fortio server
 # default localhost:8080
-# if you want to change ip or port, must input all, follows ip:port 
+# if you want to change ip or port, must input all, follows ip:port
 # cmd is same as the fortio server function
-function start_fortio_server()
-{
-    fortio server $@ > tmp_fortio_server.log 2>&1 &
-    sleep 0.2
-    echo "$@" > tmp_fortio_cmd.log
-    ip_port=$(egrep -o "[0-9]+.[0-9]+.[0-9]+.[0-9]+:[0-9]+" tmp_fortio_cmd.log) || ip_port="127.0.0.1:8080"
-    grep "http://${ip_port}/fortio/" tmp_fortio_server.log
-    CHECK_RESULT $? 0 0 "fortio server start failed"
+function start_fortio_server() {
+	fortio server $@ >tmp_fortio_server.log 2>&1 &
+	sleep 0.2
+	echo "$@" >tmp_fortio_cmd.log
+	ip_port=$(egrep -o "[0-9]+.[0-9]+.[0-9]+.[0-9]+:[0-9]+" tmp_fortio_cmd.log) || ip_port="127.0.0.1:8080"
+	grep "http://${ip_port}/fortio/" tmp_fortio_server.log
+	CHECK_RESULT $? 0 0 "fortio server start failed"
 }
 
 # start kmesh-daemon
-function start_kmesh()
-{
-    kmesh-daemon --enable-kmesh --enable-ads=false --cni-etc-path $(dirname $CURRENT_PATH)/libs > tmp_kmesh_daemon.log &
-    sleep 3
-    
-    grep "command StartServer successful" tmp_kmesh_daemon.log
-    CHECK_RESULT $? 0 0 "kmesh-daemon start failed"
+function start_kmesh() {
+	kmesh-daemon --enable-kmesh --enable-ads=false --cni-etc-path $(dirname $CURRENT_PATH)/libs >tmp_kmesh_daemon.log &
+	sleep 3
+
+	grep "command StartServer successful" tmp_kmesh_daemon.log
+	CHECK_RESULT $? 0 0 "kmesh-daemon start failed"
 }
 
 # load kmesh config and check
-function load_kmesh_config()
-{
-    kmesh-cmd -config-file=$CURRENT_PATH/conf/test_conf.json > tmp_kmesh_cmd.log &
-    CHECK_RESULT $? 0 0 "kmesh-cmd start failed"
-    sleep 2
+function load_kmesh_config() {
+	kmesh-cmd -config-file=$CURRENT_PATH/conf/test_conf.json >tmp_kmesh_cmd.log &
+	CHECK_RESULT $? 0 0 "kmesh-cmd start failed"
+	sleep 2
 
-    curl http://127.0.0.1:15200/bpf/kmesh/maps --connect-timeout 5 > tmp_kmesh_conf_read.log
-    grep "stenerConfigs\|routeConfigs\|clusterConfigs" tmp_kmesh_conf_read.log
-    CHECK_RESULT $? 0 0 "check kmesh conf failed"
+	curl http://127.0.0.1:15200/bpf/kmesh/maps --connect-timeout 5 >tmp_kmesh_conf_read.log
+	grep "stenerConfigs\|routeConfigs\|clusterConfigs" tmp_kmesh_conf_read.log
+	CHECK_RESULT $? 0 0 "check kmesh conf failed"
 }
 
 # use bpftool trace test result
-function curl_test()
-{
-    bpftool prog tracelog > tmp_bpftool_prog_trace.log &
-    
-    curl -g http://127.0.0.1:23333/fortio/ --connect-timeout 5 > /dev/null
-    CHECK_RESULT $? 0 0 "curl fortio server failed"
-    pkill bpftool
-    
-    err_num=`grep " ERR: " tmp_bpftool_prog_trace.log | wc -l`
-    CHECK_RESULT $err_num 0 0 "check kmesh-daemon log failed"
+function curl_test() {
+	bpftool prog tracelog >tmp_bpftool_prog_trace.log &
+
+	curl -g http://127.0.0.1:23333/fortio/ --connect-timeout 5 >/dev/null
+	CHECK_RESULT $? 0 0 "curl fortio server failed"
+	pkill bpftool
+
+	err_num=$(grep " ERR: " tmp_bpftool_prog_trace.log | wc -l)
+	CHECK_RESULT $err_num 0 0 "check kmesh-daemon log failed"
 
-# check fortio server log
-    grep "GET /fortio/" tmp_fortio_server.log
-    CHECK_RESULT $? 0 0 "check fortio server log failed"
+	# check fortio server log
+	grep "GET /fortio/" tmp_fortio_server.log
+	CHECK_RESULT $? 0 0 "check fortio server log failed"
 }
 
 # environment cleanup
 # end the fortio and kmesh-daemon process
 # remove fortio
-function cleanup()
-{
-    rm -rf tmp*.log
-    cgdelete net_cls:/kmesh_test
-    pkill fortio
-    pkill kmesh-daemon
-    rmmod kmesh
-    yum remove -y fortio
+function cleanup() {
+	rm -rf tmp*.log
+	cgdelete net_cls:/kmesh_test
+	pkill fortio
+	pkill kmesh-daemon
+	rmmod kmesh
+	yum remove -y fortio
 }
-
-
diff --git a/test/testcases/kmesh/oe_test_base_function/oe_test_base_function.sh b/test/testcases/kmesh/oe_test_base_function/oe_test_base_function.sh
index a0f0d2e6..3b9f6d4f 100644
--- a/test/testcases/kmesh/oe_test_base_function/oe_test_base_function.sh
+++ b/test/testcases/kmesh/oe_test_base_function/oe_test_base_function.sh
@@ -6,39 +6,39 @@ source ../libs/common.sh
 CURRENT_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
+	LOG_INFO "Start environmental preparation."
 
-    env_init
+	env_init
 
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
+	LOG_INFO "Start testing..."
 
-    set -e
+	set -e
 
-    #start fortio server
-    start_fortio_server -http-port 127.0.0.1:11466
+	#start fortio server
+	start_fortio_server -http-port 127.0.0.1:11466
 
-    #start kmesh-daemon
-    start_kmesh
+	#start kmesh-daemon
+	start_kmesh
 
-    #use kmesh-cmd load conf and check conf load ok
-    load_kmesh_config
+	#use kmesh-cmd load conf and check conf load ok
+	load_kmesh_config
 
-    #use bpftool trace test result
-    curl_test
+	#use bpftool trace test result
+	curl_test
 
-    LOG_INFO "Finish test!"
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "start environment cleanup."
+	LOG_INFO "start environment cleanup."
 
-    cleanup
+	cleanup
 
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "$@"
diff --git a/test/testcases/kmesh/oe_test_dark_launch_function/oe_test_dark_launch_function.sh b/test/testcases/kmesh/oe_test_dark_launch_function/oe_test_dark_launch_function.sh
index 4f18d001..3c9cb14f 100644
--- a/test/testcases/kmesh/oe_test_dark_launch_function/oe_test_dark_launch_function.sh
+++ b/test/testcases/kmesh/oe_test_dark_launch_function/oe_test_dark_launch_function.sh
@@ -6,57 +6,54 @@ source ../libs/common.sh
 CURRENT_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
+	LOG_INFO "Start environmental preparation."
 
-    env_init
+	env_init
 
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
-
-    # exits the shell when $? is not 0
-    set -e
-
-    # start fortio server 11466 
-    # start fortio server 11488
-    start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
-    start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
-
-    # start kmesh-daemon
-    start_kmesh
-
-    # use kmesh-cmd load conf and check conf load ok
-    load_kmesh_config
-    
-    # curl 100 times, Server: 1 and Server: 2 should be 8:2
-    # the traffic is not completely regular,Server: 1 belong 70%-90% and Server: 2 belong 10%-30%
-    for ((i=0;i<100;i++))
-    do
-        curl -v http://127.0.0.1:23333 >> tmp_trace.log 2>&1
-    done
-    
-    a=`grep -c 'Server: 1' tmp_trace.log`
-    b=`grep -c 'Server: 2' tmp_trace.log`
-    if [ $a -gt 70 ]&&[ $a -lt 90 ]&&[ $b -lt 30 ]&&[ $b -gt 10 ];then
-	result=0
-    else
-	result=1
-    fi
-    CHECK_RESULT $result 0 0 "bad dark launch"
-
-    LOG_INFO "Finish test!"
+	LOG_INFO "Start testing..."
+
+	# exits the shell when $? is not 0
+	set -e
+
+	# start fortio server 11466
+	# start fortio server 11488
+	start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
+	start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
+
+	# start kmesh-daemon
+	start_kmesh
+
+	# use kmesh-cmd load conf and check conf load ok
+	load_kmesh_config
+
+	# curl 100 times, Server: 1 and Server: 2 should be 8:2
+	# the traffic is not completely regular,Server: 1 belong 70%-90% and Server: 2 belong 10%-30%
+	for ((i = 0; i < 100; i++)); do
+		curl -v http://127.0.0.1:23333 >>tmp_trace.log 2>&1
+	done
+
+	a=$(grep -c 'Server: 1' tmp_trace.log)
+	b=$(grep -c 'Server: 2' tmp_trace.log)
+	if [ $a -gt 70 ] && [ $a -lt 90 ] && [ $b -lt 30 ] && [ $b -gt 10 ]; then
+		result=0
+	else
+		result=1
+	fi
+	CHECK_RESULT $result 0 0 "bad dark launch"
+
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "start environment cleanup."
+	LOG_INFO "start environment cleanup."
 
-    cleanup
+	cleanup
 
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "$@"
-
-
diff --git a/test/testcases/kmesh/oe_test_lb_policy_function/oe_test_lb_policy_function.sh b/test/testcases/kmesh/oe_test_lb_policy_function/oe_test_lb_policy_function.sh
index 6e21ad01..0b448f80 100644
--- a/test/testcases/kmesh/oe_test_lb_policy_function/oe_test_lb_policy_function.sh
+++ b/test/testcases/kmesh/oe_test_lb_policy_function/oe_test_lb_policy_function.sh
@@ -6,47 +6,46 @@ source ../libs/common.sh
 CURRENT_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
+	LOG_INFO "Start environmental preparation."
 
-    env_init
+	env_init
 
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
-
-    # exits the shell when $? is not 0
-    set -e
-
-    # start fortio server 11466 
-    # start fortio server 11488
-    start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
-    start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
-
-    # start kmesh-daemon
-    start_kmesh
-
-    # use kmesh-cmd load conf and check conf load ok
-    load_kmesh_config
-    
-    # load balancing test
-    # round robin
-    curl -v http://127.0.0.1:23333 > tmp_trace.log 2>&1
-    curl -v http://127.0.0.1:23333 >> tmp_trace.log 2>&1
-    grep 'Server: 1' tmp_trace.log && grep 'Server: 2' tmp_trace.log
-    CHECK_RESULT $? 0 0 "bad balancing" 
-
-    LOG_INFO "Finish test!"
+	LOG_INFO "Start testing..."
+
+	# exits the shell when $? is not 0
+	set -e
+
+	# start fortio server 11466
+	# start fortio server 11488
+	start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
+	start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
+
+	# start kmesh-daemon
+	start_kmesh
+
+	# use kmesh-cmd load conf and check conf load ok
+	load_kmesh_config
+
+	# load balancing test
+	# round robin
+	curl -v http://127.0.0.1:23333 >tmp_trace.log 2>&1
+	curl -v http://127.0.0.1:23333 >>tmp_trace.log 2>&1
+	grep 'Server: 1' tmp_trace.log && grep 'Server: 2' tmp_trace.log
+	CHECK_RESULT $? 0 0 "bad balancing"
+
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "start environment cleanup."
+	LOG_INFO "start environment cleanup."
 
-    cleanup
+	cleanup
 
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "$@"
-
diff --git a/test/testcases/kmesh/oe_test_route_function/oe_test_route_function.sh b/test/testcases/kmesh/oe_test_route_function/oe_test_route_function.sh
index b5a2a85e..fc7c680f 100644
--- a/test/testcases/kmesh/oe_test_route_function/oe_test_route_function.sh
+++ b/test/testcases/kmesh/oe_test_route_function/oe_test_route_function.sh
@@ -6,52 +6,49 @@ source ../libs/common.sh
 CURRENT_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
+	LOG_INFO "Start environmental preparation."
 
-    env_init
+	env_init
 
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
-
-    # exits the shell when $? is not 0
-    set -e
-
-    # start fortio server 11466 
-    # start fortio server 11488
-    start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
-    start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
-
-    # start kmesh-daemon
-    start_kmesh
-
-    # use kmesh-cmd load conf and check conf load ok
-    load_kmesh_config
-    
-    # curl header is end-user:jason route to 11466
-    # else route to 11488    
-    for ((i=0;i<10;i++))
-    do
-	    curl --header "end-user:jason" -v http://127.0.0.1:23333 >> tmp_trace1.log 2>&1
-	    curl -v http://127.0.0.1:23333 >> tmp_trace2.log 2>&1
-    done
-
-    grep 'Server: 1' tmp_trace1.log && grep 'Server: 2' tmp_trace2.log&&grep 'Server: 2' tmp_trace1.log || grep 'Server: 1' tmp_trace2.log || echo 'OK'
-    CHECK_RESULT $_ OK 0 "bad route"
-
-    LOG_INFO "Finish test!"
+	LOG_INFO "Start testing..."
+
+	# exits the shell when $? is not 0
+	set -e
+
+	# start fortio server 11466
+	# start fortio server 11488
+	start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
+	start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
+
+	# start kmesh-daemon
+	start_kmesh
+
+	# use kmesh-cmd load conf and check conf load ok
+	load_kmesh_config
+
+	# curl header is end-user:jason route to 11466
+	# else route to 11488
+	for ((i = 0; i < 10; i++)); do
+		curl --header "end-user:jason" -v http://127.0.0.1:23333 >>tmp_trace1.log 2>&1
+		curl -v http://127.0.0.1:23333 >>tmp_trace2.log 2>&1
+	done
+
+	grep 'Server: 1' tmp_trace1.log && grep 'Server: 2' tmp_trace2.log && grep 'Server: 2' tmp_trace1.log || grep 'Server: 1' tmp_trace2.log || echo 'OK'
+	CHECK_RESULT $_ OK 0 "bad route"
+
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "start environment cleanup."
+	LOG_INFO "start environment cleanup."
 
-    cleanup
+	cleanup
 
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "$@"
-
-
diff --git a/test/testcases/kmesh/oe_test_service_function/oe_test_service_function.sh b/test/testcases/kmesh/oe_test_service_function/oe_test_service_function.sh
index 041b34ce..e6d793ff 100644
--- a/test/testcases/kmesh/oe_test_service_function/oe_test_service_function.sh
+++ b/test/testcases/kmesh/oe_test_service_function/oe_test_service_function.sh
@@ -8,68 +8,68 @@ cd ../../../../../../
 KMESH_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
-
-    # modify Environment Variables HOME 
-    # mkdir rpmbuild
-    cd $CURRENT_PATH/
-
-    rm -rf rpmbuild
-    mkdir rpmbuild
-    cd rpmbuild
-    mkdir BUILD SOURCES BUILDROOT RPMS SPECS SRPMS   
-
-    # rpmbuild files prepare
-    cd $KMESH_PATH/
-    KMESH_VERSION=$(grep Version: kmesh.spec | egrep -o [0-9]+.[0-9]+.[0-9]+)
-    cp -r $KMESH_PATH ../kmesh_tmp
-    mv ../kmesh_tmp $CURRENT_PATH/kmesh-$KMESH_VERSION
-    cp kmesh.spec $CURRENT_PATH/rpmbuild/SPECS/
-
-    cd $CURRENT_PATH
-    (cd kmesh-$KMESH_VERSION/ && ./build.sh -c)
-    tar zcvf kmesh-$KMESH_VERSION.tar.gz kmesh-$KMESH_VERSION/
-    rm -rf kmesh-$KMESH_VERSION/
-    mv kmesh-$KMESH_VERSION.tar.gz rpmbuild/SOURCES/
-
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "Start environmental preparation."
+
+	# modify Environment Variables HOME
+	# mkdir rpmbuild
+	cd $CURRENT_PATH/
+
+	rm -rf rpmbuild
+	mkdir rpmbuild
+	cd rpmbuild
+	mkdir BUILD SOURCES BUILDROOT RPMS SPECS SRPMS
+
+	# rpmbuild files prepare
+	cd $KMESH_PATH/
+	KMESH_VERSION=$(grep Version: kmesh.spec | egrep -o [0-9]+.[0-9]+.[0-9]+)
+	cp -r $KMESH_PATH ../kmesh_tmp
+	mv ../kmesh_tmp $CURRENT_PATH/kmesh-$KMESH_VERSION
+	cp kmesh.spec $CURRENT_PATH/rpmbuild/SPECS/
+
+	cd $CURRENT_PATH
+	(cd kmesh-$KMESH_VERSION/ && ./build.sh -c)
+	tar zcvf kmesh-$KMESH_VERSION.tar.gz kmesh-$KMESH_VERSION/
+	rm -rf kmesh-$KMESH_VERSION/
+	mv kmesh-$KMESH_VERSION.tar.gz rpmbuild/SOURCES/
+
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
-    
-    set -e
-    # rpm build and install
-    cd $CURRENT_PATH/rpmbuild/SPECS/
-    rpmbuild --define="_topdir $CURRENT_PATH/rpmbuild/" -bb kmesh.spec
-    cd $CURRENT_PATH/rpmbuild/RPMS/$(arch)/
-    rpm -ivh --force kmesh-$KMESH_VERSION-1.$(arch).rpm
-    rpm -ql kmesh > tmp_rpm_install.log
-    grep kmesh tmp_rpm_install.log
-    CHECK_RESULT $? 0 0 "rpmb install error"
-    
-    # service start and stop
-    systemctl start kmesh.service
-    systemctl status kmesh.service > tmp_service.log
-    grep 'active (running)' tmp_service.log
-    CHECK_RESULT $? 0 0 "start kmesh service error"
-    systemctl stop kmesh.service
-
-    LOG_INFO "Finish test!"
+	LOG_INFO "Start testing..."
+
+	set -e
+	# rpm build and install
+	cd $CURRENT_PATH/rpmbuild/SPECS/
+	rpmbuild --define="_topdir $CURRENT_PATH/rpmbuild/" -bb kmesh.spec
+	cd $CURRENT_PATH/rpmbuild/RPMS/$(arch)/
+	rpm -ivh --force kmesh-$KMESH_VERSION-1.$(arch).rpm
+	rpm -ql kmesh >tmp_rpm_install.log
+	grep kmesh tmp_rpm_install.log
+	CHECK_RESULT $? 0 0 "rpmb install error"
+
+	# service start and stop
+	systemctl start kmesh.service
+	systemctl status kmesh.service >tmp_service.log
+	grep 'active (running)' tmp_service.log
+	CHECK_RESULT $? 0 0 "start kmesh service error"
+	systemctl stop kmesh.service
+
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "Start environment cleanup."
-    
-    cd $CURRENT_PATH/
-    rpm -evh kmesh
-    rm -rf rpmbuild
- 
-    # restore environment
-    cd $KMESH_PATH
-    ./build.sh -i 
-
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Start environment cleanup."
+
+	cd $CURRENT_PATH/
+	rpm -evh kmesh
+	rm -rf rpmbuild
+
+	# restore environment
+	cd $KMESH_PATH
+	./build.sh -i
+
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "@"
diff --git a/test/testcases/kmesh/oe_test_tcp_proxy_weight_cluster_function/oe_test_tcp_proxy_weight_cluster_function.sh b/test/testcases/kmesh/oe_test_tcp_proxy_weight_cluster_function/oe_test_tcp_proxy_weight_cluster_function.sh
index 528ed9da..4d035775 100644
--- a/test/testcases/kmesh/oe_test_tcp_proxy_weight_cluster_function/oe_test_tcp_proxy_weight_cluster_function.sh
+++ b/test/testcases/kmesh/oe_test_tcp_proxy_weight_cluster_function/oe_test_tcp_proxy_weight_cluster_function.sh
@@ -6,57 +6,54 @@ source ../libs/common.sh
 CURRENT_PATH=$(pwd)
 
 function pre_test() {
-    LOG_INFO "Start environmental preparation."
+	LOG_INFO "Start environmental preparation."
 
-    env_init
+	env_init
 
-    LOG_INFO "End of environmental preparation!"
+	LOG_INFO "End of environmental preparation!"
 }
 
 function run_test() {
-    LOG_INFO "Start testing..."
-
-    # exits the shell when $? is not 0
-    set -e
-
-    # start fortio server 11466 
-    # start fortio server 11488
-    start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
-    start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
-
-    # start kmesh-daemon
-    start_kmesh
-
-    # use kmesh-cmd load conf and check conf load ok
-    load_kmesh_config
-    
-    # curl 100 times, Server: 1 and Server: 2 should be 8:2
-    # the traffic is not completely regular,Server: 1 belong 70%-90% and Server: 2 belong 10%-30%
-    for ((i=0;i<100;i++))
-    do
-        curl -v http://127.0.0.1:23333 >> tmp_trace.log 2>&1
-    done
-    
-    a=`grep -c 'Server: 1' tmp_trace.log`
-    b=`grep -c 'Server: 2' tmp_trace.log`
-    if [ $a -gt 70 ]&&[ $a -lt 90 ]&&[ $b -lt 30 ]&&[ $b -gt 10 ];then
-	result=0
-    else
-	result=1
-    fi
-    CHECK_RESULT $result 0 0 "bad tcp weighted cluster select"
-
-    LOG_INFO "Finish test!"
+	LOG_INFO "Start testing..."
+
+	# exits the shell when $? is not 0
+	set -e
+
+	# start fortio server 11466
+	# start fortio server 11488
+	start_fortio_server -http-port 127.0.0.1:11466 -echo-server-default-params="header=server:1"
+	start_fortio_server -http-port 127.0.0.1:11488 -echo-server-default-params="header=server:2"
+
+	# start kmesh-daemon
+	start_kmesh
+
+	# use kmesh-cmd load conf and check conf load ok
+	load_kmesh_config
+
+	# curl 100 times, Server: 1 and Server: 2 should be 8:2
+	# the traffic is not completely regular,Server: 1 belong 70%-90% and Server: 2 belong 10%-30%
+	for ((i = 0; i < 100; i++)); do
+		curl -v http://127.0.0.1:23333 >>tmp_trace.log 2>&1
+	done
+
+	a=$(grep -c 'Server: 1' tmp_trace.log)
+	b=$(grep -c 'Server: 2' tmp_trace.log)
+	if [ $a -gt 70 ] && [ $a -lt 90 ] && [ $b -lt 30 ] && [ $b -gt 10 ]; then
+		result=0
+	else
+		result=1
+	fi
+	CHECK_RESULT $result 0 0 "bad tcp weighted cluster select"
+
+	LOG_INFO "Finish test!"
 }
 
 function post_test() {
-    LOG_INFO "start environment cleanup."
+	LOG_INFO "start environment cleanup."
 
-    cleanup
+	cleanup
 
-    LOG_INFO "Finish environment cleanup!"
+	LOG_INFO "Finish environment cleanup!"
 }
 
 main "$@"
-
-
diff --git a/test/unittest/workload/run_tests.sh b/test/unittest/workload/run_tests.sh
index 2cac52b5..62de9d6c 100644
--- a/test/unittest/workload/run_tests.sh
+++ b/test/unittest/workload/run_tests.sh
@@ -5,8 +5,8 @@ set -e
 
 # Ensure running as root
 if [ "$EUID" -ne 0 ]; then
-    echo "Please run as root"
-    exit 1
+	echo "Please run as root"
+	exit 1
 fi
 
 # Set memory limits
@@ -35,11 +35,11 @@ make
 # 1. Load and instrument BPF program
 echo "Loading and instrumenting BPF program..."
 coverbee load \
-    --elf=${ELF_FILE} \
-    --prog-pin-dir=${PROG_PIN_DIR} \
-    --map-pin-dir=${MAP_PIN_DIR} \
-    --block-list=${BLOCK_LIST} \
-    --log=/tmp/coverage/coverbee.log
+	--elf=${ELF_FILE} \
+	--prog-pin-dir=${PROG_PIN_DIR} \
+	--map-pin-dir=${MAP_PIN_DIR} \
+	--block-list=${BLOCK_LIST} \
+	--log=/tmp/coverage/coverbee.log
 
 # 2. Run tests
 echo "Running tests..."
@@ -48,14 +48,14 @@ echo "Running tests..."
 # 3. Collect coverage data
 echo "Collecting coverage data..."
 coverbee cover \
-    --map-pin-dir=${MAP_PIN_DIR} \
-    --block-list=${BLOCK_LIST} \
-    --output=${COVERAGE_OUTPUT} \
-    --format=html
+	--map-pin-dir=${MAP_PIN_DIR} \
+	--block-list=${BLOCK_LIST} \
+	--output=${COVERAGE_OUTPUT} \
+	--format=html
 
 # 4. Cleanup
 echo "Cleaning up..."
 rm -rf ${PROG_PIN_DIR}/*
 rm -rf ${MAP_PIN_DIR}/*
 
-echo "Coverage report generated at: ${COVERAGE_OUTPUT}"
\ No newline at end of file
+echo "Coverage report generated at: ${COVERAGE_OUTPUT}"