Новая дисциплина очереди Linux для создания очередей ... закончилась - PullRequest
5 голосов
/ 22 августа 2011

Я хочу написать новую дисциплину очередей tc для ядра linux. Цель состоит в том, чтобы стоять в очереди, например. десять пакетов, а затем отправить их все (я знаю, это не очень хорошая вещь для работы в сети, но я хочу провести некоторое исследование с этим).

Итак, что уже сделано: у меня есть скелет нового модуля sched (постановка в очередь, функции удаления из очереди и т. Д.), Который также правильно компилируется и работает правильно (один пакет поставлен в очередь, один пакет отправлен - ничего особенного) , Я собираю его на Ubuntu Maverick с теми же источниками, что и работающее ядро, и помещаю свой модуль в Makefile и Kconfig.

Я выяснил, что каждый раз, когда вызывается функция enqueue, после этого функция dequeue вызывается qdisc_restart (в sch_generic.c) - и отправляется только один пакет.

Моя проблема: как я могу отправить более одного пакета из моего модуля в сетевой интерфейс, как я собрал, например, для. 10 пакетов, и теперь я хочу отправить их все?

Я пытался вызвать функцию sch_direct_xmit (из sch_generic.c) с теми же параметрами, что и в qdisc_restart (и механизмах блокировки) - но затем компиляция моего модуля завершается неудачно: неизвестный символ sch_direct_xmit (но greping / proc / kallsyms для это дает мне результат). Есть идеи, что с этим не так? Если какой-то код требуется, просто дайте мне знать (я включил тот же .h, что и в sched_generic.c)

BR Christoph

1 Ответ

0 голосов
/ 07 ноября 2011

Я думаю, что самым простым решением было бы использовать kthread, который вы проснетесь, когда поставите в очередь 10 пакетов. Kthread будет отвечать за использование пакетов, которые вы ранее поставили в очередь.

Без некоторых примеров вашего кода трудно понять, какая последовательность событий вызывает вашу функцию dequeue, но вы, вероятно, можете сделать что-то подобное:

static struct sk_buff_head foo_skb_queue;
static DECLARE_WAIT_QUEUE_HEAD(food_wqh);

int food_sender(void* unused)
{
        struct sk_buff* skb = NULL;
        unsigned int i = 0;

        while (!kthread_should_stop()) {

                while (skb = skb_dequeue(&foo_skb_queue) && i < NUMBER_TO_SEND) {
                         send_packet(skb);
                         ++i;
                }

                DECLARE_WAITQUEUE(wq, current);
                set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&food_wqh, &wq);

                /* Avoid wake-up lost race */
                if (skb_queue_len(&foo_skb_queue) < NUMBER_TO_SEND)
                        schedule();

                remove_wait_queue(&food_wqh, &wq);
        }
        return 0;
}

int foo_enqueue(struct sk_buff* skb)
{
        skb_queue_tail(&foo_skb, skb);       
        if (skb_queue_len(&foo_skb) >= NUMBER_TO_SEND)
                wake_up(&food_wqh);

        return 0;
}

Что-то вроде этого сделало бы это, я подозреваю. Код не скомпилирован, но дает представление о том, как это сделать.

...