int pfring_bundle_read(pfring_bundle *bundle, u_char** buffer, u_int buffer_len, struct pfring_pkthdr *hdr, u_int8_t wait_for_incoming_packet) { u_int i, sock_id = 0, num_found, rc; struct timeval ts = { 0 }; redo_pfring_bundle_read: switch(bundle->policy) { case pick_round_robin: for(i=0; i<bundle->num_sockets; i++) { bundle->last_read_socket = (bundle->last_read_socket + 1) % bundle->num_sockets; if(pfring_there_is_pkt_available(bundle->sockets[bundle->last_read_socket])) { return(pfring_recv(bundle->sockets[bundle->last_read_socket], buffer, buffer_len, hdr, wait_for_incoming_packet)); } } break; case pick_fifo: num_found = 0; for(i=0; i<bundle->num_sockets; i++) { pfring *ring = bundle->sockets[i]; if(pfring_there_is_pkt_available(ring)) { struct pfring_pkthdr *header = (struct pfring_pkthdr*)&ring->slots[ring->slots_info->remove_off]; if((num_found == 0) || is_before(&header->ts, &ts)) { memcpy(&ts, &header->ts, sizeof(struct timeval)); num_found++, sock_id = i; } } } if(num_found > 0) { return(pfring_recv(bundle->sockets[sock_id], buffer, buffer_len, hdr, wait_for_incoming_packet)); } break; } if(wait_for_incoming_packet) { rc = pfring_bundle_poll(bundle, bundle->sockets[0]->poll_duration); if(rc > 0) { goto redo_pfring_bundle_read; } else return(rc); } return(0); }
int pfring_mod_next_pkt_time(pfring *ring, struct timespec *ts) { struct pfring_pkthdr *header = (struct pfring_pkthdr*) &ring->slots[ring->slots_info->remove_off]; if(!pfring_there_is_pkt_available(ring)) return PF_RING_ERROR_NO_PKT_AVAILABLE; if(!header->ts.tv_sec) return PF_RING_ERROR_WRONG_CONFIGURATION; ts->tv_sec = header->ts.tv_sec; ts->tv_nsec = header->ts.tv_usec * 1000; /* TODO In order to use ns from hw ts we should make sure that * hw ts is in sync with sys time. */ //if(header->extended_hdr.timestamp_ns) // ts->tv_nsec = header->extended_hdr.timestamp_ns % 1000000000; return 0; }
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_is_pkt_available(pfring *ring) { return(pfring_there_is_pkt_available(ring)); }
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 */ }