User talk:Nukejun

Packet
The Packet class represents Click packets. The single Packet interface has multiple implementations, one per driver. Inside the Linux kernel driver, a Packet object is equivalent to a Linux sk_buff structure; most Packet methods are inline functions that expand to sk_buff calls. The user-level driver, however, uses a purpose-built Packet implementation. Click packets separate header information from data. The Packet * pointer points to a header structure, which holds pointers to the actual packet data and a set of annotations. Packet data may be shared by two or more packet headers. Packet headers, however, should never be shared. Packets come in two flavors, Packet and WritablePacket. A Packet object represents a packet header whose data might be shared with other packets. Because of this potential sharing, Packet data is read-only, and its methods return const pointers to data. A WritablePacket object, in contrast, represents a packet header whose data is known not to be shared. Its methods return non-const pointers. The uniqueify method turns a Packet into a WritablePacket, possibly by making a copy of the packet's data. WritablePacket is a subclass of Packet, so you can turn a WritablePacket into a Packet implicitly. The Packet and WritablePacket classes are defined in .

Structure and Contents
Packet data is stored in a single flat array of bytes. There is no support for linked chains à la BSD mbuf. The actual packet data is embedded inside a buffer that may be much larger, leaving unused spaces called headroom and tailroom before and after the data proper. Therefore, tasks like prepending a header need not always reallocate memory. If the headroom is big enough, prepending space for a new header just requires bumping a pointer. This diagram shows how a typical packet is laid out, with the relevant Packet methods' names.

data |<- headroom ->|<- length ->|<- tailroom ->| |             |                    |              |             +==============+====================+==============+             |XXXXXXXXXXXXXX| PACKET CONTENTS... |XXXXXXXXXXXXXX| +==============+====================+==============+             |                                                  |             |< buffer_length ->| buffer_data

And here are those methods' descriptions.

const unsigned char * data const

Method on Packet Returns a pointer to the packet data proper.

 unsigned length  const  

Method on Packet Returns the length of the packet data proper.

 const unsigned char * buffer_data  const  

Method on Packet Returns a pointer to the buffer that contains the packet data.

 unsigned headroom  const

Method on Packet

 unsigned tailroom  const  

Method on Packet

 unsigned buffer_length  const  

Method on Packet Returns the length of the headroom area, the tailroom area, and the whole buffer, respectively.

 unsigned char * data  const  

Method on WritablePacket  unsigned char * buffer_data  const

Method on WritablePacket

These WritablePacket methods are identical to Packet's data and buffer_data methods except for their non-const return type.

Two invariants relate these methods' values:  buffer_length = headroom + length + tailroom  data = buffer_data + headroom

Creation and Destruction
Packets are created with the Packet::make static methods, and destroyed with the Packet::kill method. (The Packet and WritablePacket classes have private constructors and destructors; you cannot create or destroy packets with new or delete.)

Packet::make
The make methods always take the length of the packet data; some of them take the packet contents and the headroom and tailroom lengths as well. (The contents of any headroom and tailroom areas are always undefined.) Most of them return a WritablePacket *, since new packets are not shared. The Packet class defines two constants related to packet creation, DEFAULT_HEADROOM and MIN_BUFFER_LENGTH. Those make methods that do not take an explicit headroom parameter use DEFAULT_HEADROOM instead. Furthermore, no make method will create a packet with buffer length less than MIN_BUFFER_LENGTH. If the sum of a packet's headroom and length is less than this, the packet buffer is given extra tailroom to bump the buffer length up to MIN_BUFFER_LENGTH. These constants have the values DEFAULT_HEADROOM = 28 and MIN_BUFFER_LENGTH = 64.

WritablePacket * make (unsigned len) 

Static Method on Packet Returns a new packet containing len bytes of undefined data.

 WritablePacket * make (const char *data, unsigned len)  

Static Method on Packet

WritablePacket * make (const unsigned char *data, unsigned len)

Static Method on Packet

