在這一節講了IP協定的基本內容:包括IPv4提供的操作、資料包在IPv4下是怎麼樣的結構、資料包是怎樣切片傳送的、IPv4的編址方式有什麼……IPv6在下一節講網路層協定簇時細講。
IPv4協定的具體定義:RFC 791
按地址層級:
物理上的網路地址:區分物理介面,同一個區域網,一跳可達,用於在單個物理網路內路由PDU
網際網路地址:全球可達,地址數量跟介面數量相關,例如IP地址,用於在多個網路間路由PDU
應用層地址:程序地址,即埠
按地址範圍:
按定址方式:
IP的操作大體上可以被劃分為5種。
host和router都持有路由轉發表。轉發表指明瞭當前資料包要送達的下一個路由器,這個表既是靜態的——可能存在不同的路由路線,又是動態的——需要對擁塞和錯誤進行靈活響應;
路由需要用到的路由策略有:Distance vector
, Link state
, Path vector
。在這裡暫時不深入介紹;
傳送方可以指定路由為要遵循的路由器的順序列表;
路由器可以做到路由記錄。
資料包可能會因為環路而一直在傳播,同時route需要基於先前的網路資訊進行,還有TCP也需要基於資料包的生存週期來決定執行方式;所以我們需要設定資料包在網路中的生存週期——TTL(Time To Live)。
最簡單的TTL有hop count
(根據跳數來計時)。
PS:下面有詳細的介紹。
當資料包的長度超過了MTU(最大傳輸unit)時,需要對資料包進行切片傳送,以及切片到達目的地時進行重組。早期做法為不做全球控制,讓路由器有分片功能,切了就傳送。
處理分片重組出錯:利用重組超時機制,或者每個分片都加上一個TTL。
不監測傳播過程。由於checksum檢查或者TTL expired等事件發生,路由器需要通知src資料包「去了資料包天國」;用ICMP來返回錯誤資訊,src的I網路層收到資訊後同時需要通知高層。
流控使路由器可以控制資料流入速率。路由器buffer滿了路由器就丟棄新進來的包,同時給src傳送」停止「通知(用ICMP)。
IPv4有很多blog都幫忙精讀過了,所以也不在這寫太多生產資料垃圾……想要仔細研究的話可以去看RFC 791原文,在這裡中貼一點簡要的圖例,給自己簡單覆盤用:
在這裡要注意的是,資料包在IPv4下的最大長度為65535個位元組,包括頭部欄位和資料欄位。
並不是所有的鏈路層協定都能承載相同長度的網路層packet,有的協定能承載很大的資料包,有的則很小,如乙太網幀最大位元長度為1500位元組,而有的只能到576位元組,這個最大承載資料量用最大傳輸單元MTU來表示。
所以MTU大大限制了上一層網路層datagram
的長度。當路由器中某條出鏈路的MTU比當前要轉發的IP datagram
小時,IP datagram
是無法一次性在這條出鏈路上成功傳輸的。解決辦法就是把該IP datagram
切片成多個小資料包,再經過鏈路層封裝後進行傳輸。切片後的資料包被稱為fragment
。
各個fragment
送達destination後需要重新組裝成原來的datagram
,組裝必須在datagram送到傳輸層前完成。
如果不在destination進行組裝而是在路由器進行,會對路由器產生極大的負擔,而且後面還有可能需要繼續切片,複雜性極大。
組裝任務通過識別IP datagram
中的三個欄位來完成:identification
、flags
、fragment offset
。
identification
即標識號,是在host生成datagram時貼上去的,每生成一個值就加一,protocal
、src addr
、dest addr
、identification
四個欄位共同確定一個獨一無二的datagram。
flags
即標誌位,由於IP服務是「盡力而為」的,所以不能確保所有fragment都能到達目的地;要讓目的地確定接收已經完成(即使fragment沒有全部到達,也要有一個機制讓host確定已經收到了最後的一個fragment,結束漫長的等待),就將最後一個fragment的flags
的MF位置為1,其餘fragment的MF位為0。
fragment offset
即偏移欄位,可以用來確定該fragment在原來的datagram的哪個位置,同時讓dest host確定是否丟失了fragment。
一個直觀的圖例如下:
PS:有一個有意思的小問題:fragment再被切片會怎麼樣?
RFC 791對fragmentation操作的原文。
IP地址長度32位元,可以劃分為network部分和host部分(劃分標準是不定的,看你劃在第幾位);在地址的分配上,是一個鏈路介面與一個IP地址相關聯,而不是一個host或一個路由器。
在圖中我們可以看到有三個「子網」,要注意的是子網含有的不只有host,還有路由器的介面,這其實意味著子網是按照介面來分的。RFC950中寫了對「子網」(subnet
)的定義:Internet Standard Subnetting Procedure。在這裡,我們引入子網掩碼(subnet mask
)的概念。像綠色部分的子網,它的子網地址就是223.1.1.0/24,其中的24就是子網掩碼,指示了高24位元是network部分,是屬於網路地址。
上週有一篇博文做了對IP編址的一些總結,就放在這裡:20張圖說清楚 IP 協定 ;裡面講了早期IP地址分配策略,包括classful addressing(分類編制方式)和現在使用的CIDR(無類別域間路由選擇)。
在CIDR分配策略中,子網定址的概念被一般化:IP地址由子網掩碼被劃分成兩個部分,形式為a.b.c.d/x
,其中x
指示了地址中的最高x
位為network部分,也被稱為字首prefix
。
一個ISP可以被看成一組子網的集合——它可以給使用它服務的企業、高校等劃分Intranet,這個過程被稱為Hierarchical addressing
(分層編址)。如下圖所示:ISP手持最大的20位子網,然後剩下的12位元可以供它任意分配,於是它又把20~23位分給了8個組織,組織可以利用後面的9位host部分自由分配給組織裡面的主機。
採用CIDR的好處就是可以很方便地實現路由聚合。由於子網內部的host通常被分配一塊連續的地址,即字首相同,則當路由器轉發一個datagram進來時,在轉發表中就像上一節說的那樣,僅僅需要考慮prefix即可。
要注意的是,後面的
32-x
位為host部分,這部分並不是有2^(32-x)
個地址可以用——需要留出全0的地址作為子網地址,還有全1的地址用來做廣播地址。
分類編址方案將IP地址分為五類,詳細的已有前人總結(上面的連結),在這裡只放一些圖示,用來給自己快速覆盤:
A類地址:目前已經被全部瓜分
PS:A類地址中有一個很重要的迴環地址:127.0.0.1,這裡有較為詳細的介紹。
B類地址:同樣也被全部瓜分^^
C類地址:接近瓜分完畢
其實分類編制方案也可以用子網掩碼的視角看待,如下圖: