Click
Loading...
Searching...
No Matches
packet.hh
Go to the documentation of this file.
1// -*- related-file-name: "../../lib/packet.cc" -*-
2#ifndef CLICK_PACKET_HH
3#define CLICK_PACKET_HH
4#include <click/ipaddress.hh>
5#include <click/glue.hh>
6#include <click/timestamp.hh>
7#include <click/packet_anno.hh>
8
9#include "flow/common.hh"
10#if CLICK_LINUXMODULE
11# include <click/skbmgr.hh>
12#elif CLICK_PACKET_USE_DPDK || HAVE_DPDK
13# include <rte_debug.h>
14# include <rte_mbuf.h>
15# include <rte_malloc.h>
16# include <click/dpdk_glue.hh>
17
18#if CLICK_PACKET_USE_DPDK
19#define DPDK_ANNO_SIZE sizeof(Packet::AllAnno)
20#elif CLICK_PACKET_INSIDE_DPDK
21#define DPDK_ANNO_SIZE (((sizeof(Packet) - 1) / 4) +1) * 4 // round up to 4 bytes
22#else
23#define DPDK_ANNO_SIZE 0
24#endif
25
26#else
27# include <click/atomic.hh>
28#endif
29#if CLICK_BSDMODULE
30# include <sys/stddef.h>
31#endif
32#if CLICK_NS
33# include <click/simclick.h>
34#endif
35#if !CLICK_PACKET_USE_DPDK && \
36 (CLICK_USERLEVEL || CLICK_NS || CLICK_MINIOS) && \
37 (!HAVE_MULTITHREAD || HAVE___THREAD_STORAGE_CLASS) && \
38 HAVE_ALLOW_CLICK_PACKET_POOL
39# define HAVE_CLICK_PACKET_POOL 1
40#endif
41#ifndef CLICK_PACKET_DEPRECATED_ENUM
42# define CLICK_PACKET_DEPRECATED_ENUM CLICK_DEPRECATED_ENUM
43#endif
44#include <click/stack.hh>
45struct click_ether;
46struct click_ip;
47struct click_icmp;
48struct click_ip6;
49struct click_tcp;
50struct click_udp;
51
52CLICK_DECLS
53
54//#define HAVE_VECTOR_PACKET_POOL 1
55
56#if HAVE_BATCH && HAVE_CLICK_PACKET_POOL
57#define HAVE_BATCH_RECYCLE 1
58#endif
59
60class IP6Address;
61class WritablePacket;
62class PacketBatch;
63#if HAVE_DPDK
64class FromDPDKDevice;
65class DPDKDevice;
66#endif
67
68class Packet { public:
69
72 // PACKET CREATION
73
74 enum {
75#ifdef CLICK_MINIOS
76 default_headroom = 48,
77#elif CLICK_PACKET_USE_DPDK || HAVE_DPDK_PACKET_POOL || CLICK_PACKET_INSIDE_DPDK
78 default_headroom = RTE_PKTMBUF_HEADROOM,
79#elif HAVE_CLICK_PACKET_POOL
81#else
82 default_headroom = 28,
84#endif
87 };
88
89 static WritablePacket *make(uint32_t headroom, const void *data,
90 uint32_t length, uint32_t tailroom, bool clear = true) CLICK_WARN_UNUSED_RESULT;
91 static inline WritablePacket *make(const void *data, uint32_t length) CLICK_WARN_UNUSED_RESULT;
92 static inline WritablePacket *make(uint32_t length) CLICK_WARN_UNUSED_RESULT;
93#if HAVE_DPDK && !CLICK_PACKET_USE_DPDK
94 static WritablePacket *make_dpdk_packet(uint32_t headroom,
95 uint32_t length, uint32_t tailroom, bool clear) CLICK_WARN_UNUSED_RESULT;
96#endif
97 static WritablePacket *make_similar(Packet* original, uint32_t length) CLICK_WARN_UNUSED_RESULT;
98#if CLICK_LINUXMODULE
99 static Packet *make(struct sk_buff *skb) CLICK_WARN_UNUSED_RESULT;
100#elif CLICK_PACKET_USE_DPDK
101 static Packet *make(struct rte_mbuf *mb, bool clear = true) CLICK_WARN_UNUSED_RESULT;
102#endif
103#if CLICK_BSDMODULE
104 // Packet::make(mbuf *) wraps a Packet around an existing mbuf.
105 // Packet now owns the mbuf.
106 static inline Packet *make(struct mbuf *mbuf) CLICK_WARN_UNUSED_RESULT;
107#endif
108
109#if CLICK_USERLEVEL || CLICK_MINIOS
110 typedef void (*buffer_destructor_type)(unsigned char* buf, size_t sz, void* argument);
111
117 static void empty_destructor(unsigned char*, size_t, void*);
118
119 static WritablePacket* make(unsigned char* data, uint32_t length,
120 buffer_destructor_type buffer_destructor,
121 void* argument = (void*) 0, int headroom = 0, int tailroom = 0, bool clear = true) CLICK_WARN_UNUSED_RESULT;
122#endif //CLICK_USERLEVEL || CLICK_MINIOS
123
124
125 static int max_data_pool_size();
126 static void static_cleanup();
127
128 inline void kill();
129
130 inline void kill_nonatomic();
131
132 inline bool shared() const;
133 inline bool shared_nonatomic() const;
134 Packet *clone(bool fast = false) CLICK_WARN_UNUSED_RESULT;
135 WritablePacket *duplicate(int32_t extra_headroom = 0, int32_t extra_tailroom = 0, const bool data_only=true) CLICK_WARN_UNUSED_RESULT;
136 inline WritablePacket *uniqueify() CLICK_WARN_UNUSED_RESULT;
137#ifndef CLICK_NOINDIRECT
138# if CLICK_LINUXMODULE
139 inline void get() {skb_get(skb());};
140# elif CLICK_PACKET_USE_DPDK
141 inline void get() {rte_mbuf_refcnt_update(mb(), 1);};
142# else
143 inline void get() {_use_count++;};
144# endif
145#endif
146
147 inline const unsigned char *data() const;
148 inline const unsigned char *end_data() const;
149 inline uint32_t length() const;
150 inline uint32_t headroom() const;
151 inline uint32_t tailroom() const;
152 inline const unsigned char *buffer() const;
153 inline const unsigned char *end_buffer() const;
154 inline uint32_t buffer_length() const;
155
156#if CLICK_LINUXMODULE
157 struct sk_buff *skb() { return (struct sk_buff *)this; }
158 const struct sk_buff *skb() const { return (const struct sk_buff*)this; }
159#elif CLICK_PACKET_USE_DPDK
160 inline void prefetch_anno() {
161 rte_prefetch0(xanno());
162 }
163
164 struct rte_mbuf *mb() {
165 return reinterpret_cast<struct rte_mbuf *>(this);
166 }
167 const struct rte_mbuf *mb() const {
168 return reinterpret_cast<const struct rte_mbuf *>(this);
169 }
170 void *destructor_argument() const {
171 click_chatter("ILLEGAL CALL TO destructor_argument");
172 assert(false);
173 return NULL;
174 }
175
176 void set_buffer_destructor(buffer_destructor_type) {
177 click_chatter("ILLEGAL CALL TO set_buffer_destructor");
178 assert(false);
179 }
180 void set_destructor_argument(void*) {
181 click_chatter("ILLEGAL CALL TO set_destructor_argument");
182 assert(false);
183 }
184#elif CLICK_BSDMODULE
185 struct mbuf *m() { return _m; }
186 const struct mbuf *m() const { return (const struct mbuf *)_m; }
187 struct mbuf *steal_m();
188 struct mbuf *dup_jumbo_m(struct mbuf *mbuf);
189#elif CLICK_USERLEVEL || CLICK_MINIOS
190 void set_buffer_destructor(buffer_destructor_type destructor) {
191 _destructor = destructor;
192 }
193
194 buffer_destructor_type buffer_destructor() const {
195 return _destructor;
196 }
197
198 void* destructor_argument() const {
199 return _destructor_argument;
200 }
201
202 void reset_buffer() {
203 _head = _data = _tail = _end = 0;
204 _destructor = 0;
205 }
206
207 void set_destructor_argument(void* arg) {
208 _destructor_argument = arg;
209 }
210
211 static inline void release_buffer(unsigned char* head);
212 inline void delete_buffer(unsigned char* head, unsigned char* end);
213#endif
214
215
240 WritablePacket *push(uint32_t len) CLICK_WARN_UNUSED_RESULT;
241
251 WritablePacket *push_mac_header(uint32_t len) CLICK_WARN_UNUSED_RESULT;
252
270 Packet *nonunique_push(uint32_t len) CLICK_WARN_UNUSED_RESULT;
271
286 void pull(uint32_t len);
287
312 WritablePacket *put(uint32_t len) CLICK_WARN_UNUSED_RESULT;
313
329 Packet *nonunique_put(uint32_t len) CLICK_WARN_UNUSED_RESULT;
330
344 void take(uint32_t len);
345
346
371 Packet *shift_data(int offset, bool free_on_failure = true) CLICK_WARN_UNUSED_RESULT;
372#if CLICK_USERLEVEL || CLICK_MINIOS
373 inline void shrink_data(const unsigned char *data, uint32_t length);
374 inline void change_headroom_and_length(uint32_t headroom, uint32_t length);
375 inline void change_buffer_length(uint32_t length);
376#endif
377 bool copy(Packet* p, int headroom=0);
379
382 inline bool has_mac_header() const;
383 inline const unsigned char *mac_header() const;
384 inline int mac_header_offset() const;
385 inline uint32_t mac_header_length() const;
386 inline int mac_length() const;
387 inline void set_mac_header(const unsigned char *p);
388 inline void set_mac_header(const unsigned char *p, uint32_t len);
389 inline void clear_mac_header();
390
391 inline bool has_network_header() const;
392 inline const unsigned char *network_header() const;
393 inline int network_header_offset() const;
394 inline uint32_t network_header_length() const;
395 inline int network_length() const;
396 inline void set_network_header(const unsigned char *p);
397 inline void set_network_header(const unsigned char *p, uint32_t len);
398 inline void set_network_header_length(uint32_t len);
399 inline void clear_network_header();
400
401 inline void set_transport_header(const unsigned char *p);
402 inline bool has_transport_header() const;
403 inline const unsigned char *transport_header() const;
404 inline int transport_header_offset() const;
405 inline int transport_length() const;
406 inline void clear_transport_header();
407
408 // CONVENIENCE HEADER ANNOTATIONS
409 inline const click_ether *ether_header() const;
410 inline void set_ether_header(const click_ether *ethh);
411
412 inline const click_ip *ip_header() const;
413 inline int ip_header_offset() const;
414 inline uint32_t ip_header_length() const;
415 inline void set_ip_header(const click_ip *iph, uint32_t len);
416
417 inline const click_ip6 *ip6_header() const;
418 inline int ip6_header_offset() const;
419 inline uint32_t ip6_header_length() const;
420 inline void set_ip6_header(const click_ip6 *ip6h);
421 inline void set_ip6_header(const click_ip6 *ip6h, uint32_t len);
422
423 inline const click_icmp *icmp_header() const;
424 inline const click_tcp *tcp_header() const;
425 inline const click_udp *udp_header() const;
426
427 inline uint16_t getContentOffset() const;
428 inline void setContentOffset(uint16_t offset);
429 inline const unsigned char* getPacketContent();
430 inline bool isPacketContentEmpty() const;
431 inline uint16_t getPacketContentSize() const;
433
434#if CLICK_LINUXMODULE
435# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET) || \
436 (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
437 protected:
438 typedef typeof(((struct sk_buff*)0)->mac_header) mac_header_type;
439 typedef typeof(((struct sk_buff*)0)->network_header) network_header_type;
440 typedef typeof(((struct sk_buff*)0)->transport_header) transport_header_type;
441# endif
442#endif
443
444 private:
446 union Anno;
447#if CLICK_LINUXMODULE
448 const Anno *xanno() const { return (const Anno *)skb()->cb; }
449 Anno *xanno() { return (Anno *)skb()->cb; }
450#elif CLICK_PACKET_USE_DPDK
451 # define ANNO_OFFSET sizeof(struct rte_mbuf)
452 const Anno *xanno() const {
453 return (const Anno *) (((unsigned char*)this) + ANNO_OFFSET); }
454 Anno *xanno() {
455 return (Anno *) (((unsigned char*)this) + ANNO_OFFSET); }
456#else
457 #if INLINED_ALLANNO
458 CLICK_OPTNONE const Anno *xanno() const { return (const Anno *) &all_anno()->cb; }
459 CLICK_OPTNONE Anno *xanno() { return (Anno *) &all_anno()->cb; }
460 #else
461 inline const Anno *xanno() const { return (const Anno *) &all_anno()->cb; }
462 inline Anno *xanno() { return (Anno *) &all_anno()->cb; }
463 #endif
464#endif
466 public:
467
470
471 enum {
472 anno_size = 48
473 };
474
476 inline const Timestamp &timestamp_anno() const;
478 inline Timestamp &timestamp_anno();
481 inline void set_timestamp_anno(const Timestamp &t);
482
484 inline net_device *device_anno() const;
486 inline void set_device_anno(net_device *dev);
487
491 HOST = 0,
492 BROADCAST = 1,
494 MULTICAST = 2,
496 OTHERHOST = 3,
499 OUTGOING = 4,
501 LOOPBACK = 5,
502 FASTROUTE = 6
503 };
505 inline PacketType packet_type_anno() const;
507 inline void set_packet_type_anno(PacketType t);
508
509#if CLICK_NS
510 class SimPacketinfoWrapper { public:
511 simclick_simpacketinfo _pinfo;
512 SimPacketinfoWrapper() {
513 // The uninitialized value for the simulator packet data can't be
514 // all zeros (0 is a valid packet id) or random junk out of memory
515 // since the simulator will look at this info to see if the packet
516 // was originally generated by it. Accidental collisions with
517 // other packet IDs or bogus packet IDs can cause weird things to
518 // happen. So we set it to all -1 here to keep the simulator from
519 // getting confused.
520 memset(&_pinfo,-1,sizeof(_pinfo));
521 }
522 };
523 simclick_simpacketinfo *get_sim_packetinfo() {
524 return &(_sim_packetinfo._pinfo);
525 }
526 void set_sim_packetinfo(simclick_simpacketinfo* pinfo) {
527 _sim_packetinfo._pinfo = *pinfo;
528 }
529#endif
530
532 inline Packet *next() const;
534 inline Packet *&next();
536 inline void set_next(Packet *p);
537
539 inline Packet *prev() const;
541 inline Packet *&prev();
543 inline void set_prev(Packet *p);
544
545 inline Packet* find_tail() {
546 Packet* head = this;
547 while (head != NULL) {
548 Packet* next = head->next();
549 if (next == NULL) break;
550 head = next;
551 }
552 return head;
553 }
554
555 inline unsigned int find_count() {
556 Packet* head = this;
557 int c = 0;
558 while (head != NULL) {
559 head = head->next();
560 c++;
561 }
562 return c;
563 }
564
565 enum {
566 dst_ip_anno_offset = 0, dst_ip_anno_size = 4,
567 dst_ip6_anno_offset = 0, dst_ip6_anno_size = 16
568 };
569
573 inline IPAddress dst_ip_anno() const;
574
578 inline void set_dst_ip_anno(IPAddress addr);
579
583 void *anno() { return xanno(); }
584
586 const void *anno() const { return xanno(); }
587
589 uint8_t *anno_u8() { return &xanno()->u8[0]; }
590
592 const uint8_t *anno_u8() const { return &xanno()->u8[0]; }
593
595 uint32_t *anno_u32() { return &xanno()->u32[0]; }
596
598 const uint32_t *anno_u32() const { return &xanno()->u32[0]; }
599
602 uint8_t anno_u8(int i) const {
603 assert(i >= 0 && i < anno_size);
604 return xanno()->u8[i];
605 }
606
611 void set_anno_u8(int i, uint8_t x) {
612 assert(i >= 0 && i < anno_size);
613 xanno()->u8[i] = x;
614 }
615
621 uint16_t anno_u16(int i) const {
622 assert(i >= 0 && i < anno_size - 1);
623#if !HAVE_INDIFFERENT_ALIGNMENT
624 assert(i % 2 == 0);
625#endif
626 return *reinterpret_cast<const click_aliasable_uint16_t *>(xanno()->c + i);
627 }
628
636 void set_anno_u16(int i, uint16_t x) {
637 assert(i >= 0 && i < anno_size - 1);
638#if !HAVE_INDIFFERENT_ALIGNMENT
639 assert(i % 2 == 0);
640#endif
641 *reinterpret_cast<click_aliasable_uint16_t *>(xanno()->c + i) = x;
642 }
643
649 int16_t anno_s16(int i) const {
650 assert(i >= 0 && i < anno_size - 1);
651#if !HAVE_INDIFFERENT_ALIGNMENT
652 assert(i % 2 == 0);
653#endif
654 return *reinterpret_cast<const click_aliasable_int16_t *>(xanno()->c + i);
655 }
656
664 void set_anno_s16(int i, int16_t x) {
665 assert(i >= 0 && i < anno_size - 1);
666#if !HAVE_INDIFFERENT_ALIGNMENT
667 assert(i % 2 == 0);
668#endif
669 *reinterpret_cast<click_aliasable_int16_t *>(xanno()->c + i) = x;
670 }
671
677 uint32_t anno_u32(int i) const {
678 assert(i >= 0 && i < anno_size - 3);
679#if !HAVE_INDIFFERENT_ALIGNMENT
680 assert(i % 4 == 0);
681#endif
682 return *reinterpret_cast<const click_aliasable_uint32_t *>(xanno()->c + i);
683 }
684
692 void set_anno_u32(int i, uint32_t x) {
693 assert(i >= 0 && i < anno_size - 3);
694#if !HAVE_INDIFFERENT_ALIGNMENT
695 assert(i % 4 == 0);
696#endif
697 *reinterpret_cast<click_aliasable_uint32_t *>(xanno()->c + i) = x;
698 }
699
704 int32_t anno_s32(int i) const {
705 assert(i >= 0 && i < anno_size - 3);
706#if !HAVE_INDIFFERENT_ALIGNMENT
707 assert(i % 4 == 0);
708#endif
709 return *reinterpret_cast<const click_aliasable_int32_t *>(xanno()->c + i);
710 }
711
719 void set_anno_s32(int i, int32_t x) {
720 assert(i >= 0 && i < anno_size - 3);
721#if !HAVE_INDIFFERENT_ALIGNMENT
722 assert(i % 4 == 0);
723#endif
724 *reinterpret_cast<click_aliasable_int32_t *>(xanno()->c + i) = x;
725 }
726
727#if HAVE_INT64_TYPES
733 uint64_t anno_u64(int i) const {
734 assert(i >= 0 && i < anno_size - 7);
735#if !HAVE_INDIFFERENT_ALIGNMENT
736 assert(i % __alignof__(uint64_t) == 0);
737#endif
738 return *reinterpret_cast<const click_aliasable_uint64_t *>(xanno()->c + i);
739 }
740
748 void set_anno_u64(int i, uint64_t x) {
749 assert(i >= 0 && i < anno_size - 7);
750#if !HAVE_INDIFFERENT_ALIGNMENT
751 assert(i % __alignof__(uint64_t) == 0);
752#endif
753 *reinterpret_cast<click_aliasable_uint64_t *>(xanno()->c + i) = x;
754 }
755#endif
756
762 void *anno_ptr(int i) const {
763 assert(i >= 0 && i <= anno_size - (int)sizeof(void *));
764#if !HAVE_INDIFFERENT_ALIGNMENT
765 assert(i % __alignof__(void *) == 0);
766#endif
767 return *reinterpret_cast<const click_aliasable_void_pointer_t *>(xanno()->c + i);
768 }
769
777 void set_anno_ptr(int i, const void *x) {
778 assert(i >= 0 && i <= anno_size - (int)sizeof(void *));
779#if !HAVE_INDIFFERENT_ALIGNMENT
780 assert(i % __alignof__(void *) == 0);
781#endif
782 *reinterpret_cast<click_aliasable_void_pointer_t *>(xanno()->c + i) = const_cast<void *>(x);
783 }
784
785#if !CLICK_PACKET_USE_DPDK && !CLICK_LINUXMODULE && !defined(CLICK_NOINDIRECT)
786 inline Packet* data_packet() {
787 return _data_packet;
788 }
789 inline void set_data_packet(Packet* p) {
790 _data_packet = p;
791 _data_packet->_use_count ++;
792 }
793#else
794 inline Packet* data_packet() {
795 return 0;
796 }
797#endif
798
799 inline void clear_annotations(bool all = true);
800 inline void copy_annotations(const Packet *, bool all = true);
801 inline void copy_headers(const Packet *);
803
805 enum {
806 DEFAULT_HEADROOM = default_headroom,
807 MIN_BUFFER_LENGTH = min_buffer_length,
808 addr_anno_offset = 0,
809 addr_anno_size = 16,
810 user_anno_offset = 16,
811 user_anno_size = 32,
812 ADDR_ANNO_SIZE = addr_anno_size,
813 USER_ANNO_SIZE = user_anno_size,
814 USER_ANNO_U16_SIZE = USER_ANNO_SIZE / 2,
815 USER_ANNO_U32_SIZE = USER_ANNO_SIZE / 4,
816 USER_ANNO_U64_SIZE = USER_ANNO_SIZE / 8
817 } CLICK_PACKET_DEPRECATED_ENUM;
818 inline const unsigned char *buffer_data() const CLICK_DEPRECATED;
819 inline void *addr_anno() CLICK_DEPRECATED;
820 inline const void *addr_anno() const CLICK_DEPRECATED;
821 inline void *user_anno() CLICK_DEPRECATED;
822 inline const void *user_anno() const CLICK_DEPRECATED;
823 inline uint8_t *user_anno_u8() CLICK_DEPRECATED;
824 inline const uint8_t *user_anno_u8() const CLICK_DEPRECATED;
825 inline uint32_t *user_anno_u32() CLICK_DEPRECATED;
826 inline const uint32_t *user_anno_u32() const CLICK_DEPRECATED;
827 inline uint8_t user_anno_u8(int i) const CLICK_DEPRECATED;
828 inline void set_user_anno_u8(int i, uint8_t v) CLICK_DEPRECATED;
829 inline uint16_t user_anno_u16(int i) const CLICK_DEPRECATED;
830 inline void set_user_anno_u16(int i, uint16_t v) CLICK_DEPRECATED;
831 inline uint32_t user_anno_u32(int i) const CLICK_DEPRECATED;
832 inline void set_user_anno_u32(int i, uint32_t v) CLICK_DEPRECATED;
833 inline int32_t user_anno_s32(int i) const CLICK_DEPRECATED;
834 inline void set_user_anno_s32(int i, int32_t v) CLICK_DEPRECATED;
835#if HAVE_INT64_TYPES
836 inline uint64_t user_anno_u64(int i) const CLICK_DEPRECATED;
837 inline void set_user_anno_u64(int i, uint64_t v) CLICK_DEPRECATED;
838#endif
839 inline const uint8_t *all_user_anno() const CLICK_DEPRECATED;
840 inline uint8_t *all_user_anno() CLICK_DEPRECATED;
841 inline const uint32_t *all_user_anno_u() const CLICK_DEPRECATED;
842 inline uint32_t *all_user_anno_u() CLICK_DEPRECATED;
843 inline uint8_t user_anno_c(int) const CLICK_DEPRECATED;
844 inline void set_user_anno_c(int, uint8_t) CLICK_DEPRECATED;
845 inline int16_t user_anno_s(int) const CLICK_DEPRECATED;
846 inline void set_user_anno_s(int, int16_t) CLICK_DEPRECATED;
847 inline uint16_t user_anno_us(int) const CLICK_DEPRECATED;
848 inline void set_user_anno_us(int, uint16_t) CLICK_DEPRECATED;
849 inline int32_t user_anno_i(int) const CLICK_DEPRECATED;
850 inline void set_user_anno_i(int, int32_t) CLICK_DEPRECATED;
851 inline uint32_t user_anno_u(int) const CLICK_DEPRECATED;
852 inline void set_user_anno_u(int, uint32_t) CLICK_DEPRECATED;
855 private:
856
857 // Anno must fit in sk_buff's char cb[48].
859 union Anno {
860 char c[anno_size];
861 uint8_t u8[anno_size];
862 uint16_t u16[anno_size / 2];
863 uint32_t u32[anno_size / 4];
864#if HAVE_INT64_TYPES
865 uint64_t u64[anno_size / 8];
866#endif
867 // allocations: see packet_anno.hh
868 };
869
870#if !CLICK_LINUXMODULE
871 // All packet annotations are stored in AllAnno so that
872 // clear_annotations(true) can memset() the structure to zero.
873#if !INLINED_ALLANNO
874 struct AllAnno {
875#endif
876 Anno cb;
877 unsigned char *mac;
878 unsigned char *nh;
879 unsigned char *h;
880 Packet::PacketType pkt_type;
881#if !CLICK_PACKET_USE_DPDK
882 char timestamp[sizeof(Timestamp)];
883#endif
884#if INLINED_ALLANNO
885 Packet *nextp;
886 Packet *prevp;
887#else
888 Packet *next;
889 Packet *prev;
890 };
891#endif
892
893# if CLICK_PACKET_USE_DPDK
894 inline struct AllAnno *all_anno() {
895 return reinterpret_cast<AllAnno *>(xanno());
896 }
897 inline const struct AllAnno *all_anno() const {
898 return reinterpret_cast<const AllAnno *>(xanno());
899 }
900 static struct rte_mempool **_pktmbuf_pools;
901# elif INLINED_ALLANNO
902 CLICK_OPTNONE const class Packet* all_anno() const { return this;}
903 CLICK_OPTNONE class Packet* all_anno() { return this;}
904# else
905 CLICK_ALWAYS_INLINE const struct AllAnno* all_anno() const { return &_aa;}
906 CLICK_ALWAYS_INLINE struct AllAnno* all_anno() { return &_aa;}
907# endif
908#endif
911#if !(CLICK_LINUXMODULE || CLICK_PACKET_USE_DPDK)
912 // User-space and BSD kernel module implementations.
913protected:
914#ifndef CLICK_NOINDIRECT
915# ifndef HAVE_FULLPUSH_NONATOMIC
916 nonatomic_uint32_t _use_count;
917# else
918 atomic_uint32_t _use_count;
919#endif
920 Packet *_data_packet;
921#endif
922private:
923 /* mimic Linux sk_buff */
924 unsigned char *_head; /* start of allocated buffer */
925 unsigned char *_data; /* where the packet starts */
926 unsigned char *_tail; /* one beyond end of packet */
927 unsigned char *_end; /* one beyond end of allocated buffer */
928# if CLICK_BSDMODULE
929 struct mbuf *_m;
930# endif
931# if !INLINED_ALLANNO
932 AllAnno _aa;
933# endif
934# if CLICK_NS
935 SimPacketinfoWrapper _sim_packetinfo;
936# endif
937# if CLICK_USERLEVEL || CLICK_MINIOS
938 buffer_destructor_type _destructor;
939 void* _destructor_argument;
940# endif
941#endif
942
943 inline Packet() {
944#if CLICK_LINUXMODULE
945 panic("Packet constructor");
946#elif CLICK_PACKET_USE_DPDK
947 rte_panic("Packet constructor");
948#endif
949 }
950 Packet(const Packet &x);
951 ~Packet();
952 Packet &operator=(const Packet &x);
953
954#if !(CLICK_LINUXMODULE || CLICK_PACKET_USE_DPDK)
955 bool alloc_data(uint32_t headroom, uint32_t length, uint32_t tailroom);
956#endif
957#if CLICK_BSDMODULE
958 static void assimilate_mbuf(Packet *p);
959 void assimilate_mbuf();
960#endif
961
962 inline void shift_header_annotations(const unsigned char *old_head, int32_t extra_headroom);
963 WritablePacket *expensive_uniqueify(int32_t extra_headroom, int32_t extra_tailroom, bool free_on_failure) CLICK_WARN_UNUSED_RESULT;
964 WritablePacket *expensive_push(uint32_t nbytes) CLICK_WARN_UNUSED_RESULT;
965 WritablePacket *expensive_put(uint32_t nbytes) CLICK_WARN_UNUSED_RESULT;
966
967 friend class WritablePacket;
968 friend class PacketBatch;
969#if HAVE_DPDK
970 friend class DPDKDevice;
971#endif
972
973};
974
975#if HAVE_CLICK_PACKET_POOL
976 struct PacketPool {
977
978 PacketPool() :
979#if HAVE_VECTOR_PACKET_POOL
980 p(), pd()
981#else
982 p(0), pcount(0), pd(0), pdcount(0)
983#endif
984 {
985 }
986#if HAVE_VECTOR_PACKET_POOL
987 Stack<Packet*> p;
988 Stack<Packet*> pd;
989#else
990 WritablePacket* p; // free packets, linked by p->next()
991 unsigned pcount; // # packets in `p` list
992 WritablePacket* pd; // free data buffers, linked by pd->next
993 unsigned pdcount; // # buffers in `pd` list
994#endif
995 # if HAVE_MULTITHREAD
996 PacketPool* thread_pool_next; // link to next per-thread pool
997 # endif
998 };
999#endif
1000
1001#include <clicknet/tcp.h>
1002#include <clicknet/udp.h>
1003
1004class WritablePacket : public Packet { public:
1005
1006 inline unsigned char *data() const;
1007 inline unsigned char *end_data() const;
1008 inline unsigned char *buffer() const;
1009 inline unsigned char *end_buffer() const;
1010 inline unsigned char *mac_header() const;
1011 inline click_ether *ether_header() const;
1012 inline unsigned char *network_header() const;
1013 inline click_ip *ip_header() const;
1014 inline click_ip6 *ip6_header() const;
1015 inline unsigned char *transport_header() const;
1016 inline click_icmp *icmp_header() const;
1017 inline click_tcp *tcp_header() const;
1018 inline click_udp *udp_header() const;
1019 inline unsigned char* getPacketContent();
1020
1021 inline void rewrite_ips(IPPair pair, bool is_tcp = true);
1022 inline void rewrite_ips_ports(IPPair pair, uint16_t sport, uint16_t dport, bool is_tcp = true);
1023 inline void rewrite_ipport(IPAddress ip, uint16_t port, const int shift, bool is_tcp = true);
1024 inline void rewrite_ip(IPAddress ip, const int shift, bool is_tcp = true);
1025 inline void rewrite_seq(tcp_seq_t seq, const int shift);
1026
1027#if !CLICK_LINUXMODULE
1028# if HAVE_DPDK && !CLICK_PACKET_USE_DPDK
1029 inline void set_mbuf(rte_mbuf* mbuf, uint32_t length);
1030# endif
1031 inline void init_buffer(unsigned char *data, uint32_t buffer_length, uint32_t data_length);
1032 inline void set_buffer(unsigned char *buffer, uint32_t buffer_length);
1033 inline void set_data(unsigned char *data);
1034 inline void set_data_length(uint32_t length);
1035#endif
1036
1037# if HAVE_CLICK_PACKET_POOL
1038 static PacketPool& get_local_packet_pool();
1039 static void initialize_local_packet_pool();
1040# endif
1041
1042 static void pool_transfer(int from, int to);
1043 static WritablePacket * pool_prepare_data_burst(uint16_t count);
1044 static void pool_consumed_data_burst(uint16_t n, WritablePacket* tail);
1045
1046#if !CLICK_LINUXMODULE
1047 inline void init_buffer(unsigned char *data, uint32_t length) {
1048 init_buffer(data,length,length);
1049 }
1050
1051 inline void init_buffer(unsigned char *data) {
1052 init_buffer(data,buffer_length());
1053 }
1054#endif
1055
1056 inline WritablePacket * unique_next() {
1057 if (!next()) return NULL;
1058 if (next()->shared()) {
1059 set_next(next()->uniqueify());
1060 return static_cast<WritablePacket*>(next());
1061 }
1062 else return static_cast<WritablePacket*>(next());
1063 }
1064
1065 inline WritablePacket * unique_prev() {
1066 if (!prev()) return NULL;
1067 if (prev()->shared()) {
1068 set_prev(prev()->uniqueify());
1069 return static_cast<WritablePacket*>(prev());
1070 }
1071 else return static_cast<WritablePacket*>(prev());
1072 }
1073
1074 #if !CLICK_LINUXMODULE || CLICK_PACKET_USE_DPDK
1075 inline void initialize(bool clear);
1076 inline void initialize_data();
1077 #endif
1078 WritablePacket(const Packet &x);
1079 ~WritablePacket() { }
1081 inline unsigned char *buffer_data() const CLICK_DEPRECATED;
1084 private:
1085
1086 inline WritablePacket() { }
1087
1088#if HAVE_CLICK_PACKET_POOL
1089 static WritablePacket *pool_allocate();
1090 static WritablePacket *pool_data_allocate();
1091 static WritablePacket *pool_allocate(uint32_t headroom, uint32_t length,
1092 uint32_t tailroom, bool clear =true);
1093
1094 static void check_data_pool_size(PacketPool &packet_pool, unsigned n);
1095 static void check_packet_pool_size(PacketPool &packet_pool, unsigned n);
1096 static bool is_from_data_pool(WritablePacket *p);
1097 static void recycle(WritablePacket *p);
1098 static WritablePacket *pool_batch_allocate(uint16_t count);
1099 static void recycle_packet_batch(WritablePacket *head, Packet* tail, unsigned count);
1100 static void recycle_data_batch(WritablePacket *head, Packet* tail, unsigned count);
1101#endif
1102
1103 friend class Packet;
1104 friend class PacketBatch;
1105 friend class NetmapDevice;
1106 friend class FromDPDKDevice;
1107
1108};
1109
1122inline void
1124{
1125#if CLICK_LINUXMODULE || INLINED_ALLANNO
1126 memset(xanno(), 0, sizeof(Anno));
1127 if (all) {
1129 set_device_anno(0);
1131
1135
1136 set_next(0);
1137 set_prev(0);
1138 }
1139#elif CLICK_PACKET_USE_DPDK
1140 memset(all_anno(), 0, all ? sizeof(AllAnno) : sizeof(Anno));
1142#else
1143 memset(&_aa, 0, all ? sizeof(AllAnno) : sizeof(Anno));
1144#endif
1145}
1146
1155inline void
1157{
1158 *xanno() = *p->xanno();
1162}
1163
1164
1165#if !CLICK_LINUXMODULE
1166inline void
1167WritablePacket::initialize(bool clear)
1168{
1169#if CLICK_PACKET_USE_DPDK
1170 click_chatter("UNIMPLEMENTED");
1171 assert(false); //Should be initialized by DPDK
1172#else
1173#if !CLICK_NOINDIRECT
1174 _use_count = 1;
1175 _data_packet = 0;
1176#endif
1177# if CLICK_USERLEVEL || CLICK_MINIOS
1178 _destructor = 0;
1179# elif CLICK_BSDMODULE
1180 _m = 0;
1181# endif
1182#endif
1183 if (clear)
1185}
1186inline void
1187WritablePacket::initialize_data()
1188{
1189#if CLICK_PACKET_USE_DPDK
1190
1191 click_chatter("UNIMPLEMENTED");
1192 assert(false); //This may not illegal but I need to check what to be done
1193#else
1194# if !CLICK_NOINDIRECT
1195 _use_count = 1;
1196 _data_packet = 0;
1197# endif
1198#endif
1199 clear_annotations(false);
1200}
1201#endif
1202
1206inline const unsigned char *
1208{
1209#if CLICK_LINUXMODULE
1210 return skb()->data;
1211#elif CLICK_PACKET_USE_DPDK
1212 return rte_pktmbuf_mtod(mb(), const unsigned char *);
1213#else
1214 return _data;
1215#endif
1216}
1217
1222inline const unsigned char *
1224{
1225#if CLICK_LINUXMODULE
1226# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1227 return skb_tail_pointer(skb());
1228# else
1229 return skb()->tail;
1230# endif
1231#elif CLICK_PACKET_USE_DPDK
1232 return data() + length();
1233#else
1234 return _tail;
1235#endif
1236}
1237
1242inline const unsigned char *
1244{
1245#if CLICK_LINUXMODULE
1246 return skb()->head;
1247#elif CLICK_PACKET_USE_DPDK
1248 return (const unsigned char*)mb()->buf_addr;
1249#else
1250 return _head;
1251#endif
1252}
1253
1258inline const unsigned char *
1260{
1261#if CLICK_LINUXMODULE
1262# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1263 return skb_end_pointer(skb());
1264# else
1265 return skb()->end;
1266# endif
1267#elif CLICK_PACKET_USE_DPDK
1268 return end_data() + rte_pktmbuf_tailroom(mb());
1269#else
1270 return _end;
1271#endif
1272}
1273
1275inline uint32_t
1277{
1278#if CLICK_LINUXMODULE
1279 return skb()->len;
1280#elif CLICK_PACKET_USE_DPDK
1281 return rte_pktmbuf_data_len(mb());
1282#else
1283 return _tail - _data;
1284#endif
1285}
1286
1292inline uint32_t
1294{
1295#if CLICK_PACKET_USE_DPDK
1296 return rte_pktmbuf_headroom(mb());
1297#else
1298 return data() - buffer();
1299#endif
1300}
1301
1307inline uint32_t
1309{
1310#if CLICK_PACKET_USE_DPDK
1311 return rte_pktmbuf_tailroom(mb());
1312#else
1313 return end_buffer() - end_data();
1314#endif
1315}
1316
1320inline uint32_t
1322{
1323 return end_buffer() - buffer();
1324}
1325
1326inline Packet *
1328{
1329#if CLICK_LINUXMODULE
1330 return (Packet *)(skb()->next);
1331#elif INLINED_ALLANNO
1332 return all_anno()->nextp;
1333#else
1334 return all_anno()->next;
1335#endif
1336}
1337
1338inline Packet *&
1340{
1341#if CLICK_LINUXMODULE
1342 return (Packet *&)(skb()->next);
1343#elif INLINED_ALLANNO
1344 return all_anno()->nextp;
1345#else
1346 return all_anno()->next;
1347#endif
1348}
1349
1350inline void
1352{
1353#if CLICK_LINUXMODULE
1354 skb()->next = p->skb();
1355#elif INLINED_ALLANNO
1356 all_anno()->nextp = p;
1357#else
1358 all_anno()->next = p;
1359#endif
1360}
1361
1362inline Packet *
1364{
1365#if CLICK_LINUXMODULE
1366 return (Packet *)(skb()->prev);
1367#elif INLINED_ALLANNO
1368 return all_anno()->prevp;
1369#else
1370 return all_anno()->prev;
1371#endif
1372}
1373
1374inline Packet *&
1376{
1377#if CLICK_LINUXMODULE
1378 return (Packet *&)(skb()->prev);
1379#elif INLINED_ALLANNO
1380 return all_anno()->prevp;
1381#else
1382 return all_anno()->prev;
1383#endif
1384}
1385
1386inline void
1388{
1389#if CLICK_LINUXMODULE
1390 skb()->prev = p->skb();
1391#elif INLINED_ALLANNO
1392 all_anno()->prevp = p;
1393#else
1394 all_anno()->prev = p;
1395#endif
1396}
1397
1400inline bool
1402{
1403#if CLICK_LINUXMODULE
1404# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1405 return skb_mac_header_was_set(skb());
1406# else
1407 return skb()->mac.raw != 0;
1408# endif
1409#else
1410 return all_anno()->mac != 0;
1411#endif
1412}
1413
1418inline const unsigned char *
1420{
1421#if CLICK_LINUXMODULE
1422# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1423 return skb_mac_header(skb());
1424# else
1425 return skb()->mac.raw;
1426# endif
1427#else
1428 return all_anno()->mac;
1429#endif
1430}
1431
1434inline bool
1436{
1437#if CLICK_LINUXMODULE
1438# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1439# if NET_SKBUFF_DATA_USES_OFFSET
1440 return skb()->network_header != (network_header_type) ~0U;
1441# else
1442 return skb()->network_header != 0;
1443# endif
1444# else
1445 return skb()->nh.raw != 0;
1446# endif
1447#else
1448 return all_anno()->nh != 0;
1449#endif
1450}
1451
1456inline const unsigned char *
1458{
1459#if CLICK_LINUXMODULE
1460# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1461 return skb_network_header(skb());
1462# else
1463 return skb()->nh.raw;
1464# endif
1465#else
1466 return all_anno()->nh;
1467#endif
1468}
1469
1472inline bool
1474{
1475#if CLICK_LINUXMODULE
1476# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1477# if NET_SKBUFF_DATA_USES_OFFSET
1478 return skb()->transport_header != (transport_header_type) ~0U;
1479# else
1480 return skb()->transport_header != 0;
1481# endif
1482# else
1483 return skb()->h.raw != 0;
1484# endif
1485#else
1486 return all_anno()->h != 0;
1487#endif
1488}
1489
1494inline const unsigned char *
1496{
1497#if CLICK_LINUXMODULE
1498# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1499 return skb_transport_header(skb());
1500# else
1501 return skb()->h.raw;
1502# endif
1503#else
1504 return all_anno()->h;
1505#endif
1506}
1507
1512inline const click_ether *
1514{
1515 return reinterpret_cast<const click_ether *>(mac_header());
1516}
1517
1522inline const click_ip *
1524{
1525 return reinterpret_cast<const click_ip *>(network_header());
1526}
1527
1532inline const click_ip6 *
1534{
1535 return reinterpret_cast<const click_ip6 *>(network_header());
1536}
1537
1542inline const click_icmp *
1544{
1545 return reinterpret_cast<const click_icmp *>(transport_header());
1546}
1547
1552inline const click_tcp *
1554{
1555 return reinterpret_cast<const click_tcp *>(transport_header());
1556}
1557
1562inline const click_udp *
1564{
1565 return reinterpret_cast<const click_udp *>(transport_header());
1566}
1567
1571inline int
1573{
1574 return end_data() - mac_header();
1575}
1576
1580inline int
1582{
1583 return end_data() - network_header();
1584}
1585
1589inline int
1591{
1592 return end_data() - transport_header();
1593}
1594
1595inline const Timestamp&
1597{
1598#if CLICK_LINUXMODULE
1599# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
1600 return *reinterpret_cast<const Timestamp*>(&skb()->stamp);
1601# else
1602 return *reinterpret_cast<const Timestamp*>(&skb()->tstamp);
1603# endif
1604#elif CLICK_PACKET_USE_DPDK
1605 return *(Timestamp*)&(TIMESTAMP_FIELD(mb()));
1606#else
1607 return *reinterpret_cast<const Timestamp*>(&all_anno()->timestamp);
1608#endif
1609}
1610
1611inline Timestamp&
1613{
1614#if CLICK_LINUXMODULE
1615# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 13)
1616 return *reinterpret_cast<Timestamp*>(&skb()->stamp);
1617# else
1618 return *reinterpret_cast<Timestamp*>(&skb()->tstamp);
1619# endif
1620#elif CLICK_PACKET_USE_DPDK
1621 return *(Timestamp*)&(TIMESTAMP_FIELD(mb()));
1622#else
1623 return *reinterpret_cast<Timestamp*>(&all_anno()->timestamp);
1624#endif
1625}
1626
1627inline void
1629{
1630 timestamp_anno() = timestamp;
1631}
1632
1633inline net_device *
1635{
1636#if CLICK_LINUXMODULE
1637 return skb()->dev;
1638#elif CLICK_BSDMODULE
1639 if (m())
1640 return m()->m_pkthdr.rcvif;
1641 else
1642 return 0;
1643#else
1644 return 0;
1645#endif
1646}
1647
1648inline void
1650{
1651#if CLICK_LINUXMODULE
1652 skb()->dev = dev;
1653#elif CLICK_BSDMODULE
1654 if (m())
1655 m()->m_pkthdr.rcvif = dev;
1656#else
1657 (void) dev;
1658#endif
1659}
1660
1661inline Packet::PacketType
1663{
1664#if CLICK_LINUXMODULE && PACKET_TYPE_MASK
1665 return (PacketType)(skb()->pkt_type & PACKET_TYPE_MASK);
1666#elif CLICK_LINUXMODULE
1667 return (PacketType)(skb()->pkt_type);
1668#else
1669 return all_anno()->pkt_type;
1670#endif
1671}
1672
1673inline void
1675{
1676#if CLICK_LINUXMODULE && PACKET_TYPE_MASK
1677 skb()->pkt_type = (skb()->pkt_type & PACKET_CLEAN) | p;
1678#elif CLICK_LINUXMODULE
1679 skb()->pkt_type = p;
1680#else
1681 all_anno()->pkt_type = p;
1682#endif
1683}
1684
1696inline WritablePacket *
1697Packet::make(const void *data, uint32_t length)
1698{
1699 return make(default_headroom, data, length, 0);
1700}
1701
1711inline WritablePacket *
1712Packet::make(uint32_t length)
1713{
1714 return make(default_headroom, (const unsigned char *) 0, length, 0);
1715}
1716
1717#if CLICK_LINUXMODULE
1736inline Packet *
1737Packet::make(struct sk_buff *skb)
1738{
1739 struct sk_buff *nskb;
1740 if (atomic_read(&skb->users) == 1) {
1741 skb_orphan(skb);
1742 nskb = skb;
1743 } else {
1744 nskb = skb_clone(skb, GFP_ATOMIC);
1745 atomic_dec(&skb->users);
1746 }
1747# if HAVE_SKB_LINEARIZE
1748# if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 17)
1749 if (nskb && skb_linearize(nskb, GFP_ATOMIC) != 0)
1750# else
1751 if (nskb && skb_linearize(nskb) != 0)
1752# endif
1753 {
1754 kfree_skb(nskb);
1755 nskb = 0;
1756 }
1757# endif
1758 return reinterpret_cast<Packet *>(nskb);
1759}
1760#endif
1761
1762#if CLICK_PACKET_USE_DPDK
1776inline Packet *
1777Packet::make(struct rte_mbuf *mb, bool clear)
1778{
1779 /* if (unlikely(mb->type != RTE_MBUF_PKT)) {
1780 click_chatter("cannot convert ctrlmbuf to Packet");
1781 return 0;
1782 }
1783 if (unlikely(!rte_pktmbuf_is_contiguous(mb))) {
1784 click_chatter("cannot convert multi-segment pktmbuf to Packet");
1785 return 0;
1786 }
1787 if (unlikely(rte_pktmbuf_tailroom(mb) < DPDK_ALL_ANNO_SIZE)) {
1788 click_chatter("not enough tailroom for Click annotations");
1789 return 0;
1790 }*/
1791 Packet *p = reinterpret_cast<Packet *>(mb);
1792 if (clear)
1793 p->clear_annotations();
1794 return p;
1795}
1796#endif
1797
1803inline void
1805{
1806#if CLICK_LINUXMODULE
1807 struct sk_buff *b = skb();
1808 b->next = b->prev = 0;
1809 # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
1810 b->list = 0;
1811 # endif
1812 skbmgr_recycle_skbs(b);
1813#elif CLICK_PACKET_USE_DPDK
1814 # if HAVE_FLOW_DYNAMIC
1815 if (fcb_stack) {
1816 fcb_stack->release(1);
1817 }
1818 # endif
1819 //Dpdk takes care of indirect and related things
1820 rte_pktmbuf_free(mb());
1821#elif HAVE_CLICK_PACKET_POOL && !defined(CLICK_FORCE_EXPENSIVE)
1822 # ifndef CLICK_NOINDIRECT
1823 if (_use_count.dec_and_test())
1824 # endif
1825 {
1826 WritablePacket::recycle(static_cast<WritablePacket *>(this));
1827 }
1828#else
1829 # if HAVE_FLOW_DYNAMIC
1830 if (fcb_stack) {
1831 fcb_stack->release(1);
1832 }
1833 # endif
1834 SFCB_STACK(
1835# ifndef CLICK_NOINDIRECT
1836 if (_use_count.dec_and_test())
1837# endif
1838 {
1839 delete this;
1840 }
1841 )
1842 #endif
1843}
1844
1852inline void
1854{
1855#if CLICK_LINUXMODULE
1856 struct sk_buff *b = skb();
1857 b->next = b->prev = 0;
1858 # if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 15)
1859 b->list = 0;
1860 # endif
1861 skbmgr_recycle_skbs(b);
1862#elif CLICK_PACKET_USE_DPDK
1863# if HAVE_FLOW_DYNAMIC
1864 if (fcb_stack) {
1865 fcb_stack->release(1);
1866 }
1867# endif
1868 rte_pktmbuf_free(mb());
1869#elif HAVE_CLICK_PACKET_POOL
1870
1871# ifndef CLICK_NOINDIRECT
1872 if (_use_count.nonatomic_dec_and_test())
1873# endif
1874 {
1875 WritablePacket::recycle(static_cast<WritablePacket *>(this));
1876
1877 }
1878#else
1879# if HAVE_FLOW_DYNAMIC
1880 if (fcb_stack) {
1881
1882 click_chatter("Release ksn");
1883 fcb_stack->release(1);
1884 }
1885# endif
1886 SFCB_STACK(
1887#ifndef CLICK_NOINDIRECT
1888 if (_use_count.nonatomic_dec_and_test())
1889#endif
1890 {
1891 delete this;
1892 }
1893 )
1894#endif
1895}
1896
1897
1898#if CLICK_BSDMODULE /* BSD kernel module */
1899inline void
1900Packet::assimilate_mbuf(Packet *p)
1901{
1902 struct mbuf *m = p->m();
1903
1904 if (!m) return;
1905
1906 p->_head = (unsigned char *)
1907 (m->m_flags & M_EXT ? m->m_ext.ext_buf :
1908 m->m_flags & M_PKTHDR ? m->m_pktdat :
1909 m->m_dat);
1910 p->_data = (unsigned char *)m->m_data;
1911 p->_tail = (unsigned char *)(m->m_data + m->m_len);
1912 p->_end = p->_head +
1913 (m->m_flags & M_EXT ? min(m->m_pkthdr.len, m->m_ext.ext_size) :
1914 m->m_flags & M_PKTHDR ? MHLEN :
1915 MLEN);
1916}
1917
1918inline void
1919Packet::assimilate_mbuf()
1920{
1921 assimilate_mbuf(this);
1922}
1923
1924inline Packet *
1925Packet::make(struct mbuf *m)
1926{
1927 if (!(m->m_flags & M_PKTHDR))
1928 panic("trying to construct Packet from a non-packet mbuf");
1929
1930 Packet *p = new Packet;
1931 if (!p) {
1932 m_freem(m);
1933 return 0;
1934 }
1935#ifndef CLICK_NOINDIRECT
1936 p->_use_count = 1;
1937 p->_data_packet = NULL;
1938#endif
1939 if (m->m_pkthdr.len != m->m_len) {
1940 struct mbuf *m2;
1941 /* click needs contiguous data */
1942
1943 if (m->m_pkthdr.len <= MCLBYTES) {
1944 // click_chatter("m_pulldown, Click needs contiguous data");
1945 m2 = m_pulldown(m, 0, m->m_pkthdr.len, NULL);
1946 if (m2 == NULL)
1947 panic("m_pulldown failed");
1948 if (m2 != m) {
1949 /*
1950 * XXX: m_pulldown ensures that the data is contiguous, but
1951 * it's not necessarily in the first mbuf in the chain.
1952 * Currently that's not OK for Click, so we need to
1953 * defragment the mbuf - which involves more copying etc.
1954 */
1955 m2 = m_defrag(m, M_DONTWAIT);
1956 if (m2 == NULL) {
1957 m_freem(m);
1958 delete p;
1959 return 0;
1960 }
1961 m = m2;
1962 }
1963 } else {
1964 m2 = p->dup_jumbo_m(m);
1965 m_freem(m);
1966 if (m2 == NULL) {
1967 delete p;
1968 return 0;
1969 }
1970 m = m2;
1971 }
1972 }
1973 p->_m = m;
1974 assimilate_mbuf(p);
1975
1976 return p;
1977}
1978#endif
1979
1984inline bool
1986{
1987#ifdef CLICK_NOINDIRECT
1988 return false;
1989#else
1990# if CLICK_LINUXMODULE
1991 return skb_cloned(const_cast<struct sk_buff *>(skb()));
1992# elif CLICK_PACKET_USE_DPDK
1993 return rte_mbuf_refcnt_read(mb()) > 1 || RTE_MBUF_INDIRECT(mb());
1994# else
1995 return (_data_packet || _use_count > 1);
1996# endif
1997#endif
1998}
1999
2004inline bool
2006{
2007#ifdef CLICK_NOINDIRECT
2008 return false;
2009#else
2010# if CLICK_LINUXMODULE
2011 return skb_cloned(const_cast<struct sk_buff *>(skb()));
2012# elif CLICK_PACKET_USE_DPDK
2013 return rte_mbuf_refcnt_read(mb()) > 1 || RTE_MBUF_INDIRECT(mb());
2014# else
2015 return (_data_packet || _use_count.nonatomic_value() > 1);
2016# endif
2017#endif
2018}
2019
2020
2021class PacketRef {
2022public:
2023 PacketRef(Packet* p) : _p(p->clone()) { }
2024 ~PacketRef() { if (_p) _p->kill(); }
2025 Packet* release() {
2026 Packet* tmp = _p;
2027 _p = NULL;
2028 return tmp;
2029 }
2030private:
2031 Packet* _p;
2032};
2033
2057inline WritablePacket *
2059{
2060#ifdef CLICK_NOINDIRECT
2061 return static_cast<WritablePacket *>(this);
2062#else
2063# ifdef CLICK_FORCE_EXPENSIVE
2064 PacketRef r(this);
2065# endif
2066 if (!shared())
2067 return static_cast<WritablePacket *>(this);
2068 else
2069 return expensive_uniqueify(0, 0, true);
2070#endif
2071}
2072
2073inline WritablePacket *
2074Packet::push(uint32_t len)
2075{
2076#ifdef CLICK_FORCE_EXPENSIVE
2077 PacketRef r(this);
2078#endif
2079 if (headroom() >= len && !shared()) {
2080 WritablePacket *q = (WritablePacket *)this;
2081#if CLICK_LINUXMODULE /* Linux kernel module */
2082 __skb_push(q->skb(), len);
2083#elif CLICK_PACKET_USE_DPDK
2084 rte_pktmbuf_prepend(q->mb(), len);
2085#else /* User-space and BSD kernel module */
2086 q->_data -= len;
2087# if CLICK_BSDMODULE
2088 q->m()->m_data -= len;
2089 q->m()->m_len += len;
2090 q->m()->m_pkthdr.len += len;
2091# endif
2092#endif
2093 return q;
2094 } else {
2095 return expensive_push(len);
2096 }
2097}
2098
2099inline Packet *
2101{
2102 if (headroom() >= len) {
2103#if CLICK_LINUXMODULE /* Linux kernel module */
2104 __skb_push(skb(), len);
2105#elif CLICK_PACKET_USE_DPDK
2106 rte_pktmbuf_prepend(mb(), len);
2107#else /* User-space and BSD kernel module */
2108 _data -= len;
2109# if CLICK_BSDMODULE
2110 m()->m_data -= len;
2111 m()->m_len += len;
2112 m()->m_pkthdr.len += len;
2113# endif
2114#endif
2115 return this;
2116 } else {
2117 return expensive_push(len);
2118 }
2119}
2120
2121inline void
2122Packet::pull(uint32_t len)
2123{
2124 if (len > length()) {
2125 click_chatter("Packet::pull %d > length %d\n", len, length());
2126 len = length();
2127 }
2128#if CLICK_LINUXMODULE /* Linux kernel module */
2129 __skb_pull(skb(), len);
2130#elif CLICK_PACKET_USE_DPDK
2131 mb()->data_off += len;
2132 mb()->data_len -= len;
2133 mb()->pkt_len -= len;
2134#else /* User-space and BSD kernel module */
2135 _data += len;
2136# if CLICK_BSDMODULE
2137 m()->m_data += len;
2138 m()->m_len -= len;
2139 m()->m_pkthdr.len -= len;
2140# endif
2141#endif
2142}
2143
2144inline WritablePacket *
2145Packet::put(uint32_t len)
2146{
2147#ifdef CLICK_FORCE_EXPENSIVE
2148 PacketRef r(this);
2149#endif
2150 if (tailroom() >= len && !shared()) {
2151 WritablePacket *q = (WritablePacket *)this;
2152#if CLICK_LINUXMODULE /* Linux kernel module */
2153 __skb_put(q->skb(), len);
2154#elif CLICK_PACKET_USE_DPDK
2155 rte_pktmbuf_append(q->mb(), len);
2156#else /* User-space and BSD kernel module */
2157 q->_tail += len;
2158# if CLICK_BSDMODULE
2159 q->m()->m_len += len;
2160 q->m()->m_pkthdr.len += len;
2161# endif
2162#endif
2163 return q;
2164 } else
2165 return expensive_put(len);
2166}
2167
2168inline Packet *
2170{
2171 if (tailroom() >= len) {
2172#if CLICK_LINUXMODULE /* Linux kernel module */
2173 __skb_put(skb(), len);
2174#elif CLICK_PACKET_USE_DPDK
2175 rte_pktmbuf_append(mb(), len);
2176#else /* User-space and BSD kernel module */
2177 _tail += len;
2178# if CLICK_BSDMODULE
2179 m()->m_len += len;
2180 m()->m_pkthdr.len += len;
2181# endif
2182#endif
2183 return this;
2184 } else
2185 return expensive_put(len);
2186}
2187
2188inline void
2189Packet::take(uint32_t len)
2190{
2191 if (len > length()) {
2192 click_chatter("Packet::take %d > length %d\n", len, length());
2193 len = length();
2194 }
2195#if CLICK_LINUXMODULE /* Linux kernel module */
2196 skb()->tail -= len;
2197 skb()->len -= len;
2198#elif CLICK_PACKET_USE_DPDK
2199 rte_pktmbuf_trim(mb(), len);
2200#else /* User-space and BSD kernel module */
2201 _tail -= len;
2202# if CLICK_BSDMODULE
2203 m()->m_len -= len;
2204 m()->m_pkthdr.len -= len;
2205# endif
2206#endif
2207}
2208
2209#if CLICK_USERLEVEL || CLICK_MINIOS
2235inline void
2236Packet::shrink_data(const unsigned char *data, uint32_t length)
2237{
2238# if CLICK_PACKET_USE_DPDK
2239 // TODO find a way to support both mbuf and real packets, a way to avoid
2240 // building files depending on this function, or at least update the doc
2241 (void) data;
2242 (void) length;
2243# else
2244
2245#ifndef CLICK_NOINDIRECT
2246 assert(_data_packet);
2247#endif
2248 if (data >= _head && data + length >= data && data + length <= _end) {
2249 _head = _data = const_cast<unsigned char *>(data);
2250 _tail = _end = const_cast<unsigned char *>(data + length);
2251 }
2252# endif
2253}
2254
2273inline void
2274Packet::change_headroom_and_length(uint32_t headroom, uint32_t length)
2275{
2276# if CLICK_PACKET_USE_DPDK
2277 rte_pktmbuf_prepend(mb(), this->headroom());
2278 rte_pktmbuf_adj(mb(), headroom);
2279 rte_pktmbuf_data_len(mb()) = length;
2280# else
2281 if (headroom + length <= buffer_length()) {
2282 _data = _head + headroom;
2283 _tail = _data + length;
2284 }
2285# endif
2286}
2287
2288inline void
2289Packet::change_buffer_length(uint32_t length)
2290{
2291# if CLICK_PACKET_USE_DPDK
2292 rte_panic("Not allowed with DPDK");
2293# else
2294 _end = _head + length;
2295#endif
2296}
2297#endif
2298
2299inline IPAddress
2301{
2302 return IPAddress(xanno()->u32[dst_ip_anno_offset / 4]);
2303}
2304
2305inline void
2307{
2308 xanno()->u32[dst_ip_anno_offset / 4] = a.addr();
2309}
2310
2313inline void
2314Packet::set_mac_header(const unsigned char *p)
2315{
2316 assert(p >= buffer() && p <= end_buffer());
2317#if CLICK_LINUXMODULE /* Linux kernel module */
2318# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2319 skb_set_mac_header(skb(), p - data());
2320# else
2321 skb()->mac.raw = const_cast<unsigned char *>(p);
2322# endif
2323#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2324 all_anno()->mac = const_cast<unsigned char *>(p);
2325#endif
2326}
2327
2332inline void
2333Packet::set_mac_header(const unsigned char *p, uint32_t len)
2334{
2335 assert(p >= buffer() && p + len <= end_buffer());
2336#if CLICK_LINUXMODULE /* Linux kernel module */
2337# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2338 skb_set_mac_header(skb(), p - data());
2339 skb_set_network_header(skb(), (p + len) - data());
2340# else
2341 skb()->mac.raw = const_cast<unsigned char *>(p);
2342 skb()->nh.raw = const_cast<unsigned char *>(p) + len;
2343# endif
2344#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2345 all_anno()->mac = const_cast<unsigned char *>(p);
2346 all_anno()->nh = const_cast<unsigned char *>(p) + len;
2347#endif
2348}
2349
2355inline void
2356Packet::set_ether_header(const click_ether *ethh)
2357{
2358 set_mac_header(reinterpret_cast<const unsigned char *>(ethh), 14);
2359}
2360
2364inline void
2366{
2367#if CLICK_LINUXMODULE /* Linux kernel module */
2368# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET
2369 skb()->mac_header = (mac_header_type) ~0U;
2370# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2371 skb()->mac_header = 0;
2372# else
2373 skb()->mac.raw = 0;
2374# endif
2375#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2376 all_anno()->mac = 0;
2377#endif
2378}
2379
2380inline WritablePacket *
2382{
2383#ifdef CLICK_FORCE_EXPENSIVE
2384 PacketRef r(this);
2385#endif
2386 WritablePacket *q;
2387 if (headroom() >= len && !shared()) {
2388 q = (WritablePacket *)this;
2389#if CLICK_LINUXMODULE /* Linux kernel module */
2390 __skb_push(q->skb(), len);
2391#elif CLICK_PACKET_USE_DPDK
2392 rte_pktmbuf_prepend(q->mb(), len);
2393#else /* User-space and BSD kernel module */
2394 q->_data -= len;
2395# if CLICK_BSDMODULE
2396 q->m()->m_data -= len;
2397 q->m()->m_len += len;
2398 q->m()->m_pkthdr.len += len;
2399# endif
2400#endif
2401 } else if ((q = expensive_push(len)))
2402 /* nada */;
2403 else
2404 return 0;
2405 q->set_mac_header(q->data(), len);
2406 return q;
2407}
2408
2412inline void
2413Packet::set_network_header(const unsigned char *p)
2414{
2415#if CLICK_LINUXMODULE /* Linux kernel module */
2416# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2417 skb_set_network_header(skb(), p - data());
2418# else
2419 skb()->nh.raw = const_cast<unsigned char *>(p);
2420# endif
2421#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2422 all_anno()->nh = const_cast<unsigned char *>(p);
2423#endif
2424}
2425
2429inline void
2430Packet::set_transport_header(const unsigned char *p)
2431{
2432#if CLICK_LINUXMODULE /* Linux kernel module */
2433# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2434 skb_set_transport_header(skb(), p - data());
2435# else
2436 skb()->h.raw = const_cast<unsigned char *>(p);
2437# endif
2438#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2439 all_anno()->h = const_cast<unsigned char *>(p);
2440#endif
2441}
2442
2447inline void
2448Packet::set_network_header(const unsigned char *p, uint32_t len)
2449{
2450 assert(p >= buffer() && p + len <= end_buffer());
2451#if CLICK_LINUXMODULE /* Linux kernel module */
2452# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2453 skb_set_network_header(skb(), p - data());
2454 skb_set_transport_header(skb(), (p + len) - data());
2455# else
2456 skb()->nh.raw = const_cast<unsigned char *>(p);
2457 skb()->h.raw = const_cast<unsigned char *>(p) + len;
2458# endif
2459#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2460 all_anno()->nh = const_cast<unsigned char *>(p);
2461 all_anno()->h = const_cast<unsigned char *>(p) + len;
2462#endif
2463}
2464
2471inline void
2473{
2474 assert(network_header() + len <= end_buffer());
2475#if CLICK_LINUXMODULE /* Linux kernel module */
2476# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2477 skb_set_transport_header(skb(), (network_header() + len) - data());
2478# else
2479 skb()->h.raw = skb()->nh.raw + len;
2480# endif
2481#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2482 all_anno()->h = all_anno()->nh + len;
2483#endif
2484}
2485
2492inline void
2493Packet::set_ip_header(const click_ip *iph, uint32_t len)
2494{
2495 set_network_header(reinterpret_cast<const unsigned char *>(iph), len);
2496}
2497
2504inline void
2505Packet::set_ip6_header(const click_ip6 *ip6h, uint32_t len)
2506{
2507 set_network_header(reinterpret_cast<const unsigned char *>(ip6h), len);
2508}
2509
2515inline void
2516Packet::set_ip6_header(const click_ip6 *ip6h)
2517{
2518 set_ip6_header(ip6h, 40);
2519}
2520
2524inline void
2526{
2527#if CLICK_LINUXMODULE /* Linux kernel module */
2528# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET
2529 skb()->network_header = (network_header_type) ~0U;
2530# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2531 skb()->network_header = 0;
2532# else
2533 skb()->nh.raw = 0;
2534# endif
2535#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2536 all_anno()->nh = 0;
2537#endif
2538}
2539
2543inline int
2545{
2546 return mac_header() - data();
2547}
2548
2555inline uint32_t
2557{
2558 return network_header() - mac_header();
2559}
2560
2564inline int
2566{
2567 return network_header() - data();
2568}
2569
2576inline uint32_t
2581
2586inline int
2588{
2589 return network_header_offset();
2590}
2591
2599inline uint32_t
2601{
2602 return network_header_length();
2603}
2604
2609inline int
2611{
2612 return network_header_offset();
2613}
2614
2622inline uint32_t
2624{
2625 return network_header_length();
2626}
2627
2631inline int
2633{
2634 return transport_header() - data();
2635}
2636
2640inline void
2642{
2643#if CLICK_LINUXMODULE /* Linux kernel module */
2644# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET
2645 skb()->transport_header = (transport_header_type) ~0U;
2646# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2647 skb()->transport_header = 0;
2648# else
2649 skb()->h.raw = 0;
2650# endif
2651#else /* User-space and BSD kernel module and CLICK_PACKET_USE_DPDK */
2652 all_anno()->h = 0;
2653#endif
2654}
2655
2656inline void
2657Packet::shift_header_annotations(const unsigned char *old_head,
2658 int32_t extra_headroom)
2659{
2660#if CLICK_LINUXMODULE
2661 struct sk_buff *mskb = skb();
2662 /* From Linux 2.6.24 - 3.10, the header offsets are integers if
2663 * NET_SKBUFF_DATA_USES_OFFSET is 1. From 3.11 onward, they're
2664 * always integers. */
2665# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && NET_SKBUFF_DATA_USES_OFFSET) || \
2666 (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
2667 (void) old_head;
2668 mskb->mac_header += (mskb->mac_header == (mac_header_type) ~0U ? 0 : extra_headroom);
2669 mskb->network_header += (mskb->network_header == (network_header_type) ~0U ? 0 : extra_headroom);
2670 mskb->transport_header += (mskb->transport_header == (transport_header_type) ~0U ? 0 : extra_headroom);
2671# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
2672 ptrdiff_t shift = (mskb->head - old_head) + extra_headroom;
2673 mskb->mac_header += (mskb->mac_header ? shift : 0);
2674 mskb->network_header += (mskb->network_header ? shift : 0);
2675 mskb->transport_header += (mskb->transport_header ? shift : 0);
2676# else
2677 ptrdiff_t shift = (mskb->head - old_head) + extra_headroom;
2678 mskb->mac.raw += (mskb->mac.raw ? shift : 0);
2679 mskb->nh.raw += (mskb->nh.raw ? shift : 0);
2680 mskb->h.raw += (mskb->h.raw ? shift : 0);
2681# endif
2682#elif CLICK_PACKET_USE_DPDK
2683 ptrdiff_t shift = (buffer() - old_head) + extra_headroom;
2684 all_anno()->mac += (all_anno()->mac ? shift : 0);
2685 all_anno()->nh += (all_anno()->nh ? shift : 0);
2686 all_anno()->h += (all_anno()->h ? shift : 0);
2687#else
2688 ptrdiff_t shift = (_head - old_head) + extra_headroom;
2689 all_anno()->mac += (all_anno()->mac ? shift : 0);
2690 all_anno()->nh += (all_anno()->nh ? shift : 0);
2691 all_anno()->h += (all_anno()->h ? shift : 0);
2692#endif
2693}
2694
2698inline const unsigned char *
2699Packet::buffer_data() const
2700{
2701 return buffer();
2702}
2703
2708inline void *Packet::addr_anno() {
2709 return anno_u8() + addr_anno_offset;
2710}
2711
2713inline const void *Packet::addr_anno() const {
2714 return anno_u8() + addr_anno_offset;
2715}
2716
2721inline void *Packet::user_anno() {
2722 return anno_u8() + user_anno_offset;
2723}
2724
2726inline const void *Packet::user_anno() const {
2727 return anno_u8() + user_anno_offset;
2728}
2729
2732inline uint8_t *Packet::user_anno_u8() {
2733 return anno_u8() + user_anno_offset;
2734}
2735
2737inline const uint8_t *Packet::user_anno_u8() const {
2738 return anno_u8() + user_anno_offset;
2739}
2740
2743inline uint32_t *Packet::user_anno_u32() {
2744 return anno_u32() + user_anno_offset / 4;
2745}
2746
2748inline const uint32_t *Packet::user_anno_u32() const {
2749 return anno_u32() + user_anno_offset / 4;
2750}
2751
2756inline uint8_t Packet::user_anno_u8(int i) const {
2757 return anno_u8(user_anno_offset + i);
2758}
2759
2765inline void Packet::set_user_anno_u8(int i, uint8_t v) {
2766 set_anno_u8(user_anno_offset + i, v);
2767}
2768
2775inline uint16_t Packet::user_anno_u16(int i) const {
2776 return anno_u16(user_anno_offset + i * 2);
2777}
2778
2786inline void Packet::set_user_anno_u16(int i, uint16_t v) {
2787 set_anno_u16(user_anno_offset + i * 2, v);
2788}
2789
2796inline uint32_t Packet::user_anno_u32(int i) const {
2797 return anno_u32(user_anno_offset + i * 4);
2798}
2799
2807inline void Packet::set_user_anno_u32(int i, uint32_t v) {
2808 set_anno_u32(user_anno_offset + i * 4, v);
2809}
2810
2817inline int32_t Packet::user_anno_s32(int i) const {
2818 return anno_s32(user_anno_offset + i * 4);
2819}
2820
2828inline void Packet::set_user_anno_s32(int i, int32_t v) {
2829 set_anno_s32(user_anno_offset + i * 4, v);
2830}
2831
2832#if HAVE_INT64_TYPES
2839inline uint64_t Packet::user_anno_u64(int i) const {
2840 return anno_u64(user_anno_offset + i * 8);
2841}
2842
2850inline void Packet::set_user_anno_u64(int i, uint64_t v) {
2851 set_anno_u64(user_anno_offset + i * 8, v);
2852}
2853#endif
2854
2857inline const uint8_t *Packet::all_user_anno() const {
2858 return anno_u8() + user_anno_offset;
2859}
2860
2863inline uint8_t *Packet::all_user_anno() {
2864 return anno_u8() + user_anno_offset;
2865}
2866
2869inline const uint32_t *Packet::all_user_anno_u() const {
2870 return anno_u32() + user_anno_offset / 4;
2871}
2872
2875inline uint32_t *Packet::all_user_anno_u() {
2876 return anno_u32() + user_anno_offset / 4;
2877}
2878
2881inline uint8_t Packet::user_anno_c(int i) const {
2882 return anno_u8(user_anno_offset + i);
2883}
2884
2887inline void Packet::set_user_anno_c(int i, uint8_t v) {
2888 set_anno_u8(user_anno_offset + i, v);
2889}
2890
2893inline uint16_t Packet::user_anno_us(int i) const {
2894 return anno_u16(user_anno_offset + i * 2);
2895}
2896
2899inline void Packet::set_user_anno_us(int i, uint16_t v) {
2900 set_anno_u16(user_anno_offset + i * 2, v);
2901}
2902
2905inline int16_t Packet::user_anno_s(int i) const {
2906 return (int16_t) anno_u16(user_anno_offset + i * 2);
2907}
2908
2911inline void Packet::set_user_anno_s(int i, int16_t v) {
2912 set_anno_u16(user_anno_offset + i * 2, v);
2913}
2914
2917inline uint32_t Packet::user_anno_u(int i) const {
2918 return anno_u32(user_anno_offset + i * 4);
2919}
2920
2923inline void Packet::set_user_anno_u(int i, uint32_t v) {
2924 set_anno_u32(user_anno_offset + i * 4, v);
2925}
2926
2929inline int32_t Packet::user_anno_i(int i) const {
2930 return anno_s32(user_anno_offset + i * 4);
2931}
2932
2935inline void Packet::set_user_anno_i(int i, int32_t v) {
2936 set_anno_s32(user_anno_offset + i * 4, v);
2937}
2940inline unsigned char *
2942{
2943 return const_cast<unsigned char *>(Packet::data());
2944}
2945
2946inline unsigned char *
2947WritablePacket::end_data() const
2948{
2949 return const_cast<unsigned char *>(Packet::end_data());
2950}
2951
2952inline unsigned char *
2953WritablePacket::buffer() const
2954{
2955 return const_cast<unsigned char *>(Packet::buffer());
2956}
2957
2958inline unsigned char *
2959WritablePacket::end_buffer() const
2960{
2961 return const_cast<unsigned char *>(Packet::end_buffer());
2962}
2963
2964inline unsigned char *
2965WritablePacket::mac_header() const
2966{
2967 return const_cast<unsigned char *>(Packet::mac_header());
2968}
2969
2970inline unsigned char *
2971WritablePacket::network_header() const
2972{
2973 return const_cast<unsigned char *>(Packet::network_header());
2974}
2975
2976inline unsigned char *
2977WritablePacket::transport_header() const
2978{
2979 return const_cast<unsigned char *>(Packet::transport_header());
2980}
2981
2982inline click_ether *
2983WritablePacket::ether_header() const
2984{
2985 return const_cast<click_ether *>(Packet::ether_header());
2986}
2987
2988inline click_ip *
2989WritablePacket::ip_header() const
2990{
2991 return const_cast<click_ip *>(Packet::ip_header());
2992}
2993
2994inline click_ip6 *
2995WritablePacket::ip6_header() const
2996{
2997 return const_cast<click_ip6 *>(Packet::ip6_header());
2998}
2999
3000inline click_icmp *
3001WritablePacket::icmp_header() const
3002{
3003 return const_cast<click_icmp *>(Packet::icmp_header());
3004}
3005
3006inline click_tcp *
3007WritablePacket::tcp_header() const
3008{
3009 return const_cast<click_tcp *>(Packet::tcp_header());
3010}
3011
3012inline click_udp *
3013WritablePacket::udp_header() const
3014{
3015 return const_cast<click_udp *>(Packet::udp_header());
3016}
3017
3019inline unsigned char *
3020WritablePacket::buffer_data() const
3021{
3022 return const_cast<unsigned char *>(Packet::buffer());
3023}
3026#if !CLICK_LINUXMODULE
3027inline void
3028WritablePacket::init_buffer(unsigned char *data, uint32_t buffer_length, uint32_t data_length) {
3029# if CLICK_PACKET_USE_DPDK
3030 rte_panic("Not allowed with DPDK");
3031# else
3032 _head = _data = data;
3033 _tail = data + data_length;
3034 _end = data + buffer_length;
3035# endif
3036}
3037inline void
3038WritablePacket::set_buffer(unsigned char* buffer, uint32_t buffer_length) {
3039# if CLICK_PACKET_USE_DPDK
3040 rte_panic("Not allowed with DPDK");
3041# else
3042 _head = buffer;
3043 _end = buffer +buffer_length;
3044# endif
3045}
3046inline void
3047WritablePacket::set_data(unsigned char* data) {
3048# if CLICK_PACKET_USE_DPDK
3049 rte_panic("Not allowed with DPDK");
3050# else
3051 _data = data;
3052# endif
3053}
3054inline void
3055WritablePacket::set_data_length(uint32_t data_length) {
3056# if CLICK_PACKET_USE_DPDK
3057 rte_panic("Not allowed with DPDK");
3058# else
3059 _tail = _data + data_length;
3060# endif
3061}
3062#endif
3063
3064inline void
3065WritablePacket::rewrite_ips(IPPair pair, bool is_tcp) {
3066 assert(this->network_header());
3067 uint16_t *x = reinterpret_cast<uint16_t *>(&this->ip_header()->ip_src);
3068 uint32_t old_hw = (uint32_t) x[0] + x[1] + x[2] + x[3];
3069 old_hw += (old_hw >> 16);
3070
3071 memcpy(x, &pair, 8);
3072
3073 uint32_t new_hw = (uint32_t) x[0] + x[1] + x[2] + x[3];
3074 new_hw += (new_hw >> 16);
3075 click_ip *iph = this->ip_header();
3076 click_update_in_cksum(&iph->ip_sum, old_hw, new_hw);
3077 if (is_tcp)
3078 click_update_in_cksum(&this->tcp_header()->th_sum, old_hw, new_hw);
3079 else
3080 click_update_in_cksum(&this->udp_header()->uh_sum, old_hw, new_hw);
3081}
3082
3083inline void
3084WritablePacket::rewrite_ips_ports(IPPair pair, uint16_t sport, uint16_t dport, bool is_tcp) {
3085 assert(this->network_header());
3086 assert(this->transport_header());
3087 uint32_t old_hw, t_old_hw;
3088 uint32_t new_hw, t_new_hw;
3089
3090 uint16_t *xip = reinterpret_cast<uint16_t *>(&this->ip_header()->ip_src);
3091 old_hw = (uint32_t) xip[0] + xip[1] + xip[2] + xip[3];
3092 t_old_hw = old_hw;
3093 old_hw += (old_hw >> 16);
3094
3095 memcpy(xip, &pair, 8);
3096
3097 new_hw = (uint32_t) xip[0] + xip[1] + xip[2] + xip[3];
3098 t_new_hw = new_hw;
3099 new_hw += (new_hw >> 16);
3100 click_ip *iph = this->ip_header();
3101 click_update_in_cksum(&iph->ip_sum, old_hw, new_hw);
3102
3103 uint16_t *xport = reinterpret_cast<uint16_t *>(&this->tcp_header()->th_sport);
3104 t_old_hw += (uint32_t) xport[0] + xport[1];
3105 t_old_hw += (t_old_hw >> 16);
3106 if (sport)
3107 xport[0] = sport;
3108 if (dport)
3109 xport[1] = dport;
3110 t_new_hw += (uint32_t) xport[0] + xport[1];
3111 t_new_hw += (t_new_hw >> 16);
3112
3113 if (is_tcp)
3114 click_update_in_cksum(&this->tcp_header()->th_sum, t_old_hw, t_new_hw);
3115 else
3116 click_update_in_cksum(&this->udp_header()->uh_sum, t_old_hw, t_new_hw);
3117}
3118
3119//shift : 0 for source, 1 for dst
3120inline void
3121WritablePacket::rewrite_ipport(IPAddress ip, uint16_t port,const int shift, bool is_tcp) {
3122 assert(this->network_header());
3123 assert(this->transport_header());
3124 uint32_t old_hw, t_old_hw;
3125 uint32_t new_hw, t_new_hw;
3126
3127 uint16_t *xip = reinterpret_cast<uint16_t *>(&this->ip_header()->ip_src);
3128 old_hw = (uint32_t) xip[(shift * 2) + 0] + xip[(shift*2) + 1];
3129 t_old_hw = old_hw;
3130 old_hw += (old_hw >> 16);
3131
3132 memcpy(&xip[shift*2], &ip, 4);
3133
3134 new_hw = (uint32_t) xip[(shift*2) + 0] + xip[(shift*2) + 1];
3135 t_new_hw = new_hw;
3136 new_hw += (new_hw >> 16);
3137 click_ip *iph = this->ip_header();
3138 click_update_in_cksum(&iph->ip_sum, old_hw, new_hw);
3139
3140 uint16_t *xport = reinterpret_cast<uint16_t *>(&this->tcp_header()->th_sport);
3141 t_old_hw += (uint32_t) xport[shift + 0];
3142 t_old_hw += (t_old_hw >> 16);
3143 xport[shift + 0] = port;
3144 t_new_hw += (uint32_t) xport[shift + 0];
3145 t_new_hw += (t_new_hw >> 16);
3146
3147 if (is_tcp)
3148 click_update_in_cksum(&this->tcp_header()->th_sum, t_old_hw, t_new_hw);
3149 else
3150 click_update_in_cksum(&this->udp_header()->uh_sum, t_old_hw, t_new_hw);
3151}
3152
3153//shift : 0 for source, 1 for dst
3154inline void
3155WritablePacket::rewrite_ip(IPAddress ip, const int shift, bool is_tcp) {
3156 assert(this->network_header());
3157 assert(this->transport_header());
3158 uint32_t old_hw, t_old_hw;
3159 uint32_t new_hw, t_new_hw;
3160
3161 uint16_t *xip = reinterpret_cast<uint16_t *>(&this->ip_header()->ip_src);
3162 old_hw = (uint32_t) xip[(shift * 2) + 0] + xip[(shift*2) + 1];
3163 t_old_hw = old_hw;
3164 old_hw += (old_hw >> 16);
3165
3166 memcpy(&xip[shift*2], &ip, 4);
3167
3168 new_hw = (uint32_t) xip[(shift*2) + 0] + xip[(shift*2) + 1];
3169 t_new_hw = new_hw;
3170 new_hw += (new_hw >> 16);
3171 click_ip *iph = this->ip_header();
3172 click_update_in_cksum(&iph->ip_sum, old_hw, new_hw);
3173
3174 if (is_tcp)
3175 click_update_in_cksum(&this->tcp_header()->th_sum, t_old_hw, t_new_hw);
3176 else
3177 click_update_in_cksum(&this->udp_header()->uh_sum, t_old_hw, t_new_hw);
3178}
3179
3180//0 for seq, 1 for ack
3181inline void
3182WritablePacket::rewrite_seq(tcp_seq_t seq, const int shift) {
3183 assert(this->network_header());
3184 assert(this->transport_header());
3185 uint32_t t_old_hw = 0;
3186 uint32_t t_new_hw = 0;
3187
3188 uint16_t *xseq = reinterpret_cast<uint16_t *>(&this->tcp_header()->th_seq);
3189 t_old_hw = (uint32_t) xseq[shift * 2];
3190 t_old_hw += (t_old_hw >> 16);
3191 memcpy(&xseq[shift*2], &seq, 4);
3192 t_new_hw = (uint32_t) xseq[shift * 2];
3193 t_new_hw += (t_new_hw >> 16);
3194
3195 click_update_in_cksum(&this->tcp_header()->th_sum, t_old_hw, t_new_hw);
3196}
3197
3199
3200inline unsigned char* WritablePacket::getPacketContent()
3201{
3202 uint16_t offset = getContentOffset();
3203
3204 return (data() + offset);
3205}
3206
3207
3208inline const unsigned char* Packet::getPacketContent()
3209{
3210 uint16_t offset = getContentOffset();
3211
3212 return (data() + offset);
3213}
3214
3215inline bool Packet::isPacketContentEmpty() const
3216{
3217 uint16_t offset = getContentOffset();
3218
3219 if(offset >= length())
3220 return true;
3221 else
3222 return false;
3223}
3224
3225inline uint16_t Packet::getPacketContentSize() const
3226{
3227 uint16_t offset = getContentOffset();
3228
3229 return length() - offset;
3230}
3231
3232inline void Packet::setContentOffset(uint16_t offset)
3233{
3234 set_anno_u16(MIDDLEBOX_CONTENTOFFSET_OFFSET, offset);
3235}
3236
3237inline uint16_t Packet::getContentOffset() const
3238{
3239 return anno_u16(MIDDLEBOX_CONTENTOFFSET_OFFSET);
3240}
3241
3242
3243
3244CLICK_ENDDECLS
3245#endif
An atomic 32-bit integer.
An IPv4 address.
Definition ipaddress.hh:16
uint32_t addr() const
Return the address as a uint32_t in network byte order.
Definition ipaddress.hh:97
Definition packetbatch.hh:415
A network packet.
Definition packet.hh:68
int ip6_header_offset() const
Return the offset from the packet data to the IPv6 header.
Definition packet.hh:2610
const unsigned char * end_buffer() const
Return the packet's end data buffer pointer.
Definition packet.hh:1259
void shrink_data(const unsigned char *data, uint32_t length)
Shrink the packet's data.
Definition packet.hh:2236
void set_ip6_header(const click_ip6 *ip6h)
Set the network header pointer to an IPv6 header.
Definition packet.hh:2516
uint32_t mac_header_length() const
Return the MAC header length.
Definition packet.hh:2556
void clear_transport_header()
Unset the transport header pointer.
Definition packet.hh:2641
void set_anno_u16(int i, uint16_t x)
Set 16-bit annotation at offset i.
Definition packet.hh:636
uint8_t anno_u8(int i) const
Return annotation byte at offset i.
Definition packet.hh:602
static WritablePacket * make(uint32_t headroom, const void *data, uint32_t length, uint32_t tailroom, bool clear=true)
Create and return a new packet.
Definition packet.cc:911
const unsigned char * mac_header() const
Return the packet's MAC header pointer.
Definition packet.hh:1419
void set_anno_u64(int i, uint64_t x)
Set 64-bit annotation at offset i.
Definition packet.hh:748
void set_anno_u32(int i, uint32_t x)
Set 32-bit annotation at offset i.
Definition packet.hh:692
void set_mac_header(const unsigned char *p)
Set the MAC header pointer.
Definition packet.hh:2314
uint32_t anno_u32(int i) const
Return 32-bit annotation at offset i.
Definition packet.hh:677
const click_icmp * icmp_header() const
Return the packet's transport header pointer as ICMP.
Definition packet.hh:1543
WritablePacket * put(uint32_t len)
Add space for data after the packet.
Definition packet.hh:2145
uint32_t * anno_u32()
Return a pointer to the annotation area as uint32_ts.
Definition packet.hh:595
uint16_t anno_u16(int i) const
Return 16-bit annotation at offset i.
Definition packet.hh:621
net_device * device_anno() const
Return the device annotation.
Definition packet.hh:1634
const void * anno() const
Definition packet.hh:586
void * anno_ptr(int i) const
Return void * sized annotation at offset i.
Definition packet.hh:762
bool shared_nonatomic() const
Test whether this packet's data is shared.
Definition packet.hh:2005
void set_dst_ip_anno(IPAddress addr)
Set the destination IPv4 address annotation.
Definition packet.hh:2306
int32_t anno_s32(int i) const
Return 32-bit annotation at offset i.
Definition packet.hh:704
const click_tcp * tcp_header() const
Return the packet's transport header pointer as TCP.
Definition packet.hh:1553
WritablePacket * push_mac_header(uint32_t len)
Add space for a MAC header before the packet.
Definition packet.hh:2381
uint32_t tailroom() const
Return the packet's tailroom.
Definition packet.hh:1308
int16_t anno_s16(int i) const
Return 16-bit annotation at offset i.
Definition packet.hh:649
void kill()
Delete this packet.
Definition packet.hh:1804
void set_next(Packet *p)
Set the next packet annotation.
Definition packet.hh:1351
void pull(uint32_t len)
Remove a header from the front of the packet.
Definition packet.hh:2122
uint64_t anno_u64(int i) const
Return 64-bit annotation at offset i.
Definition packet.hh:733
void set_anno_s32(int i, int32_t x)
Set 32-bit annotation at offset i.
Definition packet.hh:719
uint8_t * anno_u8()
Return a pointer to the annotation area as uint8_ts.
Definition packet.hh:589
Packet * nonunique_push(uint32_t len)
Add space for a header before the packet.
Definition packet.hh:2100
const click_ip6 * ip6_header() const
Return the packet's network header pointer as IPv6.
Definition packet.hh:1533
const click_ip * ip_header() const
Return the packet's network header pointer as IPv4.
Definition packet.hh:1523
Packet * prev() const
Return the previous packet annotation.
Definition packet.hh:1363
const unsigned char * network_header() const
Return the packet's network header pointer.
Definition packet.hh:1457
void set_anno_s16(int i, int16_t x)
Set 16-bit annotation at offset i.
Definition packet.hh:664
void copy_annotations(const Packet *, bool all=true)
Copy most packet annotations from p.
Definition packet.hh:1156
WritablePacket * push(uint32_t len)
Add space for a header before the packet.
Definition packet.hh:2074
void set_transport_header(const unsigned char *p)
Set the transport header.
Definition packet.hh:2430
WritablePacket * uniqueify()
Return an unshared packet containing this packet's data.
Definition packet.hh:2058
Packet * shift_data(int offset, bool free_on_failure=true)
Shift packet data within the data buffer.
Definition packet.cc:1510
void set_anno_ptr(int i, const void *x)
Set void * sized annotation at offset i.
Definition packet.hh:777
int mac_header_offset() const
Return the offset from the packet data to the MAC header.
Definition packet.hh:2544
void set_ether_header(const click_ether *ethh)
Set the MAC header pointer to an Ethernet header.
Definition packet.hh:2356
const unsigned char * buffer() const
Return a pointer to the packet's data buffer.
Definition packet.hh:1243
void set_network_header_length(uint32_t len)
Set the network header length.
Definition packet.hh:2472
void change_headroom_and_length(uint32_t headroom, uint32_t length)
Shift the packet's data view to a different part of its buffer.
Definition packet.hh:2274
const unsigned char * end_data() const
Return the packet's end data pointer.
Definition packet.hh:1223
void set_device_anno(net_device *dev)
Set the device annotation.
Definition packet.hh:1649
const unsigned char * data() const
Return the packet's data pointer.
Definition packet.hh:1207
static void empty_destructor(unsigned char *, size_t, void *)
Definition packet.cc:1044
int ip_header_offset() const
Return the offset from the packet data to the IP header.
Definition packet.hh:2587
void kill_nonatomic()
Delete this packet in a thread-safe context.
Definition packet.hh:1853
PacketType
Values for packet_type_anno(). Must agree with Linux's PACKET_ constants in <linux/if_packet....
Definition packet.hh:490
@ OTHERHOST
Definition packet.hh:496
@ OUTGOING
Definition packet.hh:499
@ MULTICAST
Definition packet.hh:494
@ HOST
Definition packet.hh:491
@ BROADCAST
Definition packet.hh:492
Packet * clone(bool fast=false)
Create a clone of this packet.
Definition packet.cc:1104
const uint8_t * anno_u8() const
overload
Definition packet.hh:592
uint32_t ip6_header_length() const
Return the IPv6 header length.
Definition packet.hh:2623
uint32_t length() const
Return the packet's length.
Definition packet.hh:1276
int network_header_offset() const
Return the offset from the packet data to the network header.
Definition packet.hh:2565
@ anno_size
Size of annotation area.
Definition packet.hh:472
const click_udp * udp_header() const
Return the packet's transport header pointer as UDP.
Definition packet.hh:1563
void * anno()
Return a pointer to the annotation area.
Definition packet.hh:583
void take(uint32_t len)
Remove space from the end of the packet.
Definition packet.hh:2189
bool has_transport_header() const
Return true iff the packet's transport header pointer is set.
Definition packet.hh:1473
const unsigned char * transport_header() const
Return the packet's transport header pointer.
Definition packet.hh:1495
PacketType packet_type_anno() const
Return the packet type annotation.
Definition packet.hh:1662
void clear_mac_header()
Unset the MAC header pointer.
Definition packet.hh:2365
void set_ip_header(const click_ip *iph, uint32_t len)
Set the network header pointer to an IPv4 header.
Definition packet.hh:2493
bool has_mac_header() const
Return true iff the packet's MAC header pointer is set.
Definition packet.hh:1401
void set_anno_u8(int i, uint8_t x)
Set annotation byte at offset i.
Definition packet.hh:611
IPAddress dst_ip_anno() const
Return the destination IPv4 address annotation.
Definition packet.hh:2300
uint32_t ip_header_length() const
Return the IP header length.
Definition packet.hh:2600
int transport_header_offset() const
Return the offset from the packet data to the transport header.
Definition packet.hh:2632
const Timestamp & timestamp_anno() const
Return the timestamp annotation.
Definition packet.hh:1596
void set_network_header(const unsigned char *p)
Set the network header.
Definition packet.hh:2413
Packet * next() const
Return the next packet annotation.
Definition packet.hh:1327
Packet * nonunique_put(uint32_t len)
Add space for data after the packet.
Definition packet.hh:2169
bool copy(Packet *p, int headroom=0)
Copy the content and annotations of another packet (userlevel) into this packet.
Definition packet.cc:1064
uint32_t headroom() const
Return the packet's headroom.
Definition packet.hh:1293
bool shared() const
Test whether this packet's data is shared.
Definition packet.hh:1985
void clear_annotations(bool all=true)
Clear all packet annotations.
Definition packet.hh:1123
void set_packet_type_anno(PacketType t)
Set the packet type annotation.
Definition packet.hh:1674
int transport_length() const
Return the packet's length starting from its transport header pointer.
Definition packet.hh:1590
bool has_network_header() const
Return true iff the packet's network header pointer is set.
Definition packet.hh:1435
uint32_t buffer_length() const
Return the packet's buffer length.
Definition packet.hh:1321
void clear_network_header()
Unset the network header pointer.
Definition packet.hh:2525
@ default_headroom
Definition packet.hh:82
@ min_buffer_length
Definition packet.hh:85
void set_timestamp_anno(const Timestamp &t)
Set the timestamp annotation.
Definition packet.hh:1628
int mac_length() const
Return the packet's length starting from its MAC header pointer.
Definition packet.hh:1572
void set_prev(Packet *p)
Set the previous packet annotation.
Definition packet.hh:1387
int network_length() const
Return the packet's length starting from its network header pointer.
Definition packet.hh:1581
const uint32_t * anno_u32() const
overload
Definition packet.hh:598
uint32_t network_header_length() const
Return the network header length.
Definition packet.hh:2577
const click_ether * ether_header() const
Return the packet's MAC header pointer as Ethernet.
Definition packet.hh:1513
Represents a moment or interval in time.
Definition timestamp.hh:125
A network packet believed not to be shared.
Definition packet.hh:1004
unsigned char * data() const
Definition packet.hh:2941
static void pool_transfer(int from, int to)
Definition packet.cc:836
void rewrite_ips(IPPair pair, bool is_tcp=true)
Definition packet.hh:3065
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
The IPAddress type for IPv4 addresses.
The Timestamp class represents a moment or interval in time.