TCP/UDP/IP Checksum 基本上是使用 16-bit 1's complement 相加,也就是用一般的 16-bit 相加,再把進位加進來。這對 32-bit 處理器而言,使用 16-bit 相加,全部進位會累積在高位元的 16-bit,最後再把高位元的 16-bit 加進來,有可能再進位所以再加一次高位元的 16-bit。
IP checksum 只計算 IP header 的部份 (20 bytes),任何一個欄位改變,例如 time-to-live 每經過一個 router 減一,就要重算。而 TCP/UDP checksum 計算的範圍包括 TCP/UDP header 跟 data,以及來自 IP header 的一些欄位 (pseudo header),計算份量較多。雖然經過 router 不需要重算,但經過 NAT router 時 IP 變了則需要重算,這會對原本處理器效能就不高的 NAT home router 造成一些負擔。不過 UDP checksum 是選擇性的,可以不算,填 0 就好。TCP checksum 是不能省略的。
ICMP header checksum?
Tx Checksum Offload
首先需設定 net_device features,告訴 Kernel 硬體有什麼 checksum 功能,Kernel 就不會去算:- NETIF_F_IP_CSUM:TCP/UDP over IPv4 的 checksum
- NETIF_F_IPV6_CSUM:TCP/UDP over IPv6 的 checkcum
- NETIF_F_HW_CSUM:以上兩者
Rx Checksum Offload
netif_rx() 或 netif_receive_skb() 前,將 skb ip_summed 設為 CHECKSUM_UNNECESSARY,表示不需要再算 checksum,包括 loopback 界面也不需要算 checksum。net_device features 可設定 NETIF_F_RXCSUM 來紀錄有 Rx Checksum Offload 功能。
參考
- Linux kernel source
- TCP/IP Illustrated, Volume 1 The Protocols, W. Richard Stevens
沒有留言:
張貼留言