📄 packet.hh
字号:
if (m_pulldown(m, 0, m->m_pkthdr.len, NULL) == NULL) panic("m_pulldown failed"); } p->_m = m; assimilate_mbuf(p); return p;}#endif/** @brief Test whether this packet's data is shared. * * Returns true iff the packet's data is shared. If shared() is false, then * the result of uniqueify() will equal @c this. */inline boolPacket::shared() const{#if CLICK_LINUXMODULE return skb_cloned(const_cast<struct sk_buff *>(skb()));#else return (_data_packet || _use_count > 1);#endif}/** @brief Return an unshared packet containing this packet's data. * @return the unshared packet, which is writable * * The returned packet's data is unshared with any other packet, so it's safe * to write the data. If shared() is false, this operation simply returns the * input packet. If shared() is true, uniqueify() makes a copy of the data. * The input packet is freed if the copy fails. * * The returned WritablePacket pointer may not equal the input Packet pointer, * so do not use the input pointer after the uniqueify() call. * * The input packet's headroom and tailroom areas are copied in addition to * its true contents. The header annotations are shifted to point into the * new packet data if necessary. * * uniqueify() is usually used like this: * @code * WritablePacket *q = p->uniqueify(); * if (!q) * return 0; * // p must not be used here. * @endcode */inline WritablePacket *Packet::uniqueify(){ if (!shared()) return static_cast<WritablePacket *>(this); else return expensive_uniqueify(0, 0, true);}inline WritablePacket *Packet::push(uint32_t len){ if (headroom() >= len && !shared()) { WritablePacket *q = (WritablePacket *)this;#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_push(q->skb(), len);#else /* User-space and BSD kernel module */ q->_data -= len;# if CLICK_BSDMODULE q->m()->m_data -= len; q->m()->m_len += len; q->m()->m_pkthdr.len += len;# endif#endif return q; } else return expensive_push(len);}inline Packet *Packet::nonunique_push(uint32_t len){ if (headroom() >= len) {#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_push(skb(), len);#else /* User-space and BSD kernel module */ _data -= len;# if CLICK_BSDMODULE m()->m_data -= len; m()->m_len += len; m()->m_pkthdr.len += len;# endif#endif return this; } else return expensive_push(len);}inline voidPacket::pull(uint32_t len){ if (len > length()) { click_chatter("Packet::pull %d > length %d\n", len, length()); len = length(); }#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_pull(skb(), len);#else /* User-space and BSD kernel module */ _data += len;# if CLICK_BSDMODULE m()->m_data += len; m()->m_len -= len; m()->m_pkthdr.len -= len;# endif#endif}inline WritablePacket *Packet::put(uint32_t len){ if (tailroom() >= len && !shared()) { WritablePacket *q = (WritablePacket *)this;#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_put(q->skb(), len);#else /* User-space and BSD kernel module */ q->_tail += len;# if CLICK_BSDMODULE q->m()->m_len += len; q->m()->m_pkthdr.len += len;# endif#endif return q; } else return expensive_put(len);}inline Packet *Packet::nonunique_put(uint32_t len){ if (tailroom() >= len) {#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_put(skb(), len);#else /* User-space and BSD kernel module */ _tail += len;# if CLICK_BSDMODULE m()->m_len += len; m()->m_pkthdr.len += len;# endif#endif return this; } else return expensive_put(len);}inline voidPacket::take(uint32_t len){ if (len > length()) { click_chatter("Packet::take %d > length %d\n", len, length()); len = length(); }#if CLICK_LINUXMODULE /* Linux kernel module */ skb()->tail -= len; skb()->len -= len;#else /* User-space and BSD kernel module */ _tail -= len;# if CLICK_BSDMODULE m()->m_len -= len; m()->m_pkthdr.len -= len;# endif#endif}#if CLICK_USERLEVEL/** @brief Shrink the packet's data. * @param data new data pointer * @param length new length * * @warning This function is useful only in special contexts. * @note Only available at user level * * User-level programs that read packet logs commonly read a large chunk of * data (32 kB or more) into a base Packet object. The log reader then works * over the data buffer and, for each packet contained therein, outputs a * clone that shares memory with the base packet. This is space- and * time-efficient, but the generated packets have gigantic headroom and * tailroom. Uniqueifying a generated packet will wastefully copy this * headroom and tailroom as well. The shrink_data function addresses this * problem. * * shrink_data() removes all of a packet's headroom and tailroom. The * resulting packet has data() equal to @a data, length() equal to @a length, * and headroom() and tailroom() equal to zero. * * @pre The packet @em must be a clone() of another existing packet. * @pre @a data >= data(), @a data <= end_data(), @a data + @a length >= * data(), and @a data + @a length <= end_data() * * @sa change_headroom_and_length */inline voidPacket::shrink_data(const unsigned char *data, uint32_t length){ assert(_data_packet); if (data >= _head && data + length >= data && data + length <= _end) { _head = _data = const_cast<unsigned char *>(data); _tail = _end = const_cast<unsigned char *>(data + length); }}/** @brief Shift the packet's data view to a different part of its buffer. * @param headroom new headroom * @param length new length * * @warning This function is useful only in special contexts. * @note Only available at user level * * Shifts the packet's data() pointer to a different part of the packet's data * buffer. The buffer pointer itself is not changed, and the packet's * contents are not affected (except by the new view). * * @pre @a headroom + @a length <= buffer_length() * @post new buffer() == old buffer() * @post new end_buffer() == old end_buffer() * @post new headroom() == @a headroom * @post new length() == @a length * * @sa shrink_data */inline voidPacket::change_headroom_and_length(uint32_t headroom, uint32_t length){ if (headroom + length <= buffer_length()) { _data = _head + headroom; _tail = _data + length; }}#endifinline IPAddressPacket::dst_ip_anno() const{ return IPAddress(xanno()->u32[dst_ip_anno_offset / 4]);}inline voidPacket::set_dst_ip_anno(IPAddress a){ xanno()->u32[dst_ip_anno_offset / 4] = a.addr();}/** @brief Set the MAC header pointer. * @param p new header pointer */inline voidPacket::set_mac_header(const unsigned char *p){ assert(p >= buffer() && p <= end_buffer());#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb_set_mac_header(skb(), p - data());# else skb()->mac.raw = const_cast<unsigned char *>(p);# endif#else /* User-space and BSD kernel module */ _mac = const_cast<unsigned char *>(p);#endif}/** @brief Set the MAC and network header pointers. * @param p new MAC header pointer * @param len new MAC header length * @post mac_header() == @a p and network_header() == @a p + @a len */inline voidPacket::set_mac_header(const unsigned char *p, uint32_t len){ assert(p >= buffer() && p + len <= end_buffer());#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb_set_mac_header(skb(), p - data()); skb_set_network_header(skb(), (p + len) - data());# else skb()->mac.raw = const_cast<unsigned char *>(p); skb()->nh.raw = const_cast<unsigned char *>(p) + len;# endif#else /* User-space and BSD kernel module */ _mac = const_cast<unsigned char *>(p); _nh = const_cast<unsigned char *>(p) + len;#endif}/** @brief Set the MAC header pointer to an Ethernet header. * @param ethh new Ethernet header pointer * @post (void *) mac_header() == (void *) @a ethh * @post mac_header_length() == 14 * @post (void *) network_header() == (void *) (@a ethh + 1) */inline voidPacket::set_ether_header(const click_ether *ethh){ set_mac_header(reinterpret_cast<const unsigned char *>(ethh), 14);}/** @brief Unset the MAC header pointer. * @post has_mac_header() == false * Does not affect the network or transport header pointers. */inline voidPacket::clear_mac_header(){#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET skb()->mac_header = ~0U;# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb()->mac_header = 0;# else skb()->mac.raw = 0;# endif#else /* User-space and BSD kernel module */ _mac = 0;#endif}inline WritablePacket *Packet::push_mac_header(uint32_t len){ WritablePacket *q; if (headroom() >= len && !shared()) { q = (WritablePacket *)this;#if CLICK_LINUXMODULE /* Linux kernel module */ __skb_push(q->skb(), len);#else /* User-space and BSD kernel module */ q->_data -= len;# if CLICK_BSDMODULE q->m()->m_data -= len; q->m()->m_len += len; q->m()->m_pkthdr.len += len;# endif#endif } else if ((q = expensive_push(len))) /* nada */; else return 0; q->set_mac_header(q->data(), len); return q;}/** @brief Set the network and transport header pointers. * @param p new network header pointer * @param len new network header length * @post network_header() == @a p and transport_header() == @a p + @a len */inline voidPacket::set_network_header(const unsigned char *p, uint32_t len){ assert(p >= buffer() && p + len <= end_buffer());#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb_set_network_header(skb(), p - data()); skb_set_transport_header(skb(), (p + len) - data());# else skb()->nh.raw = const_cast<unsigned char *>(p); skb()->h.raw = const_cast<unsigned char *>(p) + len;# endif#else /* User-space and BSD kernel module */ _nh = const_cast<unsigned char *>(p); _h = const_cast<unsigned char *>(p) + len;#endif}/** @brief Set the network header length. * @param len new network header length * * Setting the network header length really just sets the transport header * pointer. * @post transport_header() == network_header() + @a len */inline voidPacket::set_network_header_length(uint32_t len){ assert(network_header() + len <= end_buffer());#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb_set_transport_header(skb(), (network_header() + len) - data());# else skb()->h.raw = skb()->nh.raw + len;# endif#else /* User-space and BSD kernel module */ _h = _nh + len;#endif}/** @brief Set the network header pointer to an IPv4 header. * @param iph new IP header pointer * @param len new IP header length in bytes * @post (char *) network_header() == (char *) @a iph * @post network_header_length() == @a len * @post (char *) transport_header() == (char *) @a iph + @a len */inline voidPacket::set_ip_header(const click_ip *iph, uint32_t len){ set_network_header(reinterpret_cast<const unsigned char *>(iph), len);}/** @brief Set the network header pointer to an IPv6 header. * @param ip6h new IP header pointer * @param len new IP header length in bytes * @post (char *) network_header() == (char *) @a ip6h * @post network_header_length() == @a len * @post (char *) transport_header() == (char *) @a ip6h + @a len */inline voidPacket::set_ip6_header(const click_ip6 *ip6h, uint32_t len){ set_network_header(reinterpret_cast<const unsigned char *>(ip6h), len);}/** @brief Set the network header pointer to an IPv6 header. * @param ip6h new IP header pointer * @post (char *) network_header() == (char *) @a ip6h * @post network_header_length() == 40 * @post (char *) transport_header() == (char *) (@a ip6h + 1) */inline voidPacket::set_ip6_header(const click_ip6 *ip6h){ set_ip6_header(ip6h, 40);}/** @brief Unset the network header pointer. * @post has_network_header() == false * Does not affect the MAC or transport header pointers. */inline voidPacket::clear_network_header(){#if CLICK_LINUXMODULE /* Linux kernel module */# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET skb()->network_header = ~0U;# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb()->network_header = 0;# else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -