Ядро Linux: получение пакетов с сетевого устройства

Я пытаюсь написать простую программу, которая берет пакет с интерфейса и распечатывает MAC-адреса назначения и источника на уровне ядра Linux. Это мой первый проект, работающий с ядром Linux, и я прочитал много исходного кода и книг, связанных с netdevice, loopback и skbuff. Теперь, из того, что я узнал до сих пор, skbuff выглядит как место размещения данных пакета, но я не могу понять, как драйвер сетевого устройства берет пакеты с интерфейса и помещает их в skb или как вы связываете skb с конкретным интерфейсом.

Может ли кто-нибудь сказать мне, как я смотрю на skb, связанный с сетевым устройством, таким как eth0? Есть ли какое-то кольцо передачи и приема, которое мне нужно, чтобы их забрать?

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

Извините, если это расплывчатый вопрос, я пытался исследовать как можно больше. Заранее спасибо.


person user2129635    schedule 03.03.2013    source источник


Ответы (2)


Возьмем, к примеру, базовые коды одного чипа Ethernet, основанного на PCI: ./drivers/net/pci-skeleton.c. Возможно, этот код является старым стилем драйвера Ethernet, но он полезен для изучения.

Поток приема пакетов: netdrv_rx_interrupt() --> выделение/замена sk_buff --> вызов netif_rx(), передавая полученный пакет/sk_buff на верхний уровень стека;

Поток отправки пакетов: netdrv_start_xmit();

Процесс инициализации устройства: можно начать с init_module();

Общие функции можно найти в ./net/core/dev.c, например, netif_rx...;

person tian_yufeng    schedule 04.03.2013
comment
Спасибо, это кажется знакомым из кода, который я прочитал. Просто чтобы подтвердить, что я прочитал ваш пост правильно, поток принимаемых пакетов: 1. выделить/заменить sk_buff на netdrv_rx_interrupt(). 2. передать пакет на верхние уровни с помощью netif_rx(). А не наоборот? - person user2129635; 05.03.2013

Вы можете попробовать использовать хуки netfilter.

Зарегистрируйте свой обратный вызов с помощью nf_register_hook(), и он будет вызываться для данного семейства адресов (например, AF_INET — это IPv4) и типа (например, NF_IP_LOCAL_IN для входящих пакетов). Ваш хук также получит skb и сетевое устройство, через которое пришел или ушел пакет.

Прототип вашего обратного вызова выглядит примерно так:

unsigned int my_hook(unsigned int hook,
                     struct sk_buff *skb,
                     const struct net_device *in,
                     const struct net_device *out,
                     int (*okfn)(struct sk_buff *));

Существует (устаревший) пример по адресу http://www.sikurezza.org/ml/12_99/msg00063.html, но вы также можете покопаться в исходниках ядра, там есть несколько примеров того, как сетевой стек или модули iptables используют перехватчики netfilter.

person ldx    schedule 03.03.2013