理解NS2中Packet的包头

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;
     constchar*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;
         }
     }
     elseif (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方法设置这个数据包的偏移量,这样我们通过包头的头指针和偏移量就可以访问到指定的包头了。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值