Projects
Eulaceura:Factory
oncn-bwm
_service:obs_scm:0003-add-proc-file-interface.p...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0003-add-proc-file-interface.patch of Package oncn-bwm
From ffe630818e3d5118ac0163e75e2f1ec774d3e4c9 Mon Sep 17 00:00:00 2001 From: JofDiamonds <kwb0523@163.com> Date: Mon, 8 May 2023 10:04:42 +0800 Subject: [PATCH] add proc file interface --- bwmcli.h | 6 +- ko/Makefile | 16 ++ ko/bwm.c | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ko/bwm.h | 69 +++++++ 4 files changed, 657 insertions(+), 1 deletion(-) create mode 100644 ko/Makefile create mode 100644 ko/bwm.c create mode 100644 ko/bwm.h diff --git a/bwmcli.h b/bwmcli.h index f7d4c62..a319130 100644 --- a/bwmcli.h +++ b/bwmcli.h @@ -60,6 +60,10 @@ struct TcCmd { #define BWM_LOG_DEBUG(fmt, args...) syslog(LOG_DEBUG, "[BWM_DEBUG]: " fmt, ## args) #define BWM_LOG_ERR(fmt, args...) syslog(LOG_ERR, "[BWM]: " fmt, ## args) -#define BWM_LOG_INFO(fmt, args...) ((void)printf(fmt, ## args)) +#define BWM_LOG_INFO(fmt, args...) \ + do { \ + (void)printf(fmt, ## args); \ + syslog(LOG_INFO, "[BWM]: " fmt, ## args); \ + } while (0) #endif /* __BWMCLI_H__ */ diff --git a/ko/Makefile b/ko/Makefile new file mode 100644 index 0000000..7eae5f5 --- /dev/null +++ b/ko/Makefile @@ -0,0 +1,16 @@ +CONFIG_MODULE_SIG=n + +obj-m := bwm.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +LINUX_VER ?= $(shell ls /usr/src/ | grep linux) +USERSRC ?= /usr/src/$(LINUX_VER) +EXTRA_CFLAGS = -I$(USERSRC) + +all: + $(MAKE) -C $(KERNELDIR) M=$(PWD) +clean: + @rm -rf *.o *.mod *.mod.c *.mod.o *.ko *.order *.symvers .*.cmd + diff --git a/ko/bwm.c b/ko/bwm.c new file mode 100644 index 0000000..6be6cbe --- /dev/null +++ b/ko/bwm.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved. + * Description: Network bandwidth management tool + */ +#include "bwm.h" + +static char *envp[] = { "HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + +static ssize_t proc_value_get(const char __user *buffer, unsigned long count, char *value) +{ + if (count == 0 || count >= MAX_BUF_SIZE) { + return -EINVAL; + } + + if (copy_from_user(value, buffer, count)) { + return -EINVAL; + } + + value[count - 1] = '\0'; + + return 0; +} + +static int proc_net_qos_enable_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_enable); + return 0; +} + +static int proc_net_qos_enable_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_enable_open, NULL); +} + +static int qos_cmd_upcall(char *cmd) +{ + int ret = 0; + char *argv[] = { + "/bin/bash", + "-c", + cmd, + NULL, + }; + + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); + if (ret) { + BWM_LOG_ERR("call_usermodehelper failed, ret = %d", ret); + } + + return ret; +} + +static ssize_t proc_net_qos_enable_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char nspid[MAX_BUF_SIZE] = { 0 }; + char cmd[MAX_CMD_LEN] = { 0 }; + + ret = proc_value_get(buffer, count, nspid); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + BWM_LOG_DEBUG("get nspid %s", nspid); + + ret = snprintf(cmd, MAX_CMD_LEN, "%s -n -t %s %s -e", NSENTER_PATH, nspid, BWMCLI_PATH); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf enable qos cmd"); + return ret; + } + BWM_LOG_DEBUG("enable qos cmd:%s", cmd); + + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("qos_enable_upcall failed"); + } + + return count; +} + +static int proc_net_qos_disable_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_disable); + return 0; +} + +static int proc_net_qos_disable_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_disable_open, NULL); +} + +static ssize_t proc_net_qos_disable_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char nspid[MAX_BUF_SIZE] = { 0 }; + char cmd[MAX_CMD_LEN] = { 0 }; + + ret = proc_value_get(buffer, count, nspid); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + BWM_LOG_DEBUG("get nspid %s.", nspid); + + ret = snprintf(cmd, MAX_CMD_LEN, "%s -n -t %s %s -d", NSENTER_PATH, nspid, BWMCLI_PATH); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf disable qos cmd"); + return ret; + } + BWM_LOG_DEBUG("disable qos cmd:%s", cmd); + + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("disable qos failed"); + } + + return count; +} + +static int proc_net_qos_bandwidth_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_bandwidth); + return 0; +} + +static int proc_net_qos_bandwidth_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_bandwidth_open, NULL); +} + +static ssize_t proc_net_qos_bandwidth_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char bandwidth[MAX_BUF_SIZE] = { 0 }; + char cmd[MAX_CMD_LEN] = { 0 }; + + ret = proc_value_get(buffer, count, bandwidth); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + BWM_LOG_DEBUG("change net_qos_bandwidth to %s.", bandwidth); + + ret = snprintf(cmd, MAX_CMD_LEN, "%s -s bandwidth %s", BWMCLI_PATH, bandwidth); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf bandwidth cmd"); + return ret; + } + BWM_LOG_DEBUG("set bandwidth cmd : %s", cmd); + + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("set bandwidth failed"); + return ret; + } + + ret = snprintf(net_qos_bandwidth, MAX_BUF_SIZE, "%s", bandwidth); + if (ret < 0) { + BWM_LOG_ERR("failed to write net_qos_bandwidth"); + return ret; + } + + return count; +} + +static int proc_net_qos_waterline_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_waterline); + return 0; +} + +static int proc_net_qos_waterline_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_waterline_open, NULL); +} + +static ssize_t proc_net_qos_waterline_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char waterline[MAX_BUF_SIZE] = { 0 }; + char cmd[MAX_CMD_LEN] = { 0 }; + + ret = proc_value_get(buffer, count, waterline); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + BWM_LOG_DEBUG("change net_qos_waterline to %s.", waterline); + + ret = snprintf(cmd, MAX_CMD_LEN, "%s -s waterline %s", BWMCLI_PATH, waterline); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf waterline cmd"); + return ret; + } + BWM_LOG_DEBUG("set waterline cmd : %s", cmd); + + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("set waterline failed"); + return ret; + } + + ret = snprintf(net_qos_waterline, MAX_BUF_SIZE, "%s", waterline); + if (ret < 0) { + BWM_LOG_ERR("failed to write net_qos_waterline"); + return ret; + } + + return count; +} + +static int proc_net_qos_devs_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_devs); + return 0; +} + +static int proc_net_qos_devs_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_devs_open, NULL); +} + +static ssize_t proc_net_qos_devs_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char nspid[MAX_BUF_SIZE] = { 0 }; + char cmd[MAX_CMD_LEN] = { 0 }; + + ret = proc_value_get(buffer, count, nspid); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + BWM_LOG_DEBUG("write nspid:%s to net_qos_devs", nspid); + + ret = snprintf(cmd, MAX_CMD_LEN, "%s -n -t %s %s -p devs > /proc/qos/net_qos_devstatus", + NSENTER_PATH, nspid, BWMCLI_PATH); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf devs status cmd"); + return ret; + } + BWM_LOG_DEBUG("get devs status cmd:%s", cmd); + + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("write net_qos_devs failed"); + } + + return count; +} + +static int proc_net_qos_devstatus_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_devstatus); + return 0; +} + +static int proc_net_qos_devstatus_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_devstatus_open, NULL); +} + +static ssize_t proc_net_qos_devstatus_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char data[MAX_BUF_SIZE] = { 0 }; + + ret = proc_value_get(buffer, count, data); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + + ret = snprintf(net_qos_devstatus, MAX_DATA_SIZE, "%s", data); + if (ret < 0) { + BWM_LOG_ERR("write net_qos_devstatus failed"); + } + + return count; +} + +static atomic_t stats_flag = ATOMIC_INIT(0); + +static int proc_net_qos_stats_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%s\n", net_qos_stats); + return 0; +} + +static int proc_net_qos_stats_single_open(struct inode *inode, struct file *file) +{ + int ret = 0; + char cmd[MAX_CMD_LEN] = { 0 }; + + if (atomic_read(&stats_flag) == 0) { + ret = snprintf(cmd, MAX_CMD_LEN, "%s -p stats > /proc/qos/net_qos_stats", BWMCLI_PATH); + if (ret < 0) { + BWM_LOG_ERR("failed to snprintf stats cmd"); + return ret; + } + BWM_LOG_DEBUG("stats cmd:%s", cmd); + + atomic_xchg(&stats_flag, 1); + ret = qos_cmd_upcall(cmd); + if (ret != 0) { + BWM_LOG_ERR("read net_qos_stats failed"); + atomic_xchg(&stats_flag, 0); + return ret; + } + single_open(file, proc_net_qos_stats_open, NULL); + return 0; + } + atomic_xchg(&stats_flag, 0); + return single_open(file, proc_net_qos_stats_open, NULL); +} + +static ssize_t proc_net_qos_stats_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char stats[MAX_BUF_SIZE] = { 0 }; + + ret = proc_value_get(buffer, count, stats); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + + ret = snprintf(net_qos_stats, MAX_DATA_SIZE, "%s", stats); + if (ret < 0) { + BWM_LOG_ERR("write net_qos_stats failed"); + } + + return count; +} + +static int proc_net_qos_version_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "version:%s\n", net_qos_version); + return 0; +} + +static int proc_net_qos_version_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_version_open, NULL); +} + +static int proc_net_qos_debug_open(struct seq_file *seq, void *offset) +{ + seq_printf(seq, "%u\n", net_qos_debug); + return 0; +} + +static int proc_net_qos_debug_single_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_net_qos_debug_open, NULL); +} + +static ssize_t proc_net_qos_debug_write(struct file *file, const char __user *buffer, + unsigned long count, loff_t *ppos) +{ + int ret = 0; + char debug_mode[MAX_BUF_SIZE] = { 0 }; + unsigned int net_qos_debug_new = net_qos_debug; + + ret = proc_value_get(buffer, count, debug_mode); + if (ret != 0) { + BWM_LOG_ERR("proc_value_get failed"); + return count; + } + + net_qos_debug_new = simple_strtoul(debug_mode, NULL, 0); + if (net_qos_debug_new != 0 && net_qos_debug_new != 1) { + BWM_LOG_ERR("invalid input of debug mode(%d), valid input: 0 or 1.", net_qos_debug_new); + return count; + } + + BWM_LOG_INFO("change debug mode, old is %u, new is %u.", net_qos_debug, net_qos_debug_new); + net_qos_debug = net_qos_debug_new; + + return count; +} + +static struct proc_ops bwm_proc_net_qos_enable_ops = { + .proc_open = proc_net_qos_enable_single_open, + .proc_write = proc_net_qos_enable_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_disable_ops = { + .proc_open = proc_net_qos_disable_single_open, + .proc_write = proc_net_qos_disable_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_bandwidth_ops = { + .proc_open = proc_net_qos_bandwidth_single_open, + .proc_write = proc_net_qos_bandwidth_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_waterline_ops = { + .proc_open = proc_net_qos_waterline_single_open, + .proc_write = proc_net_qos_waterline_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_devs_ops = { + .proc_open = proc_net_qos_devs_single_open, + .proc_write = proc_net_qos_devs_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_devstatus_ops = { + .proc_open = proc_net_qos_devstatus_single_open, + .proc_write = proc_net_qos_devstatus_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_stats_ops = { + .proc_open = proc_net_qos_stats_single_open, + .proc_write = proc_net_qos_stats_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_version_ops = { + .proc_open = proc_net_qos_version_single_open, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct proc_ops bwm_proc_net_qos_debug_ops = { + .proc_open = proc_net_qos_debug_single_open, + .proc_write = proc_net_qos_debug_write, + .proc_read = seq_read, + .proc_release = single_release, +}; + +static struct bwm_proc g_proc_table[] = { + { + .proc_name = "net_qos_enable", + .entry = NULL, + .ops = &bwm_proc_net_qos_enable_ops, + }, + { + .proc_name = "net_qos_disable", + .entry = NULL, + .ops = &bwm_proc_net_qos_disable_ops, + }, + { + .proc_name = "net_qos_bandwidth", + .entry = NULL, + .ops = &bwm_proc_net_qos_bandwidth_ops, + }, + { + .proc_name = "net_qos_waterline", + .entry = NULL, + .ops = &bwm_proc_net_qos_waterline_ops, + }, + { + .proc_name = "net_qos_devs", + .entry = NULL, + .ops = &bwm_proc_net_qos_devs_ops, + }, + { + .proc_name = "net_qos_devstatus", + .entry = NULL, + .ops = &bwm_proc_net_qos_devstatus_ops, + }, + { + .proc_name = "net_qos_stats", + .entry = NULL, + .ops = &bwm_proc_net_qos_stats_ops, + }, + { + .proc_name = "net_qos_version", + .entry = NULL, + .ops = &bwm_proc_net_qos_version_ops, + }, + { + .proc_name = "net_qos_debug", + .entry = NULL, + .ops = &bwm_proc_net_qos_debug_ops, + }, +}; + +static int bwm_proc_init(void) +{ + unsigned int i; + int ret = 0; + + bwm_proc_root_dir = proc_mkdir(BWM_PROC_ROOTDIR, NULL); + if (!bwm_proc_root_dir) { + BWM_LOG_ERR("can't create /proc/%s.", BWM_PROC_ROOTDIR); + return -EFAULT; + } + + for (i = 0; i < sizeof(g_proc_table) / sizeof(struct bwm_proc); i++) { + g_proc_table[i].entry = proc_create_seq_data(g_proc_table[i].proc_name, BWM_CTL_PROC_PERM, + bwm_proc_root_dir, NULL, NULL); + if (!g_proc_table[i].entry) { + BWM_LOG_ERR("can't create file(%s).", g_proc_table[i].proc_name); + ret = -EFAULT; + break; + } + g_proc_table[i].entry->proc_ops = g_proc_table[i].ops; + } + + if (ret != 0) { + BWM_LOG_ERR("bwm_proc_init failed"); + } + + return ret; +} + +static void bwm_proc_clean(void) +{ + unsigned int i; + + if (bwm_proc_root_dir) { + for (i = 0; i < sizeof(g_proc_table) / sizeof(struct bwm_proc); i++) { + if (g_proc_table[i].entry) { + remove_proc_entry(g_proc_table[i].proc_name, bwm_proc_root_dir); + g_proc_table[i].entry = NULL; + } + } + remove_proc_entry(BWM_PROC_ROOTDIR, NULL); + bwm_proc_root_dir = NULL; + } +} + +static int __init bwm_init(void) +{ + int ret = 0; + + ret = bwm_proc_init(); + if (ret != 0) { + bwm_proc_clean(); + return ret; + } + + BWM_LOG_INFO("bwm loaded"); + return ret; +} + +static void __exit bwm_exit(void) +{ + bwm_proc_clean(); + BWM_LOG_INFO("bwm unloaded"); +} + +module_init(bwm_init); +module_exit(bwm_exit); +MODULE_LICENSE("GPL"); diff --git a/ko/bwm.h b/ko/bwm.h new file mode 100644 index 0000000..a977c0e --- /dev/null +++ b/ko/bwm.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved. + * Description: Network bandwidth management tool + */ +#ifndef NET_BWM_H +#define NET_BWM_H + +#include <asm/atomic.h> +#include <linux/delay.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/types.h> +#include <fs/proc/internal.h> + +#define BWM_PROC_ROOTDIR "qos" +#define BWM_CTL_PROC_PERM 0644 + +#define NSENTER_PATH "/usr/bin/nsenter" +#define BWMCLI_PATH "/usr/bin/bwmcli" + +#define MAX_BUF_SIZE 128 +#define MAX_CMD_LEN (256 + NAME_MAX) +#define MAX_DATA_SIZE 1024 + +static char net_qos_disable[] = "please write <nspid> to net_qos_disable to disable qos"; +static char net_qos_enable[] = "please write <nspid> to net_qos_enable to enable qos"; +static char net_qos_bandwidth[MAX_BUF_SIZE]; +static char net_qos_waterline[MAX_BUF_SIZE]; +static char net_qos_devs[] = "please write <nspid> to net_qos_devs and read dev status from net_qos_devstatus"; +static char net_qos_devstatus[MAX_DATA_SIZE]; +static char net_qos_stats[MAX_DATA_SIZE]; +static char net_qos_version[] = "1.1"; +static unsigned int net_qos_debug = 0; + +static struct proc_dir_entry *bwm_proc_root_dir = NULL; + +struct bwm_proc { + const char *proc_name; + struct proc_dir_entry *entry; + struct proc_ops *ops; +}; + +#define PFX "BWM" + +#define BWM_LOG_INFO(fmt, ...) \ + do { \ + printk(KERN_INFO "[" PFX "] INFO:" fmt "[%s():%u]\n", ##__VA_ARGS__, __FUNCTION__, __LINE__); \ + } while (0) + +#define BWM_LOG_NOTICE(fmt, ...) \ + do { \ + printk(KERN_NOTICE "[" PFX "] NOTICE:" fmt, ##__VA_ARGS__); \ + } while (0) + +#define BWM_LOG_ERR(fmt, ...) \ + do { \ + printk(KERN_ERR "[" PFX "] ERROR:" fmt "[%s():%u]\n", ##__VA_ARGS__, __FUNCTION__, __LINE__); \ + } while (0) + +#define BWM_LOG_DEBUG(fmt, ...) \ + do { \ + if (net_qos_debug == 1) { \ + printk(KERN_DEBUG "[" PFX "] DEBUG:" fmt "[%s():%u]\n", ##__VA_ARGS__, __FUNCTION__, __LINE__); \ + } \ + } while (0) + +#endif -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2