DPDK QoS之分層排程器

2022-08-03 07:48:14 字數 3558 閱讀 6461

三、api

1.埠排程配置api

rte_sched.h裡包含了埠,子埠和流水線的配置函式。

2.埠排程器入隊api

int rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts)

3.埠排程器出隊api

int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts)

4.使用舉例

1

/**/

2#define n_pkts_rx 64

3#define n_pkts_tx 48

4#define nic_rx_port 0

5#define nic_rx_queue 0

6#define nic_tx_port 1

7#define nic_tx_queue 0

8struct rte_sched_port *port =null;

9struct rte_mbuf *pkts_rx[n_pkts_rx], *pkts_tx[n_pkts_tx];

10uint32_t n_pkts_rx, n_pkts_tx;

11/*

initialization

*/12

13/*

runtime

*/14

while (1

)

4.實現細節

每個埠的內部資料結構,下面是原理解釋圖:

#   資料結構    大小(bytes)   #每個埠    入隊    出隊    功能描述

1   子埠表項   64          #埠的子埠數   .     rd,wr    子埠的持久化資料(如積分,等等)

2   流水線表項   64          #埠的流水線數   .     rd,wr    流水線和它的流分類依據佇列(積分)(這些會在執行期間被更新)的持久化資料。流水線配置引數在執行期間不支援修改。相同流水線的配置引數會多個流水線共享,所以它們不是流水線表的一部分。

3   隊列表項     4           #埠的佇列數   rd,wr  rd,wr   佇列的持久化資料(比如讀寫指標)。所有佇列的每乙個流分類,都是一樣的佇列大小。任何乙個流水線的流水線表項都是存在同乙個cache line裡。

5.多核擴充套件策略

(1) 不同的物理埠執行不同的執行緒。同乙個埠的入隊和出隊在同乙個執行緒裡執行。

(2) 不同的執行緒使用同乙個物理埠,通過分隔同乙個物理埠(虛擬埠)的不同的子埠集合來執行。同樣,乙個子埠也能分隔成多個子埠集合,來執行不同的執行緒,出隊和入隊都是在同乙個埠的同乙個執行緒。唯一的要求是,考慮到效能,不能在乙個核裡處理全部的埠。

6.在同乙個出埠入隊和出隊

在不同的cpu核上執行同乙個出埠入隊和出隊的操作,會對排程器的效能有顯著影響,所以是不推薦這麼做。

埠的入隊和出隊操作由如下的資料結構來共享訪問:

(1)報文描述符

(2)隊列表

(3)佇列儲存區域

(4)活動佇列的點陣圖(bitmap)

能預料到的效能損耗是由於:

(1)需要保證佇列和點陣圖操作是執行緒安全的,這就需要用鎖來保證原子訪問(比如自旋鎖/訊號量)或者使用無鎖的原子訪問(比如:test/set, compare and swap(cas)等等)。這比前面說的情況影響更大。

(2)在2個cpu核的快取結構(滿足快取一致性)裡,雙向(ping-pong)地在快取記憶體線(cache line)存放共享資料結構

因此,排程器的入隊和出隊操作必須在同乙個執行緒裡執行,這樣佇列和點陣圖的操作就沒有執行緒安全的效能損耗以及可以儲存排程器資料結構在同乙個cpu核上。

7.效能調優

增加網絡卡埠的數量僅僅只需要成比例的增加用來流量排程的cpu核的數量。

8.入隊流水線

每乙個報文的步驟順序是:

(1)mbuf裡資料字段的訪問要求識別出報文的目的佇列。這些字段包括:埠,子埠,流分類和流分類的佇列,這些都是分類階段設定的。

(2)訪問佇列資料結構要識別出寫操作在佇列陣列中的位置。如果佇列是滿的,那麼這個報文會被丟棄。

(3)訪問佇列陣列儲存報文的位置(比如:寫mbuf指標)

需要注意的是,這些步驟是有強相關的資料依賴的。比如,第2步和第3步不能在第1步和第2步的返回可用的結果之前啟動。這樣就阻止了cpu通過亂序執行來顯著提高效能的優化行為。

