📄 packet.hh
字号:
// -*- related-file-name: "../../lib/packet.cc" -*-#ifndef CLICK_PACKET_HH#define CLICK_PACKET_HH#include <click/ipaddress.hh>#include <click/glue.hh>#include <click/timestamp.hh>#if CLICK_LINUXMODULE# include <click/skbmgr.hh>#else# include <click/atomic.hh>#endifstruct click_ether;struct click_ip;struct click_icmp;struct click_ip6;struct click_tcp;struct click_udp;#if CLICK_NS# include <click/simclick.h>#endifCLICK_DECLSclass IP6Address;class WritablePacket;class Packet { public: /** @name Data */ //@{ // PACKET CREATION enum { default_headroom = 28, ///< Default packet headroom() for /// Packet::make(). 4-byte aligned. min_buffer_length = 64 ///< Minimum buffer_length() for /// Packet::make() }; static WritablePacket *make(uint32_t headroom, const void *data, uint32_t length, uint32_t tailroom) CLICK_WARN_UNUSED_RESULT; static inline WritablePacket *make(const void *data, uint32_t length) CLICK_WARN_UNUSED_RESULT; static inline WritablePacket *make(uint32_t length) CLICK_WARN_UNUSED_RESULT;#if CLICK_LINUXMODULE static Packet *make(struct sk_buff *skb) CLICK_WARN_UNUSED_RESULT;#endif#if CLICK_BSDMODULE // Packet::make(mbuf *) wraps a Packet around an existing mbuf. // Packet now owns the mbuf. static inline Packet *make(struct mbuf *mbuf) CLICK_WARN_UNUSED_RESULT;#endif#if CLICK_USERLEVEL static WritablePacket *make(unsigned char *data, uint32_t length, void (*destructor)(unsigned char *, size_t)) CLICK_WARN_UNUSED_RESULT;#endif inline void kill(); inline bool shared() const; Packet *clone() CLICK_WARN_UNUSED_RESULT; inline WritablePacket *uniqueify() CLICK_WARN_UNUSED_RESULT; inline const unsigned char *data() const; inline const unsigned char *end_data() const; inline uint32_t length() const; inline uint32_t headroom() const; inline uint32_t tailroom() const; inline const unsigned char *buffer() const; inline const unsigned char *end_buffer() const; inline uint32_t buffer_length() const;#if CLICK_LINUXMODULE struct sk_buff *skb() { return (struct sk_buff *)this; } const struct sk_buff *skb() const { return (const struct sk_buff*)this; }#elif CLICK_BSDMODULE struct mbuf *m() { return _m; } const struct mbuf *m() const { return (const struct mbuf *)_m; } struct mbuf *steal_m();#endif /** @brief Add space for a header before the packet. * @param len amount of space to add * @return packet with added header space, or null on failure * * Returns a packet with an additional @a len bytes of uninitialized space * before the current packet's data(). A copy of the packet data is made * if there isn't enough headroom() in the current packet, or if the * current packet is shared(). If no copy is made, this operation is * quite efficient. * * If a data copy would be required, but the copy fails because of lack of * memory, then the current packet is freed. * * push() is usually used like this: * @code * WritablePacket *q = p->push(14); * if (!q) * return 0; * // p must not be used here. * @endcode * * @post new length() == old length() + @a len (if no failure) * * @sa nonunique_push, push_mac_header, pull */ WritablePacket *push(uint32_t len) CLICK_WARN_UNUSED_RESULT; /** @brief Add space for a MAC header before the packet. * @param len amount of space to add and length of MAC header * @return packet with added header space, or null on failure * * Combines the action of push() and set_mac_header(). @a len bytes are * pushed for a MAC header, and on success, the packet's returned MAC and * network header pointers are set as by set_mac_header(data(), @a len). * * @sa push */ WritablePacket *push_mac_header(uint32_t len) CLICK_WARN_UNUSED_RESULT; /** @brief Add space for a header before the packet. * @param len amount of space to add * @return packet with added header space, or null on failure * * This is a variant of push(). Returns a packet with an additional @a * len bytes of uninitialized space before the current packet's data(). A * copy of the packet data is made if there isn't enough headroom() in the * current packet. However, no copy is made if the current packet is * shared; and if no copy is made, this operation is quite efficient. * * If a data copy would be required, but the copy fails because of lack of * memory, then the current packet is freed. * * @note Unlike push(), nonunique_push() returns a Packet object, which * has non-writable data. * * @sa push */ Packet *nonunique_push(uint32_t len) CLICK_WARN_UNUSED_RESULT; /** @brief Remove a header from the front of the packet. * @param len amount of space to remove * * Removes @a len bytes from the initial part of the packet, usually * corresponding to some network header (for example, pull(14) removes an * Ethernet header). This operation is efficient: it just bumps a * pointer. * * It is an error to attempt to pull more than length() bytes. * * @post new data() == old data() + @a len * @post new length() == old length() - @a len * * @sa push */ void pull(uint32_t len); /** @brief Add space for data after the packet. * @param len amount of space to add * @return packet with added trailer space, or null on failure * * Returns a packet with an additional @a len bytes of uninitialized space * after the current packet's data (starting at end_data()). A copy of * the packet data is made if there isn't enough tailroom() in the current * packet, or if the current packet is shared(). If no copy is made, this * operation is quite efficient. * * If a data copy would be required, but the copy fails because of lack of * memory, then the current packet is freed. * * put() is usually used like this: * @code * WritablePacket *q = p->put(100); * if (!q) * return 0; * // p must not be used here. * @endcode * * @post new length() == old length() + @a len (if no failure) * * @sa nonunique_put, take */ WritablePacket *put(uint32_t len) CLICK_WARN_UNUSED_RESULT; /** @brief Add space for data after the packet. * @param len amount of space to add * @return packet with added trailer space, or null on failure * * This is a variant of put(). Returns a packet with an additional @a len * bytes of uninitialized space after the current packet's data (starting * at end_data()). A copy of the packet data is made if there isn't * enough tailroom() in the current packet. However, no copy is made if * the current packet is shared; and if no copy is made, this operation is * quite efficient. * * If a data copy would be required, but the copy fails because of lack of * memory, then the current packet is freed. * * @sa put */ Packet *nonunique_put(uint32_t len) CLICK_WARN_UNUSED_RESULT; /** @brief Remove space from the end of the packet. * @param len amount of space to remove * * Removes @a len bytes from the end of the packet. This operation is * efficient: it just bumps a pointer. * * It is an error to attempt to pull more than length() bytes. * * @post new data() == old data() * @post new end_data() == old end_data() - @a len * @post new length() == old length() - @a len * * @sa push */ void take(uint32_t len); /** @brief Shift packet data within the data buffer. * @param offset amount to shift packet data * @param free_on_failure if true, then delete the input packet on failure * @return a packet with shifted data, or null on failure * * Useful to align packet data. For example, if the packet's embedded IP * header is located at pointer value 0x8CCA03, then shift_data(1) or * shift_data(-3) will both align the header on a 4-byte boundary. * * If the packet is shared() or there isn't enough headroom or tailroom * for the operation, the packet is passed to uniqueify() first. This can * fail if there isn't enough memory. If it fails, shift_data returns * null, and if @a free_on_failure is true (the default), the input packet * is freed. * * The packet's mac_header, network_header, and transport_header areas are * preserved, even if they lie within the headroom. Any headroom outside * these regions may be overwritten, as may any tailroom. * * @post new data() == old data() + @a offset (if no copy is made) * @post new buffer() == old buffer() (if no copy is made) */ Packet *shift_data(int offset, bool free_on_failure = true) CLICK_WARN_UNUSED_RESULT;#if CLICK_USERLEVEL inline void shrink_data(const unsigned char *data, uint32_t length); inline void change_headroom_and_length(uint32_t headroom, uint32_t length);#endif //@} /** @name Header Pointers */ //@{ inline bool has_mac_header() const; inline const unsigned char *mac_header() const; inline int mac_header_offset() const; inline uint32_t mac_header_length() const; inline int mac_length() const; inline void set_mac_header(const unsigned char *p); inline void set_mac_header(const unsigned char *p, uint32_t len); inline void clear_mac_header(); inline bool has_network_header() const; inline const unsigned char *network_header() const; inline int network_header_offset() const; inline uint32_t network_header_length() const; inline int network_length() const; inline void set_network_header(const unsigned char *p, uint32_t len); inline void set_network_header_length(uint32_t len); inline void clear_network_header(); inline bool has_transport_header() const; inline const unsigned char *transport_header() const; inline int transport_header_offset() const; inline int transport_length() const; inline void clear_transport_header(); // CONVENIENCE HEADER ANNOTATIONS inline const click_ether *ether_header() const; inline void set_ether_header(const click_ether *ethh); inline const click_ip *ip_header() const; inline int ip_header_offset() const; inline uint32_t ip_header_length() const; inline void set_ip_header(const click_ip *iph, uint32_t len); inline const click_ip6 *ip6_header() const; inline int ip6_header_offset() const; inline uint32_t ip6_header_length() const; inline void set_ip6_header(const click_ip6 *ip6h); inline void set_ip6_header(const click_ip6 *ip6h, uint32_t len); inline const click_icmp *icmp_header() const; inline const click_tcp *tcp_header() const; inline const click_udp *udp_header() const; //@} private: /** @cond never */ union Anno;#if CLICK_LINUXMODULE const Anno *xanno() const { return (const Anno *)skb()->cb; } Anno *xanno() { return (Anno *)skb()->cb; }#else const Anno *xanno() const { return (const Anno *)_cb; } Anno *xanno() { return (Anno *)_cb; }#endif /** @endcond never */ public: /** @name Annotations */ //@{ enum { anno_size = 48 ///< Size of annotation area. }; /** @brief Return the timestamp annotation. */ inline const Timestamp ×tamp_anno() const; /** @overload */ inline Timestamp ×tamp_anno(); /** @brief Set the timestamp annotation. * @param t new timestamp */ inline void set_timestamp_anno(const Timestamp &t); /** @brief Return the device annotation. */ inline net_device *device_anno() const; /** @brief Set the device annotation */ inline void set_device_anno(net_device *dev); /** @brief Values for packet_type_anno(). * Must agree with Linux's PACKET_ constants in <linux/if_packet.h>. */ enum PacketType { HOST = 0, /**< Packet was sent to this host. */ BROADCAST = 1, /**< Packet was sent to a link-level multicast address. */ MULTICAST = 2, /**< Packet was sent to a link-level multicast address. */ OTHERHOST = 3, /**< Packet was sent to a different host, but received anyway. The receiving device is probably in promiscuous mode. */ OUTGOING = 4, /**< Packet was generated by this host and is being sent elsewhere. */ LOOPBACK = 5, FASTROUTE = 6 }; /** @brief Return the packet type annotation. */ inline PacketType packet_type_anno() const; /** @brief Set the packet type annotation. */ inline void set_packet_type_anno(PacketType t);#if CLICK_NS class SimPacketinfoWrapper { public: simclick_simpacketinfo _pinfo; SimPacketinfoWrapper() { // The uninitialized value for the simulator packet data can't be // all zeros (0 is a valid packet id) or random junk out of memory // since the simulator will look at this info to see if the packet // was originally generated by it. Accidental collisions with // other packet IDs or bogus packet IDs can cause weird things to // happen. So we set it to all -1 here to keep the simulator from // getting confused. memset(&_pinfo,-1,sizeof(_pinfo)); } }; simclick_simpacketinfo *get_sim_packetinfo() { return &(_sim_packetinfo._pinfo); } void set_sim_packetinfo(simclick_simpacketinfo* pinfo) { _sim_packetinfo._pinfo = *pinfo; }#endif /** @brief Return the next packet annotation. */ inline Packet *next() const; /** @overload */ inline Packet *&next(); /** @brief Set the next packet annotation. */ inline void set_next(Packet *p); /** @brief Return the previous packet annotation. */ inline Packet *prev() const; /** @overload */ inline Packet *&prev(); /** @brief Set the previous packet annotation. */ inline void set_prev(Packet *p); enum { dst_ip_anno_offset = 0, dst_ip_anno_size = 4, dst_ip6_anno_offset = 0, dst_ip6_anno_size = 16 }; /** @brief Return the destination IPv4 address annotation. * * The value is taken from the address annotation area. */ inline IPAddress dst_ip_anno() const; /** @brief Set the destination IPv4 address annotation. * * The value is stored in the address annotation area. */ inline void set_dst_ip_anno(IPAddress addr); /** @brief Return a pointer to the annotation area. * * The area is @link Packet::anno_size anno_size @endlink bytes long. */ void *anno() { return xanno(); } /** @overload */ const void *anno() const { return xanno(); } /** @brief Return a pointer to the annotation area as uint8_ts. */ uint8_t *anno_u8() { return &xanno()->u8[0]; } /** @brief overload */ const uint8_t *anno_u8() const { return &xanno()->u8[0]; } /** @brief Return a pointer to the annotation area as uint32_ts. */ uint32_t *anno_u32() { return &xanno()->u32[0]; } /** @brief overload */ const uint32_t *anno_u32() const { return &xanno()->u32[0]; } /** @brief Return annotation byte at offset @a i. * @pre 0 <= @a i < @link Packet::anno_size anno_size @endlink */ uint8_t anno_u8(int i) const { assert(i >= 0 && i < anno_size); return xanno()->u8[i]; } /** @brief Set annotation byte at offset @a i. * @param i annotation offset in bytes * @param v value * @pre 0 <= @a i < @link Packet::anno_size anno_size @endlink */ void set_anno_u8(int i, uint8_t v) { assert(i >= 0 && i < anno_size); xanno()->u8[i] = v; } /** @brief Return 16-bit annotation at offset @a i. * @pre 0 <= @a i < @link Packet::anno_size anno_size @endlink - 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -