DPDK Document邦訳


5. Ring Library

The ring allows the management of queues. Instead of having a linked list of infinite size, the rte_ring has the following properties:
  • FIFO
  • Maximum size is fixed, the pointers are stored in a table
  • Lockless implementation
  • Multi-consumer or single-consumer dequeue
  • Multi-producer or single-producer enqueue
  • Bulk dequeue - Dequeues the specified count of objects if successful; otherwise fails
  • Bulk enqueue - Enqueues the specified count of objects if successful; otherwise fails
  • Burst dequeue - Dequeue the maximum available objects if the specified count cannot be fulfilled
  • Burst enqueue - Enqueue the maximum available objects if the specified count cannot be fulfilled
The advantages of this data structure over a linked list queue are as follows:
  • Faster; only requires a single Compare-And-Swap instruction of sizeof(void *) instead of several double-Compare-And-Swap instructions.
  • Simpler than a full lockless queue.
  • Adapted to bulk enqueue/dequeue operations. As pointers are stored in a table, a dequeue of several objects will not produce as many cache misses as in a linked queue. Also, a bulk dequeue of many objects does not cost more than a dequeue of a simple object.
  • 早い. 複数の"double-Compare-And-Swap"に代わって、たった1つのsizeof(void*)を"Compare-And-Swap"する命令を必要とする
  • 完全なロックレスキューよりも単純である
  • バルクエンキュー・デキュー操作に対応。ポインタはテーブルに保存されるので、幾らかのオブジェクトのデキューでも、リンクドキューのように多くのキャッシュミスは発生しない。多くのオブジェクトのバルクデキューも、単純なオブジェクトのデキューよりもコストはかからない。
The disadvantages:
  • Size is fixed
  • Having many rings costs more in terms of memory than a linked list queue. An empty ring contains at least N pointers.
  • サイズは固定
  • リンクドリストキューよりも多くのメモリを必要とする。空のリングは少なくともN個のポインタから構成される。
A simplified representation of a Ring is shown in with consumer and producer head and tail pointers to objects stored in the data structure.

The following code was added in FreeBSD 8.0, and is used in some network device drivers (at least in Intel drivers):

bufring.h in FreeBSD
bufring.c in FreeBSD

The following is a link describing the Linux Lockless Ring Buffer Design.

5.3. Additional Features

5.3.1. Name
A ring is identified by a unique name.
It is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted).
同じ名前でリングを2つ作成することはできない。これが適用された場合、rte_ring_create() でNULLが返ってくる。
5.3.2. Water Marking
The ring can have a high water mark (threshold).
Once an enqueue operation reaches the high water mark, the producer is notified, if the water mark is configured.
This mechanism can be used, for example, to exert a back pressure on I/O to inform the LAN to PAUSE.
water markが設定されていれば、最初にエンキュー操作がhigh-water-markに達したなら、プロデューサが通知する。
5.3.3. Debug
When debug is enabled (CONFIG_RTE_LIBRTE_RING_DEBUG is set), the library stores some per-ring statistic counters about the number of enqueues/dequeues.
These statistics are per-core to avoid concurrent accesses or atomic operations.

5.4. Use Cases

Use cases for the Ring library include:
  • Communication between applications in the DPDK
  • Used by memory pool allocator
  • DPDK内のアプリケーション間のコミュニケーション
  • メモリプールアロケータでの使われ方

5.5. Anatomy of a Ring Buffer (リングバッファの解剖学)

This section explains how a ring buffer operates.
The ring structure is composed of two head and tail couples; one is used by producers and one is used by the consumers.
The figures of the following sections refer to them as prod_head, prod_tail, cons_head and cons_tail.

Each figure represents a simplified state of the ring, which is a circular buffer.
The content of the function local variables is represented on the top of the figure, and the content of ring structure is represented on the bottom of the figure.

5.5.1. Single Producer Enqueue
5.5.2. Single Consumer Dequeue
5.5.3. Multiple Producers Enqueue
5.5.4. Modulo 32-bit Indexes

5.6. References

  • bufring.h in FreeBSD (version 8)\ http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/sys/buf_ring.h?revision=199625&view=markup
  • bufring.c in FreeBSD (version 8)\ http://svn.freebsd.org/viewvc/base/release/8.0.0/sys/kern/subr_bufring.c?revision=199625&view=markup
  • Linux Lockless Ring Buffer Design\ http://lwn.net/Articles/340400/

7. Mbuf Library

The mbuf library provides the ability to allocate and free buffers (mbufs) that may be used by the DPDK application to store message buffers.
The message buffers are stored in a mempool, using the Mempool Library.