Returns a new packet whose contents equal the first len bytes of data. data may be a null pointer, in which case the packet contains len bytes of undefined data.

 WritablePacket * make (unsigned headroom, const unsigned char *data, unsigned len, unsigned tailroom) 

Static Method on Packet Returns a new packet containing headroom bytes of headroom, len bytes of contents, and at least tailroom bytes of tailroom. The packet contents will equal the first len bytes of data unless data is a null pointer, in which case the contents are undefined.

The following make method is only available in the user-level driver. WritablePacket * make (unsigned char *data, unsigned len, void (*destructor)(unsigned char *, size_t))

Static Method on Packet

Returns a new packet that uses data as a buffer. That is, the new packet will have the following characteristics:

buffer_data  data buffer_length  len headroom  0 length  len tailroom  0

When the resulting packet is destroyed, the function destructor will be called with data and len as arguments. destructor may be a null pointer, in which case Packet calls delete[] data instead. This method lets a user-level element manage packet memory itself, rather than relying on Packet. See Packets and sk_buffs, for a make method only available in the Linux kernel driver.

Packet::kill
To destroy a Packet, simply call its kill method.

void kill   Method on Packet

Frees this packet. If this packet contained the last reference to its data buffer, then frees the data buffer as well.

Packets and sk_buffs
In the Linux kernel driver, Packet objects are equivalent to struct sk_buffs. This avoids indirection overhead and makes it cheap to pass packets back and forth between Linux and Click. The Packet operations described in this section are mostly inline functions that expand to conventional sk_buff calls like skb_clone.

Click Packet sk_buffs should always have skb->users equal to 1. That is, the sk_buff headers should not be shared, although the data buffers they point to may be shared.

The make, skb, and steal_skb methods described in this section convert Packets to sk_buffs and vice versa.

Packet * make (struct sk_buff *skb)

Static Method on Packet

Returns a new packet equivalent to the sk_buff skb. All of skb's data pointers and annotations are left unchanged. This method generally does nothing, since Packets and sk_buffs are equivalent in the Linux kernel. However, if skb->users field is bigger than 1, the method will return a clone of skb. This method returns a Packet *, not a WritablePacket *, because the skb argument might share data with some other sk_buff.

Do not use or manipulate skb after passing it to this method, since Click and the Packet implementation now own skb.

 struct sk_buff * skb   

Method on Packet

const struct sk_buff * skb const

Method on Packet

Returns the sk_buff corresponding to this packet. Use this method to examine the sk_buff version of a Packet. Do not pass the result to a function that might free it or increment its users field; use steal_skb for that.

 struct sk_buff * steal_skb 

Method on Packet

Returns the sk_buff corresponding to this packet. Use this method to permanently change a Packet into an sk_buff--for example, to create an sk_buff you'd like to send to Linux.

Do not use or manipulate a Packet after calling its steal_skb method, since Linux now owns the resulting sk_buff.

Sharing--clone and uniqueify
The clone method creates a new packet header that shares data with an existing packet. The uniqueify method, in contrast, ensures that a packet's data is not shared by anyone, perhaps by making a copy of the data.

Packet * clone  

Method on Packet

Creates and returns a new packet header that shares this packet's data. The new packet's annotations are copied from this packet's annotations. The result may be a null pointer if there was not enough memory to make a new packet header.

 WritablePacket * uniqueify 

Method on Packet

Ensures that this packet does not share data with any other packet. This may involve copying the packet data, and perhaps creating a new packet header, but if this packet is already unshared, no real work is required. Returns a WritablePacket * because the new packet is unshared. Do not use, manipulate, or free a Packet after calling its uniqueify method. Manipulate the returned WritablePacket * instead. The result may be  a null pointer if there was not enough memory to make a required data copy. In this case, the old packet is freed.

 bool shared  const

Method on Packet

Returns true if and only if this packet shares data with some other packet.

