Linux系統中RPS/RFS介紹

http://blog.chinaunix.net/uid-20788636-id-4838269.html

1  RPS/RFS 介紹

1.1 RPS/RFS出現的原因

RPS/RFS 功能是在Linux- 2.6.35中有google的工程師提交的兩個補丁,這兩個補丁的出現主要是基於以下兩點現實的考慮:

(1)       這兩個補丁的出現,是由於服務器的CPU越來越強勁,可以到達十幾核、幾十核,而網卡硬件隊列則才4個、8個,這種發展的不匹配造成了CPU負載的不均衡。

(2)       上面的提到的是多隊列網卡的情況,在單隊列網卡的情況下,RPS/RFS相當於在系統層用軟件模擬了多隊列的情況,以便達到CPU的均衡。

出現RFS/RPS的原因主要是由於過多的網卡收包和發包中斷集中在一個CPU上,在系統繁忙時,CPU對網卡的中斷無法響應,這樣導致了服務器端的網絡性能降低,從這裏可以看出其實網絡性能的瓶頸不在於網卡,而是CPU,因爲現在的網卡很多都是萬兆並且多隊列的,如果有過多的中斷集中在一個CPU上,將導致該CPU無法處理,所以可以使用該方法將網卡的中斷分散到各個CPU上。但對於CentOS 6.1已經支持了。

1.2 多隊列網卡

當網卡驅動加載時,通過獲取的網卡型號,得到網卡的硬件queue的數量,並結合CPU核的數量,最終通過Sum=Min(網卡queue,CPU core)得出所要激活的網卡queue數量(Sum),並申請Sum箇中斷號,分配給激活的各個queue,當某個queue收到報文時,觸發相應的中斷,收到中斷的核,將該任務加入到協議棧負責收包的該核的NET_RX_SOFTIRQ隊列中(NET_RX_SOFTIRQ在每個核上都有一個實例),在NET_RX_SOFTIRQ中,調用NAPI的收包接口,將報文收到有多個netdev_queue的net_device數據結構中。

當CPU可以平行收包時,就會出現不同的核收取了同一個queue的報文,這就會產生報文亂序的問題,解決方法是將一個queue的中斷綁定到唯一的一個核上去,從而避免了亂序問題。

查看網卡是否支持MSI-X可以直接查看 interrupts 文件,看關鍵字 MSI 就知道了:

# grep -i msi /proc/interrupts

在Broadcom的網卡手冊上有關於MSI和MSI-X的定義:

MSI Version. This is the Message Signaled Interrupts (MSI) version being used. The option MSI corresponds to the PCI 2.2 specification that supports 32 messages and a single MSI address value. The option MSI-X corresponds to the PCI 3.0 specification that supports 2,048 messages and an independent message address for each message.

實際應用場景中,MSI方式的中斷對多核cpu的利用情況不佳,網卡中斷全部落在某一個cpu上,即使設置cpu affinity也沒有作用,而MSI-X中斷方式可以自動在多個cpu上分擔中斷。

1.3 RPS/RFS介紹

RPS(Receive Packet Steering)主要是把軟中斷的負載均衡到各個cpu,簡單來說,是網卡驅動對每個流生成一個hash標識,這個HASH值得計算可以通過四元組來計算(SIP,SPORT,DIP,DPORT),然後由中斷處理的地方根據這個hash標識分配到相應的CPU上去,這樣就可以比較充分的發揮多核的能力了。通俗點來說就是在軟件層面模擬實現硬件的多隊列網卡功能,如果網卡本身支持多隊列功能的話RPS就不會有任何的作用。該功能主要針對單隊列網卡多CPU環境,如網卡支持多隊列則可使用SMP irq affinity直接綁定硬中斷。


    

圖1 只有RPS的情況下(來源網絡)


由於RPS只是單純把數據包均衡到不同的cpu,這個時候如果應用程序所在的cpu和軟中斷處理的cpu不是同一個,此時對於cpu cache的影響會很大,那麼RFS(Receive flow steering)確保應用程序處理的cpu跟軟中斷處理的cpu是同一個,這樣就充分利用cpu的cache,這兩個補丁往往都是一起設置,來達到最好的優化效果, 主要是針對單隊列網卡多CPU環境。

圖2:同時開啓RPS/RFS後(來源網絡)

rps_flow_cnt,rps_sock_flow_entries,參數的值會被進位到最近的2的冪次方值,對於單隊列設備,單隊列的rps_flow_cnt值被配置成與 rps_sock_flow_entries相同。

RFS依靠RPS的機制插入數據包到指定CPU的backlog隊列,並喚醒那個CPU來執行

1.4 RSS介紹

RSS(receive side scaling)是有微軟提處理,通過這項技術能夠將網絡流量分載到多個cpu上,降低單個cpu的佔用率。默認情況下,每個cpu覈對應一個rss隊列。ixgbe驅動將收到的數據包的源、目的ip地址和端口號,交由網卡硬件計算出一個rss hash值,再根據這個hash值來決定將數據包分配到哪個隊列中。通過cat /proc/interrupts |grep 網卡名的方式,就可以看到網卡使用了幾個rss通道。

RSS(Receive-side scaling,接收端調節)技術,RSS是和硬件相關聯的,必須要有網卡的硬件進行支持,RSS把發數據包分配到不同的隊列中,其中HASH值的計算式在硬件中完成的,然後通過affinity的調整把不同的中斷映射的不同的Core上。下面是Linux內核對RFS和RSS描述。

