Udostępnij za pośrednictwem


Odciążanie zlecania łączenia segmentów odbieranych UDP (URO)

Począwszy od systemu Windows 11 w wersji 24H2, funkcja URO (UDP receive segment coalescing offload) umożliwia kartom sieciowym łączenie segmentów odbiorczych UDP. Karty sieciowe mogą łączyć datagramy UDP z tego samego przepływu, które pasują do zestawu reguł, w logicznie ciągły bufor. Te połączone datagramy są następnie przekazywane stosowi sieciowemu systemu Windows jako jeden duży pakiet.

Łączenie datagramów UDP zmniejsza koszt CPU do przetwarzania pakietów w przepływach o wysokiej przepustowości, co skutkuje większą przepustowością i mniejszą liczbą cykli na bajt.

W poniższych sekcjach opisano reguły łączenia pakietów UDP i sposobu pisania sterownika miniportu URO.

Reguły łączenia pakietów UDP

Łączenie URO można podjąć tylko na pakietach spełniających wszystkie następujące kryteria:

  • IpHeader.Version jest identyczna dla wszystkich pakietów.
  • IpHeader.SourceAddress i IpHeader.DestinationAddress są identyczne dla wszystkich pakietów.
  • UdpHeader.SourcePort i UdpHeader.DestinationPort są identyczne dla wszystkich pakietów.
  • UdpHeader.Length jest identyczne dla wszystkich pakietów, z wyjątkiem ostatniego pakietu, który może być mniejszy.
  • UdpHeader.Length musi być niezerowa.
  • UdpHeader.Checksum, jeśli niezerowa, musi być poprawna we wszystkich pakietach. Oznacza to, że odbieranie sumy kontrolnej musi zweryfikować pakiet.
  • Layer 2 headers musi być identyczne dla wszystkich pakietów.

Jeśli pakiety mają protokół IPv4, muszą również spełniać następujące kryteria:

  • IPv4Header.Protocol == 17 (UDP) dla wszystkich pakietów.
  • EthernetHeader.EtherType == 0x0800 dla wszystkich pakietów.
  • IPv4Header.HeaderChecksum odebranych pakietów musi być poprawne. Oznacza to, że odciążanie sumy kontrolnej musi zweryfikować nagłówek.
  • IPv4Header.HeaderLength == 5 (brak nagłówków opcji IPv4) dla wszystkich pakietów.
  • IPv4Header.ToS jest identyczna dla wszystkich pakietów.
  • IPv4Header.ECN jest identyczna dla wszystkich pakietów.
  • IPv4Header.DontFragment jest identyczna dla wszystkich pakietów.
  • IPv4Header.TTL jest identyczna dla wszystkich pakietów.
  • IPv4Header.TotalLength == UdpHeader.Length* + length(IPv4Header) dla wszystkich pakietów.

Jeśli pakiety są IPv6, muszą również spełniać następujące kryteria:

  • IPv6Header.NextHeader == 17 (UDP) dla wszystkich pakietów (bez nagłówków rozszerzeń).
  • EthernetHeader.EtherType == 0x86dd (IPv6) dla wszystkich pakietów.
  • IPv6Header.TrafficClass i IPv6Header.ECN są identyczne dla wszystkich pakietów.
  • IPv6Header.FlowLabel jest identyczna dla wszystkich pakietów.
  • IPv6Header.HopLimit jest identyczna dla wszystkich pakietów.
  • IPv6Header.PayloadLength == UdpHeader.Length dla wszystkich pakietów.

Struktura pakietów URO

Wynikowa pojedyncza połączona jednostka (SCU) musi mieć jeden nagłówek IP i nagłówek UDP, a następnie ładunek UDP dla wszystkich połączonych datagramów, które są ze sobą połączone.

Wskazania URO muszą ustawić pole IPv4Header.TotalLength na łączną długość SCU, pole IPv6Header.PayloadLength na długość ładunku UDP, a pole UdpHeader.Length na długość skoordynowanych ładunków.

Jeśli nagłówki warstwy 2 (L2) znajdują się w scalonych datagramach, SCU musi zawierać prawidłowy nagłówek L2. Nagłówek L2 w SCU musi przypominać nagłówek L2 z zebranych datagramów.

