Сырье Ethernet вещание - PullRequest
       45

Сырье Ethernet вещание

1 голос
/ 07 июля 2011

Я скачал WinDDK и использую ndisprot 5x для широковещательной передачи пакетов Ethernet из моего пользовательского приложения с указанием MAC-адреса назначения 0xff для больших и повторяющихся наборов данных.

То, что в настоящее время прекрасно работает, это петля - указание MAC-адреса назначения и источника как моего собственного, я получаю необходимую скорость, но пакет никогда не покидает мою сетевую карту.

Может быть, мне не хватает некоторых параметров драйвера ndis и я ожидаю завершения трансляции с использованием этого примера драйвера MS? Все, что я хочу, - это пакет, который будет транслироваться в сеть, и я не очень беспокоюсь о статусе доставки и хочу избавиться от него как можно быстрее.

Поможет ли здесь система, имеющая только 2 балла? Я не уверен, что вызывает отставание.

1 Ответ

1 голос
/ 09 июля 2011

Невозможно исключить путь отправки-завершения в режиме ядра.Причина состоит в том, что сетевая карта занята чтением байтов из памяти, пока она наконец не выдаст завершение отправки.Если вы не дожидаетесь завершения отправки перед повторным использованием пакета, то у сетевой карты не было бы возможности прочитать полный пакет.В конечном итоге вы отправите поврежденные данные.

Но вы правы, что при использовании стандартного образца NDISPROT для отправки огромных объемов данных возникает большая неэффективность.Проблема в том, что пример приложения пользовательского режима NDISPROT записывает данные в режим ядра синхронно .Это означает, что ваш поток начинает запись (отправка пакета), а затем блокируется до завершения записи (отправка пакета).(Этот пример неэффективен, потому что цель примера NDISPROT состоит в том, чтобы проиллюстрировать, как взаимодействовать с NDIS в режиме ядра, а не иллюстрировать сложные методы взаимодействия с ядром пользователя.)

Вы можете значительно ускорить это, используяодин из нескольких способов одновременной выдачи нескольких фрагментов данных:

  1. Использовать многопоточность.Сделайте то же самое, что вы делаете сейчас, за исключением того, что вы делаете это одновременно на нескольких потоках.Это довольно просто настроить, но он не очень хорошо масштабируется (для масштабирования до 10-кратного трафика вам понадобится 10-кратные потоки, и вы начинаете страдать от проблем с кэшированием).Кроме того, если ваш набор данных должен быть отправлен по порядку, вам нужна куча сложной синхронизации, чтобы убедиться, что потоки выдают запросы по порядку.

  2. Используйте асинхронные вызовы с структурами данных WriteFile и OVERLAPPED.Это требует от вас переоборудования в приложении usermode.(К счастью, вам не нужно прикасаться к драйверу ядра, поскольку это уже поддерживает это).При записи OVERLAPPED вы можете выполнить несколько одновременных записей из одного потока, а затем получать уведомление, когда какая-либо (или все) из них завершается.Если вы достаточно осторожны с перекрывающимся дизайном, вы сможете легко заполнить сетевой канал со скоростью 100 Мбит / с.

Чтобы быть более точным, это то, что у вас сейчас есть:

Your app           NDISPROT driver         Network card         The network
---------------------------------------------------------------------------------
  WriteFile
   .      \-------> NdisProtWrite
   .                            \-------> NdisSendPackets
   .                                            |
   .                                   (copy packet payload
   .                                    from system RAM to
   .                                    network card's buffer)
   .                                            |
   .                                            |---------------> Start sending
   .             NdisProtSendComplete <---------|                      .
  WriteFile <----/                              |                      .
   returns                                      |<--------------- Finish sending

Как видите, ваше приложение пользовательского режима застревает в WriteFile все время, пока сетевая карта копирует полезную нагрузку пакета из ОЗУ на оборудование NIC.Вместо этого, если вы используете асинхронную запись в режим ядра, вы получите следующее:

Your app           NDISPROT driver         Network card         The network
---------------------------------------------------------------------------------
  WriteFile
   .      \-------> NdisProtWrite
   .               |            \-------> NdisSendPackets
  WriteFile <------/                           |
   returns                              (copy packet payload
                                        from system RAM to
                                        network card's buffer)
                                                |
                                                |---------------> Start sending
                 NdisProtSendComplete <---------|                      .
  Async write <--/                              |                      .
   completes                                    |<--------------- Finish sending

В этой настройке WriteFile возвращается быстрее, и у вас есть шанс поставить в очередьдо другого пакета (или 10), пока NIC все еще читает первый пакет.Вы можете использовать любой из обычных методов OVERLAPPED, чтобы определить, когда запись (отправка пакета) завершена, и вы можете повторно использовать буфер данных.

Чтобы начать работу с асинхронным вводом / выводом, начните с thisдокументация .(Упс, похоже, что их диаграммы повернуты на 90 ° от моего удивительного ASCII-арта ...).

...