Skip to content

Commit

Permalink
feat(trafficManager): action redirecting to another service
Browse files Browse the repository at this point in the history
  • Loading branch information
ESWZY committed Sep 13, 2023
1 parent 9fdae0a commit 32b8716
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 126 deletions.
5 changes: 2 additions & 3 deletions eBPF_Supermarket/TrafficManager/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,5 @@ test:
kubectl get nodes
kubectl get pods -owide -A
kubectl get services

sudo go test -c acceptance/performance_test.go
sudo ./acceptance.test
sudo make build
sudo go test -v ./...
2 changes: 1 addition & 1 deletion eBPF_Supermarket/TrafficManager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ minikube start --kubernetes-version=1.26.6 --force

# Install eBPF development tools
apt update -y
apt install -y llvm clang
apt install -y llvm clang make gcc
apt install -y libbfd-dev libcap-dev libelf-dev
git clone --recurse-submodules https://github.com/libbpf/bpftool.git
make install -C bpftool/src/
Expand Down
54 changes: 54 additions & 0 deletions eBPF_Supermarket/TrafficManager/acceptance/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2023 The LMP 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
//
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: Woa <[email protected]>

package acceptance

import (
"fmt"
"log"
"net/http"
"strings"
)

type Router struct {
Route map[string]map[string]http.HandlerFunc
}

func (r *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if f, ok := r.Route[request.Method][request.URL.Path]; ok {
f(writer, request)
}
}

func (r *Router) HandleFunc(method, path string, f http.HandlerFunc) {
method = strings.ToUpper(method)
if r.Route == nil {
r.Route = make(map[string]map[string]http.HandlerFunc)
}
if r.Route[method] == nil {
r.Route[method] = make(map[string]http.HandlerFunc)
}
r.Route[method][path] = f
}

func startServer(portStr string) {
route := Router{}
route.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, portStr)
})

log.Fatal(http.ListenAndServe("localhost:"+portStr, &route))
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ 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))
programs.InsertServiceItem(service.Spec.ClusterIP, strconv.Itoa(int(service.Spec.Ports[0].Port)), len(pods.Items), bpf.RandomAction)
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))))
Expand Down
132 changes: 132 additions & 0 deletions eBPF_Supermarket/TrafficManager/acceptance/redirect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright 2023 The LMP 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
//
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: Woa <[email protected]>

package acceptance

import (
"fmt"
"io"
"net/http"
"testing"

"lmp/eTrafficManager/bpf"
)

func TestRedirect(t *testing.T) {
var serverPortList = []string{
"8001",
"8002",
"8003",
"8004",
"8005",
}

var repeatNum int64 = 125000
for _, s := range serverPortList {
go startServer(s)
}

progs, err := bpf.LoadProgram()
if err != nil {
fmt.Println("[ERROR] Loading program failed:", err)
return
}
s := bpf.Service{
IP: "1.1.1.1",
Port: "80",
Possibility: 0.75,
}
b := []bpf.Backend{
{
IP: "127.0.0.1",
Port: "8001",
Possibility: 0.25,
}, {
IP: "127.0.0.1",
Port: "8002",
Possibility: 0.75,
},
}
progs.AutoInsertService(s, b, bpf.WeightedAction, nil)

s2 := bpf.Service{
IP: "127.0.0.1",
Port: "8003",
}
b2 := []bpf.Backend{
{
IP: "127.0.0.1",
Port: "8004",
Possibility: 0.125,
},
{
IP: "127.0.0.1",
Port: "8005",
Possibility: 0.125,
},
}

progs.AutoInsertService(s2, b2, bpf.RedirectAction, []bpf.Service{s})

err = progs.Attach()
if err != nil {
fmt.Println("[ERROR] Attaching failed:", err)
}

countBucket := make(map[string]int)

for i := 0; i < int(repeatNum); i++ {
client := &http.Client{
Transport: &http.Transport{
// We must set DisableKeepAlives, otherwise all requests will be in one HTTP connection
DisableKeepAlives: true,
},
}

url := "http://" + "127.0.0.1:8003"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}

resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}

// fmt.Println("Response:", string(body))
countBucket[string(body)] += 1
}

for i := 0; i < len(serverPortList); i++ {
actualNumber := float64(countBucket[serverPortList[i]])
fmt.Printf("For port: %s, got actualNumber: %d.\n", serverPortList[i], int64(actualNumber))
}

fmt.Println("[INFO] Test is done...")
progs.AutoDeleteService(s, nil)
progs.AutoDeleteService(s2, []bpf.Service{s})
progs.Close()
}
86 changes: 26 additions & 60 deletions eBPF_Supermarket/TrafficManager/acceptance/weight_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,27 @@ package acceptance
import (
"fmt"
"io"
"log"
"math"
"net/http"
"strings"
"testing"

"lmp/eTrafficManager/bpf"
)

type testCase struct {
weights []float64
repeatNum int64
}

const (
targetIP = "1.1.1.1"
targetPort = "80"
)

var serverPortList = []string{
"8001",
"8002",
"8003",
}
func TestWeight(t *testing.T) {
const (
targetIP = "1.1.1.1"
targetPort = "80"
)

var serverPortList = []string{
"7001",
"7002",
"7003",
}

var repeatNum int64 = 10000
var repeatNum int64 = 10000

func TestWeight(t *testing.T) {
go startServer(serverPortList[0])
go startServer(serverPortList[1])
go startServer(serverPortList[2])
Expand All @@ -56,7 +49,10 @@ func TestWeight(t *testing.T) {
// _ = c1.Start()
// }()

for _, tc := range []testCase{
for _, tc := range []struct {
weights []float64
repeatNum int64
}{
{
weights: []float64{
1,
Expand Down Expand Up @@ -99,17 +95,17 @@ func TestWeight(t *testing.T) {
},
{
weights: []float64{
0.33333,
0.33333,
0.33333,
0.25,
0.25,
0.5,
},
repeatNum: repeatNum,
},
{
weights: []float64{
0.2,
0.3,
0.5,
0.125,
0.25,
0.625,
},
repeatNum: repeatNum,
},
Expand All @@ -120,7 +116,7 @@ func TestWeight(t *testing.T) {
return
}

progs.InsertServiceItem(targetIP, targetPort, len(serverPortList))
progs.InsertServiceItem(targetIP, targetPort, len(serverPortList), bpf.WeightedAction)
for i := 0; i < len(serverPortList); i++ {
progs.AutoInsertBackend(targetIP, targetPort, "127.0.0.1", serverPortList[i], i+1, tc.weights[i])
}
Expand Down Expand Up @@ -167,10 +163,10 @@ func TestWeight(t *testing.T) {
for i := 0; i < len(serverPortList); i++ {
expectNumber := tc.weights[i] * float64(tc.repeatNum)
actualNumber := float64(countBucket[serverPortList[i]])
if math.Abs(actualNumber-expectNumber)/expectNumber > 0.05 && false {
if math.Abs(actualNumber-expectNumber)/expectNumber > 0.05 {
t.Errorf("For port: %s, expectNumber: %f, but actualNumber: %d, rate: %f. Maybe retesting will fix this", serverPortList[i], expectNumber, int64(actualNumber), math.Abs(actualNumber-expectNumber)/expectNumber)
} else {
fmt.Printf("For port: %s, expectNumber: %f, but actualNumber: %d, rate: %f.\n", serverPortList[i], expectNumber, int64(actualNumber), math.Abs(actualNumber-expectNumber)/expectNumber)
fmt.Printf("For port: %s, expectNumber: %f, got actualNumber: %d, rate: %f.\n", serverPortList[i], expectNumber, int64(actualNumber), math.Abs(actualNumber-expectNumber)/expectNumber)
}
}

Expand All @@ -179,37 +175,7 @@ func TestWeight(t *testing.T) {
IP: targetIP,
Port: targetPort,
}
progs.AutoDeleteService(s)
progs.AutoDeleteService(s, nil)
progs.Close()
}
}

type Router struct {
Route map[string]map[string]http.HandlerFunc
}

func (r *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if f, ok := r.Route[request.Method][request.URL.Path]; ok {
f(writer, request)
}
}

func (r *Router) HandleFunc(method, path string, f http.HandlerFunc) {
method = strings.ToUpper(method)
if r.Route == nil {
r.Route = make(map[string]map[string]http.HandlerFunc)
}
if r.Route[method] == nil {
r.Route[method] = make(map[string]http.HandlerFunc)
}
r.Route[method][path] = f
}

func startServer(portStr string) {
route := Router{}
route.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, portStr)
})

log.Fatal(http.ListenAndServe("localhost:"+portStr, &route))
}
3 changes: 1 addition & 2 deletions eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified eBPF_Supermarket/TrafficManager/bpf/bpf_connect_bpf.o
Binary file not shown.
Loading

0 comments on commit 32b8716

Please sign in to comment.