Carl 10 bulan lalu
induk
melakukan
f44ca20072
2 mengubah file dengan 329 tambahan dan 166 penghapusan
  1. 157 166
      main.cpp
  2. 172 0
      table.cpp

+ 157 - 166
main.cpp

@@ -10,11 +10,11 @@
 #include <sstream>
 #include <utility>
 #include <vector>
+#include "table.cpp"
 
 constexpr const char *TRACE_PIPE_PATH = "/sys/kernel/debug/tracing/trace_pipe";
 
 // Php::out << "Value of fn: " << fnn << std::endl;
-//static std::string cb_fn;
 
 const std::vector<std::string> syscall_prefixes = {
 		"sys_",
@@ -27,47 +27,12 @@ const std::vector<std::string> syscall_prefixes = {
 		"__riscv_sys_"
 };
 
-
-class PerfEvent : public Php::Base {
-private:
-	std::string cb;
-public:
-	ebpf::BPF *bpf;
-	std::string event_name;
-
-	PerfEvent(ebpf::BPF *bpf_instance, const std::string &event_name)
-			: bpf(bpf_instance), event_name(event_name) {}
-
-	virtual ~PerfEvent() = default;
-
-	static void callbackfn(void *cookie, void *data, int data_size) {
-		auto *instance = static_cast<PerfEvent *>(cookie);
-		if (!instance) return;
-
-		Php::Value phpData((const char *) data, data_size);
-		Php::call(instance->cb.c_str(), nullptr, phpData, data_size);
-	}
-
-	void php_open_perf_buffer(Php::Parameters &params) {
-		this->cb = params[0].stringValue();
-		auto res = this->bpf->open_perf_buffer(this->event_name, callbackfn, nullptr, this);
-		if (!res.ok()) {
-			throw Php::Exception("open_perf_buffer error:" + res.msg());
-		}
-	}
-
-	int perf_buffer_poll(int timeout_ms) {
-		return bpf->poll_perf_buffer(this->event_name, timeout_ms); // perf_reader_event_read
-	}
-
-};
-
-
 class EbpfExtension : public Php::Base {
 private:
 	ebpf::BPF bpf;
+	void *mod;
 	Php::Object _perf_event;
-	PerfEvent *_class_perf_event;
+	PerfEventArrayTable *_class_perf_event;
 
 	static std::string add_prefix(const std::string &prefix, const std::string &name) {
 		if (name.rfind(prefix, 0) != 0) {
@@ -121,15 +86,38 @@ public:
 
 	virtual ~EbpfExtension() = default;
 
-//	Php::Value __get(const Php::Value &name)
-//	{
+	Php::Value __get(const Php::Value &name) {
+		int from_attr = 1;
+		auto res = get_table_cls(name, from_attr);  // 这里传递 std::vector<Php::Value>
+		if (!res.isObject()) {
+			return Php::Base::__get(name);
+		} else {
+			return res;
+		}
+
+//		printf("111111111\n");
 //		if (name == "events") return _perf_event;
 //
-//		auto a = new PerfEvent;
+//		auto a = new PerfEventArrayTable;
 //		a->getMessage();
 //
-//		return Php::Base::__get(name);
-//	}
+	}
+
+	void php_test(Php::Parameters &params) {
+		int ty = bpf_table_type(this->mod, "counters");
+		Php::out << "counters type]" << ty << std::endl;
+		int ty2 = bpf_table_type(this->mod, "events");
+		Php::out << "events type]" << ty2 << std::endl;
+//		bpf.get_map_in_map_table<int>("").get_fd();
+//		auto aaa = bpf.table<>()("counters");
+//		aaa.get_value(0, reinterpret_cast<std::string &>(val));
+//
+//		auto control_table_hdl = bpf.get_array_table<uint64_t>("counters");
+//		auto res1 = control_table_hdl.get_value(1, val);
+//		Php::out<< "ok]" <<res1.ok() <<std::endl;
+//		Php::out<< "msg]" << res1.msg() <<std::endl;
+//		Php::out <<"val]" << val <<std::endl;
+	}
 
 	void __construct(Php::Parameters &params) {
 		std::string bpf_code = params[0].stringValue();
@@ -137,6 +125,7 @@ public:
 		if (!init_res.ok()) {
 			throw Php::Exception("init error: " + init_res.msg());
 		}
+		this->mod = (void *) bpf.get_mod();
 		_trace_autoload();
 	}
 
@@ -329,8 +318,66 @@ public:
 
 	Php::Value php_perf_event(Php::Parameters &params) {
 		std::string event_name = params[0].stringValue();  // Get event_name from the parameters
-		this->_class_perf_event = new PerfEvent(&this->bpf, event_name);
-		return Php::Object("PerfEvent", this->_class_perf_event);
+		this->_class_perf_event = new PerfEventArrayTable(&this->bpf, event_name);
+		return Php::Object("PerfEventArrayTable", this->_class_perf_event);
+	}
+
+	Php::Value get_table_cls(const char *table_name, int from_attr) {
+		int ttype = bpf_table_type(this->mod, table_name);
+		switch (ttype) {
+			case BPF_MAP_TYPE_HASH:
+				return Php::Object("HashTable", new HashTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_ARRAY:
+				return Php::Object("ArrayTable", new ArrayTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_PROG_ARRAY:
+				return Php::Object("ProgArrayTable", new ProgArrayTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
+				this->_class_perf_event = new PerfEventArrayTable(&this->bpf, table_name);
+				return Php::Object("PerfEventArrayTable", this->_class_perf_event);
+			case BPF_MAP_TYPE_PERCPU_HASH:
+				return Php::Object("PerCpuHashTable", new PerCpuHashTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_PERCPU_ARRAY:
+				return Php::Object("PerCpuArrayTable", new PerCpuArrayTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_LPM_TRIE:
+				return Php::Object("LpmTrieTable", new LpmTrieTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_STACK_TRACE:
+				return Php::Object("StackTraceTable", new StackTraceTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_LRU_HASH:
+				return Php::Object("LruHashTable", new LruHashTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_LRU_PERCPU_HASH:
+				return Php::Object("LruPerCpuHashTable", new LruPerCpuHashTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_CGROUP_ARRAY:
+				return Php::Object("CgroupArrayTable", new CgroupArrayTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_DEVMAP:
+				return Php::Object("DevMapTable", new DevMapTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_CPUMAP:
+				return Php::Object("CpuMapTable", new CpuMapTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_XSKMAP:
+				return Php::Object("XskMapTable", new XskMapTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_ARRAY_OF_MAPS:
+				return Php::Object("MapInMapArrayTable", new MapInMapArrayTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_HASH_OF_MAPS:
+				return Php::Object("MapInMapHashTable", new MapInMapHashTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_QUEUE:
+			case BPF_MAP_TYPE_STACK:
+				return Php::Object("QueueStackTable", new QueueStackTable(&this->bpf, table_name));
+			case BPF_MAP_TYPE_RINGBUF:
+				return Php::Object("RingBufTable", new RingBufTable(&this->bpf, table_name));
+			default:
+				if (from_attr) {
+					return ttype;
+				}
+				throw Php::Exception("Unknown table type " + std::to_string(ttype));
+		}
+	}
+
+	Php::Value php_table(Php::Parameters &params) {
+		std::string table_name = params[0].stringValue();  // Get event_name from the parameters
+		int from_fn = 0;
+		return get_table_cls(table_name.c_str(), from_fn);
+
+//		this->_class_perf_event = new PerfEventArrayTable(&this->bpf, table_name);
+//		return Php::Object("PerfEventArrayTable", this->_class_perf_event);
 	}
 
 	void php_perf_buffer_poll(Php::Parameters &params) {
@@ -381,123 +428,9 @@ std::string get_kprobe_event(const std::string &kernel_func,
 	return res;
 }
 
-
-void bpf_new2(Php::Parameters &params) {
-	std::string param = params[0].stringValue();
-
-	ebpf::BPF bpf;
-//	void *mod = bpf_module_create_c_from_string(param.c_str(), 4, NULL, 0, true, NULL);
-	std::string kernel_func = bpf.get_syscall_fnname("clone");
-
-	bpf.init(param);
-	const char *prob_fn = "kprobe__sys_clone";
-	auto attach_res = bpf.attach_kprobe(kernel_func, prob_fn);
-	Php::out << "Value of fn:kernel_func]" << kernel_func.c_str() << std::endl;
-	Php::out << "Value of fn:prob_fn]" << prob_fn << std::endl;
-
-	std::ifstream pipe("/sys/kernel/debug/tracing/trace_pipe");
-	std::string line;
-	if (!attach_res.ok()) {
-		std::cerr << attach_res.msg() << std::endl;
-	} else {
-		std::cout << "Press Ctrl+C to stop..." << std::endl;
-		while (true) {
-			if (std::getline(pipe, line)) {
-				std::cout << line << std::endl;
-			}
-		}
-	}
-}
-
-void bpf_new(Php::Parameters &params) {
-	std::string param = params[0].stringValue();
-	void *mod = bpf_module_create_c_from_string(param.c_str(), 4, NULL, 0, true, NULL);
-//	void *mod = bpf_module_create_c_from_string("BPF_TABLE(\"array\", int, int, stats, 10);\n", 4, NULL, 0, true, NULL);
-//	bpf_prog_get_fd_by_id()	;
-	Php::out << "Value of mod: " << mod << std::endl;
-
-//	size_t num = bpf_num_functions(mod);
-//	for (size_t i = 0; i < num; ++i) {
-//		const char *fnn = bpf_function_name(mod, i);
-//		Php::out << "Value of fn: " << fnn << std::endl;
-//	}
-
-//	Php::out << "Value of bpf_num_functions: " << num << std::endl;
-	ebpf::BPF bpf;
-	std::string kernel_func = bpf.get_syscall_fnname("clone");
-
-	const char *prob_fn = "hello";
-	void *func_start = bpf_function_start(mod, prob_fn);
-	if (!func_start) {
-		Php::out << "can not find of func_start: " << func_start << std::endl;
-	}
-	int log_level = 1;
-	std::cout << "func_load ]" << prob_fn << std::endl;
-	std::cout << "func_load func_start]" << func_start << std::endl;
-	std::cout << "func_load func_size]" << bpf_function_size(mod, prob_fn) << std::endl;
-	std::cout << "func_load license]" << bpf_module_license(mod) << std::endl;
-	std::cout << "func_load kern_version]" << bpf_module_kern_version(mod) << std::endl;
-	int fn_fd = bcc_func_load(mod, BPF_PROG_TYPE_KPROBE, prob_fn,
-	                          static_cast<const bpf_insn *>(func_start),
-	                          static_cast<int>(bpf_function_size(mod, prob_fn)),
-	                          bpf_module_license(mod),
-	                          bpf_module_kern_version(mod),
-	                          log_level, nullptr, 0, 0, -1);
-	if (fn_fd < 0) {
-		Php::out << "Failed to load BPF program " << fn_fd << std::endl;
-	} else {
-		Php::out << "BPF program fd ]" << fn_fd << std::endl;
-	}
-
-
-	std::string probe_event = get_kprobe_event(kernel_func, BPF_PROBE_ENTRY);
-
-	std::cout << "kernel_func]" << kernel_func.c_str() << "! probe_event]" << probe_event.c_str() << std::endl;
-	int kernel_func_offset = 0;
-//	bpf_attach_kprobe(fn_fd, BPF_PROBE_ENTRY, probe_event.c_str(), fn, fn_offset, 0);
-	int attach_res2 = bpf_attach_kprobe(fn_fd, BPF_PROBE_ENTRY, probe_event.c_str(), kernel_func.c_str(),
-	                                    kernel_func_offset, 0);
-
-	std::cout << "main.cpp attach_res2---------->]" << attach_res2 << std::endl;
-
-
-
-//	Php::out << "Value of clone_fnname: " << kernel_func << std::endl;
-	std::ifstream pipe("/sys/kernel/debug/tracing/trace_pipe");
-	std::string line;
-//
-//	bpf.init(param);
-
-	auto attach_res = bpf.attach_kprobe(kernel_func, prob_fn);
-	std::cout << "main.cpp attach_res2-------->]" << attach_res.ok() << std::endl;
-
-	if (!attach_res.ok() && attach_res2 <= 0) {
-		std::cerr << attach_res.msg() << std::endl;
-	} else {
-		std::cout << "Starting HelloWorld with BCC " << 111 << std::endl;
-		while (true) {
-			if (std::getline(pipe, line)) {
-				std::cout << "aaa Waiting for a sys_clone event" << std::endl;
-				std::cout << line << std::endl;
-				// Detach the probe if we got at least one line.
-				auto detach_res = bpf.detach_kprobe(kernel_func);
-				if (!detach_res.ok()) {
-					std::cerr << detach_res.msg() << std::endl;
-				}
-				break;
-			} else {
-				std::cout << "Waiting for a sys_clone event" << std::endl;
-				sleep(1);
-			}
-		}
-	}
-}
-
 extern "C" {
 PHPCPP_EXPORT void *get_module() {
 	static Php::Extension extension("ebpf", "1.0.0");
-	extension.add<bpf_new>("bpf_new", {Php::ByVal("a", Php::Type::String)});
-	extension.add<bpf_new2>("bpf_new2", {Php::ByVal("a", Php::Type::String)});
 	Php::Class<EbpfExtension> ebpf_class("Ebpf");
 	ebpf_class.method<&EbpfExtension::php_trace_print>("trace_print");
 	ebpf_class.method<&EbpfExtension::php_trace_fields>("trace_fields");
@@ -537,6 +470,10 @@ PHPCPP_EXPORT void *get_module() {
 			Php::ByVal("ev_name", Php::Type::String),
 	});
 
+	ebpf_class.method<&EbpfExtension::php_table>("table", {
+			Php::ByVal("tb_name", Php::Type::String),
+	});
+
 	ebpf_class.method<&EbpfExtension::php_perf_buffer_poll>("perf_buffer_poll", {});
 
 	ebpf_class.method<&EbpfExtension::php_get_syscall_fnname>("get_syscall_fnname", {
@@ -552,16 +489,70 @@ PHPCPP_EXPORT void *get_module() {
 			Php::ByVal("symbol", Php::Type::String),
 			Php::ByVal("options", Php::Type::Array, false),
 	});
+	ebpf_class.method<&EbpfExtension::php_test>("test", {});
+	extension.add(std::move(ebpf_class));
 
-
-	Php::Class<PerfEvent> ebpf_perf_event_class("PerfEvent");
-	ebpf_perf_event_class.method<&PerfEvent::php_open_perf_buffer>("open_perf_buffer", {
+	/*HashTable*/
+	Php::Class<HashTable> ebpf_hashtable_cls("HashTable");
+	/*ArrayTable*/
+	Php::Class<ArrayTable> ebpf_array_table_cls("ArrayTable");
+	ebpf_array_table_cls.method<&ArrayTable::Value>("value", {
+			Php::ByVal("i", Php::Type::Numeric),
+	});
+	/*ProgArrayTable*/
+	Php::Class<ProgArrayTable> ebpf_prog_array_table_cls("ProgArrayTable");
+	/*PerfEventArrayTable*/
+	Php::Class<PerfEventArrayTable> ebpf_perf_event_class("PerfEventArrayTable");
+	ebpf_perf_event_class.method<&PerfEventArrayTable::php_open_perf_buffer>("open_perf_buffer", {
 			Php::ByVal("callback", Php::Type::Callable),
 	});
-
-	extension.add(std::move(ebpf_class));
+	/*PerCpuHashTable*/
+	Php::Class<PerCpuHashTable> ebpf_percpuhash_table_cls("PerCpuHashTable");
+	/*PerCpuArrayTable*/
+	Php::Class<PerCpuArrayTable> ebpf_percpuarray_table_cls("PerCpuArrayTable");
+	/*LpmTrieTable*/
+	Php::Class<LpmTrieTable> ebpf_lpmtrie_table_cls("LpmTrieTable");
+	/*StackTraceTable*/
+	Php::Class<StackTraceTable> ebpf_stack_trace_table_cls("StackTraceTable");
+	/*LruHashTable*/
+	Php::Class<LruHashTable> ebpf_lruhash_table_cls("LruHashTable");
+	/*LruPerCpuHashTable*/
+	Php::Class<LruPerCpuHashTable> ebpf_lruper_cpuhash_table_cls("LruPerCpuHashTable");
+	/*CgroupArrayTable*/
+	Php::Class<CgroupArrayTable> ebpf_cgroup_array_table_cls("CgroupArrayTable");
+	/*DevMapTable*/
+	Php::Class<DevMapTable> ebpf_devmap_table_cls("DevMapTable");
+	/*CpuMapTable*/
+	Php::Class<CpuMapTable> ebpf_cpumap_table_cls("CpuMapTable");
+	/*XskMapTable*/
+	Php::Class<XskMapTable> ebpf_xskmap_table_cls("XskMapTable");
+	/*MapInMapArrayTable*/
+	Php::Class<MapInMapArrayTable> ebpf_map_in_map_array_table_cls("MapInMapArrayTable");
+	/*MapInMapHashTable*/
+	Php::Class<MapInMapHashTable> ebpf_map_in_maphash_table_cls("MapInMapHashTable");
+	/*QueueStackTable*/
+	Php::Class<QueueStackTable> ebpf_queue_stack_table_cls("QueueStackTable");
+	/*RingBufTable*/
+	Php::Class<RingBufTable> ebpf_ringbuf_table_cls("RingBufTable");
+
+	extension.add(std::move(ebpf_hashtable_cls));
+	extension.add(std::move(ebpf_array_table_cls));
+	extension.add(std::move(ebpf_prog_array_table_cls));
 	extension.add(std::move(ebpf_perf_event_class));
+	extension.add(std::move(ebpf_percpuhash_table_cls));
+	extension.add(std::move(ebpf_percpuarray_table_cls));
+	extension.add(std::move(ebpf_lpmtrie_table_cls));
+	extension.add(std::move(ebpf_stack_trace_table_cls));
+	extension.add(std::move(ebpf_lruhash_table_cls));
+	extension.add(std::move(ebpf_lruper_cpuhash_table_cls));
+	extension.add(std::move(ebpf_cgroup_array_table_cls));
+	extension.add(std::move(ebpf_devmap_table_cls));
+	extension.add(std::move(ebpf_cpumap_table_cls));
+	extension.add(std::move(ebpf_xskmap_table_cls));
+	extension.add(std::move(ebpf_map_in_map_array_table_cls));
+	extension.add(std::move(ebpf_map_in_maphash_table_cls));
+	extension.add(std::move(ebpf_queue_stack_table_cls));
+	extension.add(std::move(ebpf_ringbuf_table_cls));
 	return extension;
 }
-}
-
+}

+ 172 - 0
table.cpp

@@ -0,0 +1,172 @@
+#include <iostream>
+#include <phpcpp.h>
+#include "bpf_module.h"
+#include "BPF.h"
+
+class BaseTable : public Php::Base {
+public:
+	ebpf::BPF *bpf;
+	std::string tb_name;
+
+	BaseTable(ebpf::BPF *bpf_instance, const std::string &tb_name)
+			: bpf(bpf_instance), tb_name(tb_name) {}
+
+	virtual ~BaseTable() = default;
+
+	void printName() { std::cout << "Table name: " << tb_name << std::endl; }
+};
+
+
+class PerfEventArrayTable : public BaseTable {
+private:
+	std::string cb;
+public:
+	using BaseTable::BaseTable;
+
+//	ebpf::BPF *bpf;
+//	std::string event_name;
+//
+//	PerfEventArrayTable(ebpf::BPF *bpf_instance, const std::string &event_name)
+//	: bpf(bpf_instance), event_name(event_name) {}
+
+//	using BaseTable::BaseTable;
+
+	virtual ~PerfEventArrayTable() = default;
+
+	static void callbackfn(void *cookie, void *data, int data_size) {
+		auto *instance = static_cast<PerfEventArrayTable *>(cookie);
+		if (!instance) return;
+
+		Php::Value phpData((const char *) data, data_size);
+		Php::call(instance->cb.c_str(), nullptr, phpData, data_size);
+	}
+
+	void php_open_perf_buffer(Php::Parameters &params) {
+		this->cb = params[0].stringValue();
+		auto res = this->bpf->open_perf_buffer(this->tb_name, callbackfn, nullptr, this);
+		if (!res.ok()) {
+			throw Php::Exception("open_perf_buffer error:" + res.msg());
+		}
+
+//		auto control_table_hdl = bpf->get_array_table<uint64_t>("counters");
+//		uint64_t val;
+//		auto res1 = control_table_hdl.get_value(0, val);
+//		Php::out << "ok]" << res1.ok() << std::endl;
+//		Php::out << "msg]" << res1.msg() << std::endl;
+//		Php::out << "val]" << val << std::endl;
+	}
+
+	int perf_buffer_poll(int timeout_ms) {
+		return bpf->poll_perf_buffer(this->tb_name, timeout_ms); // perf_reader_event_read
+	}
+
+};
+
+class HashTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class ArrayTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+	Php::Value Value(Php::Parameters &param) {
+		auto index = param[0].numericValue();
+		// todo val type
+		uint64_t val;
+		auto table = bpf->get_array_table<uint64_t>(tb_name);
+		auto res = table.get_value(index, val);
+		if (!res.ok()) {
+			throw Php::Exception("Get value error in" + std::string(tb_name));
+		}
+		Php::Value phpValue = static_cast<int64_t>(val);
+		return phpValue;
+	}
+};
+
+class ProgArrayTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+
+	void Value(Php::Parameters &param) {
+		auto index = param[0].numericValue();
+		// todo key type
+		uint64_t val;
+		auto table = bpf->get_array_table<uint64_t>(tb_name);
+		auto res = table.get_value(index, val);
+
+		printf("%d\n", val);
+	}
+
+
+};
+
+class PerCpuHashTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class PerCpuArrayTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class LpmTrieTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class StackTraceTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class LruHashTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class LruPerCpuHashTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class CgroupArrayTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class DevMapTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class CpuMapTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class XskMapTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class MapInMapArrayTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class MapInMapHashTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class QueueStackTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};
+
+class RingBufTable : public BaseTable {
+public:
+	using BaseTable::BaseTable;
+};