UDP核心發包流程

StepForwards發表於2023-05-08

背景

工作中遇到客戶反饋,上層應用UDP固定間隔100ms發包,但本地tcpdump抓包存在波動,有的資料包之間間隔107ms甚至更多,以此重新梳理了下udp的傳送流程。

udp發包流程

udp發包流程

udp_sendmsg

UDP corking 是一項最佳化技術,允許核心將多次資料累積成單個資料包傳送。在使用者程式中有兩種方法可以啟用此選項:

使用 setsockopt 系統呼叫設定 socket 的 UDP_CORK 選項
程式呼叫 send,sendto 或 sendmsg 時,帶 MSG_MORE 引數

如果沒設定UDP_CORK,直接傳送到ip層,根據客戶只是偶爾出現時延過高的情況,可以確定UDP_CORK並沒有被設定,udp這裡應該是直接下發的,udp_send_skb之後直接到ip層,排除udp_sendmsg導致時延波動問題

int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
{
... ...
/* Lockless fast path for the non-corking case. */
	if (!corkreq) {
		struct inet_cork cork;

		skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
				  sizeof(struct udphdr), &ipc, &rt,
				  &cork, msg->msg_flags);
		err = PTR_ERR(skb);
		if (!IS_ERR_OR_NULL(skb))
			err = udp_send_skb(skb, fl4, &cork);
		goto out;
	}
... ...
}

qdisc發包流程

qdisc
當配額quota < 0 || need_resched時將觸發軟中斷,否則將直接進行發包。
quota 對應 net.core.dev_weight,可透過sysctl進行更改。

網路卡及驅動

如果網路卡慢,會導致網路卡佇列滿返回BUSY,資料包重新入隊,tcpdump將抓到重複的資料包。客戶並未反饋該現象,排除網路卡及網路卡驅動。

總結

未配置UDP_CORK的情況下,上層udp應用send呼叫包含兩個路徑,一個是send直接到網路卡驅動進行傳送,另一個是send到網路裝置子系統__dev_queue_skb,然後由軟中斷呼叫繼續傳送。
決定直接發還是由軟中斷髮的條件是,net.core.dev_weight和 need_resched(需要強制排程),可以透過sysctl -a | grep weight檢視其預設值。

對於__qdisc_run來講,dev_weight代表迴圈次數,可嘗試適當增大這個值,但可能會導致上層應用傳送時延增加。
sysctl net.core.dev_weight=4096

need_resched則與中斷\異常相關。

時延大的問題可能是軟中斷排程問題。

相關文章