A rte_mbuf struct can carry network packet buffers or generic control buffers (indicated by the CTRL_MBUF_FLAG).
This can be extended to other types.
The rte_mbuf header structure is kept as small as possible and currently uses just two cache lines, with the most frequently used fields being on the first of the two cache lines.


7.1. Design of Packet Buffers

7.2. Buffers Stored in Memory Pools

7.3. Constructors

7.4. Allocating and Freeing mbufs

7.5. Manipulating mbufs

This library provides some functions for manipulating the data in a packet mbuf.
For instance:
  • Get data length
  • Get a pointer to the start of data
  • Prepend data before data
  • Append data after data
  • Remove data at the beginning of the buffer (rte_pktmbuf_adj())
  • Remove data at the end of the buffer (rte_pktmbuf_trim()) Refer to the DPDK API Reference for details.
  • データ長
  • 最初のデータへのポインタ取得
  • データの前にデータを追加
  • データの後ろにデータを追加
  • バッファの最初のデータを削除 (rte_pktmbuf_adj())
  • バッファの最後のデータを削除 (rte_pktmbuf_trim())
詳細はDPDK API Referenceを参照ください。

7.6. Meta Information

Some information is retrieved by the network driver and stored in an mbuf to make processing easier.
For instance, the VLAN, the RSS hash result (see Poll Mode Driver) and a flag indicating that the checksum was computed by hardware.

An mbuf also contains the input port (where it comes from), and the number of segment mbufs in the chain.

For chained buffers, only the first mbuf of the chain stores this meta information.


7.7. Direct and Indirect Buffers

A direct buffer is a buffer that is completely separate and self-contained.
An indirect buffer behaves like a direct buffer but for the fact that the buffer pointer and data offset in it refer to data in another direct buffer.
This is useful in situations where packets need to be duplicated or fragmented, since indirect buffers provide the means to reuse the same packet data across multiple buffers.

A buffer becomes indirect when it is “attached” to a direct buffer using the rte_pktmbuf_attach() function.
Each buffer has a reference counter field and whenever an indirect buffer is attached to the direct buffer, the reference counter on the direct buffer is incremented.
Similarly, whenever the indirect buffer is detached, the reference counter on the direct buffer is decremented.
If the resulting reference counter is equal to 0, the direct buffer is freed since it is no longer in use.

There are a few things to remember when dealing with indirect buffers.
First of all, it is not possible to attach an indirect buffer to another indirect buffer.
Secondly, for a buffer to become indirect, its reference counter must be equal to 1, that is, it must not be already referenced by another indirect buffer.
Finally, it is not possible to reattach an indirect buffer to the direct buffer (unless it is detached first).

While the attach/detach operations can be invoked directly using the recommended rte_pktmbuf_attach() and rte_pktmbuf_detach() functions, it is suggested to use the higher-level rte_pktmbuf_clone() function, which takes care of the correct initialization of an indirect buffer and can clone buffers with multiple segments.

Since indirect buffers are not supposed to actually hold any data, the memory pool for indirect buffers should be configured to indicate the reduced memory consumption.
Examples of the initialization of a memory pool for indirect buffers (as well as use case examples for indirect buffers) can be found in several of the sample applications, for example, the IPv4 Multicast sample application.



7.8. Debug

In debug mode (CONFIG_RTE_MBUF_DEBUG is enabled), the functions of the mbuf library perform sanity checks before any operation (such as, buffer corruption, bad type, and so on).

8. Poll Mode Driver

Run-to-completion scheduling is a scheduling model
in which each task runs until it either finishes, or explicitly yields control back to the scheduler.
Run to completion systems typically have an event queue which is serviced either in strict order of admission by an event loop, or by an admission scheduler which is capable of scheduling events out of order, based on other constraints such as deadlines.

The DPDK includes 1 Gigabit, 10 Gigabit and 40 Gigabit and para virtualized virtio Poll Mode Drivers.
A Poll Mode Driver (PMD) consists of APIs, provided through the BSD driver running in user space, to configure the devices and their respective queues.
In addition, a PMD accesses the RX and TX descriptors directly without any interrupts (with the exception of Link Status Change interrupts) to quickly receive, process and deliver packets in the user's application.
This section describes the requirements of the PMDs, their global design principles and proposes a high-level architecture and a generic external API for the Ethernet PMDs.

8.1. Requirements and Assumptions(要件と前提)

The DPDK environment for packet processing applications allows for two models, run-to-completion and pipe-line:
  • In the run-to-completion model, a specific port's RX descriptor ring is polled for packets through an API.
