The class Packet defines the structure of a packet and provides member functions to handle a free list for objects of this type. It is illustrated in Figure 12.1 and defined as follows in packet.h:
class Packet : public Event { private: friend class PacketQueue; u_char* bits_; u_char* data_; /* variable size buffer for 'data' / u_int datalen_; /* length of variable size buffer / protected: static Packet* free_; public: Packet* next_; /* for queues and the free list / static int hdrlen_; Packet() : bits_(0), datalen_(0), next_(0) {} u_char* const bits() { return (bits_); } Packet* copy() const; static Packet* alloc(); static Packet* alloc(int); inline void allocdata(int); static void free(Packet*); inline u_char* access(int off) { if (off \< 0) abort(); return (&bits_[off]); } inline u_char* accessdata() { return data_; } };This class holds a pointer to a generic array of unsigned characters (commonly called the ``bag of bits'' or BOB for short) where packet header fields are stored. It also holds a pointer to packet ``data'' (which is often not used in simulations). The bits_ variable contains the address of the first byte of the BOB. Effectively BOB is (currently implemented as) a concatenation of all the structures defined for each packet header (by convention, the structures with names beginning hdr_something) that have been configured in. BOB generally remains a fixed size throughout a simulation, and the size is recorded in the Packet::hdrlen_ member variable. This size is updated during simulator configuration by OTcl12.1.
The other methods of the class Packet are for creating new packets and storing old (unused) ones on a private free list. Such allocation and deallocation is performed by the following code (in ~ns/packet.h):
inline Packet* Packet::alloc() { Packet* p = free_; if (p != 0) free_ = p-\>next_; else { p = new Packet; p-\>bits_ = new u_char[hdrsize_]; if (p == 0 || p-\>bits_ == 0) abort(); } return (p); } /* allocate a packet with an n byte data buffer */ inline Packet* Packet::alloc(int n) { Packet* p = alloc(); if (n \> 0) p-\>allocdata(n); return (p); } /* allocate an n byte data buffer to an existing packet */ inline void Packet::allocdata(int n) { datalen_ = n; data_ = new u_char[n]; if (data_ == 0) abort(); } inline void Packet::free(Packet* p) { p-\>next_ = free_; free_ = p; if (p-\>datalen_) { delete p-\>data_; p-\>datalen_ = 0; } } inline Packet* Packet::copy() const { Packet* p = alloc(); memcpy(p-\>bits(), bits_, hdrlen_); if (datalen_) { p-\>datalen_ = datalen_; p-\>data_ = new u_char[datalen_]; memcpy(p-\>data_, data_, datalen_); } return (p); }The []alloc method is a support function commonly used to create new packets. It is called by []Agent::allocpkt method on behalf of agents and is thus not normally invoked directly by most objects. It first attempts to locate an old packet on the free list and if this fails allocates a new one using the C++ new operator. Note that Packet class objects and BOBs are allocated separately. The []free method frees a packet by returning it to the free list. Note that packets are never returned to the system's memory allocator. Instead, they are stored on a free list when []Packet::free is called. The []copy member creates a new, identical copy of a packet with the exception of the uid_ field, which is unique. This function is used by Replicator objects to support multicast distribution and LANs.
Tom Henderson 2011-11-05