static int pfring_zc_daq_acquire_best_effort(void *handle, int cnt, DAQ_Analysis_Func_t callback, #if (DAQ_API_VERSION >= 0x00010002) DAQ_Meta_Func_t metaback, #endif void *user) { Pfring_Context_t *context = (Pfring_Context_t *) handle; int ret = 0, c = 0; u_int32_t rx_ring_idx = context->num_devices - 1, rx_ring_idx_clone; u_int32_t mask = 0; u_char *pkt_buffer; context->analysis_func = callback; context->breakloop = 0; while (!context->breakloop && (cnt <= 0 || c < cnt)) { #ifdef SIG_RELOAD if (pfring_zc_daq_reload_requested) pfring_zc_daq_reload(context); #endif while (pfring_zc_daq_in_packets(context, &rx_ring_idx) && !context->breakloop) { pfring_zc_recv_pkt(context->rx_queues[rx_ring_idx], &context->buffer, 0); context->buffer->hash = context->ifindexes[rx_ring_idx]; pkt_buffer = pfring_zc_pkt_buff_data(context->buffer, context->rx_queues[rx_ring_idx]); #ifdef ENABLE_BPF if (!context->bpf_filter || bpf_filter(context->filter.bf_insns, pkt_buffer, context->buffer->len /* caplen */, context->buffer->len) != 0) { /* accept */ #endif /* enqueueing pkt (and don't care of no room available) */ mask = 1 << (context->num_devices); #ifdef ENABLE_BPF } else { context->stats.packets_received++; context->stats.verdicts[DAQ_VERDICT_PASS]++; } #endif mask |= 1 << (rx_ring_idx ^ 0x1); pfring_zc_send_pkt_multi(context->mq, &context->buffer, mask, 0); } rx_ring_idx_clone = rx_ring_idx; while (!(ret = pfring_zc_daq_in_packets(context, &rx_ring_idx_clone)) && !pfring_zc_queue_is_empty(context->q) && !context->breakloop) { ret = pfring_zc_recv_pkt(context->q, &context->buffer, 0); pfring_zc_daq_process(context, context->buffer, user); c++; } if (!ret) { if (usleep(1) == -1) if (errno == EINTR) break; } } return 0; }
void *packet_consumer_thread(void *data) { if (bind_core >= 0) bind2core(bind_core); while(!do_shutdown) { if(pfring_zc_recv_pkt(inzq, &tmpbuff, wait_for_packet) > 0) { if (unlikely(verbose)) { char bigbuf[4096]; pfring_print_pkt(bigbuf, sizeof(bigbuf), tmpbuff->data, tmpbuff->len, tmpbuff->len); fputs(bigbuf, stdout); } #if 0 int i; for(i = 0; i < tmpbuff->len; i++) printf("%02X ", tmpbuff->data[i]); printf("\n"); #endif numPkts++; numBytes += tmpbuff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ while (unlikely(pfring_zc_send_pkt(outzq, &tmpbuff, flush_packet) < 0 && !do_shutdown)) usleep(1); } } if (!flush_packet) pfring_zc_sync_queue(outzq, tx_only); pfring_zc_sync_queue(inzq, rx_only); return NULL; }
void* consumer_thread(void* _id) { long id = (long) _id; pfring_zc_pkt_buff *b = buffers[id]; bind2core(bind_core[id]); while(!consumers_stats[id].do_shutdown) { if(pfring_zc_recv_pkt(outzq[id], &b, wait_for_packet) > 0) { #if 0 int i; for(i = 0; i < b->len; i++) printf("%02X ", pfring_zc_pkt_buff_data(b, outzq[id])[i]); printf("\n"); #endif consumers_stats[id].numPkts++; consumers_stats[id].numBytes += b->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ } } pfring_zc_sync_queue(outzq[id], rx_only); return NULL; }
void *pipeline_stage_thread(void* _id) { long id = (long) _id; pfring_zc_pkt_buff *b = buffers[id]; bind2core(bind_core[id]); while(!do_shutdown) { if(pfring_zc_recv_pkt(zq[id], &b, wait_for_packet) > 0) { #ifdef METADATA_TEST if (id == 0) { /* first pipeline stage */ static u_int64_t counter = 0; u_int64_t *meta_p = (u_int64_t *) b->user; *meta_p = counter; counter++; } #endif if (id < num_threads-1) { /* send to the next pipeline stage */ pfring_zc_send_pkt(zq[id+1], &b, flush_packet); } else {/* last pipeline stage */ #ifdef METADATA_TEST u_int64_t *meta_p = (u_int64_t *) b->user; if (*meta_p != numPkts) printf("Buffer Metadata contains unexpected value: %llu != %llu\n", (long long unsigned) *meta_p, (long long unsigned) numPkts); #endif #if 0 int i; for(i = 0; i < b->len; i++) printf("%02X ", b->data[i]); printf("\n"); #endif numPkts++; numBytes += b->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ } } } if (id < num_threads-1) pfring_zc_sync_queue(zq[id+1], tx_only); pfring_zc_sync_queue(zq[id], rx_only); return NULL; }
void *packet_consumer_thread(void *_id) { struct volatile_globals *g = globals; pfring_zc_queue *_inzq = inzq; pfring_zc_queue **_outzq = outzq; pfring_zc_multi_queue *_mq = mq; pfring_zc_pkt_buff **_ph = ph; u_int32_t _num_slaves = num_slaves; int i, ns, flush_tx = 0, toprocess = 0; #ifdef USE_RECV_BURST int nr; #endif bind2core(bind_core); while(!g->do_shutdown) { #ifdef USE_RECV_BURST if ((nr = pfring_zc_recv_pkt_burst(_inzq, _ph, SWAP_BUFFERS, 0 /* g->wait_for_packet */)) > 0) #else if (pfring_zc_recv_pkt(_inzq, _ph, 0 /* g->wait_for_packet */) > 0) #endif { #ifdef USE_RECV_BURST toprocess = 0; while (toprocess < nr) { #endif pfring_zc_pkt_buff **buff_p = &_ph[toprocess]; pfring_zc_pkt_buff *buff = *buff_p; if (g->time_pulse) { u_int64_t pulse_timestamp_ns = *g->pulse_timestamp_ns; buff->ts.tv_sec = pulse_timestamp_ns >> 32; buff->ts.tv_nsec = pulse_timestamp_ns & 0xffffffff; } g->numPkts++; g->numBytes += buff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ ns = pfring_zc_send_pkt_multi(_mq, buff_p, 0xffffffff, 0); //drop += _num_slaves - ns; g->sentPkts += ns; #ifdef USE_RECV_BURST toprocess++; } #endif flush_tx = 1; } else {
void *packet_consumer_thread(void *_i) { struct dir_info *i = (struct dir_info *) _i; int tx_queue_not_empty = 0; if (i->bind_core >= 0) bind2core(i->bind_core); while(!do_shutdown) { if(pfring_zc_recv_pkt(i->inzq, &i->tmpbuff, 0 /* wait_for_packet */) > 0) { if (unlikely(verbose)) { #if 1 char bigbuf[4096]; pfring_print_pkt(bigbuf, sizeof(bigbuf), pfring_zc_pkt_buff_data(i->tmpbuff, i->inzq), i->tmpbuff->len, i->tmpbuff->len); fputs(bigbuf, stdout); #else u_char *pkt_data = pfring_zc_pkt_buff_data(i->tmpbuff, i->inzq); int j; for(j = 0; j < i->tmpbuff->len; j++) printf("%02X ", pkt_data[j]); printf("\n"); #endif } i->numPkts++; i->numBytes += i->tmpbuff->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ errno = 0; while (unlikely(pfring_zc_send_pkt(i->outzq, &i->tmpbuff, flush_packet) < 0 && errno != EMSGSIZE && !do_shutdown)) if (wait_for_packet) usleep(1); tx_queue_not_empty = 1; } else { if (tx_queue_not_empty) { pfring_zc_sync_queue(i->outzq, tx_only); tx_queue_not_empty = 0; } if (wait_for_packet) usleep(1); } } if (!flush_packet) pfring_zc_sync_queue(i->outzq, tx_only); pfring_zc_sync_queue(i->inzq, rx_only); return NULL; }
void *forwarder_thread(void *_info) { forwarder_info_t *info = (forwarder_info_t *) _info; pfring_zc_pkt_buff *b = info->buffer; bind2core(info->bind_core); while(!do_shutdown) if(pfring_zc_recv_pkt(info->inzq, &b, wait_for_packet) > 0) while (unlikely(pfring_zc_send_pkt(info->outzq, &b, flush_packet) < 0 && !do_shutdown)) usleep(1); pfring_zc_sync_queue(info->outzq, tx_only); pfring_zc_sync_queue(info->inzq, rx_only); return NULL; }
void recv_packets() { int ret; // Poll for packets do { ret = pfring_zc_recv_pkt(pf_recv, &pf_buffer, 0); if (ret == 0) { usleep(1000); } } while (ret == 0); // Handle other errors, by not doing anything and logging if (ret != 1) { log_error("recv", "Error: %d", ret); return; } // Successfully got a packet, now handle it handle_packet(pf_buffer->len, pf_buffer->data); }
void *packet_consumer_thread(void *_id) { struct volatile_globals *g = globals; bind2core(bind_core); while(!g->do_shutdown) { if(pfring_zc_recv_pkt(zq, &buffer, g->wait_for_packet) > 0) { if (unlikely(g->verbose)) { u_char *pkt_data = pfring_zc_pkt_buff_data(buffer, zq); if (buffer->ts.tv_nsec) printf("[%u.%u] ", buffer->ts.tv_sec, buffer->ts.tv_nsec); if(g->dump_as_sysdig_event) { struct sysdig_event_header *ev = (struct sysdig_event_header*)pkt_data; printf("[cpu_id=%u][tid=%lu][%u|%s]", buffer->hash, ev->thread_id, ev->event_type, sysdig_event2name(ev->event_type)); } else { int i; for(i = 0; i < buffer->len; i++) printf("%02X ", pkt_data[i]); } printf("\n"); } g->numPkts++; g->numBytes += buffer->len + 24; /* 8 Preamble + 4 CRC + 12 IFG */ } } pfring_zc_sync_queue(zq, rx_only); return NULL; }
static int pfring_zc_daq_acquire(void *handle, int cnt, DAQ_Analysis_Func_t callback, #if (DAQ_API_VERSION >= 0x00010002) DAQ_Meta_Func_t metaback, #endif void *user) { Pfring_Context_t *context = (Pfring_Context_t *) handle; int ret = 0, i = 0, rx_ring_idx = context->num_devices - 1, c = 0; DAQ_PktHdr_t hdr; DAQ_Verdict verdict; u_char *pkt_buffer; #ifdef DAQ_PF_RING_BEST_EFFORT_BOOST if (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge == 2) return pfring_zc_daq_acquire_best_effort(handle, cnt, callback, #if (DAQ_API_VERSION >= 0x00010002) metaback, #endif user); #endif context->analysis_func = callback; context->breakloop = 0; while (!context->breakloop && (cnt <= 0 || c < cnt)) { #ifdef SIG_RELOAD if (pfring_zc_daq_reload_requested) pfring_zc_daq_reload(context); #endif for (i = 0; i < context->num_devices; i++) { rx_ring_idx = (rx_ring_idx + 1) % context->num_devices; ret = pfring_zc_recv_pkt(context->rx_queues[rx_ring_idx], &context->buffer, 0 /* Dont't wait */); if (ret > 0) break; } if (ret <= 0) { if (usleep(1) == -1) if (errno == EINTR) break; continue; } hdr.pktlen = hdr.caplen = context->buffer->len; hdr.ts.tv_sec = context->buffer->ts.tv_sec; hdr.ts.tv_usec = context->buffer->ts.tv_nsec/1000; #if (DAQ_API_VERSION >= 0x00010002) hdr.ingress_index = context->ifindexes[rx_ring_idx]; hdr.egress_index = -1; hdr.ingress_group = -1; hdr.egress_group = -1; #else hdr.device_index = context->ifindexes[rx_ring_idx]; #endif hdr.flags = 0; pkt_buffer = pfring_zc_pkt_buff_data(context->buffer, context->rx_queues[rx_ring_idx]); #ifdef ENABLE_BPF if (!context->bpf_filter || bpf_filter(context->filter.bf_insns, pkt_buffer, hdr.caplen, hdr.pktlen) != 0) { /* analyse */ #endif verdict = context->analysis_func(user, &hdr, pkt_buffer); #ifdef ENABLE_BPF } else verdict = DAQ_VERDICT_PASS; #endif if (verdict >= MAX_DAQ_VERDICT) verdict = DAQ_VERDICT_PASS; if (context->mode == DAQ_MODE_PASSIVE && context->ids_bridge) { /* always forward the packet */ pfring_zc_daq_send_packet(context, context->tx_queues[rx_ring_idx ^ 0x1], hdr.caplen); } else if (context->mode == DAQ_MODE_INLINE && verdict != DAQ_VERDICT_PASS /* optimisation */ ) { /* parsing eth_type to forward ARP */ struct ethhdr *eh = (struct ethhdr *) pkt_buffer; u_int16_t eth_type = ntohs(eh->h_proto); u_int16_t vlan_offset = 0; if (eth_type == 0x8100 /* 802.1q (VLAN) */) { struct eth_vlan_hdr *vh; vlan_offset = sizeof(struct ethhdr) - sizeof(struct eth_vlan_hdr); while (eth_type == 0x8100 /* 802.1q (VLAN) */ ) { vlan_offset += sizeof(struct eth_vlan_hdr); vh = (struct eth_vlan_hdr *) &pkt_buffer[vlan_offset]; eth_type = ntohs(vh->h_proto); } } if (eth_type == 0x0806 /* ARP */ ) verdict = DAQ_VERDICT_PASS; } switch(verdict) { case DAQ_VERDICT_BLACKLIST: /* Block the packet and block all future packets in the same flow systemwide. */ /* TODO handle hw filters */ break; case DAQ_VERDICT_WHITELIST: /* Pass the packet and fastpath all future packets in the same flow systemwide. */ case DAQ_VERDICT_IGNORE: /* Pass the packet and fastpath all future packets in the same flow for this application. */ case DAQ_VERDICT_PASS: /* Pass the packet */ case DAQ_VERDICT_REPLACE: /* Pass a packet that has been modified in-place.(No resizing allowed!) */ if (context->mode == DAQ_MODE_INLINE) pfring_zc_daq_send_packet(context, context->tx_queues[rx_ring_idx ^ 0x1], hdr.caplen); break; case DAQ_VERDICT_BLOCK: /* Block the packet. */ /* Nothing to do really */ break; case MAX_DAQ_VERDICT: /* No way we can reach this point */ break; } context->stats.packets_received++; context->stats.verdicts[verdict]++; c++; } return 0; }