From c8ddc0e24b1b28385956100969a0c778aa40c2cd Mon Sep 17 00:00:00 2001 From: Woa Date: Mon, 18 Sep 2023 09:32:13 +0800 Subject: [PATCH] feat(trafficManager): fast weighted backend selection (#523) --- .../acceptance/performance_test.go | 6 ++-- .../TrafficManager/acceptance/weight_test.go | 7 +++- .../TrafficManager/bpf/bpf_connect_bpf.go | 10 +++--- .../TrafficManager/bpf/bpf_connect_bpf.o | Bin 13248 -> 13056 bytes eBPF_Supermarket/TrafficManager/bpf/connect.c | 8 ++--- .../TrafficManager/bpf/connect.go | 31 +++++++++++------- eBPF_Supermarket/TrafficManager/bpf/connect.h | 27 ++++++++++++++- eBPF_Supermarket/TrafficManager/bpf/type.go | 24 +++++++------- 8 files changed, 78 insertions(+), 35 deletions(-) diff --git a/eBPF_Supermarket/TrafficManager/acceptance/performance_test.go b/eBPF_Supermarket/TrafficManager/acceptance/performance_test.go index 97ae1a070..4184db41a 100644 --- a/eBPF_Supermarket/TrafficManager/acceptance/performance_test.go +++ b/eBPF_Supermarket/TrafficManager/acceptance/performance_test.go @@ -49,7 +49,7 @@ type SiegeResponse struct { func siegeService(siegePodName string, service *v1.Service) (*SiegeResponse, error) { log.Println("Start Sieging") // kubectl exec siege -- siege -c 5 -r 20000 http://sisyphe-sfs.default.svc.cluster.local - out, err := exec.Command("kubectl", "exec", siegePodName, "--", "siege", "-c", "20", "-r", "20000", "http://"+service.Spec.ClusterIPs[0]).Output() + out, err := exec.Command("kubectl", "exec", siegePodName, "--", "siege", "-c", "20", "-r", "30000", "http://"+service.Spec.ClusterIPs[0]).Output() if err != nil { return nil, err } @@ -93,9 +93,11 @@ func TestServicePerformance(t *testing.T) { // fmt.Println(service.Spec.ClusterIP, strconv.Itoa(int(service.Spec.Ports[0].Port))) programs.InsertServiceItem(service.Spec.ClusterIP, strconv.Itoa(int(service.Spec.Ports[0].Port)), len(pods.Items), bpf.RandomAction) + totalPercentage := 0.0 for i := 0; i < len(pods.Items); i++ { // fmt.Println(strconv.Itoa(int(pods.Items[i].Spec.Containers[0].Ports[0].ContainerPort))) - programs.AutoInsertBackend(service.Spec.ClusterIP, strconv.Itoa(int(service.Spec.Ports[0].Port)), pods.Items[i].Status.PodIP, strconv.Itoa(int(pods.Items[i].Spec.Containers[0].Ports[0].ContainerPort)), i+1, float64(1/float64(len(pods.Items)))) + totalPercentage += 1 / float64(len(pods.Items)) + programs.AutoInsertBackend(service.Spec.ClusterIP, strconv.Itoa(int(service.Spec.Ports[0].Port)), pods.Items[i].Status.PodIP, strconv.Itoa(int(pods.Items[i].Spec.Containers[0].Ports[0].ContainerPort)), i+1, 1/float64(len(pods.Items)), totalPercentage) } err = programs.Attach() diff --git a/eBPF_Supermarket/TrafficManager/acceptance/weight_test.go b/eBPF_Supermarket/TrafficManager/acceptance/weight_test.go index d3ce6e075..df50bef78 100644 --- a/eBPF_Supermarket/TrafficManager/acceptance/weight_test.go +++ b/eBPF_Supermarket/TrafficManager/acceptance/weight_test.go @@ -117,8 +117,13 @@ func TestWeight(t *testing.T) { } progs.InsertServiceItem(targetIP, targetPort, len(serverPortList), bpf.WeightedAction) + totalPercentage := 0.0 for i := 0; i < len(serverPortList); i++ { - progs.AutoInsertBackend(targetIP, targetPort, "127.0.0.1", serverPortList[i], i+1, tc.weights[i]) + totalPercentage += tc.weights[i] + progs.AutoInsertBackend(targetIP, targetPort, "127.0.0.1", serverPortList[i], i+1, tc.weights[i], totalPercentage) + } + if math.Abs(totalPercentage-1) > 0.005 { + fmt.Printf("[WARNING] Total weight for service %s:%s is not 1, but %f.\n", targetIP, targetPort, totalPercentage) } err = progs.Attach() diff --git a/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.go b/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.go index cf7daabc3..9bee55099 100644 --- a/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.go +++ b/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.go @@ -28,11 +28,11 @@ type bpf_connectLb4Key struct { } type bpf_connectLb4Service struct { - BackendId uint32 - Count uint16 - Possibility uint16 - Action uint16 - Pad [2]uint8 + BackendId uint32 + Count uint16 + Possibility uint16 + Action uint16 + WeightRangeUpper uint16 } // loadBpf_connect returns the embedded CollectionSpec for bpf_connect. diff --git a/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.o b/eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.o index 159f828eb95bfc9faf273606ccd80fc38c48689c..5517e72d55419c1645535c01182275ddbc3730f8 100644 GIT binary patch literal 13056 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 literal 13248 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 H7SsO#C~O`? diff --git a/eBPF_Supermarket/TrafficManager/bpf/connect.c b/eBPF_Supermarket/TrafficManager/bpf/connect.c index 0e60d7334..f6f4ff949 100644 --- a/eBPF_Supermarket/TrafficManager/bpf/connect.c +++ b/eBPF_Supermarket/TrafficManager/bpf/connect.c @@ -54,19 +54,19 @@ static int sock4_forward_entry(struct bpf_sock_addr *ctx) if(svc->action == SVC_ACTION_NORMAL) { // default action key.backend_slot = sock_select_random_slot(svc->count); } else if(svc->action == SVC_ACTION_WEIGHT) { - int slot_index = sock_select_weighted_slot(svc->count, key); + int slot_index = sock_fast_select_weighted_slot(svc->count, key); if(slot_index < 0) return slot_index; key.backend_slot = slot_index; } else if(svc->action & SVC_ACTION_REDIRECT_SVC) { - int slot_index = sock_select_weighted_slot(svc->count + 1, key); + int slot_index = sock_fast_select_weighted_slot(svc->count + 1, key); if(slot_index > svc->count) { key.backend_slot = slot_index; // 3. lookup backend slot from constructed backend key backend_slot = lookup_lb4_backend_slot(&key); if (!backend_slot) return -ENOENT; - bpf_printk("3.5. find backend slot: %d", backend_slot->backend_id); + // bpf_printk("3.5. find backend slot: %d", backend_slot->backend_id); backend_id = backend_slot->backend_id; // 4. find the info of real backend @@ -76,7 +76,7 @@ static int sock4_forward_entry(struct bpf_sock_addr *ctx) key.backend_slot = 0; key.address = backend->address; key.dport = backend->port; - slot_index = sock_select_weighted_slot(svc->count, key); + slot_index = sock_fast_select_weighted_slot(svc->count, key); if(slot_index < 0) return slot_index; key.backend_slot = slot_index; diff --git a/eBPF_Supermarket/TrafficManager/bpf/connect.go b/eBPF_Supermarket/TrafficManager/bpf/connect.go index a94277493..4f3b00315 100644 --- a/eBPF_Supermarket/TrafficManager/bpf/connect.go +++ b/eBPF_Supermarket/TrafficManager/bpf/connect.go @@ -21,6 +21,7 @@ package bpf import ( "bufio" "fmt" + "math" "net" "os" "strconv" @@ -146,7 +147,7 @@ func (p *Programs) InsertServiceItem(serviceIP string, servicePort string, backe } serviceKey := NewService4Key(net.ParseIP(serviceIP), uint16(servicePortInt), u8proto.ANY, 0, 0) // use index 0 to indicate service item, of course the possibility is zero, which is never be used - serviceValue := NewService4Value(Backend4Key{0}, uint16(backendNumber), Possibility{0}, action) + serviceValue := NewService4Value(Backend4Key{0}, uint16(backendNumber), Possibility{0, 0}, action) err = p.connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Update(serviceKey.ToNetwork(), serviceValue.ToNetwork(), ebpf.UpdateAny) if err != nil { fmt.Println("[ERROR] InsertServiceItem: connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Update failed: ", err) @@ -170,12 +171,12 @@ func (p *Programs) DeleteServiceItem(serviceIP string, servicePort int, slotInde } // InsertBackendItem inserts backend item into service map and backend map -func (p *Programs) InsertBackendItem(serviceIP string, servicePort int, backendIP string, backendPort int, backendID int, slotIndex int, possibility float64) bool { +func (p *Programs) InsertBackendItem(serviceIP string, servicePort int, backendIP string, backendPort int, backendID int, slotIndex int, possibility float64, possibilityUpperBound float64) bool { // Use allocated backendID to point to and store backend information backendKey := Backend4Key{uint32(backendID)} backendServiceKey := NewService4Key(net.ParseIP(serviceIP), uint16(servicePort), u8proto.ANY, 0, uint16(slotIndex)) // We don't specify action for backendItem, but it seems that it can be expanded in the future. - backendServiceValue := NewService4Value(backendKey, 0, Possibility{possibility}, DefaultAction) + backendServiceValue := NewService4Value(backendKey, 0, Possibility{possibility, possibilityUpperBound}, DefaultAction) err := p.connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Update(backendServiceKey.ToNetwork(), backendServiceValue.ToNetwork(), ebpf.UpdateAny) if err != nil { fmt.Println("[ERROR] InsertBackendItem: connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Update failed:", err) @@ -210,12 +211,20 @@ func (p *Programs) AutoInsertService(service Service, backendList []Backend, act if action != RedirectAction { affiliatedServiceList = nil } + + totalPercentage := 0.0 p.InsertServiceItem(service.IP, service.Port, len(backendList), action) // +len(affiliatedServiceList) for i, backend := range backendList { - p.AutoInsertBackend(service.IP, service.Port, backend.IP, backend.Port, i+1, backend.Possibility) + totalPercentage += backend.Possibility + p.AutoInsertBackend(service.IP, service.Port, backend.IP, backend.Port, i+1, backend.Possibility, totalPercentage) + } for i, affiliatedService := range affiliatedServiceList { - p.AutoInsertBackend(service.IP, service.Port, affiliatedService.IP, affiliatedService.Port, len(backendList)+i+1, affiliatedService.Possibility) + totalPercentage += affiliatedService.Possibility + p.AutoInsertBackend(service.IP, service.Port, affiliatedService.IP, affiliatedService.Port, len(backendList)+i+1, affiliatedService.Possibility, totalPercentage) + } + if math.Abs(totalPercentage-1) > 0.005 { + fmt.Printf("[WARNING] Total weight for service %s:%s is not 1, but %f.\n", service.IP, service.Port, totalPercentage) } } @@ -228,7 +237,7 @@ func (p *Programs) AutoDeleteService(service Service, affiliatedServiceList []Se return false } serviceKey := NewService4Key(net.ParseIP(serviceIP), uint16(servicePort), u8proto.ANY, 0, 0) - serviceValue := NewService4Value(Backend4Key{0}, uint16(0), Possibility{0}, DefaultAction) + serviceValue := NewService4Value(Backend4Key{0}, uint16(0), Possibility{0, 0}, DefaultAction) err = p.connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup(serviceKey.ToNetwork(), serviceValue) if err != nil { fmt.Println("[ERROR] AutoDeleteService: connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup failed:", err) @@ -238,13 +247,13 @@ func (p *Programs) AutoDeleteService(service Service, affiliatedServiceList []Se p.DeleteServiceItem(serviceIP, servicePort, 0) for i := 1; i <= int(serviceValue.Count); i++ { backendServiceKey := NewService4Key(net.ParseIP(serviceIP), uint16(servicePort), u8proto.ANY, 0, uint16(i)) - backendServiceValue := NewService4Value(Backend4Key{uint32(0)}, 0, Possibility{0}, DefaultAction) + backendServiceValue := NewService4Value(Backend4Key{uint32(0)}, 0, Possibility{0, 0}, DefaultAction) err := p.connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup(backendServiceKey.ToNetwork(), backendServiceValue) if err != nil { fmt.Println("[WARNING] AutoDeleteService: connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup failed:", err) break } - fmt.Printf("[DEBUG] To delete backend backend service: backendServiceKey: %s, backendServiceValue: %s\n", backendServiceKey.String(), backendServiceValue.String()) + fmt.Printf("[DEBUG] To delete backend service: backendServiceKey: %s, backendServiceValue: %s\n", backendServiceKey.String(), backendServiceValue.String()) p.AutoDeleteBackend(int(backendServiceValue.BackendID.ID)) p.DeleteServiceItem(serviceIP, servicePort, i) } @@ -254,7 +263,7 @@ func (p *Programs) AutoDeleteService(service Service, affiliatedServiceList []Se return false } backendServiceKey := NewService4Key(net.ParseIP(serviceIP), uint16(servicePort), u8proto.ANY, 0, uint16(int(serviceValue.Count)+i+1)) - backendServiceValue := NewService4Value(Backend4Key{uint32(0)}, 0, Possibility{0}, DefaultAction) + backendServiceValue := NewService4Value(Backend4Key{uint32(0)}, 0, Possibility{0, 0}, DefaultAction) err = p.connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup(backendServiceKey.ToNetwork(), backendServiceValue) if err != nil { fmt.Println("[WARNING] AutoDeleteService: connectObj.bpf_connectMaps.LB4SERVICES_MAP_V2.Lookup failed:", err) @@ -277,11 +286,11 @@ func (p *Programs) DeclareBackendID() int { } // AutoInsertBackend inserts an organized backend item into map -func (p *Programs) AutoInsertBackend(serviceIP string, servicePortStr string, backendIP string, backendPortStr string, slotIndex int, possibility float64) (bool, int) { +func (p *Programs) AutoInsertBackend(serviceIP string, servicePortStr string, backendIP string, backendPortStr string, slotIndex int, possibility float64, possibilityUpperBound float64) (bool, int) { backendID := p.DeclareBackendID() servicePort, _ := strconv.Atoi(servicePortStr) backendPort, _ := strconv.Atoi(backendPortStr) - ok := p.InsertBackendItem(serviceIP, servicePort, backendIP, backendPort, backendID, slotIndex, possibility) + ok := p.InsertBackendItem(serviceIP, servicePort, backendIP, backendPort, backendID, slotIndex, possibility, possibilityUpperBound) if ok { p.backEndSet[backendID] = true fmt.Printf("[INFO] AutoInsertBackend succeeded: serviceIP: %s, servicePort: %d, backendIP: %s, backendPort: %d, backendID: %d, slotIndex: %d, possibility: %.2f\n", serviceIP, servicePort, backendIP, backendPort, backendID, slotIndex, possibility) diff --git a/eBPF_Supermarket/TrafficManager/bpf/connect.h b/eBPF_Supermarket/TrafficManager/bpf/connect.h index c588f65f5..49ef603e4 100644 --- a/eBPF_Supermarket/TrafficManager/bpf/connect.h +++ b/eBPF_Supermarket/TrafficManager/bpf/connect.h @@ -75,7 +75,7 @@ struct lb4_service { __u16 count; __u16 possibility; __u16 action; - __u8 pad[2]; + __u16 weight_range_upper; }; struct lb4_backend { @@ -186,4 +186,29 @@ static __always_inline int sock_select_weighted_slot(int sbc, struct lb4_key key return -ENOENT; } return key.backend_slot; +} + +static __always_inline int sock_fast_select_weighted_slot(int sbc, struct lb4_key key) +{ + int l = 1, r = sbc; + struct lb4_service *backend_slot; + int random_point = bpf_get_prandom_u32() % MAX_BACKEND_SELECTION; + for(int i = 0; i < 10; i++) { // 10 = log_2(MAX_BACKEND_SELECTION) + if(l == r) return l; + int mid = (l + r) >> 1; + bpf_printk("%d", mid); + key.backend_slot = mid; + backend_slot = lookup_lb4_backend_slot(&key); + if (!backend_slot) + return -ENOENT; + if(backend_slot->weight_range_upper == random_point) { + if(backend_slot->possibility > 0) return mid; + // We can not reach here except setting the item's weight to 0, + // then we have a probability of triggering this + else return -ENOENT; + } + else if(backend_slot->weight_range_upper < random_point) l = mid + 1; + else r = mid; + } + return -ENOENT; // infinite loop } \ No newline at end of file diff --git a/eBPF_Supermarket/TrafficManager/bpf/type.go b/eBPF_Supermarket/TrafficManager/bpf/type.go index fa2505c3d..2297b9a2f 100644 --- a/eBPF_Supermarket/TrafficManager/bpf/type.go +++ b/eBPF_Supermarket/TrafficManager/bpf/type.go @@ -73,7 +73,7 @@ func (k *Service4Key) String() string { addr += "/i" } if k.BackendSlot != 0 { - addr += " slot:" + strconv.Itoa(int(k.BackendSlot)) + addr += " slot: " + strconv.Itoa(int(k.BackendSlot)) } return addr } @@ -91,19 +91,20 @@ type ActionAttribute struct { } type Service4Value struct { - BackendID Backend4Key `align:"backend_id"` - Count uint16 `align:"count"` - Possibility uint16 `align:"possibility"` - Action Action `align:"action"` - Pad pad2uint8 `align:"pad"` + BackendID Backend4Key `align:"backend_id"` + Count uint16 `align:"count"` + Possibility uint16 `align:"possibility"` + Action Action `align:"action"` + WeightRangeUpper uint16 `align:"weight_range_upper"` } func NewService4Value(backendId Backend4Key, count uint16, possibility Possibility, action Action) *Service4Value { value := Service4Value{ - BackendID: backendId, - Count: count, - Possibility: uint16(possibility.percentage * maxPossibilityUnit), - Action: action, + BackendID: backendId, + Count: count, + Possibility: uint16(possibility.percentage * maxPossibilityUnit), + Action: action, + WeightRangeUpper: uint16(possibility.currentPercentageRangeUpper * maxPossibilityUnit), } return &value @@ -160,7 +161,8 @@ func (v *Backend4Value) ToNetwork() *Backend4Value { } type Possibility struct { - percentage float64 + percentage float64 + currentPercentageRangeUpper float64 } // func tes() {