net_rx_action (сетевая архитектура)

Взгляд изнутри

Модератор: Модераторы разделов

featurelles
Сообщения: 8

net_rx_action

Сообщение featurelles »

Касается функции net_rx_action (определена в net/core/dev.c)
вот её код
Код:

Код: Выделить всё

static void net_rx_action(struct softirq_action *h)
{
    struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
    unsigned long time_limit = jiffies + 2;
    int budget = netdev_budget;
    void *have;

    local_irq_disable();

    while (!list_empty(list)) {
        struct napi_struct *n;
        int work, weight;

        /* If softirq window is exhuasted then punt.
         * Allow this to run for 2 jiffies since which will allow
         * an average latency of 1.5/HZ.
         */
        if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
            goto softnet_break;

        local_irq_enable();

        /* Even though interrupts have been re-enabled, this
         * access is safe because interrupts can only add new
         * entries to the tail of this list, and only ->poll()
         * calls can remove this head entry from the list.
         */
        n = list_entry(list->next, struct napi_struct, poll_list);

        have = netpoll_poll_lock(n);

        weight = n->weight;

        /* This NAPI_STATE_SCHED test is for avoiding a race
         * with netpoll's poll_napi().  Only the entity which
         * obtains the lock and sees NAPI_STATE_SCHED set will
         * actually make the ->poll() call.  Therefore we avoid
         * accidently calling ->poll() when NAPI is not scheduled.
         */
        work = 0;
        if (test_bit(NAPI_STATE_SCHED, &n->state)) {
            work = n->poll(n, weight);
            trace_napi_poll(n);
        }

        WARN_ON_ONCE(work > weight);

        budget -= work;

        local_irq_disable();

        /* Drivers must not modify the NAPI state if they
         * consume the entire weight.  In such cases this code
         * still "owns" the NAPI instance and therefore can
         * move the instance around on the list at-will.
         */
        if (unlikely(work == weight)) {
            if (unlikely(napi_disable_pending(n))) {
                local_irq_enable();
                napi_complete(n);
                local_irq_disable();
            } else
                list_move_tail(&n->poll_list, list);
        }

        netpoll_poll_unlock(have);
    }
out:
    local_irq_enable();

#ifdef CONFIG_NET_DMA
    /*
     * There may not be any more sk_buffs coming right now, so push
     * any pending DMA copies to hardware
     */
    dma_issue_pending_all();
#endif

    return;

softnet_break:
    __get_cpu_var(netdev_rx_stat).time_squeeze++;
    __raise_softirq_irqoff(NET_RX_SOFTIRQ);
    goto out;
}


Меня интересует этот участок

struct napi_struct *n;
n = list_entry(list->next, struct napi_struct, poll_list);
( если кто-то не помнит, вот описание функции list_entry )

list_entry(p, t, m) Возвращает адрес структуры типа t, включающей в себя поле типа list_head с именем m и адресом p

Как видно, код возвращает указатель на struct napi_struct ( определена в include/linux/netdevice.h)
Код:

Код: Выделить всё

struct napi_struct {
    /* The poll_list must only be managed by the entity which
     * changes the state of the NAPI_STATE_SCHED bit.  This means
     * whoever atomically sets that bit can add this napi_struct
     * to the per-cpu poll_list, and whoever clears that bit
     * can remove from the list right before clearing the bit.
     */
    struct list_head    poll_list;

    unsigned long        state;
    int            weight;
    int            (*poll)(struct napi_struct *, int);
#ifdef CONFIG_NETPOLL
    spinlock_t        poll_lock;
    int            poll_owner;
#endif

    unsigned int        gro_count;

    struct net_device    *dev;
    struct list_head    dev_list;
    struct sk_buff        *gro_list; // ЧТО ЭТО ЗА УКАЗАТЕЛЬ??????
    struct sk_buff        *skb;
};


Теперь поясню, что за функция такая net_rx_action - это процедура обработки NET_RX_SOFTIRQ по окончанию её работы, пакет skb должен передаться для обработки дальше, сетевому уровню сетевого стека. Она должна принимать из входной очереди текущего процессора пакеты и передавать их обрабатывающему протоколу.
Как я понял n->skb должен указывать на обрабатываемый пакет. Но при проверке после n = list_entry(list->next, struct napi_struct, poll_list);
оказывается что if( !n->skb ) printk ("Указатель на буфер сокета пуст!!! \n");
Мне не ясно! когда struct napi_struct будет содержать адрес текущего пакета,а также не понятно, как именно net_rx_action передаёт пакет вышележащим протоколам.
Рассчитываю на помощь.
Спасибо сказали:
Аватара пользователя
PodBot
Сообщения: 13
ОС: GNU/Linux

Re: net_rx_action

Сообщение PodBot »

Я думаю тебе стоит проверять это поле тут:

Код: Выделить всё

if (test_bit(NAPI_STATE_SCHED...) {
    work = n->poll(n, weight);
    ......
}

Хорошая дока:
http://www.gelato.unsw.edu.au/lxr/source/D.../NAPI_HOWTO.txt
Спасибо сказали:
featurelles
Сообщения: 8

Re: net_rx_action

Сообщение featurelles »

PodBot писал(а):
18.11.2009 09:31
Я думаю тебе стоит проверять это поле тут:

Код: Выделить всё

if (test_bit(NAPI_STATE_SCHED...) {
    work = n->poll(n, weight);
    ......
}

Хорошая дока:
http://www.gelato.unsw.edu.au/lxr/source/D.../NAPI_HOWTO.txt

Спасибо, я уже разобрался (нашёл информацию в тема )
За ссылку спасибо, попробую почитать , но есть ли где-то подобный HOWTO на русском?
Спасибо сказали: