2016-04-14 10 views
6

Próbuję zrozumieć pojęcie deskryptorów Rx i Tx używanych w kodzie sterownika sieci.Koncepcja deskryptora w NIC

  1. Są deskryptorami w oprogramowaniu (RAM) lub sprzętem (karta NIC).
  2. Jak się wypełniają.

EDYCJA: A więc w kodzie sterownika karty Realtek. Mam zdefiniowaną następującą strukturę.

struct Desc 
{ 
     uint32_t opts1; 
     uint32_t opts2; 
     uint64_t addr; 
}; 

txd->addr = cpu_to_le64(mapping); 
txd->opts2 = cpu_to_le32(opts2); 
txd->opts1 = cpu_to_le32(opts1 & ~DescOwn); 

Więc są opts1 and opts2 i tam bity jak DescOwn karty konkretnego? Czy zostaną określone przez producenta w arkuszu danych?

Dzięki Nayan

Odpowiedz

24

Szybka Odpowiedź:

  1. Są konstrukcje programowe Wynika definicję sprzętowo NIC tak jak rozumie i może rozmawiać ze sobą.
  2. Zostaje wypełniony przez sterownik (na przykład pusty przydział bufora RX) lub przez NIC (zapisywanie zwrotne RX). Zobacz poniżej, aby uzyskać więcej informacji.

Szczegóły architektoniczne:

Uwaga: Zakładam, że masz wiedzę na temat struktury danych pierścień, pojęcie DMA. https://en.wikipedia.org/wiki/Circular_buffer

https://en.wikipedia.org/wiki/Direct_memory_access

rozważmy najpierw RX ścieżkę. Po otrzymaniu pakietu, NIC tłumaczy sygnał elektroniczny/optyczny/radiowy na przewodzie na bajtowe bajty danych. Następnie karta sieciowa musi poinformować system operacyjny, że coś otrzymała. W dawnych czasach robiono to za pomocą przerwań, a system operacyjny czytał bajty z predefiniowanej lokalizacji na karcie NIC do pamięci RAM. Jest to jednak powolne, ponieważ 1) CPU są wymagane do udziału w transferze danych z NIC do RAM 2) może istnieć wiele pakietów, a więc wiele przerwań, które mogą być zbyt wiele, aby obsłużyć procesor. Potem pojawił się DMA i rozwiązuje pierwszy problem. Ponadto ludzie zaprojektowali sterownik trybu ankiety (lub tryb hybrydowy, tak jak w Linux NAPI), aby procesor mógł zostać zwolniony z obsługi przerwań i odpytywać wiele pakietów naraz, rozwiązując w ten sposób drugi problem.

Deskryptor to mechanizm ułatwiający NIC wykonywanie DMA. Jak sama nazwa wskazuje, opisuje pakiet. Tak więc nie zawiera danych pakietowych (dla kart sieciowych, o ile wiem), ale raczej opisuje, gdzie znajdują się dane. RX Descriptor Data Structure

Wróćmy do historii RX. NIC kończy tłumaczenie sygnału na bajty i chciałby zrobić DMA do pamięci RAM. Ale wcześniej, NIC musi wiedzieć, gdzie do DMA, ponieważ nie może losowo umieścić danych w pamięci RAM, które procesor nie będzie wiedział, gdzie i nie jest bezpieczny.

Podczas inicjalizacji kolejki RX sterownik NIC wstępnie alokuje bufor pakietów, a także tablicę deskryptorów pakietów. Inicjalizuje każdy deskryptor pakietu zgodnie z definicją NIC.

wezmę sterownik Intel XL710 jako przykład kodu (niektóre Vars są zmieniane dla lepszego zrozumienia): XL710 Descriptor format

struct i40e_rx_queue { 
    struct packet_buffer_pool *pool; /* < packet pool */ 
    volatile i40e_16byte_rx_desc *rx_ring; /* < RX ring of descriptors */ 
    struct packet_buffer *pkt_addr_backup; /* save a copy of packet buffer address for writeback descriptor reuse */ 
.... 
} 