Buffer Manipulation--push, pull, put, and take
The push, pull, put, and take methods manipulate a packet's contents by adding or removing space from its headroom or tailroom. Given a packet, use push to add space to its beginning, pull to remove space from its beginning, put to add space to its end, and take to remove space from its end. The methods that add space, push and put, uniqueify the relevant packet as a side effect. This ensures that the packet's data is unshared so you can immediately manipulate the added space.

WritablePacket * push (unsigned amt)

Method on Packet

Adds amt bytes of space to the beginning of the packet's data and returns the resulting packet. The new space is uninitialized. The result will not share data with any other packet; thus, it is a WritablePacket *. If this packet is unshared and its headroom is bigger than amt, then this operation is cheap, amounting to a bit of pointer arithmetic. Otherwise, it requires copying the packet data and possibly creating a new packet header.

Do not use, manipulate, or free a Packet after calling its push method. Manipulate the returned WritablePacket * instead. The result may be a null pointer if there was not enough memory to make a required new packet. In this case, the old packet is freed.

 void pull (unsigned amt)

Method on Packet

Removes amt bytes of space from the beginning of the packet's data. amt must be less than or equal to the packet's length . This operation is always cheap, amounting to a bit of pointer arithmetic.

 WritablePacket * put (unsigned amt)  

Method on Packet

Adds amt bytes of space to the end of the packet's data and returns the resulting packet. The new space is uninitialized. The result will not share data with any other packet; thus, it is a WritablePacket *. If this packet is unshared and its tailroom is bigger than amt, then this operation is cheap, amounting to   a bit of pointer arithmetic. Otherwise, it requires copying the packet data and possibly creating a new packet header.

Do not use, manipulate, or free a Packet after calling its put method. Manipulate the returned WritablePacket * instead. The result may be a null pointer if there was not enough memory to make a required new packet. In this case, the old packet is freed.

 void take (unsigned amt)  

Method on Packet

Removes amt bytes of space from the end of the packet's data. amt must be less than or equal to the packet's length. This operation is always cheap, amounting to a bit of pointer arithmetic. The push and put methods have "nonunique" variants, nonunique_push and nonunique_put, which do not have the side effect of   uniqueifying their resulting packet. These methods are rarely used.

Packet * nonunique_push (unsigned amt) 

Method on Packet

Adds amt bytes of space to the beginning of the packet's data and returns the resulting packet. The new space is     uninitialized. The result may share data with other packets. If this packet's  headroom is bigger than amt, then this operation is cheap, amounting to a bit of pointer arithmetic. Otherwise, it requires copying the packet data and possibly creating a new packet header. Do not use, manipulate, or free a Packet after calling its nonunique_push method. Manipulate the returned Packet * instead. The result may be a null pointer if there was not enough memory to make a required new packet. In this case, the old packet is freed.

 Packet * nonunique_put (unsigned amt) Method on Packet

Adds amt bytes of space to the end of the packet's data, returning the resulting packet. The new space is uninitialized. The result may share data with other packets. If this packet's tailroom is bigger than amt, then this operation is cheap, amounting to a bit of pointer arithmetic. Otherwise, it requires copying the packet data and possibly creating a new packet header. Do not use, manipulate, or free a Packet after calling its nonunique_put method. Manipulate the returned Packet * instead. The result may be a null pointer if there was not enough memory to make a required new packet. In this case, the old packet is freed.

Annotations
Each packet header has space for a number of annotations, extra information about the packet that is not contained in its data. Click supports header annotations, which indicate where in the packet a network header, such as an IP header, is located; user annotations, whose semantics are left undefined by Click--different elements can treat them in different ways; and other specialized annotations, such as the timestamp annotation, the destination IP address annotation, and so forth.

New packets begin with all annotations cleared: numeric annotations are zero, pointer annotations are null pointers. clone, uniqueify, and their equivalents always copy each of the original packet's annotations in the appropriate way. (For example, the new header annotations will point into the new data, if a data copy was made.)

Header Annotations
Many packets contain a network header of some kind, such as an IP header. This header may be located anywhere in the packet depending on how the packet was encapsulated. Furthermore, the data encapsulated by that network header may be located anywhere after the network header, given the presence of options. With the network header annotation and the transport header annotation, one element can determine where a network header is and how long it is, then store this information for other elements to use. For example, the CheckIPHeader element sets the header annotations on packets it receives. Elements like SetIPDSCP then require a non-null IP header annotation on their input packets.

The header annotations on new packets are each set to a null pointer.

const unsigned char * network_header const

Method on Packet

unsigned char * network_header const

Method on WritablePacket

Returns the network header annotation. The resulting pointer is read-only on Packets and read/write on WritablePackets.

 const unsigned char * transport_header  const  

Method on Packet

 unsigned char * transport_header  const  

Method on WritablePacket

Returns the transport header annotation. The resulting pointer is read-only on Packets and read/write on WritablePackets.

 int network_header_offset  const  

Method on Packet

Returns the offset from data to network_header. The result might be negative, since the data pointer may have been advanced past the network header annotation with the pull method.

 int network_header_length  const  

Method on Packet

Returns the network header's length. This equals transport_header - network_header.

 unsigned transport_header_offset  const  

Method on Packet

Returns the offset from data to transport_header. The result might be negative, since the data pointer may have been advanced past the transport header annotation with the pull method. Several invariants relate these methods' values whenever the header annotations are non-null: buffer_data <= network_header <= transport_header <= buffer_data + buffer_length network_header_offset = network_header - data transport_header_offset = transport_header - data network_header_length = transport_header - network_header

Set the network and transport header annotations simultaneously with the set_network_header method.

void set_network_header (const unsigned char *header, unsigned len) 

Method on Packet

Sets the network header annotation to header, which must lie between buffer_data and buffer_data + buffer_length. The network header is len bytes long, so network_header_length will equal len and transport_header will equal header + len.

Typed Header Annotations
For convenience, Packet provides methods for accessing and setting the network header annotation as an IP or IPv6 header. These methods use the same annotations as the generic network_header methods; they are just typed differently.

const click_ip * ip_header const  

Method on Packet

 click_ip * ip_header  const  

Method on WritablePacket

 const click_ip6 * ip6_header  const  

Method on Packet

 click_ip6 * ip6_header  const

Method on WritablePacket

Returns network_header as a pointer to an IP or IPv6 header structure.

 int ip_header_offset  const  

Method on Packet

 unsigned ip_header_length  const  

Method on Packet

 int ip6_header_offset  const  

Method on Packet

 unsigned ip6_header_length  const  

Method on Packet

Equivalent to network_header_offset and network_header_length.

 void set_ip_header (const click_ip *header, unsigned len)  

Method on Packet

 void set_ip6_header (const click_ip6 *header, unsigned len)  

Method on Packet

Equivalent to set_network_header(header, len).

 void set_ip6_header (const click_ip6 *header)  

Method on Packet

Equivalent to set_ip6_header(header, 40).

 const click_tcp * tcp_header  const  

Method on Packet

 click_tcp * tcp_header  const  

Method on WritablePacket

 const click_udp * udp_header  const  

Method on Packet

 click_udp * udp_header  const  

Method on WritablePacket

Returns transport_header as a pointer to a TCP or UDP header structure.

User Annotations
Each packet header has a user annotation area, space reserved for arbitrary annotations. Different methods access this space as an array of bytes, integers, or unsigned integers. The Packet class does not assign semantics to any particular byte in the user annotation area. Instead, macros in  provide names for particular bytes. Some of these names have overlapping byte ranges; the user must take care not to define a configuration whose elements use an annotation byte on a packet for different purposes. The next section describes the macros in Click's default . These constants define the size of the annotation area. Packet::USER_ANNO_SIZE The size of the annotation area in bytes. Packet::USER_ANNO_US_SIZE The size of the annotation area in unsigned shorts. Packet::USER_ANNO_S_SIZE The size of the annotation area in shorts. Packet::USER_ANNO_U_SIZE The size of the annotation area in unsigned ints. Packet::USER_ANNO_I_SIZE The size of the annotation area in ints. Currently, USER_ANNO_SIZE is 24, USER_ANNO_U_SIZE and USER_ANNO_I_SIZE are both 6, and USER_ANNO_US_SIZE and USER_ANNO_S_SIZE are both 12.

