【ACCESS精品源码栏目提醒】:网学会员为需要ACCESS精品源码的朋友们搜集整理了【精品】NS2.35源码分析报告 - 互联网相关资料,希望对各位网友有所帮助!
NS2-35 组件
源码分析之 分组(packet)
源码分析一、与分组相关的类图 与分组 packet 相关的类主要有四个:Packet、p_info、PacketHeaderClass、PacketHeaderManager。
二、分组 packet 的格式三、与分组 packet 相关类的框架1、Packet 类Packet 类简介: Packet 类定义了分组的结构bits_,hdrlen_等,提供了处理 Packet 对象的一系列成员函数alloc、copy、free等。
同时,packet 类维护了两个 Packet 对象的链表,一个是公有的,一个是私有的。
free_指针指向私有链表,该链表中存放着暂时不用的 Packet 对象,当需要分配一个分组时,首先查看 free_指向的链表,是否有不用的对象空间,如果有,就直接利用,如果没有,就从内存中申请一块空间。
Packet 定义: class Packet : public Event //公有继承 Event 类 private: unsigned char bits_ // 分组头集合的起始地址 AppData data_ // 指向分组数据的指针 static void initPacket // 初始化分组头 bool fflag_ //bool 型的变量 protected: static Packet free_ // 为 Packet 类所有对象共享的 free 链表 int ref_count_ // 用于分组被引用的次数,当为 0 时释放分组 public: Packet next_ // 用于连接队列中各分组的指针 static int hdrlen_ //分组头部长 Packet : bits_0 data_0 ref_count_0 next_0 //构造函数 inline unsigned char bits return bits_ //内联函数,用于返回分组头集合的起始地址 inline Packet copy const //创建一个分组的拷贝 inline Packet refcopy ref_count_ return this //引用拷贝 inline intamp ref_count return ref_count_ //用于返回 ref_count 的引用 static inline Packet alloc //创建新的分组 static inline Packet allocint //为一个分组分配 n 字节的数据空间 inline void allocdataint //为一个存在的分组分配 n 字节的数据空间 inline void initdata data_ 0 //初始化分组的数据部分 static inline void freePacket //将一个分组返回到空表中来释放一个分组 inline unsigned char accessint off const //返回相对于分组头 off 字节的分组头地址 if off lt 0 abort return ampbits_off //为了向后兼容,假定用户数据是 PacketData 类型数据,返回指向数据部分的指针 inline unsigned char accessdata const if data_ 0 return 0 assertdata_-gttype PACKET_DATA return PacketDatadata_-gtdata //用于使用特殊应用的数据,不仅仅限于 PacketData 类型的数据 inline AppData userdata const return data_ //设定数据部分 inline void setdataAppData d if data_ NULL delete data_ data_ d //返回数据部分的长度 inline int datalen const return data_ data_-gtsize : 0 // 输出分组头的信息 static void dump_headerPacket p int offset int length // PacketStamp 是一个类,携带了分组发往何处以及如何发送的信息,分组接收者用 这些信息来决定是否接收到了正确的分组 PacketStamp txinfo_ //MAC 层在收到的分组上设置的标志,这个标志随后被链路层清除 u_int8_t incoming成员函数的实现:1)initPacket p //初始化分组头 inline void Packet::initPacket p //bzero函数原型在文件 conf.h 中,为一个宏函数 //define bzerodestcount memsetdest0count //将分组头内存区域清零。
bzerop-gtbits_ hdrlen_ 2 alloc//创建新的分组 inline Packet Packet::alloc Packet p free_ if p 0 //若 free_指向的链表不为空,将利用该链表中的对象空间 assertp-gtfflag_ FALSE free_ p-gtnext_ assertp-gtdata_ 0 //p 指向的分组的数据部分为空,则继续往下执行,否则 整个程序将退出,并输出一条错误信息。
p-gtuid_ 0 p-gttime_ 0 else //free_指向的链表为空,想内存申请空间分配 p new Packet p-gtbits_ new unsigned charhdrlen_//分组空间与分组头空间独立分配内存 if p 0 p-gtbits_ 0 abort initp // 初始化 bits_ HDR_CMNp-gtnext_hop_ -2 // -1 reserved for IP_BROADCAST HDR_CMNp-gtlast_hop_ -2 // -1 reserved for IP_BROADCAST p-gtfflag_ TRUE //默认所有分组的方向都是向下的。
对应关系为:DOWN -1 NONE 0 UP 1 HDR_CMNp-gtdirection hdr_cmn::DOWN p-gtnext_ 0 return p 3 allocdataint n //为一个分组分配 n 字节的数据空间 inline void Packet::allocdataint n assertdata_ 0 data_ new PacketDatan if data_ 0 abort 4 allocint n //为一个分组分配 n 字节的数据空间 inline Packet Packet::allocint n Packet p alloc if n gt 0 p-gtallocdatan return p 5 freePacket p //释放一个分组 include quotdccp/dccp_packets.hquot //包含的文件 / DCCP 是 IETF 提 出取代 UDP 的新传 输协 议,用 来传 输实时 业务。
它是 一个 可以进 行拥塞 控制的 非可 靠传输 协议 ,并 同时 提供多 种拥塞 控制 机制 ,在 通信 开始时 由用户 进行协 商选 择。
除 预留 和自定 义方式 外, 目前 DCCP 定义了 两种 拥塞控 制机制 :TCP- Like 和 TFRC。
TCP-Like 类 似 TCP 的 AIMD 机制 ,而 TFRC 是 TCP 友好 的速 率控制 机制。
/ inline void Packet::freePacket p hdr_dccp dccph if p-gtfflag_ if p-gtref_count_ 0 //在丢弃的分组中释放 DCCP 选项 switch HDR_CMNp-gtptype_ case PT_DCCP: case PT_DCCP_REQ: case PT_DCCP_RESP: case PT_DCCP_ACK: case PT_DCCP_DATA: case PT_DCCP_DATAACK: case PT_DCCP_CLOSE: case PT_DCCP_CLOSEREQ: case PT_DCCP_RESET: dccph hdr_dccp::accessp if dccph-gtoptions_ NULL delete dccph-gtoptions_ break default: //一个分组的 uid 可能小于 0(已经被调度出事件队列)或者等于零 //(新建的但是从来没有进入事件队列) assertp-gtuid_ lt 0 // 删除用户数据 if p-gtdata_ 0 delete p-gtdata_ p-gtdata_ 0 initp p-gtnext_ free_//将不用的分组加入到 free_链表中 free_ p p-gtfflag_ FALSE else --p-gtref_count_ 6 copy//创建一个分组的拷贝 inline Packet Packet::copy const hdr_dccp dccph dccph_p Packet p alloc memcpyp-gtbits bits_ hdrlen_ //复制 DCCP 选项 switch HDR_CMNthis-gtptype_ case PT_DCCP: case PT_DCCP_REQ: case PT_DCCP_RESP: case PT_DCCP_ACK: case PT_DCCP_DATA: case PT_DCCP_DATAACK: case PT_DCCP_CLOSE: case PT_DCCP_CLOSEREQ: case PT_DCCP_RESET: dccph hdr_dccp::accessthis dccph_p hdr_dccp::accessp if dccph-gtoptions_ NULL dccph_p-gtoptions_ new DCCPOptionsdccph-gtoptions_ break default: if data_ //如果数据部分不为空,复制数据部分 p-gtdata_ data_-gtcopy p-gttxinfo_.initamptxinfo_ return p 7 dump_headerPacket p int offset int length //将头部信息输出到标准输出设备上面 inline void Packet::dump_headerPacket p int offset int length assertoffset length lt p-gthdrlen_ struct hdr_cmn ch HDR_CMNp fprintfstderr quotnPacket ID: dnquot ch-gtuid forint i 0 i lt length i16 fprintfstderrquot02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02x 02xnquot p-gtbits_offset i p-gtbits_offset i 1 p-gtbits_offset i 2 p-gtbits_offset i 3 p-gtbits_offset i 4 p-gtbits_offset i 5 p-gtbits_offset i 6 p-gtbits_offset i 7 p-gtbits_offset i 8 p-gtbits_offset i 9 p-gtbits_offset i 10 p-gtbits_offset i 11 p-gtbits_offset i 12 p-gtbits_offset i 13 p-gtbits_offset i 14 p-gtbits_offset i 15 2、common 分组头 Common 简介: 按照上面的分组的格式可知,每一个分组都有一个 common 分组头。
分组头定义 了很多字段,时间戳 ts_字段用于表示队列延迟,uid_字段用于确定分组的唯一标 识,size_字段表示分组的大小,等等。
Common 结构的定义: struct hdr_cmn enum dir_t DOWN -1 NONE 0 UP 1 //枚举类型定义了分组的方向 packet_t ptype_ // 分组的类型 int size_ // 模拟分组的大小 int uid_ // 分组的唯一标志符 int error_ // 错误标志 int errbitcnt_ // of corrupted bits jahn int fecsize_ double ts_ // 时间戳 int iface_ // 接收端口 dir_t direction_ // 分组方向: 0none 1up -1down char src_rt_valid // 源路由 double ts_arr_ // Required by Marker of JOBS nsaddr_t prev_hop_ // 分组的前一跳 IP 地址 nsaddr_t next_hop_ // 分组的下一跳 IP 地址 int addr_type_ // 下一跳 IP 类型 nsaddr_t last_hop_ // for tracing on multi-user channels ……………………………………….. 3、P_info 类 P_info 类的简介: P_info 类的功能是给定一个分组类型 packet_t,返回相应分组的字符串名。
分组类 型是一个短整型数 unsigned int。
每一个字符串名都对应一个 unsigned int 数。
当新增加 一种新分组类型时, 应将次分组类型增加到 packet_t 类型中,同时这个新分组类型的名 字应该加入到 P_info 类的构造函数中。
P_info 类的定义: class p_info public: p_info //构造函数 initName const char namepacket_t p const //返回类型对应的类型名 if p lt p_info::nPkt_ return name_p return 0 static bool data_packetpacket_t type //判断是不是数据分组 return type PT_TCP type PT_TELNET type PT_CBR type PT_AUDIO type PT_VIDEO type PT_ACK type PT_SCTP type PT_SCTP_APP1 type PT_HDLC static packetClass classifypacket_t type //将分组按类型归类 if type PT_DSR type PT_MESSAGE type PT_TORA type PT_PUMA type PT_AODV type PT_MDART return ROUTING //路由分组 if type PT_TCP type PT_TELNET type PT_CBR type PT_AUDIO type PT_VIDEO type PT_ACK type PT_SCTP type PT_SCTP_APP1 type PT_HDLC return DATApkt //数据分组 if pc_ return pc_-gtclassifytype return UNCLASSIFIED//unclassifiedstatic void addPacketClassifierPacketClassifier pc ifpc return pc-gtsetNextpc_ pc_ pcstatic void initName //初始化类型名 ifnPkt_ gt PT_NTYPE1 return char nameNew new charPT_NTYPE1 forunsigned int i unsigned intPT_SMAC1 i lt nPkt_ i nameNewi name_i ifnPkt_ delete name_ name_ nameNew nPkt_ PT_NTYPE1 // Link state routing updates //此处略去一些代码static int addPacketchar namestatic packet_t getTypeconst char name //根据类型名,返回对应的类型 forunsigned int i 0 i lt nPkt_ i ifstrcmpname name_i 0 return i return PT_NTYPE private: static char name_ static unsigned int nPkt_ static PacketClassifier pc_ 4、PacketHeaderClass PacketHeaderClass 简介: PacketHeaderClass 是各种分组头的基类,提供了足够的内部声明,用来定位任 意给定分组中分组头集合中的特定分组。
其中,hdrlen_是在构造函数中被设置, offset_则是通过调用 bind_offsest函数来设置的。
类的定义: class PacketHeaderClass : public TclClass protected: //构造函数,但是在.cc 文件中实现部分函数体为空实现 PacketHeaderClassconst char classname int hdrsize virtual int methodint argc const charconst argv void field_offsetconst char fieldname int offset inline void bind_offsetint off offset_ off inline void offsetint off offset_ off //设置偏移量 int hdrlen_ // 分组头长度 int offset_ // 分组头的偏移 public: virtual void bind virtual void export_offsets TclObject createint argc const charconst argv 成员函数实现: PacketHeaderClass::PacketHeaderClassconst char classname int hdrlen : TclClassclassname hdrlen_hdrlen offset_0 //空实现 TclObject PacketHeaderClass::createint const charconst return 0 void PacketHeaderClass::bind TclClass::bind Tclamp tcl Tcl::instance//获取一个这个实例的指针 tcl.evalfquots set hdrlen_ dquot classname_ hdrlen_//先格式化字符串,再执行 export_offsets add_methodquotoffsetquotvoid PacketHeaderClass::export_offsetsvoid PacketHeaderClass::field_offsetconst char fieldname int offset Tclamp tcl Tcl::instance//获取一个这个实例的指针 tcl.evalfquots set offset_s dquot classname_ fieldname offsetint PacketHeaderClass::methodint ac const charconst av Tclamp tcl Tcl::instance//获取一个这个实例的指针 int argc ac - 2 const charconst argv av 2 if argc 3 if strcmpargv1 quotoffsetquot 0 if offset_ offset_ atoiargv2 return TCL_OK tcl.resultfquotWarning: cannot set offset_ for squot classname_ return TCL_OK else if argc 2 if strcmpargv1 quotoffsetquot 0 if offset_ tcl.resultfquotdquot offset_ return TCL_OK return TclClass::methodac av5、PacketHeaderManager 类 PacketHeaderManager 类简介: PacketHeaderManager 类用来管理所有处于激活状态的分组头,并在 BOBbag of bit 比特包中分配给它们唯一的偏移量。
同时定义于 C和 Otcl 中。
PacketHeaderManager 类的定义: class PacketHeaderManager : public TclObject public: PacketHeaderManager bindquothdrlen_quot ampPack.