-
Notifications
You must be signed in to change notification settings - Fork 171
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
init(trafficManager): initialize basic development framework
- Loading branch information
Showing
10 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
name: Traffic Manager | ||
|
||
on: | ||
push: | ||
branches: | ||
- "*" | ||
paths: | ||
- 'eBPF_Supermarket/TrafficManager/**' | ||
- '.github/workflows/net_traffic_manager.yml' | ||
pull_request: | ||
branches: | ||
- "*" | ||
paths: | ||
- 'eBPF_Supermarket/TrafficManager/**' | ||
- '.github/workflows/net_traffic_manager.yml' | ||
|
||
jobs: | ||
build-and-test: | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Cache bpftool build directory | ||
id: cache-bpftool | ||
uses: actions/cache@v3 | ||
with: | ||
path: bpftool | ||
key: ${{ runner.os }}-bpftool | ||
|
||
# - name: Cache go pkg directory | ||
# id: cache-go | ||
# uses: actions/cache@v3 | ||
# with: | ||
# path: ${{ GOPATH }} | ||
# key: ${{ runner.os }}-go | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v4 | ||
with: | ||
go-version-file: eBPF_Supermarket/TrafficManager/go.mod | ||
cache-dependency-path: eBPF_Supermarket/TrafficManager/go.sum | ||
|
||
# - name: Install Docker | ||
# run: | | ||
# sudo snap refresh | ||
# sudo snap install docker | ||
|
||
# - name: Install Minikube | ||
# run: | | ||
# sudo snap install kubectl --classic | ||
# curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 | ||
# sudo install minikube-linux-amd64 /usr/local/bin/minikube | ||
# sudo minikube start --kubernetes-version=1.26.6 --force | ||
|
||
- name: Install eBPF development tools | ||
run: | | ||
sudo apt install -y llvm clang | ||
- name: Build bpftool | ||
if: steps.cache-bpftool.outputs.cache-hit != 'false' | ||
run: | | ||
rm -rf bpftool/ | ||
sudo apt install libbfd-dev libcap-dev libelf-dev | ||
git clone --recurse-submodules https://github.com/libbpf/bpftool.git | ||
sudo make install -C bpftool/src/ | ||
- name: Install bpftool | ||
run: | | ||
sudo cp bpftool/src/bpftool /usr/bin/ | ||
- name: Load Dependency | ||
run: | | ||
cd eBPF_Supermarket/TrafficManager/ | ||
sudo go mod tidy | ||
- name: Build | ||
run: | | ||
cd eBPF_Supermarket/TrafficManager/ | ||
sudo make init | ||
sudo make build | ||
- name: Run | ||
run: | | ||
cd eBPF_Supermarket/TrafficManager/ | ||
sudo -E timeout 10 ./main || if [[ $? != 124 && $? != 0 ]]; then exit $?; fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.idea | ||
.vscode | ||
|
||
bpf/headers/vmlinux.h | ||
|
||
bpf/headers/bpf/* | ||
!bpf/headers/bpf/update.sh | ||
|
||
*.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Install tutorial | ||
|
||
## Ubuntu 22.04 | ||
|
||
```bash | ||
# Install Go | ||
wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz | ||
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz | ||
export PATH=$PATH:/usr/local/go/bin | ||
|
||
# Install Docker | ||
sudo snap refresh | ||
sudo snap install docker | ||
|
||
# Install and start local Kubernetes | ||
sudo snap install kubectl --classic | ||
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 | ||
sudo install minikube-linux-amd64 /usr/local/bin/minikube | ||
sudo minikube start --kubernetes-version=1.26.6 --force | ||
|
||
# Install eBPF development tools | ||
sudo apt install -y llvm clang | ||
sudo apt install libbfd-dev libcap-dev libelf-dev | ||
git clone --recurse-submodules https://github.com/libbpf/bpftool.git | ||
sudo make install -C bpftool/src/ | ||
sudo cp bpftool/src/bpftool /usr/bin/ | ||
sudo rm -rf bpftool/ | ||
``` | ||
|
||
```bash | ||
sudo make init | ||
sudo make | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.DEFAULT_GOAL := all | ||
|
||
all: build | ||
sudo ./main | ||
|
||
build: | ||
cd bpf; go generate; | ||
go build -o main main.go | ||
|
||
init: | ||
cd bpf/headers/bpf/; ./update.sh | ||
cd bpf/headers/; bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h | ||
cd bpf; go generate; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// +build ignore | ||
|
||
#include "connect.h" | ||
|
||
const __be32 service_ip = 0x846F070A; // 10.7.111.132 | ||
const __be32 pod_ip = 0x0100007F; // 127.0.0.1 | ||
const __be16 service_port = 0x5000; // 80 (0x0 * 256 + 0x50) | ||
const __be16 pod_port = 0x901f; // 8080 (0x1f * 256 + 0x144) | ||
|
||
static int sock4_forward_entry(struct bpf_sock_addr *ctx) | ||
{ | ||
__be32 ori_dst_ip = ctx_get_dst_ip(ctx); | ||
__be16 ori_dst_port = ctx_get_dst_port(ctx); | ||
|
||
bpf_printk("original: %08x:%04x", ori_dst_ip, ori_dst_port); | ||
bpf_printk("service: %08x:%04x", service_ip, service_port); | ||
bpf_printk("pod: %08x:%04x", pod_ip, pod_port); | ||
|
||
if(ori_dst_ip == service_ip && ori_dst_port == service_port) | ||
{ | ||
bpf_printk("redirect to %08x:%04x", pod_ip, pod_port); | ||
ctx_set_ip(ctx, pod_ip); | ||
ctx_set_port(ctx, pod_port); | ||
} | ||
else | ||
{ | ||
bpf_printk("skipped, not modified"); | ||
} | ||
return 0; | ||
} | ||
|
||
SEC("cgroup/connect4") | ||
int sock4_connect(struct bpf_sock_addr *ctx) | ||
{ | ||
sock4_forward_entry(ctx); | ||
return SYS_PROCEED; | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package bpf | ||
|
||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -target bpf -cflags "-D__TARGET_ARCH_x86" bpf_connect connect.c -- -I./headers | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os" | ||
"os/signal" | ||
"strings" | ||
|
||
"github.com/cilium/ebpf" | ||
"github.com/cilium/ebpf/link" | ||
"github.com/cilium/ebpf/rlimit" | ||
) | ||
|
||
const MapsPinPath = "/sys/fs/bpf/sock_ops_map" | ||
|
||
type Programs struct { | ||
connectObj bpf_connectObjects | ||
connectCgroup link.Link | ||
backEndSet map[int]bool | ||
currentIndex int | ||
} | ||
|
||
// DetectCgroupPath returns the first-found mount point of type cgroup2 | ||
func DetectCgroupPath() (string, error) { | ||
f, err := os.Open("/proc/mounts") | ||
if err != nil { | ||
return "", err | ||
} | ||
defer f.Close() | ||
|
||
scanner := bufio.NewScanner(f) | ||
for scanner.Scan() { | ||
// example fields: cgroup2 /sys/fs/cgroup/unified cgroup2 rw,nosuid,nodev,noexec,relatime 0 0 | ||
fields := strings.Split(scanner.Text(), " ") | ||
if len(fields) >= 3 && fields[2] == "cgroup2" { | ||
return fields[1], nil | ||
} | ||
} | ||
|
||
return "", fmt.Errorf("cgroup2 not mounted") | ||
} | ||
|
||
func LoadProgram() (Programs, error) { | ||
var programs Programs | ||
var options ebpf.CollectionOptions | ||
options.Maps.PinPath = MapsPinPath | ||
|
||
// Allow the current process to lock memory for eBPF resources. | ||
err := rlimit.RemoveMemlock() | ||
if err != nil { | ||
fmt.Println("[ERROR] Setting limit failed:", err) | ||
return Programs{}, fmt.Errorf("setting limit failed: %s", err) | ||
} | ||
|
||
err = os.Mkdir(MapsPinPath, os.ModePerm) | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
|
||
err = loadBpf_connectObjects(&programs.connectObj, &options) | ||
if err != nil { | ||
return Programs{}, fmt.Errorf("error load objects: %s\n", err) | ||
} | ||
|
||
programs.backEndSet = make(map[int]bool) | ||
programs.currentIndex = 0 | ||
|
||
return programs, err | ||
} | ||
|
||
func (p *Programs) Attach() error { | ||
fmt.Println("Socket redirect started!") | ||
|
||
cgroupPath, err := DetectCgroupPath() | ||
if err != nil { | ||
return fmt.Errorf("detect cgroup path failed: %s", err) | ||
} | ||
|
||
p.connectCgroup, err = link.AttachCgroup(link.CgroupOptions{ | ||
Path: cgroupPath, | ||
Attach: ebpf.AttachCGroupInet4Connect, | ||
Program: p.connectObj.bpf_connectPrograms.Sock4Connect, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("error attaching connect to cgroup: %s", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *Programs) Close() { | ||
fmt.Println("Exiting...") | ||
|
||
if p.connectCgroup != nil { | ||
fmt.Printf("Closing connect cgroup...\n") | ||
p.connectCgroup.Close() | ||
} | ||
|
||
_ = os.Remove(MapsPinPath) | ||
} | ||
|
||
func Sample() { | ||
progs, err := LoadProgram() | ||
if err != nil { | ||
fmt.Println("[ERROR] Loading program failed:", err) | ||
return | ||
} | ||
|
||
err = progs.Attach() | ||
if err != nil { | ||
fmt.Println("[ERROR] Attaching failed:", err) | ||
} | ||
defer progs.Close() | ||
|
||
c := make(chan os.Signal, 1) | ||
signal.Notify(c) | ||
<-c | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#include "vmlinux.h" | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_endian.h> | ||
|
||
#define SYS_PROCEED 1 | ||
|
||
// sudo cat /sys/kernel/debug/tracing/trace_pipe | ||
|
||
#define print_ip_formatted(ip) \ | ||
({ \ | ||
bpf_printk("ip1: %d.%d", \ | ||
ip%256, (ip/256)%256); \ | ||
bpf_printk("ip2: %d.%d\n", \ | ||
(ip/65536)%256, (ip/16711680)%256); \ | ||
}) | ||
|
||
static __always_inline __be32 ctx_get_dst_ip(const struct bpf_sock_addr *ctx) | ||
{ | ||
volatile __u32 dst_ip = ctx->user_ip4; | ||
return (__be32)dst_ip; | ||
} | ||
|
||
static __always_inline __be16 ctx_get_dst_port(const struct bpf_sock_addr *ctx) | ||
{ | ||
volatile __u32 dport = ctx->user_port; | ||
return (__be16)dport; | ||
} | ||
|
||
static __always_inline void ctx_set_ip(struct bpf_sock_addr *ctx, __be32 dst_ip) | ||
{ | ||
ctx->user_ip4 = (__u32)dst_ip; | ||
} | ||
|
||
static __always_inline void ctx_set_port(struct bpf_sock_addr *ctx, __be16 dport) | ||
{ | ||
ctx->user_port = (__u32)dport; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Version of libbpf to fetch headers from | ||
LIBBPF_VERSION=1.0.0 | ||
|
||
# The headers we want | ||
prefix=libbpf-"$LIBBPF_VERSION" | ||
headers=( | ||
"$prefix"/LICENSE.BSD-2-Clause | ||
"$prefix"/src/bpf_endian.h | ||
"$prefix"/src/bpf_helper_defs.h | ||
"$prefix"/src/bpf_helpers.h | ||
"$prefix"/src/bpf_tracing.h | ||
) | ||
|
||
# Fetch libbpf release and extract the desired headers | ||
curl -sL "https://github.com/libbpf/libbpf/archive/refs/tags/v${LIBBPF_VERSION}.tar.gz" | \ | ||
tar -xz --xform='s#.*/##' "${headers[@]}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module github.com/eswzy/eTrafficManager | ||
|
||
go 1.20 | ||
|
||
require github.com/cilium/ebpf v0.10.0 | ||
|
||
require golang.org/x/sys v0.7.0 // indirect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/eswzy/eTrafficManager/bpf" | ||
) | ||
|
||
func main() { | ||
bpf.Sample() | ||
} |