背景 工作中遇到客戶反饋,上層應用UDP固定間隔100ms發包,但本地tcpdump抓包存在波動,有的數據包之間間隔107ms甚至更多,以此重新梳理了下udp的發送流程。 udp發包流程 udp_sendmsg UDP corking 是一項優化技術,允許內核將多次數據累積成單個數據報發送。在用戶程 ...
背景
工作中遇到客戶反饋,上層應用UDP固定間隔100ms發包,但本地tcpdump抓包存在波動,有的數據包之間間隔107ms甚至更多,以此重新梳理了下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發包流程
當配額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則與中斷\異常相關。
時延大的問題可能是軟中斷調度問題。