Packets are then processed on the same core and placed on a port's TX descriptor ring through an API for transmission.
  • In the pipe-line model, one core polls one or more port's RX descriptor ring through an API.
Packets are received and passed to another core via a ring.
The other core continues to process the packet which then may be placed on a port's TX descriptor ring through an API for transmission.
  • run-to-completionモデルでは、特定のポートのRXデスクリプタリングは、APIを介してパケットのためにポーリングされる。\ パケットは、同じコアに処理され、送信のためのAPIを介してポートのTXデスクリプタリング上に配置される。
  • パイプラインモデルでは、一つのコアにポーリングつまたは複数のポートのRXデスクリプタリングAPIを介する。\ パケットは受信され、リングを介して別のコアに渡される。\ 他のコアは、送信のためのAPIを介してポートのTXデスクリプタリング上に配置することができるパケットの処理を続行します。
In a synchronous run-to-completion model, each logical core assigned to the DPDK executes a packet processing loop that includes the following steps:
-Retrieve input packets through the PMD receive API
-Process each received packet one at a time, up to its forwarding
-Send pending output packets through the PMD transmit API
  • PMDの受信APIを介して、入力パケットを取得
  • プロセスごとに、その転送まで、一度に入力パケットを受信
  • PMD送信APIを介して、保留中の出力パケットを送信します
★フロー毎にlcoreを割り当てて, 送り終わるまで一括で処理を流す.
Conversely, in an asynchronous pipe-line model, some logical cores may be dedicated to the retrieval of received packets and other logical cores to the processing of previously received packets.
Received packets are exchanged between logical cores through rings. The loop for packet retrieval includes the following steps:
-Retrieve input packets through the PMD receive API
-Provide received packets to processing lcores through packet queues
  • PMDの受信APIを介して、入力パケットを取得
  • パケットキューを介して処理lcoresに受信したパケットを提供する
The loop for packet processing includes the following steps:
-Retrieve the received packet from the packet queue
-Process the received packet, up to its retransmission if forwarded
  • パケットキューから受信したパケットを取得
  • 転送された場合は、その再送信までの受信したパケットを処理する
To avoid any unnecessary interrupt processing overhead, the execution environment must not use any asynchronous notification mechanisms.
Whenever needed and appropriate, asynchronous communication should be introduced as much as possible through the use of rings.

Avoiding lock contention is a key issue in a multi-core environment.
To address this issue, PMDs are designed to work with per-core private resources as much as possible.
For example, a PMD maintains a separate transmit queue per-core, per-port.
In the same way, every receive queue of a port is assigned to and polled by a single logical core (lcore).
To comply with Non-Uniform Memory Access (NUMA), memory management is designed to assign to each logical core a private buffer pool in local memory to minimize remote memory access.
The configuration of packet buffer pools should take into account the underlying physical memory architecture in terms of DIMMS, channels and ranks.
The application must ensure that appropriate parameters are given at memory pool creation time. See Mempool Library.
詳しくは MEMPOOLライブラリ を 参照してください。

8.2. Design Principles (設計原則)

The API and architecture of the Ethernet* PMDs are designed with the following guidelines in mind.
PMDs must help global policy-oriented decisions to be enforced at the upper application level.
Conversely, NIC PMD functions should not impede the benefits expected by upper-level global policies, or worse prevent such policies from being applied.
逆に、NIC PMD機能は、上位レベルのグローバルポリシーによって期待される利益を妨げたり、
For instance, both the receive and transmit functions of a PMD have a maximum number of packets/descriptors to poll.
This allows a run-to-completion processing stack to statically fix or to dynamically adapt its overall behavior through different global loop policies, such as:
-Receive, process immediately and transmit packets one at a time in a piecemeal fashion.
-Receive as many packets as possible, then process all received packets, transmitting them immediately.
-Receive a given maximum number of packets, process the received packets, accumulate them and finally send all accumulated packets to transmit.
  • 受信すると、直ちに処理して、断片的に同時にそのパケットを送信する
  • できるだけ多くのパケットを受信し、すべての受信パケットを処理し、その後すぐにそれらを送信する
  • 指定された最大数のパケットを受信、受信したパケットは処理され、それらを蓄積し、最終的に伝送するために、すべての蓄積されたパケットを送信する
To achieve optimal performance,
overall software design choices and pure software optimization techniques must be considered and balanced against available low-level hardware-based optimization features (CPU cache properties, bus speed, NIC PCI bandwidth, and so on).
The case of packet transmission is an example of this software/hardware tradeoff issue when optimizing burst-oriented network packet processing engines.
In the initial case, the PMD could export only an rte_eth_tx_one function to transmit one packet at a time on a given queue.
On top of that, one can easily build an rte_eth_tx_burst function that loops invoking the rte_eth_tx_one function to transmit several packets at a time.
However, an rte_eth_tx_burst function is effectively implemented by the PMD to minimize the driver-level transmit cost per packet through the following optimizations:
最適なパフォーマンス、全体的なソフトウェアの設計選択と純粋なソフトウェア最適化手法を実現するために検討し、利用可能な低レベルのハードウェアベースの最適化機能(CPUキャッシュプロパティ、バス速度、NIC PCI帯域幅など)に対してバランスされなければならない。
-Share among multiple packets the un-amortized cost of invoking the rte_eth_tx_one function.
-Enable the rte_eth_tx_burst function to take advantage of burst-oriented hardware features (prefetch data in cache, use of NIC head/tail registers)
to minimize the number of CPU cycles per packet,
for example by avoiding unnecessary read memory accesses to ring transmit descriptors,
or by systematically using arrays of pointers that exactly fit cache line boundaries and sizes.
-Apply burst-oriented software optimization techniques to remove operations that would otherwise be unavoidable, such as ring index wrap back management.
  • 複数のパケットのうち、rte_eth_tx_one関数を呼び出すの未償却原価(呼び出しオーバヘッド?)
  • rte_eth_tx_burst関数を有効にする。\パケットあたりのCPUサイクル数を最小化するため、バースト志向ハードウェア機能(キャッシュ内のプリフェッチデータや、NICヘッド/テールレジスタを使う)\たとえば、リング送信デスクリプタのメモリ読み込みアクセスを除去したり、キャッシュライン境界及びサイズに正確に適合(アライメント)したポインタアレイを使う。
  • このようなリングインデックスバックラップ管理などの他の方法で避けられないだろうな操作を削除するには、バースト指向ソフトウェア最適化技術を適用します。
Burst-oriented functions are also introduced via the API for services that are intensively used by the PMD.
This applies in particular to buffer allocators used to populate NIC rings, which provide functions to allocate/free several buffers at a time.
For example, an mbuf_multiple_alloc function returning an array of pointers to rte_mbuf buffers which speeds up the receive poll function of the PMD when replenishing multiple descriptors of the receive ring.

8.3. Logical Cores, Memory and NIC Queues Relationships (論理コア、メモリ、NICキューの関係)¶

The DPDK supports NUMA allowing for better performance when a processor's logical cores and interfaces utilize its local memory.
Therefore, mbuf allocation associated with local PCIe* interfaces should be allocated from memory pools created in the local memory.
The buffers should, if possible, remain on the local processor to obtain the best performance results and RX and TX buffer descriptors should be populated with mbufs allocated from a mempool allocated from local memory.

The run-to-completion model also performs better if packet or data manipulation is in local memory instead of a remote processors memory.
This is also true for the pipe-line model provided all logical cores used are located on the same processor.

Multiple logical cores should never share receive or transmit queues for interfaces since this would require global locks and hinder performance.




8.4. Device Identification and Configuration (デバイスの識別と設定)

8.4.1. Device Identification(識別)
Each NIC port is uniquely designated by its (bus/bridge, device, function) PCI identifiers assigned by the PCI probing/enumeration function executed at DPDK initialization.
Based on their PCI identifier, NIC ports are assigned two other identifiers:
- A port index used to designate the NIC port in all functions exported by the PMD API.
- A port name used to designate the port in console messages, for administration or debugging purposes. For ease of use, the port name includes the port index.
各NICポートを一意にプロービングPCI / DPDKの初期化時に実行される列挙関数によって割り当てられたその(バス/ブリッジ、デバイス、機能)PCI識別子によって指定されている。
  • PMD APIによってエクスポートされたすべての関数でNICポートを指定するためのポートインデックス
  • 管理またはデバッグの目的のために、コンソールメッセージでポートを指定するために使用されるポート名。使いやすさのために、ポート名、ポートインデックスを含む。

8.4.2. Device Configuration(設定)
The configuration of each NIC port includes the following operations:
- Allocate PCI resources
- Reset the hardware (issue a Global Reset) to a well-known default state
- Set up the PHY and the link
- Initialize statistics counters
The PMD API must also export functions to start/stop the all-multicast feature of a port and functions to set/unset the port in promiscuous mode.
  • PCIリソースを割り当て
  • よく知られているデフォルトの状態に(グローバルリセットを発行して)ハードウェアをリセット
  • PHYとリンクを設定
  • 統計カウンタを初期化
PMD APIは、プロミスキャスモードのポートに設定/解除するための機能と、ポートのall-multicast機能を開始/停止するための関数を提供する必要があります。
Some hardware offload features must be individually configured at port initialization through specific configuration parameters.
This is the case for the Receive Side Scaling (RSS) and Data Center Bridging (DCB) features for example.

8.4.3. On-the-Fly Configuration
All device features that can be started or stopped “on the fly” (that is, without stopping the device) do not require the PMD API to export dedicated functions for this purpose.

All that is required is the mapping address of the device PCI registers to implement the configuration of these features in specific functions outside of the drivers.

For this purpose, the PMD API exports a function that provides all the information associated with a device that can be used to set up a given device feature outside of the driver.
This includes the PCI vendor identifier, the PCI device identifier, the mapping address of the PCI device registers, and the name of the driver.

The main advantage of this approach is that it gives complete freedom on the choice of the API used to configure, to start, and to stop such features.
"オンザフライ"で開始や停止ができる、すべてのデバイス機能(つまり、デバイスを停止せずにできるもの)は、この目的のために専用の関数をエクスポートするPMD APIを必要しません。


この目的のために、PMD APIはドライバの外側に所定のデバイスの機能を設定するために使用することができるデバイスに関連付けられたすべての情報を提供する関数をエクスポートする。

As an example, refer to the configuration of the IEEE1588 feature for the Intel® 82576 Gigabit Ethernet Controller and the Intel® 82599 10 Gigabit Ethernet Controller controllers in the testpmd application.

Other features such as the L3/L4 5-Tuple packet filtering feature of a port can be configured in the same way.
Ethernet* flow control (pause frame) can be configured on the individual port.
Refer to the testpmd source code for details.
Also, L4 (UDP/TCP/ SCTP) checksum offload by the NIC can be enabled for an individual packet as long as the packet mbuf is set up correctly.
In terms of UDP tunneling packet, the PKT_TX_UDP_TUNNEL_PKT flag must be set to enable tunneling packet TX checksum offload for both outer layer and inner layer.
Refer to the testpmd source code (specifically the csumonly.c file) for details.

That being said, the support of some offload features implies the addition of dedicated status bit(s) and value field(s) into the rte_mbuf data structure, along with their appropriate handling by the receive/transmit functions exported by each PMD.

For instance, this is the case for the IEEE1588 packet timestamp mechanism, the VLAN tagging and the IP checksum computation, as described in the Section 7.6 “Meta Information”.
例として、インテル®82576ギガビット·イーサネット·コントローラとtestpmdアプリケーションにおけるインテル®82599 10ギガビットイーサネットコントローラコントローラーのIEEE1588機能の設定を参照してください。

そのようなポートのL3 / L4の5タプルのパケットフィルタリング機能などの他の機能も同様に構成することができる。
また、NICによってL4(UDP / TCP / SCTP)チェックサムオフロードは、ロングパケットのmbufが正しく設定されているように、個々のパケットのために有効にすることができます。



8.4.4. Configuration of Transmit and Receive Queues
Each transmit queue is independently configured with the following information:
  • The number of descriptors of the transmit ring
  • The socket identifier used to identify the appropriate DMA memory zone from which to allocate the transmit ring in NUMA architectures
  • The values of the Prefetch, Host and Write-Back threshold registers of the transmit queue
  • The minimum transmit packets to free threshold (tx_free_thresh).
When the number of descriptors used to transmit packets exceeds this threshold, the network adaptor should be checked to see if it has written back descriptors.
A value of 0 can be passed during the TX queue configuration to indicate the default value should be used.
The default value for tx_free_thresh is 32.
This ensures that the PMD does not search for completed descriptors until at least 32 have been processed by the NIC for this queue.
  • The minimum RS bit threshold. The minimum number of transmit descriptors to use before setting the Report Status (RS) bit in the transmit descriptor. Note that this parameter may only be valid for Intel 10 GbE network adapters. The RS bit is set on the last descriptor used to transmit a packet if the number of descriptors used since the last RS bit setting, up to the first descriptor used to transmit the packet, exceeds the transmit RS bit threshold (tx_rs_thresh). In short, this parameter controls which transmit descriptors are written back to host memory by the network adapter. A value of 0 can be passed during the TX queue configuration to indicate that the default value should be used. The default value for tx_rs_thresh is 32. This ensures that at least 32 descriptors are used before the network adapter writes back the most recently used descriptor. This saves upstream PCIe* bandwidth resulting from TX descriptor write-backs. It is important to note that the TX Write-back threshold (TX wthresh) should be set to 0 when tx_rs_thresh is greater than 1. Refer to the Intel® 82599 10 Gigabit Ethernet Controller Datasheet for more details.
  • 送信リングのデスクリプタの数
  • NUMAアーキテクチャで送信リングを割り当てるのに適切なDMAメモリ領域を識別するために使用されるソケット識別子
  • プリフェッチ、ホスト、送信キューのライトバックしきい値レジスタの値
  • 送信パケットを開放するための最小のしきい値(tx_free_thresh)。\ パケットを送信するために使用されるデスクリプタの数が、このしきい値を超えたときに、ネットワークアダプタは、ディスクリプタをライトバックしているかどうかがチェックされるべきである。
tx_free_threshのデフォルト値は32です。\ これは、PMDが、少なくとも32個のデスクリプタがこのキューにNICによって処理されるまで、完了したデスクリプタを検索しないことを確実にする。
  • 最小 RSビットの閾値。送信ディスクリプタにレポートステータス(RS)ビットを設定する前に、使用する送信ディスクリプタの最小数。 このパラメータは、インテルの10 GbEネットワークアダプターに対して有効であることに注意してください。 最後のRSビットの設定から使用さ記述子の数は、パケットを送信するために使用される第1の記述子まで、送信RSビット閾値(tx_rs_thresh)を超える。RSビットは、パケットを送信するために使用される最後の記述子に設定されている 要するに、記述子を伝送するこのパラメータを制御し、ネットワークアダプタによってホストメモリに書き戻される。 0の値は、デフォルト値が使用されるべきであることを示すために、TXキューを構成中に通過させることができる。 tx_rs_threshのデフォルト値は、このネットワークアダプタは、最も最近使用された記述子を書き戻す前に、少なくとも32の記述子が使用されることを保証する32である。 これは、TXディスクリプタライトバックから生じる上流のPCIe *帯域幅を節約できます。 それはtx_rs_threshは詳細についてはインテル®82599 10ギガビットイーサネットコントローラデータシートを参照してください1よりも大きい場合、TXライトバックしきい値(TXのwthresh)が0に設定されるべきことに注意することが重要です。
The following constraints must be satisfied for tx_free_thresh and tx_rs_thresh:
- tx_rs_thresh must be greater than 0.
- tx_rs_thresh must be less than the size of the ring minus 2.
- tx_rs_thresh must be less than or equal to tx_free_thresh.
- tx_free_thresh must be greater than 0.
- tx_free_thresh must be less than the size of the ring minus 3.
- For optimal performance, TX wthresh should be set to 0 when tx_rs_thresh is greater than 1.
One descriptor in the TX ring is used as a sentinel to avoid a hardware race condition, hence the maximum threshold constraints.
以下の制約がtx_free_thresh と tx_rs_thresh とで満たさなければなりません。
  • tx_rs_threshは 0より大きくなければなりません。
  • tx_rs_threshは リングのサイズ-2 よりも 小さくなければなりません。
  • tx_rs_threshは tx_free_thresh以下でなければなりません。
  • tx_free_threshは 0より大きくなければなりません。
  • tx_free_threshは リングのサイズ -3 よりも 小さくなければなりません。
  • tx_rs_threshが 1より大きい場合に最適なパフォーマンスを得るには、TX wthreshは0に設定する必要があります。
Note When configuring for DCB operation, at port initialization, both the number of transmit queues and the number of receive queues must be set to 128.

8.5. Poll Mode Driver API¶

8.5.1. Generalities¶
By default, all functions exported by a PMD are lock-free functions that are assumed not to be invoked in parallel on different logical cores to work on the same target object.
For instance, a PMD receive function cannot be invoked in parallel on two logical cores to poll the same RX queue of the same port.
Of course, this function can be invoked in parallel by different logical cores on different RX queues.
It is the responsibility of the upper-level application to enforce this rule.
If needed, parallel accesses by multiple logical cores to shared queues can be explicitly protected by dedicated inline lock-aware functions built on top of their corresponding lock-free functions of the PMD API.

8.5.2. Generic Packet Representation (一般論)
A packet is represented by an rte_mbuf structure, which is a generic metadata structure containing all necessary housekeeping information.
This includes fields and status bits corresponding to offload hardware features, such as checksum computation of IP headers or VLAN tags.
The rte_mbuf data structure includes specific fields to represent, in a generic way, the offload features provided by network controllers.
For an input packet, most fields of the rte_mbuf structure are filled in by the PMD receive function with the information contained in the receive descriptor.
Conversely, for output packets, most fields of rte_mbuf structures are used by the PMD transmit function to initialize transmit descriptors.

