Сетевой стек Linux: добавление протоколов с помощью LKM и dev_add_pack - PullRequest
7 голосов
/ 13 мая 2010

Недавно я пытался ознакомиться с сетевым стеком Linux и драйверами устройств (обе книги с одинаковым названием O'Reilly) с возможной целью разгрузки UDP. Я уже реализовал UDP на сетевой карте, но теперь сложная часть ...

Вместо того, чтобы просить помощи в достижении этой более крупной цели, я надеялся, что кто-то сможет прояснить для меня определенный фрагмент, который я обнаружил, который является частью LKM, который регистрирует новый протокол (OTP), который действует как фильтр между драйвером устройства и сетью. стек.

http://www.phrack.org/archives/55/p55_0x0c_Building%20Into%20The%20Linux%20Network%20Layer_by_lifeline%20&%20kossak.txt

(Примечание: эта статья Phrack содержит три разных модуля, код для OTP находится внизу страницы)

В функции init его примера он имеет:

    otp_proto.type = htons(ETH_P_ALL); 
    otp_proto.func = otp_func;
    dev_add_pack(&otp_proto);

который (если я правильно понимаю) должен зарегистрировать otp_proto в качестве анализатора пакетов и поместить его в структуру данных ptype_all. Мой вопрос по поводу dev_add_pack.

Это тот случай, когда протокол, зарегистрированный в качестве фильтра, всегда будет размещаться на этом уровне между L2 и драйвером устройства? Или, например, можно ли сделать такую ​​фильтрацию между прикладным и транспортным уровнями (проанализировать параметры сокета), используя один и тот же процесс?

Я прошу прощения, если это сбивает с толку - у меня возникают некоторые проблемы, когда я зацикливаюсь на большей картине, когда речь идет о модулях, изменяющих функциональность стека ядра.

Спасибо

Ответы [ 2 ]

2 голосов
/ 22 апреля 2016

Когда вы регистрируете обработчик протокола в dev_add_pack, функция обратного вызова обработчика будет вызываться при поступлении пакета. Вот как работает обработчик протокола IP. Из inet_init:

static int __init inet_init(void)
{
    ...
    rc = proto_register(&tcp_prot, 1);
    ...
    rc = proto_register(&udp_prot, 1);
    ...
    dev_add_pack(&ip_packet_type);
    ....

Когда NIC вызывает прерывание для пакета, который прибывает, запускается обработчик прерывания NIC, который в конечном итоге вызывает netif_rx (или __napi_schedule), что вызовет softirq net_rx_action. Это приведет к вызову delivery_skb для каждого зарегистрированного обработчика протокола. От __netif_receive_skb_core

static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
    ...
    list_for_each_entry_rcu(ptype, &ptype_all, list) {
        if (pt_prev)
            ret = deliver_skb(skb, pt_prev, orig_dev);
        pt_prev = ptype;
    }

Так что да, ваша функция обратного вызова обработчика протокола будет вызываться на L2 вместе с ip_rcv для обработчика протокола IP.

Вы можете зарегистрировать обработчик протокола на L3 с помощью proto_register, если вы хотите, чтобы его вызывали на этом уровне.

1 голос
/ 02 декабря 2011

Это тот случай, когда протокол, зарегистрированный в качестве фильтра, будет всегда находиться на этом уровне между L2 и драйвером устройства? Или же, например, я мог бы сделать такую ​​фильтрацию между прикладной и транспортный уровни (анализ параметров сокета) с использованием тот же процесс?

Да. .func () зарегистрированного вами типа пакета вызывается в __netif_receive_skb () до того, как обработчик rx устройства его обработает.

...