Sprawdzanie poprawności sumy kontrolnej i indykacja

Wskazania URO muszą ustawić pola IPv4Header.HeaderChecksum i UdpHeader.Checksum na wartość zero oraz wypełnić informacje o pozapasmowym odciążaniu sumy kontrolnej w SCU, wskazujące na powodzenie sum kontrolnych IPv4 i UDP.

Pakiet, spełniający wszystkie warunki do połączenia, ale którego walidacja sumy kontrolnej kończy się niepowodzeniem, musi być wskazany oddzielnie. Pakiety odebrane po nim nie powinny być łączone z pakietami odebranymi przed nim.

Załóżmy na przykład, że pakiety 1, 2, 3, 4 i 5 są odbierane z tego samego przepływu, ale pakiet 3 kończy się niepowodzeniem weryfikacji sumy kontrolnej. Pakiety 1 i 2 mogą być scalone, a pakiety 4 i 5 mogą być scalone, ale pakiet 3 nie może być scalony ani z jednym, ani z drugim SCU. Pakiety 1 i 2 nie mogą być połączone razem z pakietami 4 i 5. Pakiet 2 jest ostatnim pakietem w scU, a pakiet 4 uruchamia nową jednostkę SCU. Ponadto należy wskazać jednostki SCU zawierające pakiety 1 i 2, zanim zostanie wskazany pakiet 3, a pakiet 3 należy wskazać przed wskazaniem SCU zawierającego pakiety 4 i 5.

Łączenie pakietów i separacja przepływów

Pakiety danych z wielu przepływów można połączyć równolegle, jeśli pozwala na to sprzęt i pamięć. Pakiety z różnych strumieni nie mogą być ze sobą łączone.

Pakiety odbierane przeplatane z wielu strumieni mogą być rozdzielone i scalone z odpowiednimi przepływami. Na przykład, biorąc pod uwagę przepływy A, B i C, jeśli pakiety docierają w kolejności A, A, B, C, B, A, pakiety z przepływu A można połączyć do AAA, a pakiety z przepływu B można połączyć w BB, podczas gdy pakiet z przepływu C może być wskazany normalnie lub połączony z oczekującym SCU z przepływu C.

Pakiety w danym przepływie nie mogą być przestawiane względem siebie. Na przykład pakiety z przepływu A muszą być łączone w kolejności odbioru, niezależnie od pakietów z przepływów B i C odebranych pomiędzy.

Słowo kluczowe INF do kontrolowania URO

Następujące słowo kluczowe może służyć do włączania/wyłączania URO z ustawieniem klucza rejestru:

  • *UdpRsc

Ustandaryzowane słowa kluczowe INF mają następujące atrybuty:

  • SubkeyName: nazwa słowa kluczowego, które należy określić w pliku INF i który pojawia się w rejestrze.

  • ParamDesc: tekst wyświetlany skojarzony z nazwą podklucza.

  • wartość: wartość całkowita wyliczenia skojarzona z każdą opcją na liście. Ta wartość jest przechowywana w NDI\params\SubkeyName\Value.

  • EnumDesc: tekst wyświetlany skojarzony z każdą wartością wyświetlaną w menu.

  • Wartość domyślna: domyślna wartość dla menu.

Nazwa podklucza ParamDesc Wartość OpisWyliczenia
*UdpRsc URO 0 Niepełnosprawny
1 (ustawienie domyślne) Włączone

Aby uzyskać więcej informacji dotyczące używania słów kluczowych wyliczenia, zobacz Słowa kluczowe wyliczenia.

Napisać sterownik miniportu URO

Począwszy od NDIS 6.89, interfejs NDIS dla URO ułatwia komunikację między tcp/IP i sterownikiem miniport NDIS.

Zdolność do raportowania URO

Sterownik miniportu ogłasza wsparcie URO w składowej UdpRsc struktury NDIS_OFFLOAD, którą przekazuje do funkcji NdisMSetMiniportAttributes.

Możliwość URO zapytań

Aby sprawdzić, czy sterownik miniportu obsługuje URO, sterowniki NDIS i inne aplikacje mogą wykonywać zapytania dotyczące identyfikatora OID OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES, który zwraca strukturę NDIS_OFFLOAD.

Sprawdź stan URO

Aby określić bieżący stan URO, sterowniki NDIS i inne aplikacje mogą wysyłać zapytania dotyczące żądania identyfikatora OID OID_TCP_OFFLOAD_CURRENT_CONFIG. NDIS obsługuje ten OID i nie przekazuje go do miniportu.

Zmienianie stanu URO

URO można włączyć lub wyłączyć, wysyłając żądanie OID OID_TCP_OFFLOAD_PARAMETERS. Ten identyfikator OID używa struktury NDIS_OFFLOAD_PARAMETERS. W tej strukturze element członkowski UdpRsc.Enabled może mieć następujące wartości:

Wartość Znaczenie
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_NO_CHANGE
0
Sterownik miniportu nie powinien zmieniać bieżącego ustawienia.
NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED
1
URO jest wyłączone.
Parametry odciążenia NDIS - UDP RSC włączone
2
URO jest włączone.

Gdy sterownik przetwarza żądanie identyfikatora OID OID_TCP_OFFLOAD_PARAMETERS z ustawioną flagą NDIS_OFFLOAD_PARAMETERS_UDP_RSC_DISABLED, karta sieciowa musi czekać z ukończeniem żądania, dopóki nie zostaną wskazane wszystkie istniejące scalone segmenty i oczekujące wskazania URO. To zapewnia synchronizację zdarzeń włączania i wyłączania URO między składnikami NDIS.

Gdy sterownik miniportu przetwarza zapytanie OID OID_TCP_OFFLOAD_PARAMETERS, musi wydać NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG indykację z zaktualizowanym stanem odciążania.

Flaga NDIS_OFFLOAD_PARAMETERS_SKIP_REGISTRY_UPDATE w NDIS_OFFLOAD_PARAMETERS umożliwia wyłączenie URO tylko w czasie działania. Zmiany wprowadzone za pomocą tej flagi nie są zapisywane w rejestrze.

Rezygnacja z URO w standardzie NDIS 6.89 i nowszych wersjach

Sterowniki przeznaczone dla NDIS 6.89 i nowszych powinny rozumieć pakiety URO i obsługiwać je płynnie. Aby zrezygnować z URO:

Takie podejście zapewnia, że składniki, które nie są zaznajomione z URO, nie otrzymują URO NBL. NDIS wyłącza URO na miniportie podczas łączenia, jeśli jest obecny sterownik LWF lub protokołowy, który nie obsługuje URO.

Zagadnienia dotyczące programowania dla sterowników URO

Podczas implementowania sterownika miniportu obsługującego URO należy wziąć pod uwagę następujące problemy.

Winsock URO API

Aby uzyskać informacje na temat interfejsu API URO Winsock, zobacz opcje gniazda IPPROTO_UDP . Zapoznaj się z informacjami na temat UDP_RECV_MAX_COALESCED_SIZE i UDP_COALESCED_INFO.

Aktualizacje stosu TCP/IP systemu Windows

Transport protokołu TCP/IP firmy Microsoft umożliwia URO podczas wiązania z NDIS, chyba że konfiguracja to uniemożliwia.

Wywołania WFP mogą używać FWP_CALLOUT_FLAG_ALLOW_URO w FWPS_CALLOUT2 do reklamowania swojego wsparcia dla URO. Jeśli niezgodne wywołanie WFP jest zarejestrowane w warstwie wrażliwej na URO, system operacyjny wyłącza funkcję URO, gdy wywołanie jest zarejestrowane.

Jeśli gniazdo zdecyduje się na URO z maksymalnym rozmiarem ściętym większym lub równym rozmiarowi odciążania sprzętu, stos dostarczy NBLs ze sprzętu niezmodyfikowanego do gniazda. Jeśli gniazdo zdecyduje się na mniejszy maksymalny rozmiar kumulacji, stos rozdziela kumulowany odbiór na mniejsze rozmiary dla tego gniazda.

Jeśli gniazdo nie wyrazi zgody na URO, stos przegrupowuje odebrane dane dla tego gniazda. W przypadku braku sprzętowej opcji URO, istniejąca funkcja URO w oprogramowaniu jest nadal dostępna.