UDP-Lite 協議 (RFC 3828)¶
UDP-Lite 是一種標準跟蹤 IETF 傳輸協議,其特點是可變長度的校驗和。 這對於透過無線網路傳輸多媒體(影片,VoIP)具有優勢,因為部分損壞的資料包仍然可以饋送到編解碼器中,而不會因校驗和測試失敗而被丟棄。
此檔案簡要描述了現有的核心支援和套接字 API。 有關深入資訊,您可以參考
UDP-Lite 主頁: http://web.archive.org/web/%2E/http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/
從這裡,您還可以下載一些示例應用程式原始碼。
UDP-Lite HOWTO on http://web.archive.org/web/%2E/http://www.erg.abdn.ac.uk/users/gerrit/udp-lite/files/UDP-Lite-HOWTO.txt
Wireshark UDP-Lite WiKi (帶有捕獲檔案): https://wiki.wireshark.org/Lightweight_User_Datagram_Protocol
協議規範, RFC 3828, http://www.ietf.org/rfc/rfc3828.txt
1. 應用¶
一些應用程式已成功移植到 UDP-Lite。 Ethereal(現在稱為 wireshark)預設情況下支援 UDP-Litev4/v6。
將應用程式移植到 UDP-Lite 非常簡單:只需更改套接字級別和 IPPROTO;傳送方還需要設定校驗和覆蓋長度(預設值 = 標頭長度 = 8)。 詳細資訊在下一節中。
2. 程式設計 API¶
UDP-Lite 提供了一種無連線、不可靠的資料報服務,因此使用與 UDP 相同的套接字型別。 事實上,從 UDP 移植到 UDP-Lite 非常容易:只需新增
IPPROTO_UDPLITE作為 socket(2) 呼叫的最後一個引數,以便語句看起來像s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE);或者,分別為
s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE);只需進行上述更改,您就可以執行 UDP-Lite 服務或連線到 UDP-Lite 伺服器。 核心將假定您對使用部分校驗和覆蓋不感興趣,因此會模擬 UDP 模式(完全覆蓋)。
要利用部分校驗和覆蓋工具,需要設定一個套接字選項,該選項採用一個整數來指定覆蓋長度
傳送方校驗和覆蓋:UDPLITE_SEND_CSCOV
例如
int val = 20; setsockopt(s, SOL_UDPLITE, UDPLITE_SEND_CSCOV, &val, sizeof(int));將校驗和覆蓋長度設定為 20 位元組(12b 資料 + 8b 標頭)。 每個資料包只有前 20 個位元組(加上偽標頭)將被校驗和。 這對於具有 12 位元組基本標頭的 RTP 應用程式很有用。
接收方校驗和覆蓋:UDPLITE_RECV_CSCOV
此選項是接收方類似的選項。 它是真正可選的,即不需要啟用具有部分校驗和覆蓋的流量。 它的功能是作為流量過濾器:啟用後,它指示核心丟棄所有覆蓋範圍_小於_此值的資料包。 例如,如果要保護 RTP 和 UDP 標頭,則接收方可以強制僅允許最小覆蓋範圍為 20 的資料包
int min = 20; setsockopt(s, SOL_UDPLITE, UDPLITE_RECV_CSCOV, &min, sizeof(int));對 getsockopt(2) 的呼叫是類似的。 作為一種擴充套件而不是獨立的協議,所有從 UDP 已知的套接字選項都可以與以前完全相同的方式使用,例如 UDP_CORK 或 UDP_ENCAP。
UDP-Lite 校驗和覆蓋選項的詳細討論在第 IV 節中。
3. 標頭檔案¶
套接字 API 需要透過 /usr/include 中的標頭檔案提供支援
/usr/include/netinet/in.h 定義 IPPROTO_UDPLITE
/usr/include/netinet/udplite.h 用於 UDP-Lite 標頭欄位和協議常量
出於測試目的,以下內容可以用作
mini標頭檔案#define IPPROTO_UDPLITE 136 #define SOL_UDPLITE 136 #define UDPLITE_SEND_CSCOV 10 #define UDPLITE_RECV_CSCOV 11適用於各種發行版的現成標頭檔案位於 UDP-Lite tarball 中。
4. 核心關於各種套接字選項的行為¶
要啟用除錯訊息,需要將日誌級別設定為 8,因為大多數訊息都使用 KERN_DEBUG 級別 (7)。
傳送方套接字選項
如果傳送方指定值 0 作為覆蓋長度,則模組假定完全覆蓋,傳輸覆蓋長度為 0 且校驗和正確的資料包。 如果傳送方指定的覆蓋範圍 < 8 且與 0 不同,則核心假定 8 作為預設值。 最後,如果指定的覆蓋長度超過資料包長度,則使用資料包長度代替覆蓋長度。
接收方套接字選項
接收方指定它願意接受的覆蓋長度的最小值。 此處的值 0 表示接收方始終希望覆蓋整個資料包。 在這種情況下,所有部分覆蓋的資料包都將被丟棄並記錄錯誤。
無法指定非法值 (<0 和 <8);在這些情況下,假定預設值為 8。
所有覆蓋值小於指定閾值的資料包都將被丟棄,這些事件也會被記錄。
停用校驗和計算
在傳送方和接收方,始終會執行校驗和,並且無法使用 SO_NO_CHECK 停用。 因此
setsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, ... );將始終被忽略,而
getsockopt(sockfd, SOL_SOCKET, SO_NO_CHECK, &value, ...);的值沒有意義(如 TCP 中)。 校驗和欄位為零的資料包是非法的(參見 RFC 3828,第 3.1 節),並且將被靜默丟棄。
分片
校驗和計算遵循緩衝區大小和 MTU。 UDP-Lite 資料包的大小由傳送緩衝區的大小決定。 傳送緩衝區的最小大小為 2048(在 include/net/sock.h 中定義為 SOCK_MIN_SNDBUF),預設值可配置為 net.core.wmem_default 或透過設定 SO_SNDBUF socket(7) 選項。 傳送緩衝區的最大上限由 net.core.wmem_max 決定。
給定一個大於傳送緩衝區大小的有效負載大小,UDP-Lite 將有效負載分成幾個單獨的資料包,在每種情況下都填充發送緩衝區大小。
精確的值還取決於介面 MTU。 介面 MTU 反過來可能會觸發 IP 分片。 在這種情況下,生成的 UDP-Lite 資料包被分成幾個 IP 資料包,其中只有第一個包含 L4 標頭。
傳送緩衝區大小對校驗和覆蓋長度有影響。 考慮以下示例
Payload: 1536 bytes Send Buffer: 1024 bytes MTU: 1500 bytes Coverage Length: 856 bytesUDP-Lite 將在兩個單獨的資料包中運送 1536 位元組
Packet 1: 1024 payload + 8 byte header + 20 byte IP header = 1052 bytes Packet 2: 512 payload + 8 byte header + 20 byte IP header = 540 bytes覆蓋資料包覆蓋第一個資料包中的 UDP-Lite 標頭和 848 位元組的有效負載,第二個資料包完全覆蓋。 請注意,對於第二個資料包,覆蓋長度超過了資料包長度。 在這種情況下,核心始終會將覆蓋長度重新調整為資料包長度。
作為將一個 UDP-Lite 資料包分成幾個小片段時會發生什麼的一個例子,考慮以下示例
Payload: 1024 bytes Send buffer size: 1024 bytes MTU: 300 bytes Coverage length: 575 bytes +-+-----------+--------------+--------------+--------------+ |8| 272 | 280 | 280 | 280 | +-+-----------+--------------+--------------+--------------+ 280 560 840 1032 ^ *****checksum coverage*************UDP-Lite 模組生成一個 1032 位元組的資料包(1024 + 8 位元組標頭)。 根據介面 MTU,這些被分成 4 個 IP 資料包(280 位元組 IP 有效負載 + 20 位元組 IP 標頭)。 核心模組在將片段釋放到 IP 模組之前,對前兩個完整資料包的內容加上最後一個數據包的 15 個位元組求和。
要檢視 IPv6 分片的類似情況,請考慮連結 MTU 為 1280 位元組,寫入緩衝區為 3356 位元組。 如果校驗和覆蓋率小於 1232 位元組(MTU 減去 IPv6/片段標頭長度),則只需要考慮第一個片段。 使用更大的校驗和覆蓋長度時,需要對每個符合條件的片段進行校驗和。 假設我們的校驗和覆蓋率為 3062。3356 位元組的緩衝區將分成以下片段
Fragment 1: 1280 bytes carrying 1232 bytes of UDP-Lite data Fragment 2: 1280 bytes carrying 1232 bytes of UDP-Lite data Fragment 3: 948 bytes carrying 900 bytes of UDP-Lite data前兩個片段必須完全進行校驗和,最後一個片段只有 598 (= 3062 - 2*1232) 位元組進行校驗和。
雖然正確處理這些情況很重要,但它們(令人惱火地)很少見:UDP-Lite 旨在最佳化無線(或通常嘈雜的)鏈路上的多媒體效能,因此可能需要更小的覆蓋長度。
5. UDP-Lite 執行時統計資訊及其含義¶
異常和錯誤情況以 KERN_DEBUG 級別記錄到 syslog。 有關 UDP-Lite 的即時統計資訊可在 /proc/net/snmp 中找到,並且(使用較新版本的 netstat)可以使用以下命令檢視
netstat -svu這會顯示 UDP-Lite 統計變數,其含義如下。
InDatagrams
傳遞給使用者的總資料報數。
NoPorts
接收到未知埠的資料包數量。 這些情況是單獨計數的(不作為 InErrors)。
InErrors
錯誤 UDP-Lite 資料包的數量。 錯誤包括
內部套接字佇列接收錯誤
資料包太短(小於 8 個位元組或宣告的覆蓋長度超過接收到的長度)
xfrm4_policy_check() 返回錯誤
應用程式指定了比傳入資料包更大的最小覆蓋長度
校驗和覆蓋違反
錯誤的校驗和
OutDatagrams
傳送的資料報總數。
這些統計資料來自 UDP MIB(RFC 2013)。
6. IPtables¶
有針對 UDP-Lite 的資料包匹配支援以及對 LOG 目標的支援。 如果您將以下行復制並貼上到 /etc/protocols 中
udplite 136 UDP-Lite # UDP-Lite [RFC 3828]然後
iptables -A INPUT -p udplite -j LOG將生成到 syslog 的日誌輸出。 丟棄和拒絕資料包也有效。
7. 維護者地址¶
UDP-Lite 補丁是在以下地址開發的
University of Aberdeen Electronics Research Group Department of Engineering Fraser Noble Building Aberdeen AB24 3UE; UK
當前的維護者是 Gerrit Renker, <gerrit@erg.abdn.ac.uk>。 初始程式碼由 William Stanislaus, <william@erg.abdn.ac.uk> 開發。