2#ifndef CLICK_PACKETBATCH_HH
3#define CLICK_PACKETBATCH_HH
12#define FOR_EACH_PACKET_LL(first,p) for(Packet* p = first;p != 0;p=p->next())
18#define FOR_EACH_PACKET(batch,p) FOR_EACH_PACKET_LL(batch->first(),p)
25#define FOR_EACH_PACKET_LL_SAFE(first,p) \
26 Packet* fep_next = ((first != 0)? first->next() : 0 );\
28 for (;p != 0;p=fep_next,fep_next=(p==0?0:p->next()))
31#define FOR_EACH_PACKET_SAFE(batch,p) FOR_EACH_PACKET_LL_SAFE(batch->first(),p)
38#define EXECUTE_FOR_EACH_PACKET(fnt,batch) \
39 Packet* efep_next = ((batch != 0)? batch->first()->next() : 0 );\
40 Packet* p = batch->first();\
42 for (;p != 0;p=efep_next,efep_next=(p==0?0:p->next())) {\
48 batch = reinterpret_cast<PacketBatch*>(q);\
50 q->set_next(efep_next);\
62#define EXECUTE_FOR_EACH_PACKET_UNTIL_DO(fnt,batch,on_stop) \
63 Packet* efep_next = ((batch != 0)? batch->first()->next() : 0 );\
64 Packet* p = batch->first();\
66 int count = batch->count();\
67 for (;p != 0;p=efep_next,efep_next=(p==0?0:p->next())) {\
74 batch = reinterpret_cast<PacketBatch*>(q);\
75 batch->set_count(count);\
77 q->set_next(efep_next);\
79 if (unlikely(drop)) {\
80 on_stop(batch, q, efep_next);\
87#define EXECUTE_FOR_EACH_PACKET_UNTIL(fnt,batch) \
88 EXECUTE_FOR_EACH_PACKET_UNTIL_DO(fnt, batch, [](PacketBatch*& batch, Packet*, Packet*){batch->kill();batch = 0;})
94#define EXECUTE_FOR_EACH_PACKET_UNTIL_DROP(fnt,batch) \
95 EXECUTE_FOR_EACH_PACKET_UNTIL_DO(fnt, batch, [](PacketBatch*& batch, Packet* dropped, Packet* next){ if (!next) return; PacketBatch* remain = PacketBatch::make_from_simple_list(next);batch->set_count(batch->count() - remain->count()); batch->set_tail(dropped); dropped->set_next(0); remain->kill(); })
113#define EXECUTE_FOR_EACH_PACKET_DROPPABLE(fnt,batch,on_drop) {\
114 Packet* efepd_next = ((batch != 0)? batch->first()->next() : 0 );\
115 Packet* p = batch->first();\
117 int count = batch->count();\
118 for (;p != 0;p=efepd_next,efepd_next=(p==0?0:p->next())) {\
123 last->set_next(efepd_next);\
125 batch = PacketBatch::start_head(efepd_next);\
129 } else if (q != p) {\
133 batch = reinterpret_cast<PacketBatch*>(q);\
135 q->set_next(efepd_next);\
140 batch->set_count(count);\
141 batch->set_tail(last);\
150#define EXECUTE_FOR_EACH_PACKET_DROP_LIST(fnt,batch,drop_list) \
151 PacketBatch* drop_list = 0;\
152 auto on_drop = [&drop_list](Packet* p) {\
153 if (drop_list == 0) {\
154 drop_list = PacketBatch::make_from_packet(p);\
156 drop_list->append_packet(p);\
159 EXECUTE_FOR_EACH_PACKET_DROPPABLE(fnt,batch,on_drop);
172#define EXECUTE_FOR_EACH_PACKET_SPLITTABLE(fnt,batch,on_drop,on_flush) {\
173 Packet* next = ((batch != 0)? batch->first()->next() : 0 );\
174 Packet* p = batch->first();\
177 for (;p != 0;p=next,next=(p==0?0:p->next())) {\
178 Packet* q = (fnt(p));\
181 batch->set_count(count);\
182 batch->set_tail(last);\
188 batch = PacketBatch::start_head(next);\
190 } else if (q != p) {\
194 batch = reinterpret_cast<PacketBatch*>(q);\
202 batch->set_count(count);\
203 batch->set_tail(last);\
218#define EXECUTE_FOR_EACH_PACKET_ADD(fnt,batch) {\
219 Packet* next = ((batch != 0)? batch->first()->next() : 0 );\
220 Packet* p = batch->first();\
223 for (;p != 0;p=next,next=(p==0?0:p->next())) {\
224 auto add = [&batch,&last,&count](Packet*q) {\
228 batch = reinterpret_cast<PacketBatch*>(q);\
236 batch->set_count(count);\
237 batch->set_tail(last);\
261#define CLASSIFY_EACH_PACKET(nbatches,fnt,cep_batch,on_finish)\
263 PacketBatch* out[(nbatches)];\
264 bzero(out,sizeof(PacketBatch*)*(nbatches));\
265 PacketBatch* cep_next = ((cep_batch != 0)? reinterpret_cast<PacketBatch*>(cep_batch->first()->next()) : 0 );\
266 Packet* p = cep_batch->first();\
270 for (;p != 0;p=cep_next->first(),cep_next=(p==0?0:reinterpret_cast<PacketBatch*>(p->next()))) {\
272 if (o < 0 || o>=(int)(nbatches)) o = (nbatches - 1);\
277 out[o] = reinterpret_cast<PacketBatch*>(p);\
278 reinterpret_cast<PacketBatch*>(p)->set_count(1);\
279 reinterpret_cast<PacketBatch*>(p)->set_tail(p);\
281 out[last_o]->set_tail(last);\
282 out[last_o]->set_count(out[last_o]->count() + passed);\
284 out[o] = reinterpret_cast<PacketBatch*>(p);\
285 out[o]->set_count(1);\
286 out[o]->set_tail(p);\
288 out[o]->append_packet(p);\
298 out[last_o]->set_tail(last);\
299 out[last_o]->set_count(out[last_o]->count() + passed);\
303 for (; i < (unsigned)(nbatches); i++) {\
305 out[i]->tail()->set_next(0);\
306 (on_finish(i,out[i]));\
315#define CLASSIFY_EACH_PACKET_IGNORE(nbatches,fnt,cep_batch,on_finish)\
317 PacketBatch* out[(nbatches)];\
318 bzero(out,sizeof(PacketBatch*)*(nbatches));\
319 PacketBatch* cep_next = ((cep_batch != 0)? reinterpret_cast<PacketBatch*>(cep_batch->first()->next()) : 0 );\
320 Packet* p = cep_batch->first();\
324 for (;p != 0;p=cep_next->first(),cep_next=(p==0?0:reinterpret_cast<PacketBatch*>(p->next()))) {\
326 if (o>=(nbatches)) o = (nbatches - 1);\
331 if (o == -1) continue;\
332 out[o] = reinterpret_cast<PacketBatch*>(p);\
333 out[o]->set_count(1);\
334 out[o]->set_tail(p);\
337 out[last_o]->set_tail(last);\
338 out[last_o]->set_count(out[last_o]->count() + passed);\
342 out[o] = reinterpret_cast<PacketBatch*>(p);\
343 out[o]->set_count(1);\
344 out[o]->set_tail(p);\
346 out[o]->append_packet(p);\
356 if (passed && last_o != -1) {\
357 out[last_o]->set_tail(last);\
358 out[last_o]->set_count(out[last_o]->count() + passed);\
362 for (; i < (nbatches); i++) {\
364 out[i]->tail()->set_next(0);\
365 (on_finish(i,out[i]));\
384#define MAKE_BATCH(fnt,head,max) {\
385 head = PacketBatch::start_head(fnt);\
387 Packet* last = head->first();\
388 unsigned int count = 1;\
389 while (count < (unsigned)(max>0?max:BATCH_MAX_PULL)) {\
390 Packet* current = fnt;\
393 last->set_next(current);\
397 head->make_tail(last,count);\
418#define MAX_BATCH_SIZE 8192
431 inline void set_tail(
Packet* p) {
439 return first()->
prev();
447 inline void append_simple_list(
Packet* lhead,
Packet* ltail,
int lcount) {
459 set_tail(head->tail());
466 inline void append_packet(
Packet* p) {
476 unsigned int r = BATCH_COUNT_ANNO(first());
508 click_chatter(
"BUG in make_tail : last packet is the head, but count is %u",
count);
522 SET_BATCH_COUNT_ANNO(first(),c);
535 click_chatter(
"BUG Warning : cutting a batch without a location to cut !");
539 if (middle == tail()) {
544 int total_count =
count();
549 Packet* second_tail = tail();
552 second->set_tail(second_tail);
553 second->
set_count(total_count - first_batch_count);
567 if (unlikely(!safe)) {
568 assert(first_batch_count > 0);
570 for (
int i = 0; i < first_batch_count - 1; i++) {
571 middle = middle->
next();
572 if (unlikely(!safe && middle == 0)) {
578 int total_count =
count();
583 Packet* second_tail = tail();
586 second->set_tail(second_tail);
587 second->
set_count(total_count - first_batch_count);
594 split(first_batch_count,second,
false);
607 poped->set_tail(tail());
673#if !CLICK_LINUXMODULE
674 static PacketBatch *make_batch(
unsigned char *data, uint16_t
count, uint16_t *length,
675 Packet::buffer_destructor_type destructor,
676 void* argument = (
void*) 0,
const bool clear=
true) CLICK_WARN_UNUSED_RESULT;
704 FOR_EACH_PACKET(
this, p) {
707 q = p->duplicate(0, 0, duplicate_data_only);
721#if HAVE_BATCH && HAVE_CLICK_PACKET_POOL
725 void recycle_batch(
bool is_data);
728 void fast_kill_nonatomic();
730 inline void fast_kill() {
734 void fast_kill_nonatomic() {
744 FOR_EACH_PACKET_SAFE(
this,p) {
749#if HAVE_BATCH_RECYCLE
750#define BATCH_RECYCLE_START() \
751 WritablePacket* head_packet = 0;\
752 WritablePacket* head_data = 0;\
753 WritablePacket* last_packet = 0;\
754 WritablePacket* last_data = 0;\
755 unsigned int n_packet = 0;\
756 unsigned int n_data = 0;
758#define BATCH_RECYCLE_ADD_PACKET(p) {\
759 if (head_packet == 0) {\
760 head_packet = static_cast<WritablePacket*>(p);\
761 last_packet = static_cast<WritablePacket*>(p);\
763 last_packet->set_next(p);\
764 last_packet = static_cast<WritablePacket*>(p);\
768#define BATCH_RECYCLE_ADD_DATA_PACKET(p) {\
769 if (head_data == 0) {\
770 head_data = static_cast<WritablePacket*>(p);\
771 last_data = static_cast<WritablePacket*>(p);\
773 last_data->set_next(p);\
774 last_data = static_cast<WritablePacket*>(p);\
778#define BATCH_RECYCLE_PACKET(p) {\
782 BATCH_RECYCLE_UNKNOWN_PACKET(p);\
786#define BATCH_RECYCLE_PACKET_NONATOMIC(p) {\
787 if (p->shared_nonatomic()) {\
788 p->kill_nonatomic();\
790 BATCH_RECYCLE_UNKNOWN_PACKET(p);\
794#if HAVE_DPDK_PACKET_POOL
795#define BATCH_RECYCLE_UNKNOWN_PACKET(p) {\
796 if (p->data_packet() == 0 && (DPDKDevice::is_dpdk_packet(p)) && p->buffer() != 0) {\
797 BATCH_RECYCLE_ADD_DATA_PACKET(p);\
799 BATCH_RECYCLE_ADD_PACKET(p);}}
800#elif !defined(CLICK_NOINDIRECT)
801#define BATCH_RECYCLE_UNKNOWN_PACKET(p) {\
802 if (p->data_packet() == 0 && p->buffer_destructor() == 0 && p->buffer() != 0) {\
803 BATCH_RECYCLE_ADD_DATA_PACKET(p);\
805 BATCH_RECYCLE_ADD_PACKET(p);}}
807#define BATCH_RECYCLE_UNKNOWN_PACKET(p) {\
808 if (p->buffer_destructor() == 0 && p->buffer() != 0) {\
809 BATCH_RECYCLE_ADD_DATA_PACKET(p);\
811 BATCH_RECYCLE_ADD_PACKET(p);}}
814#define BATCH_RECYCLE_END() \
816 last_packet->set_next(0);\
817 PacketBatch::make_from_simple_list(head_packet,last_packet,n_packet)->recycle_batch(false);\
820 last_data->set_next(0);\
821 PacketBatch::make_from_simple_list(head_data,last_data,n_data)->recycle_batch(true);\
824#define BATCH_RECYCLE_START() {}
825#define BATCH_RECYCLE_END() {}
826#define BATCH_RECYCLE_PACKET(p) {p->kill();}
827#define BATCH_RECYCLE_PACKET_NONATOMIC(p) {p->kill_nonatomic();}
833#define BATCH_RECYCLE_PACKET_CONTEXT(p) {\
834 if (likely(is_fullpush())) {\
835 BATCH_RECYCLE_PACKET_NONATOMIC(p);\
837 BATCH_RECYCLE_PACKET(p);\
844#define BATCH_CREATE_INIT(batch) \
845 PacketBatch* batch = 0; \
846 int batch ## count = 0; \
847 Packet* batch ## last = 0;
848#define BATCH_CREATE_APPEND(batch,p) \
850 batch ## last->set_next(p); \
852 batch = PacketBatch::start_head(p); \
856#define BATCH_CREATE_FINISH(batch) \
858 batch->make_tail(batch ## last, batch ## count)
862#if HAVE_BATCH && HAVE_CLICK_PACKET_POOL
868inline void PacketBatch::recycle_batch(
bool is_data) {
Definition packetbatch.hh:415
void set_count(unsigned int c)
Definition packetbatch.hh:521
void kill()
Definition packetbatch.hh:743
unsigned count()
Definition packetbatch.hh:475
Packet * begin()
Definition packetbatch.hh:682
static PacketBatch * start_head(Packet *p)
Start a new batch.
Definition packetbatch.hh:490
static PacketBatch * make_from_simple_list(Packet *head, Packet *tail, unsigned int size)
Definition packetbatch.hh:633
PacketBatch * clone_batch(const bool duplicate=false, const bool duplicate_data_only=false)
Definition packetbatch.hh:701
PacketBatch * pop_front()
Definition packetbatch.hh:602
void split(int first_batch_count, PacketBatch *&second, const bool &safe=false)
Cut a batch in two batches.
Definition packetbatch.hh:565
PacketBatch * make_tail(Packet *last, unsigned int count)
Finish a batch started with start_head()
Definition packetbatch.hh:504
Packet * end()
Definition packetbatch.hh:689
static PacketBatch * make_from_simple_list(Packet *head)
Definition packetbatch.hh:645
void cut(Packet *middle, int first_batch_count, PacketBatch *&second)
Cut a batch in two batches.
Definition packetbatch.hh:532
static PacketBatch * make_from_tailed_list(Packet *head, unsigned int size)
Definition packetbatch.hh:620
static PacketBatch * make_from_packet(Packet *p)
Definition packetbatch.hh:664
A network packet.
Definition packet.hh:68
void kill()
Delete this packet.
Definition packet.hh:1804
void set_next(Packet *p)
Set the next packet annotation.
Definition packet.hh:1351
Packet * prev() const
Return the previous packet annotation.
Definition packet.hh:1363
PacketType
Values for packet_type_anno(). Must agree with Linux's PACKET_ constants in <linux/if_packet....
Definition packet.hh:490
Packet * clone(bool fast=false)
Create a clone of this packet.
Definition packet.cc:1104
Packet * next() const
Return the next packet annotation.
Definition packet.hh:1327
void set_prev(Packet *p)
Set the previous packet annotation.
Definition packet.hh:1387
A network packet believed not to be shared.
Definition packet.hh:1004
The Packet class models packets in Click.