主从同步性能优化,主从同步性能测试。
This commit is contained in:
18
ebpf/old.c/.gitignore
vendored
Normal file
18
ebpf/old.c/.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/.output
|
||||
/bootstrap
|
||||
/bootstrap_legacy
|
||||
/minimal
|
||||
/minimal_legacy
|
||||
/minimal_ns
|
||||
/uprobe
|
||||
/kprobe
|
||||
/fentry
|
||||
/profile
|
||||
/usdt
|
||||
/sockfilter
|
||||
/tc
|
||||
/ksyscall
|
||||
/task_iter
|
||||
/lsm
|
||||
/cmake-build-debug/
|
||||
/cmake-build-release/
|
||||
133
ebpf/old.c/CMakeLists.txt
Normal file
133
ebpf/old.c/CMakeLists.txt
Normal file
@@ -0,0 +1,133 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(examples C)
|
||||
|
||||
# Tell cmake where to find BpfObject module
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/cmake)
|
||||
|
||||
# Build vendored libbpf
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(libbpf
|
||||
PREFIX libbpf
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../libbpf/src
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND make
|
||||
CC=${CMAKE_C_COMPILER}
|
||||
BUILD_STATIC_ONLY=1
|
||||
OBJDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf
|
||||
DESTDIR=${CMAKE_CURRENT_BINARY_DIR}/libbpf
|
||||
INCLUDEDIR=
|
||||
LIBDIR=
|
||||
UAPIDIR=
|
||||
install install_uapi_headers
|
||||
BUILD_IN_SOURCE TRUE
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS build
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf.a
|
||||
)
|
||||
|
||||
ExternalProject_Add(bpftool
|
||||
PREFIX bpftool
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../bpftool/src
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND make bootstrap
|
||||
OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/bpftool/
|
||||
BUILD_IN_SOURCE TRUE
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS build
|
||||
)
|
||||
|
||||
find_program(CARGO_EXISTS cargo)
|
||||
if(CARGO_EXISTS)
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
# Determine target triple
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||
set(CARGO_TARGET "x86_64-unknown-linux-gnu")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(CARGO_TARGET "aarch64-unknown-linux-gnu")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported processor for Linux: ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER)
|
||||
set(RUST_LINKER ${CMAKE_CXX_COMPILER})
|
||||
else()
|
||||
set(RUST_LINKER ${CMAKE_C_COMPILER})
|
||||
endif()
|
||||
else()
|
||||
message((FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}"))
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(blazesym
|
||||
PREFIX blazesym
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../blazesym
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E env
|
||||
RUSTFLAGS=-C\ linker=${RUST_LINKER}
|
||||
cargo build --package=blazesym-c --release --target=${CARGO_TARGET}
|
||||
BUILD_IN_SOURCE TRUE
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS build
|
||||
)
|
||||
else() # Host
|
||||
ExternalProject_Add(blazesym
|
||||
PREFIX blazesym
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../blazesym
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND
|
||||
cargo build --package=blazesym-c --release
|
||||
BUILD_IN_SOURCE TRUE
|
||||
INSTALL_COMMAND ""
|
||||
STEP_TARGETS build
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set BpfObject input parameters -- note this is usually not necessary unless
|
||||
# you're in a highly vendored environment (like libbpf-bootstrap)
|
||||
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
|
||||
set(ARCH "x86")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm")
|
||||
set(ARCH "arm")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
|
||||
set(ARCH "arm64")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64le")
|
||||
set(ARCH "powerpc")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips")
|
||||
set(ARCH "mips")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "riscv64")
|
||||
set(ARCH "riscv")
|
||||
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64")
|
||||
set(ARCH "loongarch")
|
||||
endif()
|
||||
|
||||
set(BPFOBJECT_BPFTOOL_EXE ${CMAKE_CURRENT_BINARY_DIR}/bpftool/bootstrap/bpftool)
|
||||
set(BPFOBJECT_VMLINUX_H ${CMAKE_CURRENT_SOURCE_DIR}/../../vmlinux.h/include/${ARCH}/vmlinux.h)
|
||||
set(LIBBPF_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/libbpf)
|
||||
set(LIBBPF_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/libbpf/libbpf.a)
|
||||
find_package(BpfObject REQUIRED)
|
||||
|
||||
# Create an executable for each application
|
||||
file(GLOB apps *.bpf.c)
|
||||
if(NOT CARGO_EXISTS)
|
||||
list(REMOVE_ITEM apps ${CMAKE_CURRENT_SOURCE_DIR}/profile.bpf.c)
|
||||
endif()
|
||||
foreach(app ${apps})
|
||||
get_filename_component(app_stem ${app} NAME_WE)
|
||||
|
||||
# Build object skeleton and depend skeleton on libbpf build
|
||||
bpf_object(${app_stem} ${app_stem}.bpf.c)
|
||||
add_dependencies(${app_stem}_skel libbpf bpftool)
|
||||
|
||||
add_executable(${app_stem} ${app_stem}.c)
|
||||
target_link_libraries(${app_stem} ${app_stem}_skel)
|
||||
if(${app_stem} STREQUAL profile)
|
||||
target_include_directories(${app_stem} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../blazesym/capi/include)
|
||||
target_link_libraries(${app_stem}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../blazesym/target/${CARGO_TARGET}/release/libblazesym_c.a -lpthread -lrt -ldl)
|
||||
add_dependencies(${app_stem} blazesym)
|
||||
endif()
|
||||
endforeach()
|
||||
139
ebpf/old.c/Makefile
Normal file
139
ebpf/old.c/Makefile
Normal file
@@ -0,0 +1,139 @@
|
||||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
OUTPUT := .output
|
||||
CLANG ?= clang
|
||||
LIBBPF_SRC := $(abspath ../../libbpf/src)
|
||||
BPFTOOL_SRC := $(abspath ../../bpftool/src)
|
||||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
|
||||
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
|
||||
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
|
||||
LIBBLAZESYM_SRC := $(abspath ../../blazesym/)
|
||||
LIBBLAZESYM_INC := $(abspath $(LIBBLAZESYM_SRC)/capi/include)
|
||||
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym_c.a)
|
||||
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
|
||||
| sed 's/arm.*/arm/' \
|
||||
| sed 's/aarch64/arm64/' \
|
||||
| sed 's/ppc64le/powerpc/' \
|
||||
| sed 's/mips.*/mips/' \
|
||||
| sed 's/riscv64/riscv/' \
|
||||
| sed 's/loongarch64/loongarch/')
|
||||
VMLINUX := ../../vmlinux.h/include/$(ARCH)/vmlinux.h
|
||||
# Use our own libbpf API headers and Linux UAPI headers distributed with
|
||||
# libbpf to avoid dependency on system-wide headers, which could be missing or
|
||||
# outdated
|
||||
INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX)) -I$(LIBBLAZESYM_INC)
|
||||
CFLAGS := -g -Wall
|
||||
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)
|
||||
|
||||
# APPS = minimal minimal_legacy minimal_ns bootstrap bootstrap_legacy uprobe kprobe fentry \
|
||||
usdt sockfilter tc ksyscall task_iter lsm
|
||||
APPS = replica
|
||||
|
||||
CARGO ?= $(shell which cargo)
|
||||
ifeq ($(strip $(CARGO)),)
|
||||
BZS_APPS :=
|
||||
else
|
||||
BZS_APPS := profile
|
||||
APPS += $(BZS_APPS)
|
||||
# Required by libblazesym
|
||||
ALL_LDFLAGS += -lrt -ldl -lpthread -lm
|
||||
endif
|
||||
|
||||
# Get Clang's default includes on this system. We'll explicitly add these dirs
|
||||
# to the includes list when compiling with `-target bpf` because otherwise some
|
||||
# architecture-specific dirs will be "missing" on some architectures/distros -
|
||||
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h,
|
||||
# sys/cdefs.h etc. might be missing.
|
||||
#
|
||||
# Use '-idirafter': Don't interfere with include mechanics except where the
|
||||
# build would have failed anyways.
|
||||
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \
|
||||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
|
||||
|
||||
ifeq ($(V),1)
|
||||
Q =
|
||||
msg =
|
||||
else
|
||||
Q = @
|
||||
msg = @printf ' %-8s %s%s\n' \
|
||||
"$(1)" \
|
||||
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
|
||||
"$(if $(3), $(3))";
|
||||
MAKEFLAGS += --no-print-directory
|
||||
endif
|
||||
|
||||
define allow-override
|
||||
$(if $(or $(findstring environment,$(origin $(1))),\
|
||||
$(findstring command line,$(origin $(1)))),,\
|
||||
$(eval $(1) = $(2)))
|
||||
endef
|
||||
|
||||
$(call allow-override,CC,$(CROSS_COMPILE)cc)
|
||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||
|
||||
.PHONY: all
|
||||
all: $(APPS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(call msg,CLEAN)
|
||||
$(Q)rm -rf $(OUTPUT) $(APPS)
|
||||
|
||||
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
|
||||
$(call msg,MKDIR,$@)
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
# Build libbpf
|
||||
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
|
||||
$(call msg,LIB,$@)
|
||||
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
|
||||
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
|
||||
INCLUDEDIR= LIBDIR= UAPIDIR= \
|
||||
install
|
||||
|
||||
# Build bpftool
|
||||
$(BPFTOOL): | $(BPFTOOL_OUTPUT)
|
||||
$(call msg,BPFTOOL,$@)
|
||||
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap
|
||||
|
||||
|
||||
$(LIBBLAZESYM_SRC)/target/release/libblazesym_c.a::
|
||||
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --package=blazesym-c --release
|
||||
|
||||
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym_c.a | $(OUTPUT)
|
||||
$(call msg,LIB, $@)
|
||||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym_c.a $@
|
||||
|
||||
# Build BPF code
|
||||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
|
||||
$(call msg,BPF,$@)
|
||||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
|
||||
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
|
||||
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
|
||||
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
|
||||
|
||||
# Generate BPF skeletons
|
||||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL)
|
||||
$(call msg,GEN-SKEL,$@)
|
||||
$(Q)$(BPFTOOL) gen skeleton $< > $@
|
||||
|
||||
# Build user-space code
|
||||
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h
|
||||
|
||||
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@
|
||||
|
||||
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_OBJ)
|
||||
|
||||
$(BZS_APPS): $(LIBBLAZESYM_OBJ)
|
||||
|
||||
# Build application binary
|
||||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
|
||||
$(call msg,BINARY,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@
|
||||
|
||||
# delete failed targets
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
# keep intermediate (.skel.h, .bpf.o, etc) targets
|
||||
.SECONDARY:
|
||||
80
ebpf/old.c/replica.bpf.c
Normal file
80
ebpf/old.c/replica.bpf.c
Normal file
@@ -0,0 +1,80 @@
|
||||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
#include "replica.h"
|
||||
|
||||
char LICENSE[] SEC("license") = "Dual BSD/GPL";
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
} events SEC(".maps");
|
||||
|
||||
/* __completed_cmd(const uint8_t *cmd, size_t len, unsigned long long seq); */
|
||||
SEC("uprobe//home/lian/share/9.1-kvstore/kvstore:__completed_cmd")
|
||||
int BPF_KPROBE(handle_completed_cmd,
|
||||
const __u8 *cmd, size_t len, __u64 seq)
|
||||
{
|
||||
struct replica_event evt = {};
|
||||
__u32 copy_len;
|
||||
|
||||
evt.type = EVENT_COMPLETED_CMD;
|
||||
evt.complete.seq = seq;
|
||||
|
||||
copy_len = len;
|
||||
if (copy_len > MAX_CMD_LEN)
|
||||
copy_len = MAX_CMD_LEN;
|
||||
|
||||
evt.complete.len = copy_len;
|
||||
|
||||
if (cmd)
|
||||
bpf_probe_read_user(evt.complete.cmd, copy_len, cmd);
|
||||
|
||||
bpf_perf_event_output(ctx, &events,
|
||||
BPF_F_CURRENT_CPU,
|
||||
&evt, sizeof(evt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* __ssync(const uint8_t *ip, uint32_t ip_len, int port, unsigned long long seq); */
|
||||
SEC("uprobe//home/lian/share/9.1-kvstore/kvstore:__ssync")
|
||||
int BPF_KPROBE(handle_ssync,
|
||||
const __u8 *ip, __u32 ip_len, int port, __u64 seq)
|
||||
{
|
||||
struct replica_event evt = {};
|
||||
|
||||
evt.type = EVENT_SSYNC;
|
||||
evt.sync.seq = seq;
|
||||
evt.sync.port = port;
|
||||
|
||||
__u32 copy_len = ip_len;
|
||||
if (copy_len > sizeof(evt.sync.ip))
|
||||
copy_len = sizeof(evt.sync.ip);
|
||||
|
||||
if (ip)
|
||||
bpf_probe_read_user(evt.sync.ip, copy_len, ip);
|
||||
|
||||
bpf_perf_event_output(ctx, &events,
|
||||
BPF_F_CURRENT_CPU,
|
||||
&evt, sizeof(evt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* __sready(void); */
|
||||
SEC("uprobe//home/lian/share/9.1-kvstore/kvstore:__sready")
|
||||
int BPF_KPROBE(handle_sready)
|
||||
{
|
||||
struct replica_event evt = {};
|
||||
|
||||
evt.type = EVENT_SREADY;
|
||||
|
||||
bpf_perf_event_output(ctx, &events,
|
||||
BPF_F_CURRENT_CPU,
|
||||
&evt, sizeof(evt));
|
||||
return 0;
|
||||
}
|
||||
355
ebpf/old.c/replica.c
Normal file
355
ebpf/old.c/replica.c
Normal file
@@ -0,0 +1,355 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include "replica.skel.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "replica.h"
|
||||
|
||||
#define DEBUGLOG printf
|
||||
|
||||
typedef enum {
|
||||
OFFLINE = 0,
|
||||
ONLINE = 1,
|
||||
}replica_state_e ;
|
||||
|
||||
struct cmd_node {
|
||||
__u64 seq;
|
||||
__u32 len;
|
||||
uint8_t *cmd;
|
||||
struct cmd_node *next;
|
||||
};
|
||||
|
||||
struct pending_queue {
|
||||
struct cmd_node *head;
|
||||
struct cmd_node *tail;
|
||||
int count;
|
||||
};
|
||||
|
||||
/* ================= 全局状态 ================= */
|
||||
|
||||
static replica_state_e state = OFFLINE;
|
||||
static int sockfd = -1;
|
||||
static int epollfd = -1;
|
||||
|
||||
static char peer_ip[MAX_IP_LEN];
|
||||
static int peer_port;
|
||||
static __u64 peer_seq;
|
||||
|
||||
static struct pending_queue pending = {
|
||||
.head = NULL,
|
||||
.tail = NULL,
|
||||
.count = 0,
|
||||
};
|
||||
|
||||
/* ================= pending 队列操作 ================= */
|
||||
static void pending_free()
|
||||
{
|
||||
struct pending_queue *q = &pending;
|
||||
struct cmd_node *cur = q->head;
|
||||
while (cur) {
|
||||
struct cmd_node *tmp = cur;
|
||||
cur = cur->next;
|
||||
free(tmp->cmd);
|
||||
free(tmp);
|
||||
}
|
||||
q->head = q->tail = NULL;
|
||||
q->count = 0;
|
||||
}
|
||||
|
||||
static void pending_push(__u64 seq, __u32 len, const uint8_t *cmd)
|
||||
{
|
||||
struct cmd_node *node = malloc(sizeof(*node));
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
node->cmd = malloc(len);
|
||||
if (!node->cmd) {
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(node->cmd, cmd, len);
|
||||
node->seq = seq;
|
||||
node->len = len;
|
||||
node->next = NULL;
|
||||
|
||||
if (!pending.tail) {
|
||||
pending.head = pending.tail = node;
|
||||
} else {
|
||||
pending.tail->next = node;
|
||||
pending.tail = node;
|
||||
}
|
||||
|
||||
pending.count++;
|
||||
}
|
||||
|
||||
static void pending_gc(__u64 min_seq)
|
||||
{
|
||||
struct cmd_node *cur = pending.head;
|
||||
|
||||
int n = pending.count;
|
||||
while (cur && cur->seq < min_seq) {
|
||||
struct cmd_node *tmp = cur;
|
||||
cur = cur->next;
|
||||
|
||||
free(tmp->cmd);
|
||||
free(tmp);
|
||||
pending.count--;
|
||||
}
|
||||
|
||||
DEBUGLOG("gc:%d\n", n-pending.count);
|
||||
|
||||
pending.head = cur;
|
||||
if (!cur)
|
||||
pending.tail = NULL;
|
||||
}
|
||||
|
||||
static void pending_send_all(void)
|
||||
{
|
||||
struct cmd_node *cur = pending.head;
|
||||
while (cur) {
|
||||
int rt = send(sockfd, cur->cmd, cur->len, 0);
|
||||
|
||||
if(rt == (int)cur->len){
|
||||
struct cmd_node *tmp = cur;
|
||||
cur = cur->next;
|
||||
|
||||
free(tmp->cmd);
|
||||
free(tmp);
|
||||
pending.count--;
|
||||
}else{
|
||||
DEBUGLOG("error\n");
|
||||
// 失败:不移动 cur,直接 break
|
||||
if (rt < 0) {
|
||||
perror("send failed");
|
||||
if (errno == ECONNRESET || errno == EPIPE) {
|
||||
state = OFFLINE;
|
||||
if (sockfd >= 0) {
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
DEBUGLOG("connect closed\n");
|
||||
}
|
||||
} else if (rt == 0) {
|
||||
fprintf(stderr, "send returned 0 (peer closed?)\n");
|
||||
} else {
|
||||
fprintf(stderr, "partial send: %d/%u\n", rt, cur->len);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pending.head = cur;
|
||||
if(!cur)
|
||||
pending.tail = NULL;
|
||||
}
|
||||
|
||||
/* ================= 网络逻辑 ================= */
|
||||
static void try_connect(void)
|
||||
{
|
||||
if(sockfd > 0){
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in addr = {};
|
||||
int i = 0;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(peer_port);
|
||||
inet_pton(AF_INET, peer_ip, &addr.sin_addr);
|
||||
|
||||
for(i = 0;i < 10; ++ i){
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
perror("socket");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGLOG("connect try %d...\n", i + 1);
|
||||
if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
|
||||
DEBUGLOG("connect success: %s:%d\n", peer_ip, peer_port);
|
||||
|
||||
int flags = fcntl(sockfd, F_GETFL, 0);
|
||||
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
struct epoll_event ev;
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = sockfd;
|
||||
epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev);
|
||||
|
||||
state = ONLINE;
|
||||
pending_send_all();
|
||||
return;
|
||||
}
|
||||
|
||||
perror("connect");
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
DEBUGLOG("connect failed after 10 retries\n");
|
||||
}
|
||||
|
||||
static void handle_socket_readable(void)
|
||||
{
|
||||
char buf[65536];
|
||||
while (1) {
|
||||
int n = recv(sockfd, buf, sizeof(buf), MSG_DONTWAIT);
|
||||
if (n > 0) {
|
||||
continue;
|
||||
} else if (n == 0) {
|
||||
state = OFFLINE;
|
||||
epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, NULL);
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
DEBUGLOG("connection closed\n");
|
||||
break;
|
||||
} else {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
break;
|
||||
}
|
||||
perror("recv");
|
||||
state = OFFLINE;
|
||||
epoll_ctl(epollfd, EPOLL_CTL_DEL, sockfd, NULL);
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_socket_writable(void)
|
||||
{
|
||||
pending_send_all();
|
||||
if (!pending.head) {
|
||||
struct epoll_event ev;
|
||||
ev.events = EPOLLIN; // 只监听读
|
||||
ev.data.fd = sockfd;
|
||||
epoll_ctl(epollfd, EPOLL_CTL_MOD, sockfd, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ================= perf buffer 回调 ================= */
|
||||
static void handle_event(void *ctx, int cpu, void *data, __u32 size)
|
||||
{
|
||||
struct replica_event *evt = data;
|
||||
switch (evt->type) {
|
||||
|
||||
case EVENT_SSYNC:
|
||||
strncpy(peer_ip, evt->sync.ip, sizeof(peer_ip));
|
||||
peer_port = evt->sync.port;
|
||||
peer_seq = evt->sync.seq;
|
||||
DEBUGLOG("SSYNC [seq:%lld], [%s:%d]\n", peer_seq, peer_ip, peer_port);
|
||||
|
||||
state = OFFLINE;
|
||||
pending_gc(peer_seq);
|
||||
break;
|
||||
|
||||
case EVENT_COMPLETED_CMD:
|
||||
// DEBUGLOG("CMD [seq:%lld], cmd:\n[\n%s]\n", evt->complete.seq, evt->complete.cmd);
|
||||
pending_push(evt->complete.seq,
|
||||
evt->complete.len,
|
||||
evt->complete.cmd);
|
||||
|
||||
if (state == ONLINE && sockfd >= 0) {
|
||||
struct epoll_event ev;
|
||||
ev.events = EPOLLIN | EPOLLOUT;
|
||||
ev.data.fd = sockfd;
|
||||
epoll_ctl(epollfd, EPOLL_CTL_MOD, sockfd, &ev);
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_SREADY:
|
||||
DEBUGLOG("SREADY \n");
|
||||
if (state == OFFLINE)
|
||||
try_connect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================= main ================= */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct replica_bpf *skel;
|
||||
struct perf_buffer *pb = NULL;
|
||||
int err;
|
||||
|
||||
/* Open BPF application */
|
||||
skel = replica_bpf__open();
|
||||
if (!skel) {
|
||||
fprintf(stderr, "Failed to open BPF skeleton\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Load & verify BPF programs */
|
||||
err = replica_bpf__load(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to load and verify BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Attach tracepoint handler */
|
||||
err = replica_bpf__attach(skel);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to attach BPF skeleton\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
printf("Successfully started! \n");
|
||||
|
||||
|
||||
pb = perf_buffer__new(bpf_map__fd(skel->maps.events), 8,
|
||||
handle_event, NULL, NULL, NULL);
|
||||
|
||||
if(!pb){
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
epollfd = epoll_create1(0);
|
||||
if (epollfd < 0) {
|
||||
fprintf(stderr, "epoll_create1 failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
struct epoll_event events[10];
|
||||
|
||||
perf_buffer__poll(pb, 1000); // 处理事件
|
||||
|
||||
if(OFFLINE) continue;
|
||||
|
||||
int nfds = epoll_wait(epollfd, events, 10, 0);
|
||||
for (int i = 0; i < nfds; i++) {
|
||||
if (events[i].data.fd == sockfd) {
|
||||
if (events[i].events & EPOLLIN) {
|
||||
handle_socket_readable(); // 快速消费接收数据
|
||||
}
|
||||
if (events[i].events & EPOLLOUT) {
|
||||
handle_socket_writable(); // 发送数据
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
perf_buffer__free(pb);
|
||||
|
||||
cleanup:
|
||||
pending_free();
|
||||
if (sockfd >= 0) close(sockfd);
|
||||
replica_bpf__destroy(skel);
|
||||
return -err;
|
||||
}
|
||||
37
ebpf/old.c/replica.h
Normal file
37
ebpf/old.c/replica.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef __REPLICA_H__
|
||||
#define __REPLICA_H__
|
||||
|
||||
|
||||
#define MAX_CMD_LEN 256
|
||||
#define MAX_IP_LEN 64
|
||||
|
||||
enum event_type {
|
||||
EVENT_COMPLETED_CMD,
|
||||
EVENT_SSYNC,
|
||||
EVENT_SREADY,
|
||||
};
|
||||
|
||||
struct complete_cmd_evt {
|
||||
__u64 seq;
|
||||
__u32 len;
|
||||
__u8 cmd[MAX_CMD_LEN];
|
||||
};
|
||||
|
||||
struct sync_evt {
|
||||
__u64 seq;
|
||||
char ip[MAX_IP_LEN];
|
||||
__s32 port;
|
||||
};
|
||||
|
||||
struct replica_event {
|
||||
__u32 type;
|
||||
__u32 _pad;
|
||||
|
||||
union {
|
||||
struct complete_cmd_evt complete;
|
||||
struct sync_evt sync;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
126
ebpf/old.c/xmake.lua
Normal file
126
ebpf/old.c/xmake.lua
Normal file
@@ -0,0 +1,126 @@
|
||||
add_rules("mode.release", "mode.debug")
|
||||
add_rules("platform.linux.bpf")
|
||||
set_license("GPL-2.0")
|
||||
|
||||
if xmake.version():satisfies(">=2.5.7 <=2.5.9") then
|
||||
on_load(function (target)
|
||||
raise("xmake(%s) has a bug preventing BPF source code compilation. Please run `xmake update -f 2.5.6` to revert to v2.5.6 version or upgrade to xmake v2.6.1 that fixed the issue.", xmake.version())
|
||||
end)
|
||||
end
|
||||
|
||||
option("system-libbpf", {showmenu = true, default = false, description = "Use system-installed libbpf"})
|
||||
option("require-bpftool", {showmenu = true, default = false, description = "Require bpftool package"})
|
||||
|
||||
add_requires("elfutils", "zlib")
|
||||
if is_plat("android") then
|
||||
add_requires("ndk >=22.x <26", "argp-standalone")
|
||||
set_toolchains("@ndk", {sdkver = "23"})
|
||||
else
|
||||
add_requires("llvm >=10.x")
|
||||
set_toolchains("@llvm")
|
||||
add_requires("linux-headers")
|
||||
end
|
||||
|
||||
-- fix error: libbpf: map 'my_pid_map': unsupported map linkage static. for bpftool >= 7.2.0
|
||||
-- we cannot add `"-fvisibility=hidden"` when compiling *.bpf.c
|
||||
set_symbols("none")
|
||||
|
||||
if is_arch("arm64", "arm64-v8a") then
|
||||
add_includedirs("../../vmlinux.h/include/arm64")
|
||||
elseif is_arch("arm.*") then
|
||||
add_includedirs("../../vmlinux.h/include/arm")
|
||||
elseif is_arch("riscv32", "riscv64") then
|
||||
add_includedirs("../../vmlinux.h/include/riscv")
|
||||
elseif is_arch("loongarch") then
|
||||
add_includedirs("../../vmlinux.h/include/loongarch")
|
||||
elseif is_arch("ppc", "powerpc") then
|
||||
add_includedirs("../../vmlinux.h/include/powerpc")
|
||||
elseif is_arch("x86_64", "i386") then
|
||||
add_includedirs("../../vmlinux.h/include/x86")
|
||||
else
|
||||
add_includedirs("../../vmlinux.h/include")
|
||||
end
|
||||
|
||||
-- we can run `xmake f --require-bpftool=y` to pull bpftool from xmake-repo repository
|
||||
if has_config("require-bpftool") then
|
||||
add_requires("linux-tools", {configs = {bpftool = true}})
|
||||
add_packages("linux-tools")
|
||||
else
|
||||
before_build(function (target)
|
||||
os.addenv("PATH", path.join(os.scriptdir(), "..", "..", "tools"))
|
||||
end)
|
||||
end
|
||||
|
||||
-- we use the vendored libbpf sources for libbpf-bootstrap.
|
||||
-- for some projects you may want to use the system-installed libbpf, so you can run `xmake f --system-libbpf=y`
|
||||
if has_config("system-libbpf") then
|
||||
add_requires("libbpf", {system = true})
|
||||
else
|
||||
target("libbpf")
|
||||
set_kind("static")
|
||||
set_basename("bpf")
|
||||
add_files("../../libbpf/src/*.c")
|
||||
add_includedirs("../../libbpf/include")
|
||||
add_includedirs("../../libbpf/include/uapi", {public = true})
|
||||
add_includedirs("$(buildir)", {interface = true})
|
||||
add_configfiles("../../libbpf/src/(*.h)", {prefixdir = "bpf"})
|
||||
add_packages("elfutils", "zlib")
|
||||
if is_plat("android") then
|
||||
add_defines("__user=", "__force=", "__poll_t=uint32_t")
|
||||
end
|
||||
end
|
||||
|
||||
target("minimal")
|
||||
set_kind("binary")
|
||||
add_files("minimal.c", "minimal.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("minimal_legacy")
|
||||
set_kind("binary")
|
||||
add_files("minimal_legacy.c", "minimal_legacy.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("bootstrap")
|
||||
set_kind("binary")
|
||||
add_files("bootstrap.c", "bootstrap.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
if is_plat("android") then
|
||||
add_packages("argp-standalone")
|
||||
end
|
||||
|
||||
target("fentry")
|
||||
set_kind("binary")
|
||||
add_files("fentry.c", "fentry.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("uprobe")
|
||||
set_kind("binary")
|
||||
add_files("uprobe.c", "uprobe.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
|
||||
target("kprobe")
|
||||
set_kind("binary")
|
||||
add_files("kprobe.c", "kprobe.bpf.c")
|
||||
add_packages("linux-headers")
|
||||
if not has_config("system-libbpf") then
|
||||
add_deps("libbpf")
|
||||
end
|
||||
if is_plat("android") then
|
||||
-- TODO we need fix vmlinux.h to support android
|
||||
set_default(false)
|
||||
end
|
||||
Reference in New Issue
Block a user