The mbuf structure is fully described in the Mbuf Library chapter.


8.5.3. Ethernet Device API
The Ethernet device API exported by the Ethernet PMDs is described in the DPDK API Reference.
イーサネットのPMDによってエクスポートされた、イーサネットデバイスAPIは、DPDK APIリファレンスで説明されています。

8.6. Vector PMD for IXGBE

Vector PMD uses Intel® SIMD instructions to optimize packet I/O.
It improves load/store bandwidth efficiency of L1 data cache by using a wider SSE/AVX register 1 (1).
The wider register gives space to hold multiple packet buffers so as to save instruction number when processing bulk of packets.
There is no change to PMD API.
The RX/TX handler are the only two entries for vPMD packet I/O.
They are transparently registered at runtime RX/TX execution if all condition checks pass.
PMD APIへの変更はありません。RX/TXハンドラは vPMDパケットI/Oのための唯一つのエントリです。
1. To date, only an SSE version of IX GBE vPMD is available.
To ensure that vPMD is in the binary code, ensure that the option CONFIG_RTE_IXGBE_INC_VECTOR=y is in the configure file.
現在までに、IX GBE vPMDの唯一のSSEバージョンが利用可能です。
vPMDはバイナリコードであることを保証するために、オプションの"CONFIG_RTE_IXGBE_INC_VECTOR = y"が構成ファイル内にあることを確認してください。
Some constraints apply as pre-conditions for specific optimizations on bulk packet transfers.
The following sections explain RX and TX constraints in the vPMD.

8.6.1. RX Constraints Prerequisites and Pre-conditions
The following prerequisites apply:
- To enable vPMD to work for RX, bulk allocation for Rx must be allowed.
- The RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC=y configuration MACRO must be set before compiling the code.
  • RXのためにvPMDを有効にするには、Rxのためのバルク割り当てが許可されなければならない。
  • RTE_LIBRTE_IXGBE_RX_ALLOW_BULK_ALLOC = Yの構成マクロは、コードをコンパイルする前に設定する必要があります。
Ensure that the following pre-conditions are satisfied:
- rxq->rx_free_thresh >= RTE_PMD_IXGBE_RX_MAX_BURST
- rxq->rx_free_thresh < rxq->nb_rx_desc
- (rxq->nb_rx_desc % rxq->rx_free_thresh) == 0
These conditions are checked in the code.

Scattered packets are not supported in this mode.
If an incoming packet is greater than the maximum acceptable length of one “mbuf” data size (by default, the size is 2 KB), vPMD for RX would be disabled.

By default, IXGBE_MAX_RING_DESC is set to 4096 and RTE_PMD_IXGBE_RX_MAX_BURST is set to 32.
  • rxq-> rx_free_thresh> = RTE_PMD_IXGBE_RX_MAX_BURST
  • rxq-> rx_free_thresh nb_rx_desc
  • (rxq-> nb_rx_desc%rxq-> rx_free_thresh)== 0

入力パケットは、一つの"buf"データサイズの最大許容長さよりも大きい場合(デフォルトでは、サイズが2 KBです)、RX用vPMDを無効にすることでしょう。

デフォルトでは、IXGBE_MAX_RING_DESCは4096に設定され、RTE_PMD_IXGBE_RX_MAX_BURSTは32に設定されている。 Feature not Supported by RX Vector PMD
Some features are not supported when trying to increase the throughput in vPMD.
They are:
- IEEE1588
- Header split
- RX checksum off load
- IEEE1588
- Header split
- RX checksum off load

Other features are supported using optional MACRO configuration. They include:
- HW VLAN strip
- HW extend dual VLAN
その他の機能は、オプションのマクロ設定を使用してサポートされます。 それらは次のとおりです。
- HW VLAN strip
- HW extend dual VLAN