The user annotation area may be accessed as an array of bytes, an array of unsigned ints, or an array of ints. The elements of these arrays are numbered from 0 to k - 1, where k is the appropriate SIZE constant.

unsigned char user_anno_c (int i) const 

Method on Packet

Returns the ith byte in the user annotation area. i must be   between 0 and USER_ANNO_SIZE - 1.

 unsigned user_anno_u (int i)  

Method on Packet

 int user_anno_i (int i)  

Method on Packet

Returns the ith unsigned int or int in the user annotation area. i must be between 0 and USER_ANNO_U_SIZE - 1. The ith unsigned int or int annotation occupies bytes 4i through 4i + 3 of   the user annotation area.

void set_user_anno_c (int i, unsigned char value)   void set_user_anno_u (int i, unsigned value)   void set_user_anno_i (int i, int value)

Sets the ith byte, unsigned int, or int user annotation to value. unsigned * all_user_anno_u   Method on Packet Returns a pointer to the user annotation area, treated as an array of unsigned ints.

Specific User Annotations
The  header file defines macros for accessing a packet's user annotation area by name. These macros follow some simple guidelines. Each user annotation is given a name like PAINT or FIX_IP_SRC. Then, two macros are written for each annotation, name_ANNO and SET_name_ANNO.

name_ANNO (const Packet *p) 

Macro Returns the value of p's name annotation.

 SET_name_ANNO (Packet *p, value)  

Macro Sets p's name annotation to value.

For example, here are the definitions of PAINT_ANNO and SET_PAINT_ANNO from Click's default . #define PAINT_ANNO(p)         ((p)->user_anno_c(0)) #define SET_PAINT_ANNO(p, v)  ((p)->set_user_anno_c(0, (v)))

This table lists the annotations declared in Click's default .

Annotation name  Type   Bytes   Some relevant elements PAINT  unsigned char   0   Paint, CheckPaint, PaintTee ICMP_PARAM_PROB  unsigned char   1   IPGWOptions, ICMPError FIX_IP_SRC  unsigned char   3   ICMPError, FixIPSrc FWD_RATE  int   4-7   IPRateMonitor REV_RATE  int   8-11   IPRateMonitor

Other Annotations
Packet headers have space for four other particular annotations, and special methods for accessing them. These annotations do not overlap the user annotation area. There are annotations that hold a destination IP address, a timestamp, the device on which the packet arrived, a packet type constant, and, in the Linux kernel module, a performance counter value.

Destination Address
The destination address annotation stores the IP or IPv6 address of the next hop towards the packet's destination. Elements check and manipulate this address, rather than the IP header's destination address, since the next-hop address often differs from the final destination. The destination IP address and IPv6 address are different annotations, but they overlap; you may set only one at a time.

IPAddress dst_ip_anno const   Method on Packet

Returns this packet's destination IP address annotation.

 const IP6Address & dst_ip6_anno  const  

Method on Packet

Returns a reference to this packet's destination IPv6 address annotation.

 void set_dst_ip_anno (IPAddress value)  

Method on Packet

 void set_dst_ip6_anno (const IP6Address &value)  

Method on Packet

Sets this packet's destination IP or IPv6 address annotation to value. The destination IP address annotation is set by the GetIPAddress and SetIPAddress elements, manipulated by LookupIPRoute and its cousins, and used by ARPQuerier. It defaults to zero.

Timestamp
The timestamp annotation generally indicates when a packet was received.

const struct timeval & timestamp_anno const  

Method on Packet

 struct timeval & timestamp_anno   

Method on Packet

Returns a reference to this packet's timestamp annotation.

 void set_timestamp_anno (const struct timeval &value)  

