Bagikan melalui


Menerima data jaringan dengan cincin bersih

Driver klien NetAdapterCx menerima data jaringan ketika kerangka kerja memanggil fungsi panggilan balik EvtPacketQueueAdvance mereka untuk antrean terima. Selama panggilan balik ini, driver klien menunjukkan menerima dengan menguras fragmen dan paket yang diterima ke OS, lalu memposting buffer baru ke perangkat keras.

Gambaran umum operasi kirim (Rx) dan pengurasan

Animasi berikut menggambarkan bagaimana driver klien untuk kartu antarmuka jaringan (NIC) PCI sederhana melakukan operasi pasca dan pengosongan untuk antrean terima (Rx). Buffer fragmen dalam skenario contoh ini dialokasikan dan dilampirkan ke cincin fragmen oleh OS. Contoh ini mengasumsikan hubungan satu-ke-satu antara perangkat keras menerima antrean dan OS menerima antrean.

Animasi yang mengilustrasikan posting cincin bersih dan operasi pengosongan untuk menerima kartu antarmuka jaringan PCI.

Dalam animasi ini, paket yang dimiliki oleh driver klien disorot dengan warna biru muda dan biru tua, dan fragmen yang dimiliki oleh driver klien disorot dengan warna kuning dan oranye. Warna yang lebih terang mewakili subbagian pengurasan dari elemen yang dimiliki driver, sementara warna yang lebih gelap mewakili subbagian pos dari elemen yang dimiliki driver.

Menerima data secara berurutan

Berikut adalah urutan umum untuk driver yang menerima data secara berurutan, dengan satu fragmen per paket.

  1. Panggil NetRxQueueGetRingCollection untuk mengambil struktur kumpulan cincin antrean penerima. Anda dapat menyimpan ini di ruang konteks antrean untuk mengurangi panggilan keluar dari driver. Gunakan koleksi cincin untuk mengambil iterator pengurasan untuk cincin fragmen antrean penerima dan cincin paket.
  2. Tunjukkan data yang diterima ke OS dengan menguras cincin bersih:
    1. Alokasikan variabel UINT32 untuk melacak indeks cincin fragmen saat ini dan indeks cincin paket saat ini. Atur variabel ini ke BeginIndex dari cincin bersih masing-masing, yang merupakan awal dari sub bagian pengurasan cincin. Alokasikan variabel UINT32 untuk akhir bagian pengosongan cincin fragmen dengan mengaturnya ke NextIndex cincin fragmen.
    2. Lakukan hal berikut ini dalam perulangan:
      1. Periksa apakah fragmen telah diterima oleh perangkat keras. Jika tidak, keluar dari perulangan.
      2. Panggil NetRingGetFragmentAtIndex untuk mendapatkan fragmen.
      3. Isi informasi fragmen, seperti ValidLength-nya, berdasarkan pendeskripsi perangkat keras yang cocok.
      4. Dapatkan paket untuk fragmen ini dengan memanggil NetRingGetPacketAtIndex.
      5. Ikat fragmen ke paket dengan mengatur FragmentIndex paket ke indeks fragmen saat ini di cincin fragmen dan mengatur jumlah fragmen dengan tepat (dalam contoh ini, diatur ke 1).
      6. Secara opsional, isi informasi paket lain seperti info checksum.
      7. Lanjutkan indeks fragmen dengan memanggil NetRingIncrementIndex.
      8. Tingkatkan indeks paket dengan memanggil NetRingIncrementIndex.
    3. Perbarui BeginIndex cincin fragmen ke variabel indeks fragmen saat ini dan perbarui BeginIndex cincin paket ke indeks paket saat ini untuk menyelesaikan yang menunjukkan paket yang diterima dan fragmennya ke OS.
  3. Memposting buffer fragmen ke perangkat keras untuk penerimaan berikutnya:
    1. Atur indeks fragmen saat ini ke NextIndex cincin fragmen, yang merupakan awal dari sub bagian pos cincin. Atur indeks akhir fragmen ke EndIndex cincin fragmen.
    2. Lakukan hal berikut ini dalam perulangan:
      1. Posting informasi fragmen ke deskriptor perangkat keras yang cocok.
      2. Lanjutkan indeks fragmen dengan memanggil NetRingIncrementIndex.
    3. Perbarui NextIndex cincin fragmen ke variabel indeks fragmen saat ini untuk menyelesaikan memposting fragmen ke perangkat keras.

