Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在UMA下获取系统当前node以及node中所有的zone #857

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/ebpf_frag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

name: fraginfo

on:
push:
branches:
- "*"
paths:
- 'eBPF_Supermarket/Memory_Subsystem/fraginfo/**'
- '.github/workflows/ebpf_frag.yml'
pull_request:
branches:
- "*"
paths:
- 'eBPF_Supermarket/Memory_Subsystem/fraginfo/**'
- '.github/workflows/ebpf_frag.yml'

jobs:
fraginfo-project-build-and-test:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3

- name: Install dependencies
run: |
sudo apt update
sudo apt install libbpf-dev clang llvm libelf-dev libpcap-dev gcc-multilib build-essential linux-tools-$(uname -r)
git submodule update --init --recursive

- name: Run fraginfo
continue-on-error: true
run: |
cd eBPF_Supermarket/Memory_Subsystem/fraginfo/
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
make
sudo ./fraginfo -i 5
2 changes: 1 addition & 1 deletion .github/workflows/ebpf_mem_watcher.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ jobs:
cd eBPF_Supermarket/Memory_Subsystem/mem_watcher/
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
make
sudo timeout 20 ./mem_watcher
sudo ./mem_watcher -f -i 10
131 changes: 131 additions & 0 deletions eBPF_Supermarket/Memory_Subsystem/fraginfo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@

# Makefile
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

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/')
VMDIR := ../vmlinux
VMLINUXSRC := $(VMDIR)/$(ARCH)
VMLINUX := $(VMLINUXSRC)/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../../lib/libbpf/include/uapi -I$(dir $(VMLINUX)) -I./include
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)

APPS = fraginfo

# 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: deps $(APPS)

.PHONY: deps
deps:
mkdir -p $(VMLINUXSRC)
bpftool btf dump file /sys/kernel/btf/vmlinux format c > $(VMLINUX)

.PHONY: clean
clean:
$(call msg,CLEAN)
$(Q)rm -rf $(OUTPUT) $(APPS)
rm -rf $(VMDIR)