union i40e_16byte_rx_desc { 
    struct { 
     __le64 pkt_addr; /* Packet buffer address, points to a free packet buffer in packet_buffer_pool */ 
     __le64 hdr_addr; /* Header buffer address, normally isn't used */ 
    } read; /* initialized by driver */ 

    struct { 
     struct { 
      struct { 
       union { 
        __le16 mirroring_status; 
        __le16 fcoe_ctx_id; 
       } mirr_fcoe; 
       __le16 l2tag1; 
      } lo_dword; 
      union { 
       __le32 rss; /* RSS Hash */ 
       __le32 fd_id; /* Flow director filter id */ 
       __le32 fcoe_param; /* FCoE DDP Context id */ 
      } hi_dword; 
     } qword0; 
     struct { 
      /* ext status/error/pktype/length */ 
      __le64 status_error_len; 
     } qword1; 
    } wb; /* writeback by NIC */ 
}; 

enter image description here

  1. sterownik przydziela pewną liczbę bufora pakietów w pamięci RAM (przechowywane w strukturze danych bin_buffer_pool).

    pool = alloc_packet_buffer_pool(buffer_size=2048, num_buffer=512); 
    
  2. sterownik szuka adres każdego bufora Packet w polu deskryptora jak

    rx_ring[i]->read.pkt_addr = pool.get_free_buffer(); 
    
  3. sterownik przekazuje Nić lokalizację wyjściową rx_ring, jego długość i głowicę/ogon. Zatem NIC będzie wiedziało, które deskryptory są wolne (w ten sposób bufor pakietów wskazywany przez te deskryptory jest wolny). Proces ten jest wykonywany przez kierowcę wpisującego te informacje do rejestrów NIC (naprawiono, można go znaleźć w arkuszu danych NIC).

    rx_ring_addr_reg = &rx_ring; 
    rx_ring_len_reg = sizeof(rx_ring); 
    rx_ring_head = 0; /* meaning all free at start */ 
    /* rx_ring_tail is a register in NIC as NIC updates it */ 
    
  4. teraz NIC wie, że deskryptor rx_ring [{X, Y, Z}], są wolne, a {X, Y, Z} .pkt_addr może być wprowadzone nowe dane pakietowe. Dodaje nowe pakiety DMA do {x, y, z} .pkt_addr. W międzyczasie NIC może wstępnie przetwarzać (odciążać) przetwarzanie pakietów (np. Sprawdzanie sumy kontrolnej, wydobywać znacznik VLAN), więc potrzebowałoby również miejsca na pozostawienie tych informacji dla oprogramowania. Tutaj deskryptory są ponownie wykorzystywane do tego celu na writeback (patrz druga struktura w deskryptorze unii). Następnie NIC przesuwa wskaźnik przesunięcia ogona rx_ring, wskazując, że nowy deskryptor został zapisany przez NIC. [W tym miejscu, ponieważ deskryptory są ponownie wykorzystywane do wyników przed procesem, sterownik musi zapisać {x, y, z}. pkt_addr w strukturze danych kopii zapasowych].

    /* below is done in hardware, shown just for illustration purpose */ 
    if (rx_ring_head != rx_ring_tail) { /* ring not full */ 
        copy(rx_ring[rx_ring_tail].read.pkt_addr, raw_packet_data); 
        result = do_offload_procesing(); 
    
        if (pre_processing(raw_packet_data) & BAD_CHECKSUM))  
         rx_ring[rx_ring_tail].writeback.qword1.stats_error_len |= RX_BAD_CHECKSUM_ERROR; 
        rx_ring_head++; /* actually driver sets a Descriptor done indication flag */ 
            /* along in writeback descriptor so driver can figure out */ 
            /* current HEAD, thus saving a PCIe write message */ 
    } 
    
  5. sterownik odczytuje nowy wskaźnik ogon przesunięcia i znaleziono {X, Y, Z} są nowe pakiety. Odczytuje pakiet z pkt_addr_backup [{x, y, z}] i związany z nim wstępny wynik.

  6. Gdy oprogramowanie warstwy górnej zostanie wykonane z pakietami, {x, y, z} zostanie przywrócone do rx_ring, a wskaźnik pierścienia zostanie zaktualizowany w celu wskazania wolnych deskryptorów.