考慮到很高速率的報文接收以及很大數量的佇列,可以預料到在當前cpu,對當前報文入隊需要訪問的資料結構是不在l1,或者l2快取的,因此會去記憶體中訪問,這樣會導致l1和l2資料快取未命中(cache miss)。大量的l1、l2快取未命中在效能上肯定是不可接受的。

乙個解決方案是通過預先讀取需要的資料結構。預取操作有乙個執行延遲,資料結構在當前預取的狀態時,cpu是不能訪問它的,這個時候,cpu可以去執行其他的工作。其他工作是去執行其他報文的入隊順序不同階段的操作,因此就實現了入隊操作的流水線。

下圖闡述了流水線4個階段的入隊操作實現,每個階段執行2個報文。沒有那個報文可以在同一時間處於大於乙個流水線階段。

擁塞管理方案通過佇列流水線來描述就非常簡單了:

報文入隊直到特定的佇列滿了,這時,所有的報文都只能到同乙個丟包佇列,直到報文被消耗完(通過出隊操作),這裡可以通過使能red/wred來改進佇列流水線,通過檢視佇列的使用情況和特定報文的報文優先順序來決定出隊或丟棄。(這就與任意的讓所有報文都入隊/丟棄所有報文不同了。)

9.出隊狀態機

從當前流水線排程下乙個報文的步驟順序是:

(1)使用bitmap掃瞄識別出下乙個活動流水線,預取流水線。

(2)讀取流水線資料結構。更新當前流水線和它的子埠的積分。識別當前流水線的第乙個活動流分類,通過wrr來選擇下乙個佇列,預取當前流水線的16個佇列的佇列指標。

(3)從當前wrr佇列裡讀取下乙個元素並預取它的報文描述符。

(4)從報文描述符(mbuf資料結構)裡讀取報文長度。基於報文長度和可用積分(如當前流水線,流水線流分類,子埠和子埠流分類),來執行或不執行排程。

為了避免快取未命中,上述的資料結構(流水線,佇列,佇列陣列,mbufs)都會在訪問之前預取過來。隱藏預取操作的延遲方案是在當前流水線的預取指令發出之後立即從當前流水線(流水線 grinder a)切換到另外乙個流水線(grinder b)。這就給了足夠的時間在執行權切換回之前的流水線(grinder a)之前來完成預取操作。

出隊流水線狀態機利用資料在cpu快取記憶體裡會提高效能的原理,因此,在從同乙個流水線的活動流分類移動到另外乙個流水線之前,它會嘗試從乙個流水線和流水線流分類裡傳送盡可能多的報文(直到最大的可用報文和積分)

移動App設計之分層架構 MVC

場景分析 我們知道,乙個移動裝置的應用大多與網路有關,也就是說,我在移動裝置上看到的資料,一般都是從server上 拉 過來,顯示在我們的移動裝置 ios androiud wpohone等 上。那我們就這個 拉 的過程分析,拉什麼樣的資料?去 拉?拉過來的資料怎麼處理?用程式設計 開發 的思維看,...

網路初識之分層模型和網路傳輸

1.每層介紹 osi,全稱是 開放式系統互聯通訊參考模型 第一層 物理層,網路的物理形式,集線器工作在物理層 物理層交換的單元名稱是位元 第二層 資料鏈路層,負責裝置之間的資料幀的傳送和識別,交換機工作在資料鏈路層 經資料鏈路層協議封裝後的資料叫資料幀 第三層 網路層,負責位址的管理和路由的選擇,例...

Golang分布式設計模式之 分層設計

提到分布式系統,我們會想到很多機器,分別部署著各自的服務,然後整體組成乙個分布式系統。在這類系統中,分布式系統與常規的集中式系統存在著以下三個區別。來自分布式演算法導論 1 缺乏全域性狀態知識 2 缺乏全域性時間幀 3 非確定性 這三大特點也成為分布式系統設計的難點。也正是如此,分布式系統的設計比常...