Немного о реализации сетевых драйверов в линукс.
Как протестировать сетевую часть процессора на максимальное быстродействие?
Тестирование, конечно, лучше производить с помощью какого-нибудь аппаратного сетевого тестера, как правило, это тестеры jdsu. Или, как вариант, это написание простой утилиты, которая бы непрерывно посылала трафик в сеть.
Самый простейший пример такой программы:
while (number > 0) { c = sendto(fd, file_buf, frameLen, 0, (struct sockaddr *)&sa, sizeof (sa)); number --; }
Что должен делать процессор с поступающим трафиком?
Поскольку нас интересует именно максимальное быстродействие, то нам не нужно, чтобы входящий пакет попадал в ядро и разбирался там на всех сетевых уровнях.
Нам требуется сделать заворот прямо в прерывании по приёму и отправить его обратно в сеть. По-научному, наверное, это будет называться loop.
Сетевой стек линукса очень крут, и поэтому решить поставленную задачу довольно просто и при этом данное решение не будет привязано к какой-то определенной архитектуре процессоров и сетевых плат.
Сетевые драйвера находятся здесь:
kernel/drivers/net/ethernet
Чтобы сделать заворот пакета, нужно найти функцию прерывания по приёму и там принятый пакет отправить обратно в сеть. Как правило, каждый приём пакета заканчивается вызовом функции netif_receive_skb, которая передаёт принятый пакет ядру.
Запускаем поиск по функции netif_receive_skb. То место, откуда она вызывается, как правило, и есть функция-обработчик прерывания по приёму.
Прямо перед вызовом netif_receive_skb делаем отправку пакета обратно в сеть, а вызов netif_receive_skb отключаем.
if (dev_queue_xmit(skb)){ dev_kfree_skb(skb); } // netif_receive_skb(skb);
Также нужно найти место, где удаляется начальный заголовок, обычно это выглядит вот так:
skb->protocol = eth_type_trans(skb, mp->dev);
И тоже его закомментировать:
//skb->protocol = eth_type_trans(skb, mp->dev);
Всё, теперь все поступающие пакеты будут мгновенно отправляться обратно в сеть, не попадая в ядро.