Repository: kmesh-net/kmesh
Pull request #743 (2024-08-16 08:25:07)

passthrough go test flag
**What type of PR is this?**

/kind enhancement


**What this PR does / why we need it**:

The E2E test will eventually call the `go test` command, which has a variety of flags for adjusting the test.

Obviously, it's very tedious to encapsulate each flag. Therefore we adopt the direct passthrough unknown flags to make full use of existing capabilities of `go test`.

Although it's not very robust, I think it's ok for running test cases.

For example, now we could directly run the follow command:

```bash
./test/e2e/run_test.sh --only-run-tests -run "TestKmeshRestart"  -count 10 -timeout 30m
``` 

**Which issue(s) this PR fixes**:
Fixes #

**Special notes for your reviewer**:

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required.
-->
```release-note

```



Patch:
diff --git a/Makefile b/Makefile
index 495a7c5d..398ca6f8 100644
--- a/Makefile
+++ b/Makefile
@@ -68,7 +68,8 @@ TMP_FILES := bpf/kmesh/bpf2go/bpf2go.go \
 	bpf/include/bpf_helper_defs_ext.h \
 	depends/include/bpf_helper_defs_ext.h
 
-.PHONY: all
+.PHONY: all install uninstall clean build docker
+
 all:
 	$(QUIET) find $(ROOT_DIR)/mk -name "*.pc" | xargs sed -i "s#^prefix=.*#prefix=${ROOT_DIR}#g"
 
@@ -108,7 +109,6 @@ gen: tidy\
 gen-check: gen
 	hack/gen-check.sh
 
-.PHONY: install
 install:
 	$(QUIET) make install -C api/v2-c
 	$(QUIET) make install -C bpf/deserialization_to_bpf_map
@@ -125,7 +125,6 @@ install:
 	$(call printlog, INSTALL, $(INSTALL_BIN)/$(APPS3))
 	$(QUIET) install -Dp -m 0500 $(APPS3) $(INSTALL_BIN)
 
-.PHONY: uninstall
 uninstall:
 	$(QUIET) make uninstall -C api/v2-c
 	$(QUIET) make uninstall -C bpf/deserialization_to_bpf_map
@@ -141,23 +140,19 @@ uninstall:
 .PHONY: build
 build:
 	./kmesh_compile.sh
-
-.PHONY: docker
+	
 docker:
 	docker build -f build/docker/dockerfile -t $(HUB)/$(TARGET):$(TAG) .
 
 docker.push: docker
 	docker push $(HUB)/$(TARGET):$(TAG)
 
-.PHONY: e2e
 e2e:
 	./test/e2e/run_test.sh
 
-.PHONY: e2e-ipv6
 e2e-ipv6:
 	./test/e2e/run_test.sh --ipv6
 
-.PHONY: format
 format:
 	./hack/format.sh
 
@@ -170,7 +165,6 @@ test:
 	./hack/run-ut.sh --local
 endif
 
-.PHONY: clean
 clean:
 	$(QUIET) rm -rf ./out
 	$(QUIET) rm -rf ./config/linux-bpf.h
