Задать вопрос
@Jarikstron228

Как импортировать пользовательский модуль в Linux ядро?

есть код, который я написал на пару с 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-маршрутизаторов на нечёткой логике
  • Вопрос задан
  • 57 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
выдаёт ошибку
insmod: ERROR: could not insert module flc2.ko: Invalid parameters

Это значит что твоя функция flc2_module_init() возвращает -EINVAL. Заглянув в единственную функцию register_qdisc() которую ты вызываешь, можно увидеть следующее:
if (qops->peek == NULL) {
                if (qops->dequeue == NULL)
                        qops->peek = noop_qdisc_ops.peek;
                else
                        goto out_einval;
        }

т.е. одновременное peek == NULL и dequeue != NULL гарантированно приводит к ошибке которую ты наблюдаешь.
Разбирайся с заполнением структуры flc2_qdisc_ops.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы