理解NS2中Packet的包头

理解NS2中Packet的包头

原帖:http://blog.csdn.net/lights_joy/archive/2007/08/16/1746949.aspx

 

 ns2中的数据包全部是由Packet进行表示的,当我们需要创建一个新的数据包时,就调用Packet::alloc方法,下面看看Packet::alloc都做了什么:

inline  Packet* Packet::alloc()
{
     Packet* p = free_;
     if (p != 0) {
         assert(p->fflag_ == FALSE);
         free_ = p->next_;
         assert(p->data_ == 0);
         p->uid_ = 0;
         p->time_ = 0;
     } else {
         p = new Packet;
         p->bits_ = new unsigned char[hdrlen_];
         if (p == 0 || p->bits_ == 0)
              abort();
     }
     init(p); // Initialize bits_[]
     (HDR_CMN(p))->next_hop_ = -2; // -1 reserved for IP_BROADCAST
     (HDR_CMN(p))->last_hop_ = -2; // -1 reserved for IP_BROADCAST
     p->fflag_ = TRUE;
     (HDR_CMN(p))->direction() = hdr_cmn::DOWN;
     /* setting all direction of pkts to be downward as default;
        until channel changes it to +1 (upward) */
     p->next_ = 0;
     return (p);
}
问题出现了,看这行
p->bits_ = new unsigned char[hdrlen_];
hdrlen_ 是从哪来的,在哪里初始化的?
在C++代码中一搜,发现了这样的语句:
     PacketHeaderManager() {
         bind("hdrlen_", &Packet::hdrlen_);
     }
原来Packet::hdrlen_被绑定到 PacketHeaderManager这个OTCL类了。
继续在tcl文件中搜索,发现了这样的一个函数:
PacketHeaderManager instproc allochdr cl {
     set size [$cl set hdrlen_]
 
     $self instvar hdrlen_
     set NS_ALIGN 8
     # round up to nearest NS_ALIGN bytes
     # (needed on sparc/solaris)
     set incr [expr ($size + ($NS_ALIGN-1)) & ~($NS_ALIGN-1)]
     set base $hdrlen_
     incr hdrlen_ $incr
 
     return $base
}
哈哈,原来 PacketHeaderManager每增加一个包头的定义,就把这个包头的长度加起来,难怪在NS2的文档中说要删除不必要的包头定义!!
再看看 allochdr 是由谁调用的?
Simulator instproc create_packetformat { } {
     PacketHeaderManager instvar tab_
     set pm [new PacketHeaderManager]
     foreach cl [PacketHeader info subclass] {
         if [info exists tab_($cl)] {
              set off [$pm allochdr $cl]
              $cl offset $off
         }
     }
     $self set packetManager_ $pm
}
清楚了吧,在创建Simulator时,它将把所有启动的数据包的包头长度加起来,因此文档中又说对数据包头的增删应该在Simulator创建之前,原因就在这里。
下一个问题, 如何访问指定包头中的数据?
在NS2中,每个不同的数据包都必须从PacketHeaderClass这个C++类继承一个子类,并在构造函数中调用PacketHeaderClass::bind_offset方法,看看这个函数做了什么:
inline  void bind_offset(int* off) { offset_ = off; }
就是保存了一个偏移量的指针而已,通常这个偏移量是存放在 hdr*::offset_中的。
PacketHeaderClass这个类还实现了一个叫做 offset的方法可以读取和设置偏移量。
int  PacketHeaderClass::method(int ac, const char*const* av)
{
     Tcl& tcl = Tcl::instance();
     int argc = ac - 2;
     const char*const* argv = av + 2;
     if (argc == 3) {
         if (strcmp(argv[1], "offset") == 0) {
              if (offset_) {
                   *offset_ = atoi(argv[2]);
                   return TCL_OK;
              }
              tcl.resultf("Warning: cannot set offset_ for %s",
                       classname_);
              return TCL_OK;
         }
     }
     else if (argc == 2) {
         if (strcmp(argv[1], "offset") == 0) {
              if (offset_) {
                   tcl.resultf("%d", *offset_);
                   return TCL_OK;
              }
         }
     }
     return TclClass::method(ac, av);
}
这样当在 OTCL中调用“offset ?大小?”时,这个指定的值就被保存到hdr*::offset_这个变量中了。
再看看上面的 create_packetformat方法,在这一行:
$cl offset $off
就调用了PacketHeaderClass的 offset方法设置这个数据包的偏移量,这样我们通过包头的头指针和偏移量就可以访问到指定的包头了。

 

 

 

 

《NS与网络模拟》学习8——分组头管理

转自http://elennatuzi.spaces.live.com/blog/cns!1A9FD94426AD53B!378.entry

 

 

 

 分组(Packet)是对象间交互的基本单元,由一系列分组头和一个可选的数据空间组成。分组头的结构在Simulator对象创建时就被初始化了,同时每个分组头相对于分组的起始地址的偏移量也被记录下来。

     用户可以为新的协议定义该协议自己的分组头,也可以通过增加域的方式扩展现有的分组头。假如我们想要增加一个叫newhdr的新的分组头,需要完成以下几个步骤:

1)在C++中创建一个名为hdr_newhdr的新的structure来定义所需要的字段,定义offset_字段和访问字段的方法。
2)定义所需要的访问其他字段的成员函数
3)创建一个叫做PacketHeader/Newhdr的static类来完成Otcl连接,在它的构造函数里进行bind_offset()。(PacketHeaderClass)
4)编辑~ns/tcl/lib/ns-packet.tcl来激活新的分组头(PacketHeaderManager)。另外也需修改~/ns/common/packet.h,来绑定分组类型值和它们的名字(p_info)。

     与分组相关的类概括起来有四个:Packet、p_info、PacketHeaderClass、PacketHeaderManager

1.Packet类定义了分组的结构(bits_,hdrlen_等),提供了处理Packet对象的一系列成员函数(alloc()、copy()、free()等)。

2.p_info类,用来绑定各个分组类型值和它们的名字。

  当定义新的分组类型后,数字代码应添加到枚举类型packet_t中,同时应添加到p_info类的构造函数中。注意,PT_NTYPE必须是最后一个。

3.PacketHeaderClass是各种分组头的基类。其中,hdrlen_是在构造函数中被设置,offset_则是通过调用bind_offsest()函数来设置的。

4.PacketHeaderManager类用来管理所有处于激活状态的分组头,并在BOB中分配给它们唯一的偏移量。同时定义于C++和Otcl中。

   模拟过程初始化时,ns-packet.tcl代码被执行。foreach循环中所有需要激活的分组头,通过调用add-packet-header来激活(Common头始终被激活)。create_packet_format{}被调用一次,它首先创建一个PacketHeaderManager对象,之后,对于被激活的分组头,由实例过程allochdr{}来给出分组头的位置。

   在Tcl中选择分组头的命令包括:remove-packet-header、remove-all-packet-header和add-packet-header。remove-packet-header必须在Simlator对象创建前执行。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值