To kończy ścieżkę RX. Ścieżka TX jest w zasadzie odwrotna: górna warstwa tworzy pakiet, sterownik kopiuje pakiety danych do packetbuffer_pool, a tx_ring [x] .buffer_addr wskazuje na to. Sterownik przygotowuje również niektóre znaczniki odciążenia TX (takie jak kontrole sprzętu, TSO) w deskryptorze TX. NIC czyta deskryptor TX i DMA tx_ring [x] .buffer_addr z RAM na NIC.

Ta informacja pojawia się zwykle w arkuszu danych NIC, takim jak arkusz danych sterownika Intel XL710 xl710-10-40, rozdział 8.3 & 8.4 Ścieżka danych LAN RX/TX.

http://www.intel.com/content/www/us/en/embedded/products/networking/xl710-10-40-controller-datasheet.html

Ponadto można sprawdzić kod sterownika open source (albo jądro albo jakiś kosmiczny użytkownik biblioteki jak DPDK PMD), który będzie zawierał definicję struct deskryptora.

Przy okazji sugeruję, abyś oznaczył pytanie także "Sieć".

- Edycja 1 -

Dla Państwa dodatkowe pytanie dotyczące sterownika Realtek: Tak, te bity są specyficzne NIC. Podpowiedź jest kwestia jak

desc->opts1 = cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz); 

DescOwn jest znacznik bitowy który poprzez ustawienie mówi NIC, że teraz jest właścicielem tego deskryptora i związanego z bufora. Konieczne jest również przekonwertowanie z endianizmu (może to być moc procesora, która jest BE) na Little Endian, którą NIC zgadza się zrozumieć.

Możesz znaleźć odpowiednie informacje w numerze http://realtek.info/pdf/rtl8139cp.pdf (np. Strona 70 dla DescOwn), ale nie jest to zgodne z XL710, ale zawiera przynajmniej wszystkie informacje dotyczące rejestru/deskryptora.

- Edycja 2 -

deskryptor NIC jest bardzo zależne od definicji sprzedawca. Jak pokazano powyżej, deskryptor NIC Intela używa pierścienia deskryptora RX , aby zapewnić bufory NIC do zapisu, a dla karty NIC do zapisywania informacji RX. Istnieją inne implementacje, takie jak kolejka składania/uzupełniania RX (bardziej rozpowszechniona w technologii NVMe). Na przykład, niektóre karty sieciowe Broadcom mają jeden pierścień nadawczy (w celu zapewnienia bufora dla karty NIC) i wielokrotny pierścień zakończenia. Jest zaprojektowany do tego, aby NIC zdecydować i umieścić pakiety w innym pierścieniu np. inny priorytet klasy ruchu, aby kierowca mógł najpierw uzyskać najważniejsze pakiety. enter image description here (Z BCM5756M NIC programisty Przewodnika)

--edit 3--

ja generalnie znaleźć NIC arkusz Intela za najbardziej otwarty i informacyjnych na temat ich konstrukcji. Bardzo krótkie podsumowanie przepływu Tx/Rx zostało opisane w jego rodzinnej karcie katalogowej Intel 82599, rozdział 1.8 Architektura i podstawowe operacje.

+0

Aby wyjaśnić, zapoznaj się z poprawką do pytania !! – Haswell

+0

Proszę zobaczyć moją edycję. Dzięki. –