Работа с драйвером виртуального сетевого адаптера (OpenVPN)
От: sizeof_void Россия  
Дата: 04.07.13 08:25
Оценка:
Всем привет! У меня некое продолжение закрытой темы (http://www.rsdn.ru/forum/network/3842938.1
Автор: MikelSV
Дата: 14.06.10
).

Я сейчас пробую работать с OpenVPN драйвером виртуального адаптера под Виндой из консольного приложения,
пытаюсь открыть его и выставить флаг коннекта (TAP_IOCTL_SET_MEDIA_STATUS), чтобы можно было посылать/принимать данные на его интерфейсе.
Почему-то вызов DeviceIoControl(TAP_IOCTL_SET_MEDIA_STATUS) возвращает ошибку "ERROR_INVALID_FUNCTION"(1).
Тестирую пока на WinXP SP3 (x32), но надо, чтобы код работал и на других виндах...

     
#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)

HANDLE tap = INVALID_HANDLE_VALUE;          
         
GetAdaptersAddresses(...);

if (!_wcsicmp(MY_VNIC_DEVICE_NAME, a->FriendlyName))
{
     std::string dn("\\\\.\\Global\\");
     dn += a->AdapterName;
     //dn += ".tap";  // С суффиксом не открывается!

     cout << "device name to open is: " << dn.c_str() << endl;

     tap = CreateFileA(dn.c_str(),
                MAXIMUM_ALLOWED,
                0,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
                            NULL
                );
           
          
      if (INVALID_HANDLE_VALUE == tap)
      {
        cout<<"Failed to open device!\n"<<endl;
      }
      else
      {
        cout<<"Device opened...\n"<<endl;
        DWORD len=0;
    DWORD uState = TRUE, uOut = FALSE;

    if (!::DeviceIoControl(tap, TAP_IOCTL_SET_MEDIA_STATUS, 
                &uState, sizeof(uState), 
                &uOut, sizeof(uOut), 
                &len, NULL))
    {
            int nErr = ::GetLastError();  // ТУТ ВОЗВРАЩАЕТ "1"!
            cout << "DeviceIoControl(): Error = " << nErr << endl;
            cout << "WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.\n";
    }          

        ...
      }
}


Подскажите, в чём причина ошибки и где посмотреть ещё инфу / примеры работы с этим драйвером...
"May the Force be with us all!" (c)
openvpn драйвер virtual adapter deviceiocontrol()
Re: Работа с драйвером виртуального сетевого адаптера (OpenVPN)
От: sizeof_void Россия  
Дата: 04.07.13 10:30
Оценка:
Блин, что-то я не так делал до этого, с суффиксом .tap интерфейс открывается и DeviceIoControl() работает.
=)
"May the Force be with us all!" (c)
Re: Работа с драйвером виртуального сетевого адаптера (OpenVPN)
От: sizeof_void Россия  
Дата: 12.07.13 14:31
Оценка:
В общем, появился ещё важный вопрос по этой теме:

При работе тестовой программы (эмуляция OpenVPN), работающей с драйвером виртуального адаптера (версия 9.6) и пересылающей поток данных между двумя машинами через обычный UDP сокет, наблюдается расхождение в скорости трафика при работе под WinXP (x86) и под Win7 (x86). Замедление передачи файлов по самбе идёт в обоих случаях, но под XP это уменьшение скорости в 1,5 — 2 раза, а под Win7 — в 5 — 6 раз! Если точнее, то скорость передачи большого файла (3 Гб) по SMB через реальный адаптер у меня, примерно, 240-250 Mbps на обеих конфигурациях, а через TAP-интерфейс и мою программу она составляет около 140-150 Mbps между XP системами и 30-50 Mbps между Win7 системами... Повышение класса приоритета процессов не меняет общую картину.
На саму программку нет смысла грешить, так как тормоза были и при использовании реального OpenVPN. Поэтому я и выясняю, где тут "затык".

Похоже, что это замедление чтения/записи данных в объект устройства TAP-драйвера. Его код у меня есть, но я его не отлаживал, только смотрю принципы работы.
Я нашёл также инфу на MSDN-е про то, что в Windows 6.0 и старше для драйверов NDIS 5.x используется специальная "прослойка" к драйверам NDIS 6.x, которые передают пакеты скопом (NET_BUFFER_LIST и т.п.), а не по одному, и это может замедлять передачу данных системе. Но действительно ли это преобразование буферов такое долгое?

Подскажите, пожалуйста, в чём тут может быть проблема и какие расхождения систем это вызывают.

Тестирую на реальных машинах с гигабитным интерфейсом и прямым соединением между ними.
"May the Force be with us all!" (c)
скорость передачи данных виртуальный адаптер openvpn ndis 6.x
Re[2]: Работа с драйвером виртуального сетевого адаптера (OpenVPN)
От: sizeof_void Россия  
Дата: 12.07.13 14:35
Оценка:
Здравствуйте, sizeof_void, Вы писали:

_>В общем, появился ещё важный вопрос по этой теме:


_>При работе тестовой программы (эмуляция OpenVPN), работающей с драйвером виртуального адаптера (версия 9.6) и пересылающей поток данных между двумя машинами через обычный UDP сокет, наблюдается расхождение в скорости трафика при работе под WinXP (x86) и под Win7 (x86). Замедление передачи файлов по самбе идёт в обоих случаях, но под XP это уменьшение скорости в 1,5 — 2 раза, а под Win7 — в 5 — 6 раз! Если точнее, то скорость передачи большого файла (3 Гб) по SMB через реальный адаптер у меня, примерно, 240-250 Mbps на обеих конфигурациях, а через TAP-интерфейс и мою программу она составляет около 140-150 Mbps между XP системами и 30-50 Mbps между Win7 системами... Повышение класса приоритета процессов не меняет общую картину.

_>На саму программку нет смысла грешить, так как тормоза были и при использовании реального OpenVPN. Поэтому я и выясняю, где тут "затык".

_>Похоже, что это замедление чтения/записи данных в объект устройства TAP-драйвера. Его код у меня есть, но я его не отлаживал, только смотрю принципы работы.

_>Я нашёл также инфу на MSDN-е про то, что в Windows 6.0 и старше для драйверов NDIS 5.x используется специальная "прослойка" к драйверам NDIS 6.x, которые передают пакеты скопом (NET_BUFFER_LIST и т.п.), а не по одному, и это может замедлять передачу данных системе. Но действительно ли это преобразование буферов такое долгое?

_>Подскажите, пожалуйста, в чём тут может быть проблема и какие расхождения систем это вызывают.


_>Тестирую на реальных машинах с гигабитным интерфейсом и прямым соединением между ними.



Прикладываю, на всякий случай, код рабочих потоков чтения/записи:




  unsigned __stdcall thread0(void*)
  {
    char* buffer = static_cast<char*>(_aligned_malloc(PAGE_SIZE, PAGE_SIZE));
    assert(buffer);
    OVERLAPPED ol;
    memset(&ol, 0, sizeof(ol));
    ol.hEvent = CreateEvent(0, TRUE, FALSE,0);
    if (ol.hEvent)
    {
      cout<<"event created"<<endl;
#pragma warning (push)
#pragma warning (disable:4127)
      while (true)
#pragma warning (pop)
      {
        DWORD read = PAGE_SIZE;
        if (ReadFile(tap, buffer, read, &read, &ol))
        {
          sendto( peerd, buffer, read, 0, (sockaddr*)&peer, peer_len );
        }
        else if (GetLastError() == ERROR_IO_PENDING)
        {
          if (GetOverlappedResult(tap, &ol, &read, TRUE))
          {
            sendto( peerd, buffer, read, 0, (sockaddr*)&peer, peer_len );
          }
        }
      }
    }
    else
    {
      cout<<"failed to create event"<<endl;
    }

    _aligned_free(buffer);
    return 0;
  }

  unsigned __stdcall thread1(void*)
  {
    char* buffer = static_cast<char*>(_aligned_malloc(PAGE_SIZE, PAGE_SIZE));
    assert(buffer);
    OVERLAPPED ol;
    memset(&ol, 0, sizeof(ol));
    ol.hEvent = CreateEvent(0, TRUE, FALSE,0);
    if (ol.hEvent)
    {
#pragma warning (push)
#pragma warning (disable:4127)
      while (true)
#pragma warning (pop)
      {
        const int readn = recv( peerd, buffer, PAGE_SIZE, 0 );
        if (readn && (readn != SOCKET_ERROR))
        {
          DWORD written;
          WriteFile(tap, buffer, readn, &written, &ol);
        }
      }
    }

    _aligned_free(buffer);
    return 0;
  }
}
"May the Force be with us all!" (c)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.