ns3 packet

refer

packet官網的module
packet doxygen

design

overview

  • 每個網絡數據包包含一個字節緩衝區,一組字節標籤,一組數據包標籤和元數據。
  • 開發人員通常希望將數據存儲在實際數據包中找不到的數據包對象中(例如時間戳或流ID)。Packet類通過存儲一組標籤(Tag類)來滿足此要求。

這些標籤有兩類用例,這導致了兩種不同類型的標籤。所謂的“byte”標籤用於標記分組字節緩衝區中字節的子集,而“packet”標籤用於標記分組本身。兩種標籤之間的主要區別是複製,分段和重新組合數據包時會發生什麼:“byte”標籤緊隨字節,而“packet”標籤緊隨數據包。這兩種標籤之間的另一個重要區別是byte標籤無法刪除,只能寫入一次並讀取多次,而packet標籤只能寫入一次,讀取多次,並刪除了一次。“byte”標籤的一個示例是FlowIdTag,其中包含流ID,由生成流量的應用程序設置。“packet”標籤的一個示例是由應用程序設置並由較低級別的MAC層處理的跨層QoS類ID。

header & trailer

  • Packet類旨在廉價複製。總體設計基於寫入時複製(COW)。當有多個對包對象的引用,並且其中有一個操作時,只有所謂的“髒”操作纔會觸發包的深層副本:
ns3::Packet::AddHeader()
ns3::Packet::AddTrailer()
both versions of ns3::Packet::AddAtEnd()
Packet::RemovePacketTag()
  • 用於添加和刪除字節緩衝區的基本類是Header和Trailer。Header更常見,但module裏面的討論也很大程度上適用於使用trailers的協議。

需要從Packet實例中插入和刪除的每個協議標頭都應從抽象Header基類派生並實現下面列出的私有純虛擬方法:

ns3::Header::SerializeTo()
ns3::Header::DeserializeFrom()
ns3::Header::GetSerializedSize()
ns3::Header::PrintTo()

前三個功能用於將協議控制信息串行化和反序列化到緩衝區或從緩衝區反序列化。例如,可以定義 class TCPHeader : public Header。TCPHeader對象通常由一些私有數據(如序列號)和公共接口訪問功能(如檢查輸入範圍)組成。但是,數據包緩衝區中TCPHeader的基本表示形式是20個序列化字節(加上TCP選項)。因此,TCPHeader :: SerializeTo()函數將被設計爲以網絡字節順序將這20個字節正確地寫入數據包。最後一個函數用於定義Header對象如何將自身打印到輸出流上。

或更多細節參見官網。

tag

  • 可以將用戶定義的標籤附加到數據包。與Header不同,標籤不會序列化到連續的緩衝區中,而是存儲在列表中。標籤可以靈活地定義爲任何類型,但是在任何時候標籤緩衝區中只能有一個特定對象類型的實例。

detail

  • ByteTag跟隨字節,而PacketTag跟隨數據包。這意味着在對數據包進行操作(例如分段,串聯以及附加或刪除標頭)時,字節標記會跟蹤它們所覆蓋的數據包字節。例如,如果用戶創建一個TCP段,並將ByteTag應用於該段,則將標記該TCP段的每個字節。但是,如果下一層插入IPv4標頭,則此ByteTag將不會覆蓋這些字節。Packet Tag則相反;儘管對其進行了操作,但它仍然覆蓋一個數據包。

  • PacketTag的大小限制爲20個字節。這是中的可修改編譯時常量src/network/model/packet-tag-list.h。ByteTag沒有這樣的限制。

  • 每種標籤類型都必須是ns3::Tag的子類,並且每種標籤類型中只能有一個實例。

  • 數據包標籤和字節標籤行爲上的​​一些差異。

    • 分段: 如上所述,當一個數據包被分段時,每個數據包分段(是一個新數據包)將獲得所有數據包標籤的副本,而字節標籤將遵循新的數據包邊界(即,如果分段的數據包跨緩衝區分段)字節標記所覆蓋的區域,兩個數據包片段仍將具有標記爲字節的適當緩衝區。
    • 串聯:將數據包合併後,兩個不同的緩衝區將變爲一個。對於字節標籤,字節標籤僅跟隨相應的緩衝區。對於數據包標籤,只有第一個數據包上的標籤才能在合併中倖存。
    • 查找和打印:這兩個類都允許您遍歷所有標籤並進行打印。
    • 刪除:用戶可以在單個數據包上多次添加和刪除相同的數據包標籤(AddPacketTag()和RemovePacketTag())。但是,一旦添加了字節標記,則只能通過從數據包中剝離所有字節標記將其刪除。當前API不支持刪除可能的多個字節標籤之一。
  • 從ns-3.5及更高版本開始,在調用Packet::Serialize ()和Packet::Deserialize ()時,Tag不會被序列化和反序列化到緩衝區 。這是一個open bug。

  • 如果用戶要獲取現有的數據包對象並將其用作新數據包,則他或她應先刪除所有字節標籤和數據包標籤,然後再這樣做。一個示例是UdpEchoServer類,該類接收接收到的數據包並“轉過來”以發送回回顯客戶端。

源碼閱讀與學習

  • FlowIdTag.cc
  • UdpEchoServer.cc
  • packet.cc
  • main-packet-tag.cc
  • 仿寫的時候要確定分片操作會怎麼辦

    packet tag會被複制

  • packet-list.cc

    設計得很有意思,有空讀一下他的設計模式

attention

一些細節注意

  • packet->GetSize()是把頭部(還有尾部)信息加進去的,但是不包括tag的字節數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章