比治山日記

比治山スカイウォーカーです

ns-3でパケットのペイロードに対しデータを付加・取得する

NS-3でパケットに送信側でペイロードに独自データを付加して,受信側でそれを取得する方法についてのメモ.なおこの記事ではTCPソケットでパケットを送受信する想定です.

まず送信側で送るパケットのペイロードにメッセージを付加してパケットを生成・送信します.下の例ではstring文字列をuint8_tのポインタで保持してパケットのペイロードに付加しています.

std::ostringstream msg;
msg << "Hello, world!";
uint16_t packetSize = msg.str().length();
Ptr<Packet> packet = Create<Packet>((uint8_t *)msg.str().c_str(), packetSize);
m_socket->Send(packet);

受信側ではIPパケットの受信イベントを監視しておき,イベントが発生したら受信したパケットのペイロードからデータを取得します.

static void Rx(std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4,
               uint32_t interface) {
  Ptr<Packet> p = packet->Copy();

  Ipv4Header ipheader;
  TcpHeader tcpheader;
  p->RemoveHeader(ipheader);
  p->RemoveHeader(tcpheader);

  uint8_t *buffer = new uint8_t[p->GetSize()];
  p->CopyData(buffer, p->GetSize());
  std::string s = std::string(buffer, buffer + p->GetSize());
  std::cout << "Received:" << s << std::endl;
  delete buffer;
}

この例では

$ns3::Ipv4L3Protocol/Rx

をトレースしています.

ここでの注意は,受信側データを読むためには,送信したレイヤと同じレイヤまでパケットのヘッダを受信側で取り除く必要がある点です.今回はデータを付加したパケットをL4(TCP)レイヤで送信し,L3(IP)レイヤでパケットをトレースしているので,パケットからデータを読むにはIPヘッダとTCPヘッダを順に取り除きます.ですのでもしL2(MAC)レイヤでトレースしたのなら,まず該当するデータリンク層のヘッダから取り除く必要があります.