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