For a multi-queue system, if RSS is configured so that a hardware

receive queue is mapped to each CPU, then RPS is probably redundant

and unnecessary. If there are fewer hardware queues than CPUs, then

RPS might be beneficial if the rps_cpus for each queue are the ones that

share the same memory domain as the interrupting CPU for that queue.

在Intel架構上的一些硬件上是有該功能的。

On the Intel architecture, multi-queue NICs use MSI-X (the extended version of Message Signaled Interrupts) to send interrupts to multiple cores. The feature that distributes arriving packets to different CPUs based on (hashed) connection identifiers is called RSS (Receive Side Scaling) on Intel adapters, and its kernel-side support on Windows was introduced as part of the Scalable Networking Pack in Windows 2003 SP2.

This performance enhancement works as follows: Incoming packets are distributed over multiple logical CPUs (e.g. cores) based on a hash over the source and destination IP addresses and port numbers. This hashing ensures that packets from the same logical connection (e.g. TCP connection) are always handled by the same CPU/core. On some network adapters, the work of computing the hash can be outsourced to the network adapter. For example, some Intel and Myricom adapters compute a Toeplitz hashfrom these header fields. This has the beneficial effect of avoiding cache misses on the CPU that performs the steering - the receiving CPU will usually have to read these fields anyway.

Receive-Side Scaling (RSS), also known as multi-queue receive, distributes network receive processing across several hardware-based receive queues, allowing inbound network traffic to be processed by multiple CPUs. RSS can be used to relieve bottlenecks in receive interrupt processing caused by overloading a single CPU, and to reduce network latency。(https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/network-rss.html

通過上面的介紹可以知道,對於RSS和RFS的區別,它們都是把同一個流的數據包給同一個CPU,但是RSS是使用硬件實現的,而RFS是純軟件實現的。

1.5  網卡的affinity特性

SMP IRQ affinity Linux 2.4內核之後引入了將特定中斷綁定到指定的CPU的技術,稱爲SMP IRQ affinity。

smp_affinity是否需要設置,根據網卡是否支持多隊列,如果網卡支持多隊列則設置纔有作用,如果網卡有多隊列,就會有多箇中斷號,這樣就可以把不同的中斷號分配到不同CPU上,這樣中斷號就能相對均勻的分配到不同的CPU上。

這裏簡單的理解一下,smp_affinity值得映射關係,下面簡單的舉個例子:

如果cat  /proc/irq/84/smp_affinity的值爲:20(二進制爲:00100000),則84這個IRQ的親和性爲#5號CPU。

每個IRQ的默認的smp affinity在這裏:cat /proc/irq/default_smp_affinity,默認值是全F。

但是對於單隊列的網卡配置「smp_affinity」和「smp_affinity_list」對多CPU無效。

1.6 總結

如果是單隊列的話/proc/sys/net/core/rps_sock_flow_entries值和rps_flow_cnt設置爲相同,rps更多的是針對網卡驅動是NAPI方式的,如果應用場景更多是內核的forward,RPS就足夠了,再在該基礎上使用RFS也不會有性能的提升。

在執行腳本向/sys/class/net/eth0/queues/rx-0/ rps_cpus文件中寫對應的數據時,提示

./set_irq_affinity.sh

./set_irq_affinity.sh: line 52: echo: write error: Value too large for defined data type                 

這是由於rps_cpus文件中的數,需要和CPU的個數相匹配,當寫入的數據大於CPU的個數時,會出現上面的錯誤提示信息。

使用舉例

可使用逗號爲不連續的 32 位組限定 smp_affinity 值。在有 32 個以上核的系統有這個要求。例如:以下示例顯示在一個 64 核系統的所有核中提供 IRQ 40。

# cat /proc/irq/40/smp_affinity

ffffffff,ffffffff

在 64 核系統的上 32 核中提供 IRQ 40,請執行:

# echo 0xffffffff,00000000 > /proc/irq/40/smp_affinity

# cat /proc/irq/40/smp_affinity

ffffffff,00000000

 

RFS需要內核編譯CONFIG_RPS選項,RFS才起作用。全局數據流表(rps_sock_flow_table)的總數可以通過下面的參數來設置:

 /proc/sys/net/core/rps_sock_flow_entries

每個隊列的數據流表總數可以通過下面的參數來設置:

 /sys/class/net/<dev>/queues/rx/rps_flow_cnt

echo ff > /sys/class/net//queues/rx-/rps_cpus

echo 4096 > /sys/class/net//queues/rx-/rps_flow_cnt

echo 30976 > /proc/sys/net/core/rps_sock_flow_entries

對於2個物理cpu,8核的機器爲ff,具體計算方法是第一顆cpu是00000001,第二個cpu是00000010,第3個cpu是 00000100,依次類推,由於是所有的cpu都負擔,所以所有的cpu數值相加,得到的數值爲11111111,十六進制就剛好是ff。而對於 /proc/sys/net/core/rps_sock_flow_entries的數值是根據你的網卡多少個通道,計算得出的數據,例如你是8通道的 網卡,那麼1個網卡,每個通道設置4096的數值,8*4096就是/proc/sys/net/core/rps_sock_flow_entries 的數值,對於內存大的機器可以適當調大rps_flow_cnt,

參考文獻:

http://blog.csdn.net/turkeyzhou/article/details/7528182

http://lwn.net/Articles/328339/

發佈了15 篇原創文章 · 獲贊 9 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章