Linux - RPS (Receive Packet Steering)

之前 介紹過 RSS, 但這個需要 硬體 配合,

Google 在 2010 年時有提出 RPS (Receive Packet Steering) 的方式,
利用報文的 hash 值, 來決定選用的 cpu, 這個 hash 值可以由網卡 硬體計算,
也可以由 軟體來計算. 這樣可以充分利用多核 (software interrupt load balance),
使得相對原本 no RPS 的作法, 有比較好的效能

https://lwn.net/Articles/378617/

1. multiqueue

首先 network device driver 需要決定 rx queue 個數, 這邊介紹一篇
   HowTo for multiqueue network device support

device driver 先透過 alloc_etherdev_mq() 告訴 kernel 有多少個 RX queues (TX queues)
( 這兩個數量是相同的), kernel 會進行配置.

#define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)



這邊相對應可以在底下目錄看到
   /sys/class/net/<device>/queues/rx-?

如果 count 為 1, 則只有一個 rx-0, tx-0
如果 count 為 4, 則會看到  rx-0, rx-1, rx-2, rx-3, tx-0, tx-1, tx-2, tx-3


2. 指定 cpu

Scaling in the Linux Networking Stack
SMP IQ affinity

/sys/class/net/(dev)/queues/rx-(n)/rps_cpus
例如假設有 8 核, 我們想設置第 0, 2, 4, 6 CPU 用這個 queue

# echo 55 > /sys/class/net/eth0/queues/rx-0/rps_cpus


3. RPS 處理

當網卡 driver 報 rx packet 給 kernel 時, 會透過底下 function :
- netif_rx() : 非 NAPI
- netif_receive_skb(): NAPI

(1) 透過 get_rps_cpu() 得知決定該封包由哪一個 cpu 處理

      作法:  通過 skb 計算 hash, 然後通過 hash 從對應的 queue 的 rps_mapping 取得 對應的 cpu id
                 這 hash 值可以交給 hardware network device 計算, 或 software 計算.
                 但 software 計算可能造成 cpu cache miss 效能問題

(2) 將該 packet 放到該 cpu 的 softnet_data 中的 input_pkt_queue 中,
      每個 CPU 都有一個 softnet 結構, 和各自的 input_pkt_queue
     softnet_data struct 中有 backlog, 在 enqueue_to_backlog 中, 會將 backlog 加入 cpu 輪詢,
    並觸發 software interrupt, 而在net_rx_action() 處理
    ( net_rx_action() 會呼叫到 napi_poll() 和 net_rps_poll() )



另外可以在 /proc/softirqs 看到各 CPU 處理 NET_RX 的個數

--
下回介紹 RFS (receive flow steering)
https://lwn.net/Articles/381955/




留言

熱門文章