Langkah-langkah ini mungkin terlihat seperti ini dalam kode:

void
MyEvtRxQueueAdvance(
    NETPACKETQUEUE RxQueue
)
{
    //
    // Retrieve the receive queue's ring collection and net rings. 
    // This example stores the Rx queue's ring collection in its queue context space.
    //
    PMY_RX_QUEUE_CONTEXT rxQueueContext = MyGetRxQueueContext(RxQueue);
    NET_RING_COLLECTION const * ringCollection = rxQueueContext->RingCollection;
    NET_RING * packetRing = ringCollection->Rings[NET_RING_TYPE_PACKET];
    NET_RING * fragmentRing = ringCollection->Rings[NET_RING_TYPE_FRAGMENT];
    UINT32 currentPacketIndex = 0;
    UINT32 currentFragmentIndex = 0;
    UINT32 fragmentEndIndex = 0;

    //
    // Indicate receives by draining the rings
    //
    currentPacketIndex = packetRing->BeginIndex;
    currentFragmentIndex = fragmentRing->BeginIndex;
    fragmentEndIndex = fragmentRing->NextIndex;
    while(currentFragmentIndex != fragmentEndIndex)
    {
        // Test for fragment reception. Break if fragment has not been received.
        ...
        //

        NET_FRAGMENT * fragment = NetRingGetFragmentAtIndex(fragmentRing, currentFragmentIndex);
        fragment->ValidLength = ... ;
        NET_PACKET * packet = NetRingGetPacketAtIndex(packetRing, currentPacketIndex);
        packet->FragmentIndex = currentFragmentIndex;
        packet->FragmentCount = 1;

        if(rxQueueContext->IsChecksumExtensionEnabled)
        {
            // Fill in checksum info
            ...
            //
        }        

        currentFragmentIndex = NetRingIncrementIndex(fragmentRing, currentFragmentIndex);
        currentPacketIndex = NetRingIncrementIndex(packetRing, currentPacketIndex);
    }
    fragmentRing->BeginIndex = currentFragmentIndex;
    packetRing->BeginIndex = currentPacketIndex;

    //
    // Post fragment buffers to hardware
    //
    currentFragmentIndex = fragmentRing->NextIndex;
    fragmentEndIndex = fragmentRing->EndIndex;
    while(currentFragmentIndex != fragmentEndIndex)
    {
        // Post fragment information to hardware descriptor
        ...
        //

        currentFragmentIndex = NetRingIncrementIndex(fragmentRing, currentFragmentIndex);
    }
    fragmentRing->NextIndex = currentFragmentIndex;
}

Menerima data tidak berurutan

Tidak seperti antrean Tx , driver klien biasanya tidak menerima data yang tidak berurutan jika mereka memiliki satu OS yang menerima antrean per perangkat keras menerima antrean. Ini terlepas dari jenis NIC driver klien. Apakah perangkat berbasis PCI dan OS mengalokasikan dan memiliki buffer penerima, atau apakah perangkat berbasis USB dan tumpukan USB memiliki buffer penerima, driver klien menginisialisasi paket untuk setiap fragmen yang diterima dan menunjukkannya ke OS. Urutannya tidak penting dalam kasus ini.

Jika perangkat keras Anda mendukung lebih dari satu OS yang menerima antrean per perangkat keras yang menerima antrean, Anda harus menyinkronkan akses ke buffer penerima. Ruang lingkup melakukannya berada di luar topik ini dan tergantung pada desain perangkat keras Anda.