есть код, который я написал на пару с gpt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/random.h>
#include <net/pkt_sched.h>
// Лицензия GPL
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ярик");
MODULE_DESCRIPTION("Модуль FLC2 для борьбы с перегрузками");
// Структура для хранения состояний
struct flc2_sched_data {
struct Qdisc *qdisc;
u32 queue_len; // текущая длина очереди
s32 queue_diff; // изменение длины очереди с последнего вызова
u32 prev_queue_len; // предыдущая длина очереди
};
// основная функция flc2
static u32 fuzzy_logic_infer(u32 qlen, s32 dqlen)
{
// уровни вероятности: от Very Low до Very High
enum { VL = 0, L = 25, M = 50, H = 75, VH = 100 };
// классификация длины очереди по уровням
int q_class = (qlen < 20) ? VL : (qlen < 40) ? L : (qlen < 60) ? M : (qlen < 80) ? H : VH;
// аналогично изменения длины очереди
int dq_class = (dqlen < -20) ? VL : (dqlen < -10) ? L : (dqlen < 10) ? M : (dqlen < 20) ? H : VH;
// Матрица нечётких правил (таблица соответствий): строки — qlen, столбцы — dqlen
// Каждая ячейка задаёт вероятность сброса пакета
static const u32 fuzzy_matrix[5][5] = {
// dqlen: VL L M H VH
/* qlen = VL */ { VL, VL, L, M, H },
/* qlen = L */ { VL, L, M, H, VH },
/* qlen = M */ { L, M, M, H, VH },
/* qlen = H */ { M, M, H, VH, VH },
/* qlen = VH */ { M, H, VH, VH, VH },
};
// выбор значения вероятности из матрицы правил
u32 drop_prob = fuzzy_matrix[q_class / 25][dq_class / 25];
return drop_prob;
}
// основная функция добавления пакета в очередь
static int flc2_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
{
struct flc2_sched_data *q = qdisc_priv(sch); // получаем структуру данных для планировщика
q->queue_len = sch->q.qlen; // текущая длина очереди
q->queue_diff = q->queue_len - q->prev_queue_len; // разница с предыдущей длиной
// вычисляем вероятность сброса пакета по FLC2
u32 drop_probability = fuzzy_logic_infer(q->queue_len, q->queue_diff);
// если вероятность превышена — сбрасываем пакет
if (prandom_u32() % 100 < drop_probability) {
qdisc_qstats_drop(sch);
kfree_skb(skb);
return NET_XMIT_DROP;
}
// только если пакет не сброшен, обновляем предыдущее значение длины
q->prev_queue_len = q->queue_len;
return qdisc_enqueue_tail(skb, sch); // добавляем в конец очереди
}
// извлекаем пакет из очереди (FIFO логика)
static struct sk_buff *flc2_dequeue(struct Qdisc *sch)
{
return qdisc_dequeue_head(sch);
}
// инициализация планировщика
static int flc2_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack)
{
struct flc2_sched_data *q = qdisc_priv(sch);
memset(q, 0, sizeof(*q)); // обнуляем структуру
return 0;
}
// сброс очереди
static void flc2_reset(struct Qdisc *sch)
{
qdisc_reset_queue(sch);
}
// запись операций планировщика
static struct Qdisc_ops flc2_qdisc_ops __read_mostly = {
.id = "flc2",
.priv_size = sizeof(struct flc2_sched_data),
.enqueue = flc2_enqueue,
.dequeue = flc2_dequeue,
.init = flc2_init,
.reset = flc2_reset,
.owner = THIS_MODULE,
};
// инициализация модуля при загрузке
static int __init flc2_module_init(void)
{
return register_qdisc(&flc2_qdisc_ops);
}
// очистка модуля при выгрузке
static void __exit flc2_module_exit(void)
{
unregister_qdisc(&flc2_qdisc_ops);
}
module_init(flc2_module_init);
module_exit(flc2_module_exit);
Собрал через make, машина ubuntu server 24.04.2 ядро 6.8.0-57-generic
при попытке его добавить в ядро Linux командой
sudo insmod flc2.ko
выдаёт ошибку
insmod: ERROR: could not insert module flc2.ko: Invalid parameters
модуль должен быть планировщиком для linux-маршрутизаторов на нечёткой логике