From fe54409f84fa6005583428843c188cb233907a21 Mon Sep 17 00:00:00 2001 From: Linos Giannopoulos Date: Tue, 1 Feb 2022 21:25:06 +0200 Subject: [PATCH] mezoura: Add new package `mezoura` uses `tc` subsystem eBPF hook (direct-action [0]). It's attached as a TC classifier for both ingress and egress. The eBPF program is used to measure traffic (bandwidth and packets per second) from/to the internet (non-private addresses). It utilizes `uci` to parse static entries for DHCP (/etc/config/dhcp) to map MAC addresses -> hostnames. For each new IP/MAC address pair seen on the network, it attempts to resolve the MAC address to a hostname. If there's no mapping, the entry is skipped. It works for both v4 and v6 without having to maintain some weird iptables rules to count packets/bytes as seen in other packages. Lastly, it exposes a prometheus exporter for a widely used method to consume the metrics held in the eBPF maps. There's an option to disable exposing the embedded prometheus exporter. The exporter component, flushes the metrics to `/tmp/prom_c`. From that point, `prometheus-node-exporter-lua-textfile` can be used to consume the metrics instead of exposing yet another service. [0]: https://man7.org/linux/man-pages/man8/tc-bpf.8.html Signed-off-by: Linos Giannopoulos --- utils/mezoura/Makefile | 50 ++++++++++++++++++++++++ utils/mezoura/files/etc/config/mezoura | 4 ++ utils/mezoura/files/etc/init.d/mezoura | 53 ++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 utils/mezoura/Makefile create mode 100644 utils/mezoura/files/etc/config/mezoura create mode 100644 utils/mezoura/files/etc/init.d/mezoura diff --git a/utils/mezoura/Makefile b/utils/mezoura/Makefile new file mode 100644 index 0000000000..72842ddbd3 --- /dev/null +++ b/utils/mezoura/Makefile @@ -0,0 +1,50 @@ +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mezoura +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/linosgian/mezoura +PKG_SOURCE_DATE:=2022-02-01 +PKG_SOURCE_VERSION:=ae8969d207f9f68535cc9f5cabdf8345226352e2 +PKG_MIRROR_HASH:=3cd82bf5cf5754aaffbb7656fc3e0c525ac925f42a70eb23aa3004d1e2542096 + +PKG_MAINTAINER:=Linos Giannopoulos +PKG_LICENSE:=GPL-3.0-or-later + +PKG_BUILD_DEPENDS:=bpf-headers +PKG_FLAGS:=nonshared + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk +include $(INCLUDE_DIR)/bpf.mk + +define Package/mezoura + SECTION:=utils + CATEGORY:=Base system + TITLE:=eBPF-based bandwidth monitoring utility + DEPENDS:=+libbpf +kmod-sched-bpf +tc-full +libuci $(BPF_DEPENDS) +endef + +define Build/Compile + $(call CompileBPF,$(PKG_BUILD_DIR)/mezoura.bpf.c) + $(Build/Compile/Default) +endef + +define Package/mezoura/conffiles +/etc/config/mezoura +endef + +define Package/mezoura/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/etc/config/mezoura $(1)/etc/config/mezoura + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/init.d/mezoura $(1)/etc/init.d/mezoura + $(INSTALL_DIR) $(1)/lib/bpf + $(INSTALL_DATA) $(PKG_BUILD_DIR)/mezoura.bpf.o $(1)/lib/bpf + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mezoura $(1)/usr/bin +endef + +$(eval $(call BuildPackage,mezoura)) diff --git a/utils/mezoura/files/etc/config/mezoura b/utils/mezoura/files/etc/config/mezoura new file mode 100644 index 0000000000..a9b5782e48 --- /dev/null +++ b/utils/mezoura/files/etc/config/mezoura @@ -0,0 +1,4 @@ +config mezoura 'main' + option exporter_port '9999' + option exporter '1' + list interface 'lan' diff --git a/utils/mezoura/files/etc/init.d/mezoura b/utils/mezoura/files/etc/init.d/mezoura new file mode 100644 index 0000000000..bf4eca7599 --- /dev/null +++ b/utils/mezoura/files/etc/init.d/mezoura @@ -0,0 +1,53 @@ +#!/bin/sh /etc/rc.common + +START=60 + +USE_PROCD=1 +PROG=/usr/bin/mezoura + +. /lib/functions/network.sh + +add_iface_v4() { + local addr + network_get_subnet addr "$1" + network_get_physdev iface "$1" + addr=$(echo "$addr" | sed "s/ /\//") + procd_append_param command -4 "${addr}/${iface}" +} + +start_service() { + local iface interface6 port addr6 + + config_load "mezoura" + config_get interface6 main interface6 "" + config_get_bool exporter main exporter '1' + config_get port main listen_port "9999" + config_get config_file main config_file "" + + procd_open_instance + procd_set_param command "$PROG" + [ $exporter -eq 1 ] && procd_append_param command -e + if [ -n "$interface6" ]; then + network_get_prefix6 addr6 "$interface6" + + addr6=$(echo "$addr6" | sed "s/ /\//") + procd_append_param command -6 "${addr6}" + fi + procd_append_param command -p "${port}" + config_list_foreach 'main' interface "add_iface_v4" + + procd_set_param respawn + procd_close_instance +} + +stop_service() { + local pid + + # kill all previous mezoura processes + for pid in $(pidof mezoura) + do + [ "$pid" = "$$" ] && continue + [ -e "/proc/$pid/stat" ] && kill $pid + done + return 0; +}