diff --git a/daemon/manager/manager.go b/daemon/manager/manager.go
index 884697f9..0c99e580 100644
--- a/daemon/manager/manager.go
+++ b/daemon/manager/manager.go
@@ -23,7 +23,6 @@ import (
 	"os/signal"
 	"syscall"
 
-	"github.com/cilium/ebpf/rlimit"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 
@@ -74,13 +73,8 @@ func NewCommand() *cobra.Command {
 
 // Execute start daemon manager process
 func Execute(configs *options.BootstrapConfigs) error {
-	err := rlimit.RemoveMemlock()
-	if err != nil {
-		log.Warn("rlimit.RemoveMemlock failed")
-	}
-
 	bpfLoader := bpf.NewBpfLoader(configs.BpfConfig)
-	if err = bpfLoader.Start(configs.BpfConfig); err != nil {
+	if err := bpfLoader.Start(configs.BpfConfig); err != nil {
 		return err
 	}
 	log.Info("bpf Start successful")
diff --git a/pkg/bpf/bpf.go b/pkg/bpf/bpf.go
index fd064d15..3e585156 100644
--- a/pkg/bpf/bpf.go
+++ b/pkg/bpf/bpf.go
@@ -30,6 +30,7 @@ import (
 	"syscall"
 
 	"github.com/cilium/ebpf"
+	"github.com/cilium/ebpf/rlimit"
 
 	"kmesh.net/kmesh/daemon/options"
 	"kmesh.net/kmesh/pkg/constants"
@@ -115,6 +116,10 @@ func StartMda() error {
 func (l *BpfLoader) Start(config *options.BpfConfig) error {
 	var err error
 
+	if err = rlimit.RemoveMemlock(); err != nil {
+		return err
+	}
+
 	if l.VersionMap == nil {
 		return fmt.Errorf("NewVersionMap failed")
 	}
diff --git a/pkg/controller/bypass/bypass_controller.go b/pkg/controller/bypass/bypass_controller.go
index 4679b1af..cfea1602 100644
--- a/pkg/controller/bypass/bypass_controller.go
+++ b/pkg/controller/bypass/bypass_controller.go
@@ -18,16 +18,17 @@ package bypass
 
 import (
 	"fmt"
+	"os"
 	"time"
 
 	netns "github.com/containernetworking/plugins/pkg/ns"
 	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/tools/cache"
 
 	ns "kmesh.net/kmesh/pkg/controller/netns"
-	"kmesh.net/kmesh/pkg/kube"
 	"kmesh.net/kmesh/pkg/logger"
 	"kmesh.net/kmesh/pkg/utils"
 	"kmesh.net/kmesh/pkg/utils/istio"
@@ -49,7 +50,11 @@ type Controller struct {
 }
 
 func NewByPassController(client kubernetes.Interface) *Controller {
-	informerFactory := kube.NewInformerFactory(client)
+	nodeName := os.Getenv("NODE_NAME")
+	informerFactory := informers.NewSharedInformerFactoryWithOptions(client, DefaultInformerSyncPeriod,
+		informers.WithTweakListOptions(func(options *metav1.ListOptions) {
+			options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeName)
+		}))
 
 	podInformer := informerFactory.Core().V1().Pods().Informer()
 	_, _ = podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
@@ -139,6 +144,7 @@ func isPodBeingDeleted(pod *corev1.Pod) bool {
 	return pod.ObjectMeta.DeletionTimestamp != nil
 }
 
+// TODO: make it a idempotent operation
 func addIptables(ns string) error {
 	iptArgs := [][]string{
 		{"-t", "nat", "-I", "PREROUTING", "1", "-j", "RETURN"},
@@ -147,14 +153,6 @@ func addIptables(ns string) error {
 
 	execFunc := func(netns.NetNS) error {
 		log.Infof("Running add iptables rule in namespace:%s", ns)
-		//To avoid iptables rules being added multiple times due to problems with k8s resource synchronization
-		delIptArgs := [][]string{
-			{"-t", "nat", "-D", "PREROUTING", "-j", "RETURN"},
-			{"-t", "nat", "-D", "OUTPUT", "-j", "RETURN"},
-		}
-		for _, delargs := range delIptArgs {
-			_ = utils.Execute("iptables", delargs)
-		}
 		for _, args := range iptArgs {
 			if err := utils.Execute("iptables", args); err != nil {
 				return fmt.Errorf("failed to exec command: iptables %v\", err: %v", args, err)
@@ -168,6 +166,7 @@ func addIptables(ns string) error {
 	return nil
 }
 
+// TODO: make it a idempotent operation
 func deleteIptables(ns string) error {
 	iptArgs := [][]string{
 		{"-t", "nat", "-D", "PREROUTING", "-j", "RETURN"},
diff --git a/pkg/controller/manage/manage_controller.go b/pkg/controller/manage/manage_controller.go
index ea602e3c..72b90f97 100644
--- a/pkg/controller/manage/manage_controller.go
+++ b/pkg/controller/manage/manage_controller.go
@@ -19,6 +19,7 @@ package kmeshmanage
 import (
 	"fmt"
 	"net"
+	"os"
 
 	"github.com/cilium/ebpf/link"
 	netns "github.com/containernetworking/plugins/pkg/ns"
@@ -26,6 +27,7 @@ import (
 	"istio.io/istio/pkg/spiffe"
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/kubernetes"
@@ -36,7 +38,6 @@ import (
 	"kmesh.net/kmesh/pkg/constants"
 	ns "kmesh.net/kmesh/pkg/controller/netns"
 	kmeshsecurity "kmesh.net/kmesh/pkg/controller/security"
-	"kmesh.net/kmesh/pkg/kube"
 	"kmesh.net/kmesh/pkg/logger"
 	"kmesh.net/kmesh/pkg/utils"
 )
@@ -77,7 +78,12 @@ func isPodReady(pod *corev1.Pod) bool {
 }
 
 func NewKmeshManageController(client kubernetes.Interface, security *kmeshsecurity.SecretManager, xdpProgFd int, mode string) (*KmeshManageController, error) {
-	informerFactory := kube.NewInformerFactory(client)
+	nodeName := os.Getenv("NODE_NAME")
+
+	informerFactory := informers.NewSharedInformerFactoryWithOptions(client, 0,
+		informers.WithTweakListOptions(func(options *metav1.ListOptions) {
+			options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeName)
+		}))
 	podInformer := informerFactory.Core().V1().Pods().Informer()
 	podLister := informerFactory.Core().V1().Pods().Lister()
 
diff --git a/pkg/controller/workload/bpfcache/fake_map.go b/pkg/controller/workload/bpfcache/fake_map.go
index 28f19690..d17a45c3 100644
--- a/pkg/controller/workload/bpfcache/fake_map.go
+++ b/pkg/controller/workload/bpfcache/fake_map.go
@@ -21,13 +21,11 @@ import (
 	"unsafe"
 
 	"github.com/cilium/ebpf"
-	"github.com/cilium/ebpf/rlimit"
 
 	"kmesh.net/kmesh/bpf/kmesh/bpf2go"
 )
 
 func NewFakeWorkloadMap(t *testing.T) bpf2go.KmeshCgroupSockWorkloadMaps {
-	_ = rlimit.RemoveMemlock()
 	backEndMap, err := ebpf.NewMap(&ebpf.MapSpec{
 		Name:       "kmesh_backend",
 		Type:       ebpf.Hash,
diff --git a/pkg/controller/workload/cache/workload_cache.go b/pkg/controller/workload/cache/workload_cache.go
index d3180f40..4763b1b3 100644
--- a/pkg/controller/workload/cache/workload_cache.go
+++ b/pkg/controller/workload/cache/workload_cache.go
@@ -28,12 +28,9 @@ import (
 type WorkloadCache interface {
 	GetWorkloadByUid(uid string) *workloadapi.Workload
 	GetWorkloadByAddr(networkAddress NetworkAddress) *workloadapi.Workload
-	AddOrUpdateWorkload(workload *workloadapi.Workload) (deletedServices []string, newServices []string)
+	AddWorkload(workload *workloadapi.Workload)
 	DeleteWorkload(uid string)
 	List() []*workloadapi.Workload
-	GetRelationShip(workloadId uint32, serviceId uint32) (uint32, bool)
-	UpdateRelationShip(workloadId uint32, serviceId uint32, relationId uint32)
-	DeleteRelationShip(serviceId uint32, relationId uint32)
 }
 
 type NetworkAddress struct {
@@ -41,76 +38,16 @@ type NetworkAddress struct {
 	Address netip.Addr
 }
 
-type ServiceRelationShipByWorkload struct {
-	workloadId uint32
-	serviceId  uint32
-}
-
-type ServiceRelationShipById struct {
-	serviceId  uint32
-	relationId uint32
-}
-
 type cache struct {
-	byUid                  map[string]*workloadapi.Workload
-	byAddr                 map[NetworkAddress]*workloadapi.Workload
-	relationShipByWorkload map[ServiceRelationShipByWorkload]uint32
-	relationShipById       map[ServiceRelationShipById]uint32
-	mutex                  sync.RWMutex
+	byUid  map[string]*workloadapi.Workload
+	byAddr map[NetworkAddress]*workloadapi.Workload
+	mutex  sync.RWMutex
 }
 
 func NewWorkloadCache() *cache {
 	return &cache{
-		byUid:                  make(map[string]*workloadapi.Workload),
-		byAddr:                 make(map[NetworkAddress]*workloadapi.Workload),
-		relationShipByWorkload: make(map[ServiceRelationShipByWorkload]uint32),
-		relationShipById:       make(map[ServiceRelationShipById]uint32),
-	}
-}
-
-func (w *cache) GetRelationShip(workloadId uint32, serviceId uint32) (uint32, bool) {
-	var relationKey = ServiceRelationShipByWorkload{
-		workloadId: workloadId,
-		serviceId:  serviceId,
-	}
-
-	w.mutex.RLock()
-	defer w.mutex.RUnlock()
-	relationId, exist := w.relationShipByWorkload[relationKey]
-	return relationId, exist
-}
-
-func (w *cache) UpdateRelationShip(workloadId uint32, serviceId uint32, relationId uint32) {
-	var relationKey = ServiceRelationShipByWorkload{
-		workloadId: workloadId,
-		serviceId:  serviceId,
-	}
-	var relationKeyById = ServiceRelationShipById{
-		serviceId:  serviceId,
-		relationId: relationId,
-	}
-
-	w.mutex.Lock()
-	defer w.mutex.Unlock()
-	w.relationShipByWorkload[relationKey] = relationId
-	w.relationShipById[relationKeyById] = workloadId
-}
-
-func (w *cache) DeleteRelationShip(serviceId uint32, relationId uint32) {
-	var relationKeyById = ServiceRelationShipById{
-		serviceId:  serviceId,
-		relationId: relationId,
-	}
-
-	w.mutex.Lock()
-	defer w.mutex.Unlock()
-	if workloadId, ok := w.relationShipById[relationKeyById]; ok {
-		delete(w.relationShipById, relationKeyById)
-		var relationKey = ServiceRelationShipByWorkload{
-			workloadId: workloadId,
-			serviceId:  serviceId,
-		}
-		delete(w.relationShipByWorkload, relationKey)
+		byUid:  make(map[string]*workloadapi.Workload),
+		byAddr: make(map[NetworkAddress]*workloadapi.Workload),
 	}
 }
 
@@ -133,59 +70,26 @@ func composeNetworkAddress(network string, addr netip.Addr) NetworkAddress {
 	}
 }
 
-func (w *cache) getUniqueServicesOnLeftWorkload(workload1, workload2 *workloadapi.Workload) []string {
-	var diff []string
-	if workload1 == nil {
-		return diff
-	}
-
-	for key := range workload1.Services {
-		if workload2 == nil {
-			diff = append(diff, key)
-			continue
-		}
-		if _, exist := workload2.Services[key]; !exist {
-			diff = append(diff, key)
-		}
-	}
-	return diff
-}
-
-func (w *cache) compareWorkloadServices(workload1, workload2 *workloadapi.Workload) ([]string, []string) {
-	dels := w.getUniqueServicesOnLeftWorkload(workload1, workload2)
-	news := w.getUniqueServicesOnLeftWorkload(workload2, workload1)
-	return dels, news
-}
-
-func (w *cache) AddOrUpdateWorkload(workload *workloadapi.Workload) ([]string, []string) {
-	var deletedServices []string
-	var newServices []string
-
+func (w *cache) AddWorkload(workload *workloadapi.Workload) {
 	if workload == nil {
-		return nil, nil
+		return
 	}
 	uid := workload.Uid
 
 	w.mutex.Lock()
 	defer w.mutex.Unlock()
 
-	oldWorkload, exist := w.byUid[uid]
+	workloadByUid, exist := w.byUid[uid]
 	if exist {
-		if proto.Equal(workload, oldWorkload) {
-			return nil, nil
+		if proto.Equal(workload, workloadByUid) {
+			return
 		}
-		// remove same uid but old address workload, avoid leak workload by address.
-		for _, ip := range oldWorkload.Addresses {
+		// remove same uid but old address workload, avoid leak worklaod by address.
+		for _, ip := range workloadByUid.Addresses {
 			addr, _ := netip.AddrFromSlice(ip)
-			networkAddress := composeNetworkAddress(oldWorkload.Network, addr)
+			networkAddress := composeNetworkAddress(workloadByUid.Network, addr)
 			delete(w.byAddr, networkAddress)
 		}
-
-		// compare services
-		deletedServices, newServices = w.compareWorkloadServices(oldWorkload, workload)
-	} else {
-		deletedServices = nil
-		newServices = w.getUniqueServicesOnLeftWorkload(workload, oldWorkload)
 	}
 
 	w.byUid[uid] = workload
@@ -199,7 +103,6 @@ func (w *cache) AddOrUpdateWorkload(workload *workloadapi.Workload) ([]string, [
 			w.byAddr[networkAddress] = workload
 		}
 	}
-	return deletedServices, newServices
 }
 
 func (w *cache) DeleteWorkload(uid string) {
diff --git a/pkg/controller/workload/workload_processor.go b/pkg/controller/workload/workload_processor.go
index 5b474134..1d3aa745 100644
--- a/pkg/controller/workload/workload_processor.go
+++ b/pkg/controller/workload/workload_processor.go
@@ -156,8 +156,12 @@ func (p *Processor) removeWorkloadResource(removedResources []string) error {
 
 func (p *Processor) removeWorkloadFromBpfMap(uid string) error {
 	var (
-		err      error
-		bkDelete = bpf.BackendKey{}
+		err               error
+		skUpdate          = bpf.ServiceKey{}
+		svUpdate          = bpf.ServiceValue{}
+		lastEndpointKey   = bpf.EndpointKey{}
+		lastEndpointValue = bpf.EndpointValue{}
+		bkDelete          = bpf.BackendKey{}
 	)
 
 	backendUid := p.hashName.StrToNum(uid)
@@ -169,20 +173,57 @@ func (p *Processor) removeWorkloadFromBpfMap(uid string) error {
 
 	// 1. find all endpoint keys related to this workload
 	if eks := p.bpf.EndpointIterFindKey(backendUid); len(eks) != 0 {
-		err = p.deleteEndpointRecords(eks)
-		if err != nil {
-			return err
+		for _, ek := range eks {
+			log.Debugf("Find EndpointKey: [%#v]", ek)
+			// 2. find the service
+			skUpdate.ServiceId = ek.ServiceId
+			if err = p.bpf.ServiceLookup(&skUpdate, &svUpdate); err == nil {
+				log.Debugf("Find ServiceValue: [%#v]", svUpdate)
+				// 3. find the last indexed endpoint of the service
+				lastEndpointKey.ServiceId = skUpdate.ServiceId
+				lastEndpointKey.BackendIndex = svUpdate.EndpointCount
+				if err = p.bpf.EndpointLookup(&lastEndpointKey, &lastEndpointValue); err == nil {
+					log.Debugf("Find EndpointValue: [%#v]", lastEndpointValue)
+					// 4. switch the index of the last with the current removed endpoint
+					if err = p.bpf.EndpointUpdate(&ek, &lastEndpointValue); err != nil {
+						log.Errorf("EndpointUpdate failed: %s", err)
+						goto failed
+					}
+					if err = p.bpf.EndpointDelete(&lastEndpointKey); err != nil {
+						log.Errorf("EndpointDelete failed: %s", err)
+						goto failed
+					}
+					svUpdate.EndpointCount = svUpdate.EndpointCount - 1
+					if err = p.bpf.ServiceUpdate(&skUpdate, &svUpdate); err != nil {
+						log.Errorf("ServiceUpdate failed: %s", err)
+						goto failed
+					}
+				} else {
+					// last indexed endpoint not exists, this should not occur
+					// we should delete the endpoint just in case leak
+					if err = p.bpf.EndpointDelete(&ek); err != nil {
+						log.Errorf("EndpointDelete failed: %s", err)
+						goto failed
+					}
+				}
+			} else { // service not exist, we should delete the endpoint
+				if err = p.bpf.EndpointDelete(&ek); err != nil {
+					log.Errorf("EndpointDelete failed: %s", err)
+					goto failed
+				}
+			}
 		}
 	}
 
 	bkDelete.BackendUid = backendUid
 	if err = p.bpf.BackendDelete(&bkDelete); err != nil {
 		log.Errorf("BackendDelete failed: %s", err)
-		return err
+		goto failed
 	}
-
 	p.hashName.Delete(uid)
-	return nil
+
+failed:
+	return err
 }
 
 func (p *Processor) deleteFrontendData(id uint32) error {
@@ -242,7 +283,6 @@ func (p *Processor) removeServiceResourceFromBpfMap(name string) error {
 		for i = 1; i <= svDelete.EndpointCount; i++ {
 			ekDelete.ServiceId = serviceId
 			ekDelete.BackendIndex = i
-
 			if err = p.bpf.EndpointDelete(&ekDelete); err != nil {
 				log.Errorf("EndpointDelete failed: %s", err)
 				goto failed
@@ -273,7 +313,6 @@ func (p *Processor) storeEndpointWithService(sk *bpf.ServiceKey, sv *bpf.Service
 		return err
 	}
 
-	p.WorkloadCache.UpdateRelationShip(ev.BackendUid, ek.ServiceId, ek.BackendIndex)
 	return nil
 }
 
@@ -287,92 +326,104 @@ func (p *Processor) storeServiceEndpoint(workload_uid string, serviceName string
 	wls[workload_uid] = struct{}{}
 }
 
-func (p *Processor) deleteResidualServicesWithWorkload(workload *workloadapi.Workload, services []string) error {
+func (p *Processor) storeBackendData(uid uint32, ip []byte, waypoint *workloadapi.GatewayAddress, portList map[string]*workloadapi.PortList, networkMode workloadapi.NetworkMode) error {
 	var (
-		err       error
-		serviceId uint32
+		bk = bpf.BackendKey{}
+		bv = bpf.BackendValue{}
 	)
 
-	if services == nil {
-		return nil
-	}
-
-	log.Infof("deleteResidualServicesWithWorkload: %v", services)
-	eks := make([]bpf.EndpointKey, 0)
-	workloadUid := p.hashName.StrToNum(workload.GetUid())
-	serviceIds := make(map[uint32]struct{})
-	for _, serviceName := range services {
-		serviceId = p.hashName.StrToNum(serviceName)
-		if relationId, ok := p.WorkloadCache.GetRelationShip(workloadUid, serviceId); ok {
-			eks = append(eks, bpf.EndpointKey{
-				ServiceId:    serviceId,
-				BackendIndex: relationId,
-			})
+	bk.BackendUid = uid
+	nets.CopyIpByteFromSlice(&bv.Ip, ip)
+	bv.ServiceCount = 0
+	for serviceName := range portList {
+		bv.Services[bv.ServiceCount] = p.hashName.StrToNum(serviceName)
+		bv.ServiceCount++
+		if bv.ServiceCount >= bpf.MaxServiceNum {
+			log.Warnf("exceed the max service count, currently, a pod can belong to a maximum of 10 services")
+			break
 		}
-		serviceIds[serviceId] = struct{}{}
 	}
 
-	err = p.deleteEndpointRecords(eks)
-	if err != nil {
-		log.Errorf("removeResidualServices delete endpoint failed:%v", err)
+	if waypoint != nil {
+		nets.CopyIpByteFromSlice(&bv.WaypointAddr, waypoint.GetAddress().Address)
+		bv.WaypointPort = nets.ConvertPortToBigEndian(waypoint.GetHboneMtlsPort())
 	}
-	return err
+
+	if err := p.bpf.BackendUpdate(&bk, &bv); err != nil {
+		log.Errorf("Update backend map failed, err:%s", err)
+		return err
+	}
+
+	// we should not store frontend data of hostname network mode pods
+	// because host network pod cannot be managed by kmesh
+	// please see https://github.com/kmesh-net/kmesh/issues/631
+	if networkMode != workloadapi.NetworkMode_HOST_NETWORK {
+		if err := p.storePodFrontendData(uid, ip); err != nil {
+			log.Errorf("storePodFrontendData failed, err:%s", err)
+			return err
+		}
+	}
+
+	return nil
 }
 
-func (p *Processor) addNewServicesWithWorkload(workload *workloadapi.Workload, newServices []string) error {
+func (p *Processor) handleDataWithService(workload *workloadapi.Workload) error {
 	var (
 		err error
 		sk  = bpf.ServiceKey{}
 		sv  = bpf.ServiceValue{}
-	)
 
-	if newServices == nil {
-		return nil
-	}
+		bk = bpf.BackendKey{}
+		bv = bpf.BackendValue{}
+	)
 
-	log.Infof("addNewServicesWithWorkload: %v", newServices)
 	backend_uid := p.hashName.StrToNum(workload.GetUid())
-	for _, serviceName := range newServices {
-		sk.ServiceId = p.hashName.StrToNum(serviceName)
-		// the service already stored in map, add endpoint
-		if err = p.bpf.ServiceLookup(&sk, &sv); err == nil {
-			if err = p.storeEndpointWithService(&sk, &sv, backend_uid); err != nil {
-				log.Errorf("storeEndpointWithService failed, err:%s", err)
-				return err
+	for serviceName := range workload.GetServices() {
+		bk.BackendUid = backend_uid
+		// for update sense, if the backend is exist, just need update it
+		if err = p.bpf.BackendLookup(&bk, &bv); err != nil {
+			sk.ServiceId = p.hashName.StrToNum(serviceName)
+			// the service already stored in map, add endpoint
+			if err = p.bpf.ServiceLookup(&sk, &sv); err == nil {
+				if err = p.storeEndpointWithService(&sk, &sv, backend_uid); err != nil {
+					log.Errorf("storeEndpointWithService failed, err:%s", err)
+					return err
+				}
+			} else {
+				p.storeServiceEndpoint(workload.GetUid(), serviceName)
 			}
-		} else {
-			p.storeServiceEndpoint(workload.GetUid(), serviceName)
 		}
 	}
+
+	if len(workload.GetAddresses()) > 1 {
+		log.Warnf("current only support single ip of a pod")
+	}
+
+	for _, ip := range workload.GetAddresses() { // current only support single ip, if a pod have multi ips, the last one will be stored finally
+		if err = p.storeBackendData(backend_uid, ip, workload.GetWaypoint(), workload.GetServices(), workload.GetNetworkMode()); err != nil {
+			log.Errorf("storeBackendData failed, err:%s", err)
+			return err
+		}
+	}
+
 	return nil
 }
 
-func (p *Processor) updateWorkload(workload *workloadapi.Workload) error {
+func (p *Processor) handleDataWithoutService(workload *workloadapi.Workload) error {
 	var (
-		err         error
-		bk          = bpf.BackendKey{}
-		bv          = bpf.BackendValue{}
-		networkMode = workload.GetNetworkMode()
+		err error
+		bk  = bpf.BackendKey{}
+		bv  = bpf.BackendValue{}
 	)
 
 	uid := p.hashName.StrToNum(workload.GetUid())
 	ips := workload.GetAddresses()
-
-	if waypoint := workload.GetWaypoint(); waypoint != nil {
-		nets.CopyIpByteFromSlice(&bv.WaypointAddr, waypoint.GetAddress().Address)
-		bv.WaypointPort = nets.ConvertPortToBigEndian(waypoint.GetHboneMtlsPort())
-	}
-
-	for serviceName := range workload.GetServices() {
-		bv.Services[bv.ServiceCount] = p.hashName.StrToNum(serviceName)
-		bv.ServiceCount++
-		if bv.ServiceCount >= bpf.MaxServiceNum {
-			log.Warnf("exceed the max service count, currently, a pod can belong to a maximum of 10 services")
-			break
+	for _, ip := range ips {
+		if waypoint := workload.GetWaypoint(); waypoint != nil {
+			nets.CopyIpByteFromSlice(&bv.WaypointAddr, waypoint.GetAddress().Address)
+			bv.WaypointPort = nets.ConvertPortToBigEndian(waypoint.GetHboneMtlsPort())
 		}
-	}
 
-	for _, ip := range ips {
 		bk.BackendUid = uid
 
 		nets.CopyIpByteFromSlice(&bv.Ip, ip)
@@ -382,8 +433,9 @@ func (p *Processor) updateWorkload(workload *workloadapi.Workload) error {
 		}
 
 		// we should not store frontend data of hostname network mode pods
+		// because host network pod cannot be managed by kmesh
 		// please see https://github.com/kmesh-net/kmesh/issues/631
-		if networkMode != workloadapi.NetworkMode_HOST_NETWORK {
+		if workload.GetNetworkMode() != workloadapi.NetworkMode_HOST_NETWORK {
 			if err = p.storePodFrontendData(uid, ip); err != nil {
 				log.Errorf("storePodFrontendData failed, err:%s", err)
 				return err
@@ -394,28 +446,20 @@ func (p *Processor) updateWorkload(workload *workloadapi.Workload) error {
 }
 
 func (p *Processor) handleWorkload(workload *workloadapi.Workload) error {
-	var deletedServices []string
-	var newServices []string
 	log.Debugf("handle workload: %s", workload.Uid)
+	p.WorkloadCache.AddWorkload(workload)
 
-	deletedServices, newServices = p.WorkloadCache.AddOrUpdateWorkload(workload)
-
-	// Delete Residual Services on the Workload
-	if err := p.deleteResidualServicesWithWorkload(workload, deletedServices); err != nil {
-		log.Errorf("deleteResidualServicesWithWorkload %s failed: %v", workload.GetUid(), err)
-		return err
-	}
-
-	// Add new services associated with the workload
-	if err := p.addNewServicesWithWorkload(workload, newServices); err != nil {
-		log.Errorf("addNewServicesWithWorkload %s failed: %v", workload.Uid, err)
-		return err
-	}
-
-	// Update workload
-	if err := p.updateWorkload(workload); err != nil {
-		log.Errorf("updateWorkload %s failed: %v", workload.Uid, err)
-		return err
+	// if have the service name, the workload belongs to a service
+	if workload.GetServices() != nil {
+		if err := p.handleDataWithService(workload); err != nil {
+			log.Errorf("handleDataWithService %s failed: %v", workload.Uid, err)
+			return err
+		}
+	} else { // independent workload without service
+		if err := p.handleDataWithoutService(workload); err != nil {
+			log.Errorf("handleDataWithoutService %s failed: %v", workload.Uid, err)
+			return err
+		}
 	}
 
 	return nil
@@ -490,7 +534,6 @@ func (p *Processor) storeServiceData(serviceName string, waypoint *workloadapi.G
 					log.Errorf("Update Endpoint failed, err:%s", err)
 					return err
 				}
-				p.WorkloadCache.UpdateRelationShip(ev.BackendUid, ek.ServiceId, ek.BackendIndex)
 			}
 		}
 		delete(p.endpointsByService, serviceName)
@@ -658,90 +701,3 @@ func (p *Processor) handleAuthorizationTypeResponse(rsp *service_discovery_v3.De
 
 	return nil
 }
-
-func (p *Processor) deleteEndpointRecords(endpoint_keys []bpf.EndpointKey) error {
-	var (
-		err               error
-		skUpdate          = bpf.ServiceKey{}
-		svUpdate          = bpf.ServiceValue{}
-		lastEndpointKey   = bpf.EndpointKey{}
-		lastEndpointValue = bpf.EndpointValue{}
-	)
-
-	for _, ek := range endpoint_keys {
-		log.Debugf("Find EndpointKey: [%#v]", ek)
-
-		// 2. find the service
-		skUpdate.ServiceId = ek.ServiceId
-		if err = p.bpf.ServiceLookup(&skUpdate, &svUpdate); err == nil {
-			log.Debugf("Find ServiceValue: [%#v]", svUpdate)
-			// 3. find the last indexed endpoint of the service
-			lastEndpointKey.ServiceId = skUpdate.ServiceId
-			lastEndpointKey.BackendIndex = svUpdate.EndpointCount
-			if err = p.bpf.EndpointLookup(&lastEndpointKey, &lastEndpointValue); err == nil {
-				log.Debugf("Find EndpointValue: [%#v]", lastEndpointValue)
-				// 4. switch the index of the last with the current removed endpoint
-				if err = p.updateRelationShipWithWorkloadAndService(lastEndpointValue.BackendUid, ek.ServiceId, ek.BackendIndex); err != nil {
-					log.Errorf("EndpointUpdate failed: %s", err)
-					return err
-				}
-
-				if err = p.bpf.EndpointDelete(&lastEndpointKey); err != nil {
-					log.Errorf("EndpointDelete failed: %s", err)
-					return err
-				}
-				p.WorkloadCache.DeleteRelationShip(ek.ServiceId, ek.BackendIndex)
-
-				svUpdate.EndpointCount = svUpdate.EndpointCount - 1
-				if err = p.bpf.ServiceUpdate(&skUpdate, &svUpdate); err != nil {
-					log.Errorf("ServiceUpdate failed: %s", err)
-					return err
-				}
-			} else {
-				// last indexed endpoint not exists, this should not occur
-				// we should delete the endpoint just in case leak
-				if err = p.deleteRelationShipWithWorkloadAndService(ek.ServiceId, ek.BackendIndex); err != nil {
-					log.Errorf("EndpointDelete failed: %s", err)
-					return err
-				}
-			}
-		} else { // service not exist, we should delete the endpoint
-			if err = p.deleteRelationShipWithWorkloadAndService(ek.ServiceId, ek.BackendIndex); err != nil {
-				log.Errorf("EndpointDelete failed: %s", err)
-				return err
-			}
-		}
-	}
-	return nil
-}
-
-func (p *Processor) updateRelationShipWithWorkloadAndService(workloadId uint32, serviceId uint32, relationId uint32) error {
-	var ek = bpf.EndpointKey{
-		ServiceId:    serviceId,
-		BackendIndex: relationId,
-	}
-	var ev = bpf.EndpointValue{
-		BackendUid: workloadId,
-	}
-
-	if err := p.bpf.EndpointUpdate(&ek, &ev); err != nil {
-		log.Errorf("EndpointUpdate failed: %s", err)
-		return err
-	}
-	p.WorkloadCache.UpdateRelationShip(workloadId, serviceId, relationId)
-	return nil
-}
-
-func (p *Processor) deleteRelationShipWithWorkloadAndService(serviceId uint32, relationId uint32) error {
-	var ek = bpf.EndpointKey{
-		ServiceId:    serviceId,
-		BackendIndex: relationId,
-	}
-
-	if err := p.bpf.EndpointDelete(&ek); err != nil {
-		log.Errorf("EndpointDelete failed: %s", err)
-		return err
-	}
-	p.WorkloadCache.DeleteRelationShip(serviceId, relationId)
-	return nil
-}
diff --git a/pkg/kube/informer.go b/pkg/kube/informer.go
deleted file mode 100644
index d7d7a20d..00000000
--- a/pkg/kube/informer.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright The Kmesh Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package kube
-
-import (
-	"fmt"
-	"os"
-
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/client-go/informers"
-	"k8s.io/client-go/kubernetes"
-)
-
-func NewInformerFactory(client kubernetes.Interface) informers.SharedInformerFactory {
-	nodeName := os.Getenv("NODE_NAME")
-	informerFactory := informers.NewSharedInformerFactoryWithOptions(client, 0,
-		informers.WithTweakListOptions(func(options *metav1.ListOptions) {
-			options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeName)
-		}))
-	return informerFactory
-}
diff --git a/pkg/utils/exec.go b/pkg/utils/exec.go
index ce508d63..b51142ee 100644
--- a/pkg/utils/exec.go
+++ b/pkg/utils/exec.go
@@ -41,6 +41,7 @@ func ExecuteWithRedirect(cmd string, args []string, stdout io.Writer) error {
 	err = executeCore(cmd, args, stdout, stderr)
 	if len(stderr.String()) != 0 {
 		err = fmt.Errorf("command error output: %s", stderr.String())
+		log.Error(err)
 		return err
 	}
 	return err
@@ -58,6 +59,7 @@ func Execute(cmd string, args []string) error {
 
 	if len(stderr.String()) != 0 {
 		err = fmt.Errorf("command error output: %s", stderr.String())
+		log.Error(err)
 		return err
 	}
 	return err


Test patch:
diff --git a/pkg/auth/rbac_test.go b/pkg/auth/rbac_test.go
index 5bd72046..2980e77b 100644
--- a/pkg/auth/rbac_test.go
+++ b/pkg/auth/rbac_test.go
@@ -1967,7 +1967,7 @@ func TestRbac_doRbac(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			workloadCache := cache.NewWorkloadCache()
-			workloadCache.AddOrUpdateWorkload(tt.args.workload)
+			workloadCache.AddWorkload(tt.args.workload)
 			rbac := &Rbac{
 				policyStore:   tt.fields.policyStore,
 				workloadCache: workloadCache,
@@ -2145,7 +2145,7 @@ func TestRbac_Run(t *testing.T) {
 	}
 
 	workloadCache := cache.NewWorkloadCache()
-	workloadCache.AddOrUpdateWorkload(&workloadapi.Workload{
+	workloadCache.AddWorkload(&workloadapi.Workload{
 		Name: "ut-workload",
 		Uid:  "123456",
 		Addresses: [][]byte{
diff --git a/pkg/controller/manage/manage_controller_test.go b/pkg/controller/manage/manage_controller_test.go
index 9e89f361..8b3fb296 100644
--- a/pkg/controller/manage/manage_controller_test.go
+++ b/pkg/controller/manage/manage_controller_test.go
@@ -198,6 +198,7 @@ func TestHandleKmeshManage(t *testing.T) {
 	if err != nil {
 		t.Fatalf("error creating KmeshManageController: %v", err)
 	}
+
 	stopChan := make(chan struct{})
 	defer close(stopChan)
 
diff --git a/pkg/controller/telemetry/metric_test.go b/pkg/controller/telemetry/metric_test.go
index 4085602a..0bb0a4f7 100644
--- a/pkg/controller/telemetry/metric_test.go
+++ b/pkg/controller/telemetry/metric_test.go
@@ -353,7 +353,7 @@ func TestMetricGetWorkloadByAddress(t *testing.T) {
 			m := MetricController{
 				workloadCache: cache.NewWorkloadCache(),
 			}
-			m.workloadCache.AddOrUpdateWorkload(workload)
+			m.workloadCache.AddWorkload(workload)
 			if got, _ := m.getWorkloadByAddress(tt.args.address); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("Metric.getWorkloadByAddress() = %v, want %v", got, tt.want)
 			}
@@ -441,8 +441,8 @@ func TestBuildworkloadMetric(t *testing.T) {
 			m := MetricController{
 				workloadCache: cache.NewWorkloadCache(),
 			}
-			m.workloadCache.AddOrUpdateWorkload(dstWorkload)
-			m.workloadCache.AddOrUpdateWorkload(srcWorkload)
+			m.workloadCache.AddWorkload(dstWorkload)
+			m.workloadCache.AddWorkload(srcWorkload)
 			got := m.buildWorkloadMetric(tt.args.data)
 			if !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("Metric.buildMetric() = %v, want %v", got, tt.want)
@@ -576,8 +576,8 @@ func TestBuildServiceMetric(t *testing.T) {
 			m := MetricController{
 				workloadCache: cache.NewWorkloadCache(),
 			}
-			m.workloadCache.AddOrUpdateWorkload(dstWorkload)
-			m.workloadCache.AddOrUpdateWorkload(srcWorkload)
+			m.workloadCache.AddWorkload(dstWorkload)
+			m.workloadCache.AddWorkload(srcWorkload)
 			got := m.buildServiceMetric(tt.args.data)
 			assert.Equal(t, tt.want, got)
 		})
diff --git a/pkg/controller/workload/cache/workload_cache_test.go b/pkg/controller/workload/cache/workload_cache_test.go
index b6715ef8..29e90f91 100644
--- a/pkg/controller/workload/cache/workload_cache_test.go
+++ b/pkg/controller/workload/cache/workload_cache_test.go
@@ -25,7 +25,7 @@ import (
 	"kmesh.net/kmesh/api/v2/workloadapi"
 )
 
-func TestAddOrUpdateWorkload(t *testing.T) {
+func TestAddWorkload(t *testing.T) {
 	t.Run("adding a workload when none exists", func(t *testing.T) {
 		w := NewWorkloadCache()
 		workload := &workloadapi.Workload{
@@ -37,7 +37,7 @@ func TestAddOrUpdateWorkload(t *testing.T) {
 				[]byte("1.2.3.4"),
 			},
 		}
-		w.AddOrUpdateWorkload(workload)
+		w.AddWorkload(workload)
 		assert.Equal(t, workload, w.byUid["123456"])
 		addr1, _ := netip.AddrFromSlice([]byte("192.168.224.22"))
 		addr2, _ := netip.AddrFromSlice([]byte("1.2.3.4"))
@@ -56,7 +56,7 @@ func TestAddOrUpdateWorkload(t *testing.T) {
 				[]byte("1.2.3.4"),
 			},
 		}
-		w.AddOrUpdateWorkload(workload)
+		w.AddWorkload(workload)
 		assert.Equal(t, workload, w.byUid["123456"])
 		addr1, _ := netip.AddrFromSlice([]byte("192.168.224.22"))
 		addr2, _ := netip.AddrFromSlice([]byte("1.2.3.4"))
@@ -71,7 +71,7 @@ func TestAddOrUpdateWorkload(t *testing.T) {
 				[]byte("2.3.4.5"),
 			},
 		}
-		w.AddOrUpdateWorkload(newWorkload)
+		w.AddWorkload(newWorkload)
 		assert.Equal(t, newWorkload, w.byUid["123456"])
 		addr3, _ := netip.AddrFromSlice([]byte("192.168.10.25"))
 		addr4, _ := netip.AddrFromSlice([]byte("2.3.4.5"))
@@ -91,7 +91,7 @@ func TestAddOrUpdateWorkload(t *testing.T) {
 				[]byte("192.168.224.22"),
 			},
 		}
-		w.AddOrUpdateWorkload(workload)
+		w.AddWorkload(workload)
 		assert.Equal(t, workload, w.byUid["123456"])
 		addr, _ := netip.AddrFromSlice([]byte("192.168.224.22"))
 		assert.Equal(t, workload, w.byAddr[NetworkAddress{Network: workload.Network, Address: addr}])
@@ -104,7 +104,7 @@ func TestAddOrUpdateWorkload(t *testing.T) {
 				[]byte("2.3.4.5"),
 			},
 		}
-		w.AddOrUpdateWorkload(newWorkload)
+		w.AddWorkload(newWorkload)
 		assert.Equal(t, newWorkload, w.byUid["123456"])
 		addr1, _ := netip.AddrFromSlice([]byte("192.168.224.22"))
 		addr2, _ := netip.AddrFromSlice([]byte("2.3.4.5"))
@@ -126,7 +126,7 @@ func TestDeleteWorkload(t *testing.T) {
 				[]byte("world"),
 			},
 		}
-		w.AddOrUpdateWorkload(workload)
+		w.AddWorkload(workload)
 		assert.Equal(t, workload, w.byUid["123456"])
 		w.DeleteWorkload("123456")
 		assert.Equal(t, (*workloadapi.Workload)(nil), w.byUid["123456"])
@@ -136,33 +136,3 @@ func TestDeleteWorkload(t *testing.T) {
 		assert.Equal(t, (*workloadapi.Workload)(nil), w.byAddr[NetworkAddress{Network: "ut-net", Address: addr2}])
 	})
 }
-
-func TestWorkloadRelationShip(t *testing.T) {
-	t.Run("normal function test", func(t *testing.T) {
-		w := NewWorkloadCache()
-
-		var serviceId uint32 = 12345678
-		var relationId uint32 = 87654321
-		var workloadId uint32 = 12341234
-
-		var relationKey = ServiceRelationShipByWorkload{
-			workloadId: workloadId,
-			serviceId:  serviceId,
-		}
-		var relationKeyById = ServiceRelationShipById{
-			serviceId:  serviceId,
-			relationId: relationId,
-		}
-
-		w.UpdateRelationShip(workloadId, serviceId, relationId)
-		assert.Equal(t, workloadId, w.relationShipById[relationKeyById])
-		assert.Equal(t, relationId, w.relationShipByWorkload[relationKey])
-
-		val, ok := w.GetRelationShip(workloadId, serviceId)
-		assert.Equal(t, ok, true)
-		assert.Equal(t, val, relationId)
-
-		w.DeleteRelationShip(serviceId, relationId)
-		assert.Equal(t, (uint32)(0), w.relationShipById[relationKeyById])
-	})
-}
diff --git a/pkg/controller/workload/workload_controller_test.go b/pkg/controller/workload/workload_controller_test.go
index b9aab7e3..883fc57b 100644
--- a/pkg/controller/workload/workload_controller_test.go
+++ b/pkg/controller/workload/workload_controller_test.go
@@ -124,7 +124,7 @@ func TestWorkloadStreamCreateAndSend(t *testing.T) {
 
 				workloadController.Processor = newProcessor(workloadMap)
 				workload := createFakeWorkload("10.10.10.1", workloadapi.NetworkMode_STANDARD)
-				workloadController.Processor.WorkloadCache.AddOrUpdateWorkload(workload)
+				workloadController.Processor.WorkloadCache.AddWorkload(workload)
 				patches2.ApplyMethodFunc(fakeClient.DeltaClient, "Send",
 					func(req *discoveryv3.DeltaDiscoveryRequest) error {
 						if req.TypeUrl == AddressType {
diff --git a/pkg/controller/workload/workload_processor_test.go b/pkg/controller/workload/workload_processor_test.go
index 388f0b54..046724e6 100644
--- a/pkg/controller/workload/workload_processor_test.go
+++ b/pkg/controller/workload/workload_processor_test.go
@@ -41,10 +41,8 @@ func Test_handleWorkload(t *testing.T) {
 
 	// 1. handle workload with service, but service not handled yet
 	// In this case, only frontend map and backend map should be updated.
-	wl := createTestWorkloadWithService(true)
-	err := p.handleWorkload(wl)
-	assert.NoError(t, err)
-
+	wl := createTestWorkloadWithService()
+	_ = p.handleDataWithService(createTestWorkloadWithService())
 	var (
 		ek bpfcache.EndpointKey
 		ev bpfcache.EndpointValue
@@ -76,14 +74,13 @@ func Test_handleWorkload(t *testing.T) {
 	// 2.3 check endpoint map now contains the workloads
 	ek.BackendIndex = 1
 	ek.ServiceId = svcID
-	err = p.bpf.EndpointLookup(&ek, &ev)
+	err := p.bpf.EndpointLookup(&ek, &ev)
 	assert.NoError(t, err)
 	assert.Equal(t, ev.BackendUid, workloadID)
 
 	// 3. add another workload with service
 	workload2 := createFakeWorkload("1.2.3.5", workloadapi.NetworkMode_STANDARD)
-	err = p.handleWorkload(workload2)
-	assert.NoError(t, err)
+	_ = p.handleDataWithService(workload2)
 
 	// 3.1 check endpoint map now contains the new workloads
 	workload2ID := checkFrontEndMap(t, workload2.Addresses[0], p)
@@ -96,56 +93,13 @@ func Test_handleWorkload(t *testing.T) {
 	// 3.2 check service map contains service
 	checkServiceMap(t, p, svcID, fakeSvc, 2)
 
-	// 4 modify workload2 attribute not relationship with services
-	workload2.Waypoint = &workloadapi.GatewayAddress{
-		Destination: &workloadapi.GatewayAddress_Address{
-			Address: &workloadapi.NetworkAddress{
-				Address: netip.MustParseAddr("10.10.10.10").AsSlice(),
-			},
-		},
-		HboneMtlsPort: 15008,
-	}
-
-	err = p.handleWorkload(workload2)
-	assert.NoError(t, err)
-
-	// 4.1 check endpoint map now contains the new workloads
-	workload2ID = checkFrontEndMap(t, workload2.Addresses[0], p)
-	ek.BackendIndex = 2
-	ek.ServiceId = svcID
-	err = p.bpf.EndpointLookup(&ek, &ev)
-	assert.NoError(t, err)
-	assert.Equal(t, ev.BackendUid, workload2ID)
-
-	// 4.2 check service map contains service
-	checkServiceMap(t, p, svcID, fakeSvc, 2)
-
-	// 4.3 check backend map contains waypoint
-	checkBackendMap(t, p, workload2ID, workload2)
-
-	// 5 remove relationship with workload and service
-	workload5 := createTestWorkloadWithService(false)
-	workload5.Uid = wl.Uid
-	err = p.handleWorkload(workload5)
-	assert.NoError(t, err)
-
-	// 5.1 check service map
-	checkServiceMap(t, p, svcID, fakeSvc, 1)
-
-	// 5.2 check endpoint map
-	ek.BackendIndex = 1
-	ek.ServiceId = svcID
-	err = p.bpf.EndpointLookup(&ek, &ev)
-	assert.NoError(t, err)
-	assert.Equal(t, workload2ID, ev.BackendUid)
-
-	// 6. add namespace scoped waypoint service
+	// 4. add namespace scoped waypoint service
 	wpSvc := createFakeService("waypoint", "10.240.10.5", "10.240.10.5")
 	_ = p.handleService(wpSvc)
 	assert.Nil(t, wpSvc.Waypoint)
-	// 6.1 check front end map contains service
+	// 4.1 check front end map contains service
 	svcID = checkFrontEndMap(t, wpSvc.Addresses[0].Address, p)
-	// 6.2 check service map contains service, but no waypoint address
+	// 4.2 check service map contains service, but no waypoint address
 	checkServiceMap(t, p, svcID, wpSvc, 0)
 
 	hashNameClean(p)
@@ -194,7 +148,7 @@ func checkServiceMap(t *testing.T, p *Processor, svcId uint32, fakeSvc *workload
 	var sv bpfcache.ServiceValue
 	err := p.bpf.ServiceLookup(&bpfcache.ServiceKey{ServiceId: svcId}, &sv)
 	assert.NoError(t, err)
-	assert.Equal(t, endpointCount, sv.EndpointCount)
+	assert.Equal(t, sv.EndpointCount, endpointCount)
 	waypointAddr := fakeSvc.GetWaypoint().GetAddress().GetAddress()
 	if waypointAddr != nil {
 		assert.Equal(t, test.EqualIp(sv.WaypointAddr, waypointAddr), true)
@@ -239,7 +193,7 @@ func checkFrontEndMap(t *testing.T, ip []byte, p *Processor) (upstreamId uint32)
 	return
 }
 
-func BenchmarkAddNewServicesWithWorkload(b *testing.B) {
+func BenchmarkHandleDataWithService(b *testing.B) {
 	t := &testing.T{}
 	config := options.BpfConfig{
 		Mode:        constants.WorkloadMode,
@@ -254,14 +208,14 @@ func BenchmarkAddNewServicesWithWorkload(b *testing.B) {
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		workload := createTestWorkloadWithService(true)
-		err := workloadController.Processor.handleWorkload(workload)
+		workload := createTestWorkloadWithService()
+		err := workloadController.Processor.handleDataWithService(workload)
 		assert.NoError(t, err)
 	}
 	workloadController.Processor.hashName.Reset()
 }
 
-func createTestWorkloadWithService(withService bool) *workloadapi.Workload {
+func createTestWorkloadWithService() *workloadapi.Workload {
 	workload := workloadapi.Workload{
 		Namespace:         "ns",
 		Name:              "name",
@@ -273,11 +227,7 @@ func createTestWorkloadWithService(withService bool) *workloadapi.Workload {
 		WorkloadName:      "name",
 		Status:            workloadapi.WorkloadStatus_HEALTHY,
 		ClusterId:         "cluster0",
-		Services:          map[string]*workloadapi.PortList{},
-	}
-
-	if withService == true {
-		workload.Services = map[string]*workloadapi.PortList{
+		Services: map[string]*workloadapi.PortList{
 			"default/testsvc.default.svc.cluster.local": {
 				Ports: []*workloadapi.Port{
 					{
@@ -294,7 +244,7 @@ func createTestWorkloadWithService(withService bool) *workloadapi.Workload {
 					},
 				},
 			},
-		}
+		},
 	}
 	workload.Uid = "cluster0/" + rand.String(6)
 	return &workload
@@ -379,9 +329,8 @@ func Test_deleteWorkloadWithRestart(t *testing.T) {
 
 	// 1. handle workload with service, but service not handled yet
 	// In this case, only frontend map and backend map should be updated.
-	wl := createTestWorkloadWithService(true)
-	err := p.handleWorkload(wl)
-	assert.NoError(t, err)
+	wl := createTestWorkloadWithService()
+	_ = p.handleDataWithService(createTestWorkloadWithService())
 
 	workloadID := checkFrontEndMap(t, wl.Addresses[0], p)
 	checkBackendMap(t, p, workloadID, wl)
diff --git a/pkg/status/status_server_test.go b/pkg/status/status_server_test.go
index c06cb2c2..98b24f35 100644
--- a/pkg/status/status_server_test.go
+++ b/pkg/status/status_server_test.go
@@ -265,7 +265,7 @@ func TestServer_configDumpWorkload(t *testing.T) {
 		}}
 	fakeWorkloadCache := cache.NewWorkloadCache()
 	fakeServiceCache := cache.NewServiceCache()
-	fakeWorkloadCache.AddOrUpdateWorkload(w1)
+	fakeWorkloadCache.AddWorkload(w1)
 	fakeServiceCache.AddOrUpdateService(svc)
 	// Create a new instance of the Server struct
 	server := &Server{
diff --git a/test/e2e/run_test.sh b/test/e2e/run_test.sh
index 5456d4a0..d31ea0f5 100755
--- a/test/e2e/run_test.sh
+++ b/test/e2e/run_test.sh
@@ -204,7 +204,7 @@ function cleanup_docker_registry() {
     docker rm "${KIND_REGISTRY_NAME}" || echo "Failed to remove or no such registry '${KIND_REGISTRY_NAME}'."
 }
 
-PARAMS=""
+PARAMS=()
 
 while (( "$#" )); do
     case "$1" in
@@ -235,13 +235,9 @@ while (( "$#" )); do
       CLEANUP_REGISTRY=true
       shift
     ;;
-    --select-cases)
-      PARAMS+="-test.run \"$2\""
-      shift 2
-    ;;
-    --skip-cases)
-      PARAMS+="-test.skip \"$2\""
-      shift 2
+    *)
+      PARAMS+=("$1")
+      shift
     ;;
     esac
 done
@@ -265,7 +261,7 @@ if [[ -z "${SKIP_SETUP:-}" ]]; then
     setup_kmesh
 fi
 
-cmd="go test -v -tags=integ $ROOT_DIR/test/e2e/... -count=1 $PARAMS"
+cmd="go test -v -tags=integ $ROOT_DIR/test/e2e/... ${PARAMS[*]}"
 
 bash -c "$cmd"