Method on Packet

Sets this packet's timestamp annotation to value.

 void set_timestamp_anno (int sec, int usec)  

Method on Packet

Sets this packet's timestamp annotation to sec and usec. Equivalent to struct timeval tv; tv.tv_sec = sec; tv.tv_usec = \ usec; set_timestamp_anno(tv).

Linux device drivers set this annotation, so packets emitted by FromDevice and PollDevice in the Linux kernel driver have the annotation set. Packet sources like InfiniteSource and RatedSource also set the annotation, as does FromDump in the user-level driver. Debugging elements like Print generally take a keyword argument that makes them print packet timestamps. The timestamp annotation defaults to zero.

Device
In the Linux kernel, packets received from some device are annotated with a pointer to the relevant struct net_device object. (In versions of the kernel prior to 2.3, this type was called struct device.) The Packet class provides access to this annotation. The annotation has type net_device *; Click defines net_device as a synonym for struct device in kernel versions 2.2 and prior.

net_device * device_anno const  

Method on Packet

Returns this packet's device annotation.

 void set_device_anno (net_device *value)  

Method on Packet

Sets this packet's device annotation to value. In the user-level driver, device_anno always returns 0, and set_device_anno does nothing. The ARPResponder element sets this annotation on every generated response to the value of the annotation on the relevant query. Because of this, those responses can be safely forwarded to Linux: Linux's ARP-response code requires a correct device annotation. The device annotation defaults to a null pointer.

Packet Type
The packet type annotation specifies how a packet was received. Its value is one of the following constants, which are defined in the Packet::PacketType enumeration.

HOST The packet was sent to this host.

BROADCAST The packet was sent to a link-level broadcast address.

MULTICAST The packet was sent to a link-level multicast address.

OTHERHOST The packet was sent to a different host, but received anyway. The relevant device is probably in promiscuous mode.

OUTGOING The packet was generated at this host and is being sent to another host.

LOOPBACK, FASTROUTE See the Linux kernel documentation. These values correspond to PACKET_LOOPBACK and PACKET_FASTROUTE, which are defined in .  Packet::PacketType packet_type_anno const

Method on Packet

Returns this packet's packet type annotation.

 void set_packet_type_anno (Packet::PacketType value) 

Method on Packet

Sets this packet's packet type annotation to value. In the Linux kernel, device drivers set the packet type annotation for the packets they receive. Thus, the FromDevice and PollDevice elements generate packets with correct packet type annotations. The user-level driver's FromDevice also sets the packet type annotation. The ICMPError and DropBroadcasts elements use the annotation's value.

The packet type annotation defaults to Packet::HOST.

Performance Counter
This annotation is available only in the Linux kernel driver. Its value is an unsigned long long that generally corresponds to some performance counter value.

unsigned long long perfctr_anno const  

Method on Packet

Returns this packet's performance counter annotation.

 void set_perfctr_anno (unsigned long long value)  

Method on Packet

Sets this packet's performance counter annotation to value.

The SetCycleCount, SetPerfCount, CycleCountAccum, and PerfCountAccum elements manipulate this annotation. Its default value is zero.

Annotations In General
Packet provides methods for clearing a packet's annotations, and for copying all of a packet's annotations from another packet.

void clear_annotations 

Method on Packet

Clears all of this packet's annotations to their default state, which is generally zero.

 void copy_annotations (const Packet *p) 

Method on Packet

Copies all of p's annotations into this packet except for its header annotations. (This packet's current header annotations are left unchanged.)

Out-of-Memory Conditions
Any method that potentially allocates memory for a Packet may fail due to an out-of-memory condition. The complete list of these methods follows:

* make variants * clone * uniqueify * push * put * nonunique_push * nonunique_put

These methods always return a null pointer on out-of-memory. Methods that manipulate existing packets--uniqueify, push, put, nonunique_push, and nonunique_put--additionally free any existing packet before returning a null pointer. You should always check the results of these methods to see if you have run out of memory.