.PHONY: clean2
clean2:
$(call msg,CLEAN)
rm -f $(APPS)
rm -f $(OUTPUT)/*.skel.h
rm -f $(OUTPUT)/*.o
rm -rf $(VMDIR)

$(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

# Build BPF code
$(OUTPUT)/%.bpf.o: src/%.bpf.c $(LIBBPF_OBJ) $(wildcard src/*.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)): $(OUTPUT)/%.o: src/%.c $(OUTPUT)/%.skel.h $(wildcard src/*.h) | $(OUTPUT)
$(call msg,CC,$@)
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@

# 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:

SHELL := /bin/bash
76 changes: 76 additions & 0 deletions eBPF_Supermarket/Memory_Subsystem/fraginfo/src/fraginfo.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#include "fraginfo.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 102400);
__type(key, u64);
__type(value, struct zone_info);
} zones SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 102400);
__type(key, u64);
__type(value, struct pgdat_info);
} nodes SEC(".maps");

static void fill_contig_page_info(struct zone *zone, unsigned int suitable_order,
struct contig_page_info *info)
{
unsigned int order;
info->free_pages = 0;
info->free_blocks_total = 0;
info->free_blocks_suitable = 0;
for (order = 0; order <= MAX_ORDER; order++) {
unsigned long blocks;
unsigned long nr_free;
nr_free = BPF_CORE_READ(&zone->free_area[order], nr_free);
blocks = nr_free;
info->free_blocks_total += blocks;
info->free_pages += blocks << order;
if (order >= suitable_order)
info->free_blocks_suitable += blocks << (order - suitable_order);
}
}

SEC("kprobe/get_page_from_freelist")
int BPF_KPROBE(get_page_from_freelist, gfp_t gfp_mask, unsigned int order, int alloc_flags,
const struct alloc_context *ac)
{
struct pgdat_info node_info = {};
struct zone_info zone_data = {};

struct pglist_data *pgdat;
struct zoneref *zref;
struct zone *z;
int i;

pgdat = BPF_CORE_READ(ac, preferred_zoneref, zone, zone_pgdat);
node_info.node_id = BPF_CORE_READ(pgdat, node_id);
node_info.nr_zones = BPF_CORE_READ(pgdat, nr_zones);
node_info.pgdat_ptr = (u64)pgdat;
u64 key = (u64)pgdat;

bpf_map_update_elem(&nodes, &key, &node_info, BPF_ANY);

for (i = 0; i < __MAX_NR_ZONES; i++) {
zref = &pgdat->node_zonelists[0]._zonerefs[i];
z = BPF_CORE_READ(zref, zone);
if ((u64)z == 0) break;
zone_data.zone_ptr = (u64)z;
u64 zone_key = (u64)z;
zone_data.zone_start_pfn = BPF_CORE_READ(z, zone_start_pfn);
zone_data.spanned_pages = BPF_CORE_READ(z, spanned_pages);
zone_data.present_pages = BPF_CORE_READ(z, present_pages);
bpf_probe_read_kernel_str(zone_data.comm, sizeof(zone_data.comm), BPF_CORE_READ(z, name));
bpf_map_update_elem(&zones, &zone_key, &zone_data, BPF_ANY);
}

return 0;
}
121 changes: 121 additions & 0 deletions eBPF_Supermarket/Memory_Subsystem/fraginfo/src/fraginfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include "fraginfo.skel.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <argp.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include "fraginfo.h"

static struct env {
int interval;
int duration;
} env = {
.interval = 1,
.duration = 10,
};

const char *argp_program_version = "fraginfo 0.1";
const char *argp_program_bug_address = "<your_email@example.com>";
const char argp_program_doc[] =
"Fraginfo BPF program.\n"
"\n"
"USAGE: ./fraginfo [--interval INTERVAL] [--duration DURATION]\n";

static const struct argp_option opts[] = {
{ "interval", 'i', "INTERVAL", 0, "Print interval in seconds (default 1)"},
{ "duration", 'd', "DURATION", 0, "Total duration in seconds to run (default 10)"},
{},
};

static error_t parse_arg(int key, char *arg, struct argp_state *state) {
switch (key) {
case 'i':
env.interval = atoi(arg);
break;
case 'd':
env.duration = atoi(arg);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}

static volatile bool exiting = false;

static void sig_handler(int sig) {
exiting = true;
}

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) {
return vfprintf(stderr, format, args);
}

void print_nodes(int fd) {
struct pgdat_info pinfo;
__u64 key = 0, next_key;
printf(" Node ID PGDAT_PTR NR_ZONES \n");
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
bpf_map_lookup_elem(fd, &next_key, &pinfo);
printf(" %5d 0x%llx %5d\n",
pinfo.node_id, pinfo.pgdat_ptr, pinfo.nr_zones);
key = next_key;
}
}

void print_zones(int fd) {
struct zone_info zinfo;
__u64 key = 0, next_key;
printf(" COMM ZONE_PTR ZONE_PFN SUM_PAGES FACT_PAGES \n");
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
bpf_map_lookup_elem(fd, &next_key, &zinfo);
printf(" %s 0x%llx %llu %5llu %llu \n", zinfo.comm, zinfo.zone_ptr, zinfo.zone_start_pfn,zinfo.spanned_pages,zinfo.present_pages);
key = next_key;
}
}

int main(int argc, char **argv) {
struct fraginfo_bpf *skel;
int err;

struct argp argp = { opts, parse_arg, NULL, argp_program_doc };
err = argp_parse(&argp, argc, argv, 0, 0, NULL);
if (err)
return err;

// libbpf_set_print(libbpf_print_fn);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);

skel = fraginfo_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeleton\n");
return 1;
}

err = fraginfo_bpf__load(skel);
if (err) {
fprintf(stderr, "Failed to load BPF skeleton\n");
goto cleanup;
}

err = fraginfo_bpf__attach(skel);
if (err) {
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto cleanup;
}

printf("Tracing... Press Ctrl-C to end.\n");

while (!exiting) {
sleep(env.interval);
print_nodes(bpf_map__fd(skel->maps.nodes));
print_zones(bpf_map__fd(skel->maps.zones));
}

cleanup:
fraginfo_bpf__destroy(skel);
return -err;
}
22 changes: 22 additions & 0 deletions eBPF_Supermarket/Memory_Subsystem/fraginfo/src/fraginfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef FRAGINFO_H
#define FRAGINFO_H

#define MAX_ORDER 10
typedef __u64 u64;


struct zone_info {
u64 zone_ptr;
u64 zone_start_pfn;
u64 spanned_pages;
u64 present_pages;
char comm[32];
};

struct pgdat_info {
u64 pgdat_ptr;
int nr_zones;
int node_id;
};

#endif
Loading
Loading