第2章 IPv6 ICMPv6
在研究IPv6的頭部之前我們先對比一下IPv4的頭:
// IPv4 header in iphdr.h
ntypedef struct ip_hdr
n{
n unsigned char ip_verlen; // 4-bit IPv4 version
n // 4-bit header length (in 32-bit words)
n unsigned char ip_tos; // IP type of service
n unsigned short ip_totallength; // Total length
n unsigned short ip_id; // Unique identifier
n unsigned short ip_offset; // Fragment offset field
n unsigned char ip_ttl; // Time to live
n unsigned char ip_protocol; // Protocol(TCP,UDP etc)
n unsigned short ip_checksum; // IP checksum
n unsigned int ip_srcaddr; // Source address
n unsigned int ip_destaddr; // Source address
n} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;
n// IPv4 option header
ntypedef struct ipv4_option_hdr
n{
n unsigned char opt_code; // option type
n unsigned char opt_len; // length of the option header
n unsigned char opt_ptr; // offset into options
n unsigned long opt_addr[9]; // list of IPv4 addresses
n} IPV4_OPTION_HDR, *PIPV4_OPTION_HDR, FAR *LPIPV4_OPTION_HDR;
版本:4位長。記錄了數據報對應的協議版本號。當前的IP協議有兩個版本:IPV4 和IPV6。
nIHL:4位長。代表頭部的總長度,以32位爲一個單位。
n服務類型:8位長。使主機可以告訴子網它想要什麼樣的服務。如下圖所示,服務類型域又分爲了5個部分。優先權字段是標志優先級的;三個標志位分別代表延遲、吞吐量、可靠性。
n總長:16位。指頭部和數據的總長。最大長度是65535個字節。
n標識:16位。通過它使目的主機判斷新來的分段屬於哪個分組,所有屬於同一分組的分段包含同樣的標識值。
nDF:代表不要分段。它命令路由器不要將數據報分段,因爲目的端不能重組分段。
nMF:代表還有進一步的分段,用它來標志是否所有的分組都已到達。除了最後一個分段的所有分段都設置了這一位。
n分段偏移:13位。標明分段在當前數據報的什麼位置。
n生命期:8位。用來限制分組生命週期的計數器。它在每個節點中都遞減,而且當在一個路由器中排隊時可以倍數遞減。
n協議:8位。說明將分組發送給那個傳輸進程,如TCP、UDP等。
n頭校驗和:16位。僅用來校驗頭部。
n源地址: 32位。產生IP數據報的源主機IP地址。
n目的地址:32位。IP數據報的目的主機的IP地址。
n可選項:是變長的。每個可選項用一個字節標明內容。有些可選項還跟有一字節的可選項長度字段,其後是一個或多個數據字節。現在已定義了安全性、嚴格的源路由選擇、鬆的源路由選擇、記錄路由和時間標記五個可選項。但不是所有的路由器都支持全部5個可選項。
n
安全性選項說明瞭信息的安全程度。
ipv4頭部結構圖
再看下IPv6的頭:
n// IPv6 protocol header
ntypedef struct ipv6_hdr
n{
n unsigned long ipv6_vertcflow; // 4-bit IPv6 version
n // 8-bit traffic class
n // 20-bit flow label
n unsigned short ipv6_payloadlen; // payload length
n unsigned char ipv6_nexthdr; // next header protocol value
n unsigned char ipv6_hoplimit; // TTL
n struct in6_addr ipv6_srcaddr; // Source address
n struct in6_addr ipv6_destaddr; // Destination address
n} IPV6_HDR, *PIPV6_HDR, FAR * LPIPV6_HDR;
n// IPv6 fragment header
ntypedef struct ipv6_fragment_hdr
n{
n unsigned char ipv6_frag_nexthdr;
n unsigned char ipv6_frag_reserved;
n unsigned short ipv6_frag_offset;
n unsigned long ipv6_frag_id;
n} IPV6_FRAGMENT_HDR, *PIPV6_FRAGMENT_HDR, FAR * LPIPV6_FRAGMENT_HDR;
IPv6頭部結構圖
對比之下我們發現儘管這些頭字段中有一些與I P v 6頭類似,但其中真正完全保持不變的只有第一個字段,即版本字段,因爲在同一條線路上傳輸時,必須保證I P v 4和I P v 6的兼容性。下一個字段,即包頭長度,則與I P v 6無關,因爲I P v 6頭是固定長度,I P v 4中需要這個字段是因爲它的
包頭可能在2 0字節到4 0字節間變化。服務類型字段與I P v 6的流類別字段相似,但TOS的位置比該字段要靠後一些,而且在具體實現中也沒有廣泛應用。下一個字段是數據報長度,後來發展成了I P v 6中的淨荷長度。I P v 6的淨荷長度中包含了擴展頭,而I P v 4數據報長度字段中則指明包含
包頭在內的整個數據報的長度。這樣一來,在I P v 4中,路由器可以通過將數據報長度減去包頭長度來計算包的淨荷長度,而在I P v 6中則無須這種計算。
後面的三個字段是數據報I D、分段標志和分段偏移值,它們都用於I P v 4數據報的分段。 由於I P v 6中由源結點取代中間路由器來進行分段,這些字段在I P v 6中變得不重要,並被I P v 6從包頭中去掉了。
而生存期字段,正如上面所述,變成了跳極限字段。生存期字段最初表示的是一個包穿越I n t e r n e t時以秒爲單位的存在時間的上限。如果生存期計數值變爲0,該包將被丟棄。其原因是包可能會存在於循環路由中,如果沒有方法讓它消失,它可能會一直選路(或者直到網絡崩潰爲止)。在最初的規範中要求路由器根據轉發包的時間與收到包的時間的差值(以秒爲單位) 來減小生存期的值。在實際情況中,大部分路由器都設計爲每次對該值減1,而不是計算路由器上真正的處理時間。
協議字段,如前所述,指出在I P v 4包中封裝的高層協議類型。各協議對應的數值在最新版本的R F C (現在是RFC 1700)中可以查到。這個字段後來發展成爲I P v 6中的下一個頭字段,其中定義了下一個頭是一個擴展頭字段還是另一層的協議頭。
由於如T C P和U D P等高層協議均計算頭的校驗和, I P v 4頭校驗顯得有些多餘,因此這個字段在I P v 6中已消失。對於那些真的需要對內容進行身份驗證的應用, I P v 6中提供了身份驗證頭。
I P v 6中仍然保留了3 2位的I P v 4源地址和目的地址,但將它們擴展爲
1 2 8位。而I P選項字段則已經徹底消失,取而代之的是I P v 6擴展頭。
流標籤(flow label)
I P v 4通常被描述爲無連接協議。就像任何一個包交換網絡一樣, I P v 4設計爲讓每個包找到自己的路徑以到達其目的地。每個包都分別處理,而結果是兩個從相同數據源發往相同目的地的包可以採用完全不同的路由來穿越整個網絡。這對於適應網絡突發事件來說是個好辦法,因爲突發事件意味着任何一條路由都可能在任何時間出現故障,但只要兩主機間存在某些路由則可以進行數據的交互。
但是,這種方法的效率可能不太高,尤其是當包並不是孤立的,且實際上是兩個通信系統間的業務流的一部分時。進一步考慮一個包流從一臺主機發往另一主機時在它所經過的路徑上將發生的事情:每個中間路由器對每個包的處理將導致在鏈路上輕微地增加延時。對於類似文件傳輸或終端仿真之類的大部分傳統I n t e r n e t應用,延時只會帶來一點不方便而已,
但對於一些提供互操作的音頻和視頻應用而言,即使只是增加一點點延時也會顯著降低服務質量。
對每個I P v 4包均進行單獨處理帶來的另一個問題在於難以把特定的業務流指定到較低代價的鏈路上。例如,電子郵件的傳輸優先級不高,並且不是實時應用,但I P v 4網絡管理員卻沒有簡單的辦法來標識這些包,把它們傳輸到較低開銷的I n t e r n e t鏈路,並爲實時應用保留較高開銷的鏈路。
I P v 6中定義的流的概念將有助於解決類似問題。I P v 6頭字段中的流標籤把單個包作爲一系列源地址和目的地址相同的包流的一部分。同一個流中的所有包具有相同的流標籤。
擴展頭
I P v 4選項的問題在於改變了I P頭的大小,因此更像一個“特例”,即需要特別的處理。路由器必須優化其性能,這意味着將爲最普遍的包進行最佳性能的優化。這使得I P v 4選項引發一個路由器把包含該選項的包擱置一邊,等到有時間的時候再進行處理。I P v 6中實現的擴展頭可以消滅或至少大量減少選項帶來的對性能的衝擊。通過把選項從I P頭中搬到淨荷中,路由器可以像轉發無選項包一樣來轉發包含選項的包。除了規定必須由
每個轉發路由器進行處理的逐跳選項之外, I P v 6包中的選項對於中間路由器而言是不可見的。
可用的選項
除了減少I P v 6包轉發時選項的影響外, I P v 6規範使得對於新的擴展和選項的定義變得更加簡單。在需要的時候可能還會定義其他的選項和擴展。本節僅列出已定義的擴展,而對於擴展頭和選項的使用暫不介紹
IPv6 定義瞭如下選項擴展:
• 逐跳選項頭:此擴展頭必須緊隨在I P v 6頭之後。它包含包所經路徑上的每個節點都必須
檢查的選項數據。由於它需要每個中間路由器進行處理,逐跳選項只有在絕對必要的時
候纔會出現。到目前爲止,已經定義了兩個選項:巨型淨荷選項和路由器提示選項。巨
型淨荷選項指明包的淨荷長度超過I P v 6的1 6位淨荷長度字段。只要包的淨荷超過65 535
字節(其中包括逐跳選項頭),就必須包含該選項。如果節點不能轉發該包,則必須回送 一個I C M P v 6出錯報文。路由器提示選項用來通知路由器, I P v 6數據報中的信息希望能夠得到中間路由器的查看和處理,即使這個包是發給其他某個節點的(例如,包含帶寬預留協議信息的控制數據報)。
• 選路頭:此擴展頭指明包在到達目的地途中將經過哪些節點。它包含包沿途經過的各節點的地址列表。I P v 6頭的最初目的地址是路由頭的一系列地址中的第一個地址,而不是包的最終目的地址。此地址對應的節點接收到該包之後,對I P v 6頭和選路頭進行處理,並把包發送到選路頭列表中的第二個地址。如此繼續,直到包到達其最終目的地。
• 分段頭:此擴展頭包含一個分段偏移值、一個“更多段”標志和一個標識符字段。用於源節點對長度超出源端和目的端路徑M T U的包進行分段。
• 目的地選項頭:此擴展頭代替了I P v 4選項字段。目前,唯一定義的目的地選項是在需要時把選項填充爲6 4位的整數倍。此擴展頭可以用來攜帶由目的地節點檢查的信息。
• 身份驗證頭( A H ):此擴展頭提供了一種機制,對I P v 6頭、擴展頭和淨荷的某些部分進行加密的校驗和的計算。
• 封裝安全性淨荷( E S P )頭:這是最後一個擴展頭,不進行加密。它指明剩餘的淨荷已經加密,並爲已獲得授權的目的節點提供足夠的解密信息。
下面我們對比一下ICMPv4和ICMPv6:他們在頭文件中的描述如下
n// ICMPv4 header in iphdr.h
ntypedef struct icmp_hdr
n{
n unsigned char icmp_type;
n unsigned char icmp_code;
n unsigned short icmp_checksum;
n unsigned short icmp_id;
n unsigned short icmp_sequence;
n} ICMP_HDR, *PICMP_HDR, FAR *LPICMP_HDR;
n// ICMPv6 header
ntypedef struct icmpv6_hdr {
n unsigned char icmp6_type;
n unsigned char icmp6_code;
n unsigned short icmp6_checksum;
n} ICMPV6_HDR;
n// ICMPv6 echo request body
ntypedef struct icmpv6_echo_request
n{
n unsigned short icmp6_echo_id;
n unsigned short icmp6_echo_sequence;
n} ICMPV6_ECHO_REQUEST;
可以看出ICMPv6並沒有對ICMPv4的定義進行更改,只是將id和sequence獨立出來作爲另一個結構,當ICMP需要請求回送信息時將被填充
n