https://velog.io/@brian11hwang/Tracing-mlx5esetuptc

#include <linux/kmod.h>
#device name and Gbit limit should be variables.
char *argv[] = { "/sbin/tc", "qdisc", "add", "dev", "enp6s0", "root", "handle", "1:", "htb", "default", "10", NULL };
static char* envp[] = {
"HOME=/",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
NULL
};
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
Yet, when trying to test tc, the driver would die, due placing the code inside the __init functions, which:
1) states all initialization functions
2) runs them in thread workqueue

Thus, tc applications are executed before device is fully ready.

Therefore, we will first test with a simple logger:
char *argv[] = { "/usr/bin/logger", "help!", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };ㅓㅓ
return call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC );

Or, we could also run .sh files
printk("IS AFTER ALL FINISH?");
char *argv[] = { "/usr/bin/tc.sh", NULL };
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
call_usermodehelper( argv[0], argv, envp, UMH_WAIT_PROC );
where .sh file is:
#!/bin/bash
sudo logger -p kern.notice "Test for call usermodhelper"

Therefore, once the backchannel is made, we can do something like:
#include <linux/kmod.h>
// Define interface and bandwidth limit
char *interface = "enp6s0";
char *bw_limit = "20Gbit";
// Define command arrays
char *argv1[] = { "/sbin/tc", "qdisc", "del", "dev", interface, "root", NULL };
char *argv2[] = { "/sbin/tc", "qdisc", "add", "dev", interface, "root", "handle", "1:", "htb", "default", "10", NULL };
char *argv3[] = { "/sbin/tc", "class", "add", "dev", interface, "parent", "1:", "classid", "1:1", "htb", "rate", bw_limit, NULL };
char *argv4[] = { "/sbin/tc", "class", "add", "dev", interface, "parent", "1:1", "classid", "1:10", "htb", "rate", bw_limit, NULL };
// Define environment
static char* envp[] = {
"HOME=/",
"PATH=/sbin:/bin:/usr/sbin:/usr/bin",
NULL
};
// Run the commands
call_usermodehelper(argv1[0], argv1, envp, UMH_WAIT_PROC);
call_usermodehelper(argv2[0], argv2, envp, UMH_WAIT_PROC);
call_usermodehelper(argv3[0], argv3, envp, UMH_WAIT_PROC);
call_usermodehelper(argv4[0], argv4, envp, UMH_WAIT_PROC);
which will run:

This approach is to create a user-space application (daemon) which monitors a sysfs or procfs file, and when a change is noted, it will apply the tc command. The kernel module will write to the sysfs/procfs file to trigger the application.
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/module.h>
static ssize_t my_sysfs_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
return count;
}
static struct kobj_attribute my_sysfs_attribute =
__ATTR(my_sysfs_file, 0220, NULL, my_sysfs_store);
static struct kobject *my_kobject;
static int __init my_module_init (void)
{
int error = 0;
my_kobject = kobject_create_and_add("my_kobject", kernel_kobj);
if(!my_kobject)
return -ENOMEM;
error = sysfs_create_file(my_kobject, &my_sysfs_attribute.attr);
if (error) {
printk("failed to create the my_sysfs_file file in /sys/kernel/my_kobject \n");
}
return error;
}
my_sysfs_storeis a function that is called when data is written to themy_sysfs_filefile in sysfs. The parameters are:
-kobjpoints to the struct kobject that the attribute belongs to.
-attrpoints to the struct kobj_attribute for the specific attribute that was written.
-bufpoints to the buffer that contains the written data.
-countis the number of bytes that were written.
my_sysfs_attributeis a struct of typestruct kobj_attribute. The__ATTRmacro is used to initialize it. The macro takes four arguments:
- The name of the attribute (my_sysfs_file).
- The mode of the attribute (0220, write permission for owner and group).
- A pointer to theshowmethod for the attribute (not used here, set toNULL).
- A pointer to thestoremethod for the attribute (my_sysfs_store).
#!/bin/bash
interface="enp6s0"
bw_limit="20Gbit"
while inotifywait -e modify /sys/kernel/my_kobject/my_sysfs_file; do
/sbin/tc qdisc del dev $interface root
/sbin/tc qdisc add dev $interface root handle 1: htb default 10
/sbin/tc class add dev $interface parent 1: classid 1:1 htb rate $bw_limit
/sbin/tc class add dev $interface parent 1:1 classid 1:10 htb rate $bw_limit
done
소중한 정보 감사드립니다!