To guarantee the constraint, configuration flags in dev_conf.rxmode will be checked:
- hw_vlan_strip
- hw_vlan_extend
- hw_ip_checksum
- header_split
- dev_conf
fdir_conf->mode will also be checked.
- hw_vlan_strip
- hw_vlan_extend
- hw_ip_checksum
- header_split
- dev_conf RX Burst Size
As vPMD is focused on high throughput, it assumes that the RX burst size is equal to or greater than 32 per burst.
It returns zero if using nb_pkt < 32 as the expected packet number in the receive handler.
受信ハンドラで予想パケット番号としてnb_pkt <32を使用している場合には 0を返します。
8.6.2. TX Constraint (送信制約) Prerequisite (前提条件)
The only prerequisite is related to tx_rs_thresh.
The tx_rs_thresh value must be greater than or equal to RTE_PMD_IXGBE_TX_MAX_BURST, but less or equal to RTE_IXGBE_TX_MAX_FREE_BUF_SZ.
Consequently, by default the tx_rs_thresh value is in the range 32 to 64.
このため、デフォルトではtx_rs_thresh値が範囲内に32から64である。 Feature not Supported by RX Vector PMD
TX vPMD only works when txq_flags is set to IXGBE_SIMPLE_FLAGS.
This means that it does not support TX multi-segment, VLAN offload and TX csum offload.
The following MACROs are used for these three features:
TX vPMDは、txq_flagsがIXGBE_SIMPLE_FLAGSに設定されている場合にのみ機能します。
これは、TXマルチセグメント、VLANオフロードとTX CS​​UMオフロードをサポートしていないことを意味します。

8.6.3. Sample Application Notes

22. IP Fragmentation and Reassembly Library

The IP Fragmentation and Reassembly Library implements IPv4 and IPv6 packet fragmentation and reassembly.

22.1. Packet fragmentation

Packet fragmentation routines devide input packet into number of fragments.
Both rte_ipv4_fragment_packet() and rte_ipv6_fragment_packet() functions assume that input mbuf data points to the start of the IP header of the packet
(i.e. L2 header is already stripped out).
To avoid copying for the actual packet's data zero-copy technique is used (rte_pktmbuf_attach).
For each fragment two new mbufs are created:
  • Direct mbuf – mbuf that will contain L3 header of the new fragment.
  • Indirect mbuf – mbuf that is attached to the mbuf with the original packet. It's data field points to the start of the original packets data plus fragment offset.
(すなわち、L2ヘッダ=ethernet headerは既にストリップされていることを前提としています)
  • ダイレクトmbuf: 新しいフラグメントのL3ヘッダを構成するmbuf
  • インダイレクトmbuf: オリジナルパケットにattachされたmbuf. このデータフィールドはオリジナルパケットデータの先頭にフラグメントオフセットを加算した位置を指している。
Then L3 header is copied from the original mbuf into the 'direct' mbuf and updated to reflect new fragmented status.
Note that for IPv4, header checksum is not recalculated and is set to zero.

Finally 'direct' and 'indirect' mbufs for each fragnemt are linked together via mbuf's next filed to compose a packet for the new fragment.

The caller has an ability to explicitly specify which mempools should be used to allocate 'direct' and 'indirect' mbufs from.
Note that configuration macro RTE_MBUF_SCATTER_GATHER has to be enabled to make fragmentation library build and work correctly.
For more information about direct and indirect mbufs, refer to the DPDK Programmers guide "7.7 Direct and Indirect Buffers".

22.2. Packet reassembly

22.2.1. IP Fragment Table
Fragment table maintains information about already received fragments of the packet.

Each IP packet is uniquely identified by triple , , .
Note that all update/lookup operations on Fragmen Table are not thread safe.
So if different execution contexts (threads/processes) will access the same table simultaneously, then some exernal syncing mechanism have to be provided.

Each table entry can hold information about packets consisting of up to RTE_LIBRTE_IP_FRAG_MAX (by default: 4) fragments.
Code example, that demonstrates creation of a new Fragment table:

>frag_cycles = (rte_get_tsc_hz() + MS_PER_S - 1) / MS_PER_S * max_flow_ttl;
>bucket_num = max_flow_num + max_flow_num / 4;
>frag_tbl = rte_ip_frag_table_create(max_flow_num, bucket_entries, max_flow_num, frag_cycles, socket_id);
Internally Fragment table is a simple hash table.
The basic idea is to use two hash functions and * associativity.
This provides 2 * possible locations in the hash table for each key.
When the collision occurs and all 2 * are occupied, instead of reinserting existing keys into alternative locations, ip_frag_tbl_add() just returns a faiure.
基本のアイデアは、2つのハッシュ関数と、 *の結合性です。
これは、それぞれのキーのハッシュテーブル内の"2 * "可能な位置を提供する。
Also, entries that resides in the table longer then are considered as invalid, and could be removed/replaced by the new ones.

Note that reassembly demands a lot of mbuf's to be allocated.
At any given time up to (2 * bucket_entries * RTE_LIBRTE_IP_FRAG_MAX * ) can be stored inside Fragment Table waiting for remaining fragments.