int pfring_mod_recv(pfring *ring, u_char** buffer, u_int buffer_len, struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet) { int rc = 0; if(ring->is_shutting_down || (ring->buffer == NULL)) return(-1); ring->break_recv_loop = 0; do_pfring_recv: if(ring->break_recv_loop) return(0); if(ring->reentrant) pthread_spin_lock(&ring->spinlock); //rmb(); if(pfring_there_is_pkt_available(ring)) { char *bucket = &ring->slots[ring->slots_info->remove_off]; u_int32_t next_off, real_slot_len, insert_off, bktLen; memcpy(hdr, bucket, ring->slot_header_len); if(ring->slot_header_len != sizeof(struct pfring_pkthdr)) bktLen = hdr->caplen; else bktLen = hdr->caplen+hdr->extended_hdr.parsed_header_len; real_slot_len = ring->slot_header_len + bktLen; insert_off = ring->slots_info->insert_off; if(bktLen > buffer_len) bktLen = buffer_len; if(buffer_len == 0) *buffer = (u_char*)&bucket[ring->slot_header_len]; else memcpy(*buffer, &bucket[ring->slot_header_len], bktLen); next_off = ring->slots_info->remove_off + real_slot_len; if((next_off + ring->slots_info->slot_len) > (ring->slots_info->tot_mem - sizeof(FlowSlotInfo))) { next_off = 0; } #ifdef USE_MB /* This prevents the compiler from reordering instructions. * http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier */ gcc_mb(); #endif ring->slots_info->tot_read++; ring->slots_info->remove_off = next_off; /* Ugly safety check */ if((ring->slots_info->tot_insert == ring->slots_info->tot_read) && (ring->slots_info->remove_off > ring->slots_info->insert_off)) { ring->slots_info->remove_off = ring->slots_info->insert_off; } if(ring->reentrant) pthread_spin_unlock(&ring->spinlock); return(1); } /* Nothing to do: we need to wait */ if(ring->reentrant) pthread_spin_unlock(&ring->spinlock); if(wait_for_incoming_packet) { rc = pfring_poll(ring, ring->poll_duration); if((rc == -1) && (errno != EINTR)) return(-1); else goto do_pfring_recv; } return(0); /* non-blocking, no packet */ }
int pfring_mod_recv(pfring *ring, u_char** buffer, u_int buffer_len, struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet) { int rc = 0; if(ring->is_shutting_down || (ring->buffer == NULL)) return(-1); ring->break_recv_loop = 0; do_pfring_recv: if(ring->break_recv_loop) return(0); if(unlikely(ring->reentrant)) pthread_rwlock_wrlock(&ring->rx_lock); //rmb(); if(pfring_there_is_pkt_available(ring)) { char *bucket = &ring->slots[ring->slots_info->remove_off]; u_int32_t next_off, real_slot_len, bktLen; /* Keep it for packet sending */ ring->tx.last_received_hdr = (struct pfring_pkthdr*)bucket; memcpy(hdr, bucket, ring->slot_header_len); //if((hdr->caplen > 1518) || (hdr->len > 1518)) // fprintf(stderr, "%s:%d-----> Invalid packet length [caplen: %u][len: %u]" // "[hdr len: %u][slot len: %u][real slot len: %u]" // "[insert_off: %u][remove_off: %u][tot_insert: %lu][tot_read: %lu]\n", // __FUNCTION__, __LINE__, hdr->caplen, hdr->len, ring->slot_header_len, // ring->slots_info->slot_len, ring->slot_header_len+hdr->caplen, // ring->slots_info->insert_off, ring->slots_info->remove_off, // ring->slots_info->tot_insert, ring->slots_info->tot_read); if(ring->slot_header_len != sizeof(struct pfring_pkthdr)) /* using short_pkt_header, parsed_header_len is not available */ bktLen = hdr->caplen; else bktLen = hdr->caplen + hdr->extended_hdr.parsed_header_len; real_slot_len = ring->slot_header_len + bktLen; if(bktLen > buffer_len) bktLen = buffer_len; if(buffer_len == 0) *buffer = (u_char*)&bucket[ring->slot_header_len]; else memcpy(*buffer, &bucket[ring->slot_header_len], bktLen); next_off = ring->slots_info->remove_off + real_slot_len; if((next_off + ring->slots_info->slot_len) > (ring->slots_info->tot_mem - sizeof(FlowSlotInfo))) next_off = 0; #ifdef USE_MB /* This prevents the compiler from reordering instructions. * http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier */ gcc_mb(); #endif ring->slots_info->tot_read++, ring->slots_info->remove_off = next_off; /* Ugly safety check */ if(unlikely((ring->slots_info->tot_insert == ring->slots_info->tot_read) && (ring->slots_info->remove_off > ring->slots_info->insert_off))) { ring->slots_info->remove_off = ring->slots_info->insert_off; fprintf(stderr, " *** corrupted ring buffer indexes (recovered) ***\n"); } if(unlikely(ring->reentrant)) pthread_rwlock_unlock(&ring->rx_lock); return(1); } /* Nothing to do: we need to wait */ if(unlikely(ring->reentrant)) pthread_rwlock_unlock(&ring->rx_lock); if(wait_for_incoming_packet) { rc = pfring_poll(ring, ring->poll_duration); if((rc == -1) && (errno != EINTR)) return(-1); else goto do_pfring_recv; } return(0); /* non-blocking, no packet */ }