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 *time_pulse_thread(void *data) { struct volatile_globals *g = globals; u_int64_t ns; struct timespec tn; #if 1 u_int64_t pulse_clone = 0; #endif bind2core(bind_time_pulse_core); while (likely(!g->do_shutdown)) { /* clock_gettime takes up to 30 nsec to get the time */ clock_gettime(CLOCK_REALTIME, &tn); ns = ((u_int64_t) ((u_int64_t) tn.tv_sec * 1000000000) + (tn.tv_nsec)); #if 1 /* reduce cache thrashing*/ if(ns >= pulse_clone + g->pulse_timestamp_precision_nsec /* (avoid updating each cycle) */ ) { #endif *g->pulse_timestamp_ns = ((u_int64_t) ((u_int64_t) tn.tv_sec << 32) | tn.tv_nsec); #if 1 pulse_clone = ns; } #endif } 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 *time_pulse_thread(void *data) { struct timespec tn; bind2core(bind_time_pulse_core); while (likely(!do_shutdown)) { /* clock_gettime takes up to 30 nsec to get the time */ clock_gettime(CLOCK_REALTIME, &tn); if (append_timestamp) *pulse_timestamp_ns_n = ((u_int64_t) ((u_int64_t) htonl(tn.tv_sec) << 32) | htonl(tn.tv_nsec)); if (use_pulse_time) *pulse_timestamp_ns = ((u_int64_t) ((u_int64_t) tn.tv_sec * 1000000000) + tn.tv_nsec); } return NULL; }
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 *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; }
void send_traffic() { ticks hz, tick_start = 0, tick_delta = 0; u_int32_t buffer_id = 0; int sent_bytes; #ifdef BURST_API int i, sent_packets; #endif if (bind_core >= 0) bind2core(bind_core); if(pps > 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/; printf("Estimated CPU freq: %lu Hz\n", (long unsigned int) hz); tick_delta = (double) (hz / pps); tick_start = getticks(); } #ifdef BURST_API /****** Burst API ******/ if (use_pkt_burst_api) { while (likely(!do_shutdown && (!num_to_send || numPkts < num_to_send))) { if (numPkts < num_queue_buffers + NBUFF || num_ips > 1) { /* forge all buffers 1 time */ for (i = 0; i < BURSTLEN; i++) { buffers[buffer_id + i]->len = packet_len; if (stdin_packet_len > 0) memcpy(buffers[buffer_id + i]->data, stdin_packet, stdin_packet_len); else forge_udp_packet(buffers[buffer_id + i]->data, numPkts + i); } } /* TODO send unsent packets when a burst is partially sent */ while (unlikely((sent_packets = pfring_zc_send_pkt_burst(zq, &buffers[buffer_id], BURSTLEN, flush_packet)) <= 0)) { if (unlikely(do_shutdown)) break; if (!active) usleep(1); } numPkts += sent_packets; numBytes += ((packet_len + 24 /* 8 Preamble + 4 CRC + 12 IFG */ ) * sent_packets); buffer_id += BURSTLEN; buffer_id &= NBUFFMASK; if(pps > 0) { u_int8_t synced = 0; while((getticks() - tick_start) < (numPkts * tick_delta)) if (!synced) pfring_zc_sync_queue(zq, tx_only), synced = 1; } } } else { #endif /****** Packet API ******/ while (likely(!do_shutdown && (!num_to_send || numPkts < num_to_send))) { buffers[buffer_id]->len = packet_len; #if 1 if (numPkts < num_queue_buffers + NBUFF || num_ips > 1) { /* forge all buffers 1 time */ if (stdin_packet_len > 0) memcpy(buffers[buffer_id]->data, stdin_packet, stdin_packet_len); else forge_udp_packet(buffers[buffer_id]->data, numPkts); } #else { int k; u_int8_t j = numPkts; for(k = 0; k < buffers[buffer_id]->len; k++) buffers[buffer_id]->data[k] = j++; buffers[buffer_id]->data[k-1] = cluster_id; } #endif while (unlikely((sent_bytes = pfring_zc_send_pkt(zq, &buffers[buffer_id], flush_packet)) < 0)) { if (unlikely(do_shutdown)) break; if (!active) usleep(1); } numPkts++; numBytes += sent_bytes + 24; /* 8 Preamble + 4 CRC + 12 IFG */ buffer_id++; buffer_id &= NBUFFMASK; if(pps > 0) { u_int8_t synced = 0; while((getticks() - tick_start) < (numPkts * tick_delta)) if (!synced) pfring_zc_sync_queue(zq, tx_only), synced = 1; } } #ifdef BURST_API } #endif if (!flush_packet) pfring_zc_sync_queue(zq, tx_only); }
int main(int argc, char* argv[]) { pfring *a_ring, *b_ring; char *a_dev = NULL, *b_dev = NULL, c; u_int8_t verbose = 0, use_pfring_send = 0; int a_ifindex, b_ifindex; int bind_core = -1; u_int16_t watermark = 1; while((c = getopt(argc,argv, "ha:b:c:fvpg:w:")) != -1) { switch(c) { case 'h': printHelp(); return 0; break; case 'a': a_dev = strdup(optarg); break; case 'b': b_dev = strdup(optarg); break; case 'p': use_pfring_send = 1; break; case 'v': verbose = 1; break; case 'g': bind_core = atoi(optarg); break; case 'w': watermark = atoi(optarg); break; } } if ((!a_dev) || (!b_dev)) { printf("You must specify two devices!\n"); return -1; } if(strcmp(a_dev, b_dev) == 0) { printf("Bridge devices must be different!\n"); return -1; } /* Device A */ if((a_ring = pfring_open(a_dev, MAX_PKT_LEN, PF_RING_PROMISC | PF_RING_LONG_HEADER | (use_pfring_send ? 0 : PF_RING_RX_PACKET_BOUNCE)) ) == NULL) { printf("pfring_open error for %s [%s]\n", a_dev, strerror(errno)); return(-1); } pfring_set_application_name(a_ring, "pfbridge-a"); pfring_set_direction(a_ring, rx_only_direction); pfring_set_socket_mode(a_ring, recv_only_mode); pfring_set_poll_watermark(a_ring, watermark); pfring_get_bound_device_ifindex(a_ring, &a_ifindex); /* Device B */ if((b_ring = pfring_open(b_dev, MAX_PKT_LEN, PF_RING_PROMISC|PF_RING_LONG_HEADER)) == NULL) { printf("pfring_open error for %s [%s]\n", b_dev, strerror(errno)); pfring_close(a_ring); return(-1); } pfring_set_application_name(b_ring, "pfbridge-b"); pfring_set_socket_mode(b_ring, send_only_mode); pfring_get_bound_device_ifindex(b_ring, &b_ifindex); /* Enable Sockets */ if (pfring_enable_ring(a_ring) != 0) { printf("Unable enabling ring 'a' :-(\n"); pfring_close(a_ring); pfring_close(b_ring); return(-1); } if(use_pfring_send) { if (pfring_enable_ring(b_ring)) { printf("Unable enabling ring 'b' :-(\n"); pfring_close(a_ring); pfring_close(b_ring); return(-1); } } else { pfring_close(b_ring); } signal(SIGALRM, my_sigalarm); alarm(1); if(bind_core >= 0) bind2core(bind_core); while(1) { u_char *buffer; struct pfring_pkthdr hdr; if(pfring_recv(a_ring, &buffer, 0, &hdr, 1) > 0) { int rc; if(use_pfring_send) { rc = pfring_send(b_ring, (char *) buffer, hdr.caplen, 1); if(rc < 0) printf("pfring_send(caplen=%u <= mtu=%u?) error %d\n", hdr.caplen, b_ring->mtu_len, rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } else { rc = pfring_send_last_rx_packet(a_ring, b_ifindex); if(rc < 0) printf("pfring_send_last_rx_packet() error %d\n", rc); else if(verbose) printf("Forwarded %d bytes packet\n", hdr.len); } if(rc >= 0) num_sent++; } } pfring_close(a_ring); if(use_pfring_send) pfring_close(b_ring); return(0); }
int main(int argc, char* argv[]) { char c, *pcap_in = NULL, mac_address[6]; int promisc, i, verbose = 0, active_poll = 0, reforge_mac = 0; u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f; char buffer[1500]; int send_len = 60; u_int32_t num = 1; int bind_core = -1; u_int16_t cpu_percentage = 0; double gbit_s = 0, td, pps; ticks tick_start = 0, tick_delta = 0; ticks hz = 0; struct packet *tosend; while((c = getopt(argc,argv,"hi:n:g:l:af:r:vm:" #if 0 "b:" #endif )) != -1) { switch(c) { case 'h': printHelp(); break; case 'i': in_dev = strdup(optarg); break; case 'f': pcap_in = strdup(optarg); break; case 'n': num = atoi(optarg); break; case 'g': bind_core = atoi(optarg); break; case 'l': send_len = atoi(optarg); break; case 'v': verbose = 1; break; case 'a': active_poll = 1; break; case 'r': sscanf(optarg, "%lf", &gbit_s); break; #if 0 case 'b': cpu_percentage = atoi(optarg); #endif break; case 'm': if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) { printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n"); return(0); } else { reforge_mac = 1; mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c; mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f; } break; } } if(in_dev == NULL) printHelp(); printf("Sending packets on %s\n", in_dev); /* hardcode: promisc=1, to_ms=500 */ promisc = 1; pd = pfring_open(in_dev, promisc, 1500, 0); if(pd == NULL) { printf("pfring_open %s error\n", in_dev); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "pfdnasend"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); if(send_len < 60) send_len = 60; if(gbit_s > 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/; printf("Estimated CPU freq: %llu Hz\n", hz); /* computing max rate */ pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/); td = (double)(hz / pps); tick_delta = (ticks)td; printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps); } if(pcap_in) { char ebuf[256]; u_char *pkt; struct pcap_pkthdr *h; pcap_t *pt = pcap_open_offline(pcap_in, ebuf); u_int num_pcap_pkts = 0; if(pt) { struct packet *last = NULL; while(1) { struct packet *p; int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt); if(rc <= 0) break; p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = h->caplen; p->next = NULL; p->pkt = (char*)malloc(p->len); if(p->pkt == NULL) { printf("Not enough memory\n"); break; } else { memcpy(p->pkt, pkt, p->len); if(reforge_mac) memcpy(p->pkt, mac_address, 6); } if(last) { last->next = p; last = p; } else pkt_head = p, last = p; } else { printf("Not enough memory\n"); break; } if(verbose) printf("Read %d bytes packet from pcap file %s\n", p->len, pcap_in); num_pcap_pkts++; } /* while */ pcap_close(pt); printf("Read %d packets from pcap file %s\n", num_pcap_pkts, pcap_in); last->next = pkt_head; /* Loop */ num *= num_pcap_pkts; } else { printf("Unable to open file %s\n", pcap_in); pfring_close(pd); return(-1); } } else { struct packet *p; for(i=0; i<send_len; i++) buffer[i] = i; if(reforge_mac) memcpy(buffer, mac_address, 6); p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = send_len; p->next = p; /* Loop */ p->pkt = (char*)malloc(p->len); memcpy(p->pkt, buffer, send_len); pkt_head = p; } } if(bind_core >= 0) bind2core(bind_core); if(wait_for_packet && (cpu_percentage > 0)) { if(cpu_percentage > 99) cpu_percentage = 99; pfring_config(cpu_percentage); } if(!verbose) { signal(SIGALRM, my_sigalarm); alarm(1); } gettimeofday(&startTime, NULL); memcpy(&lastTime, &startTime, sizeof(startTime)); if(gbit_s > 0) tick_start = getticks(); tosend = pkt_head; i = 0; pfring_set_direction(pd, tx_only_direction); if(pfring_enable_ring(pd) != 0) { printf("Unable to enable ring :-(\n"); pfring_close(pd); return(-1); } while(!num || i < num) { int rc; redo: rc = pfring_send(pd, tosend->pkt, tosend->len, 0 /* Don't flush (it does PF_RING automatically) */); if(verbose) printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc); if(rc == -1) { /* Not enough space in buffer */ if(gbit_s == 0) { if(!active_poll) { if(bind_core >= 0) usleep(1); else pfring_poll(pd, 0); } } else { /* Just waste some time */ while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ; } goto redo; } else num_pkt_good_sent++, num_bytes_good_sent += tosend->len+24 /* 8 Preamble + 4 CRC + 12 IFG */, tosend = tosend->next; if(num > 0) i++; } /* for */ print_stats(0); pfring_close(pd); return(0); }
int main(int argc, char* argv[]) { char c, *pcap_in = NULL; int i, verbose = 0, active_poll = 0, disable_zero_copy = 0; int use_zero_copy_tx = 0; u_int mac_a, mac_b, mac_c, mac_d, mac_e, mac_f; char buffer[9000]; u_int32_t num_to_send = 0; int bind_core = -1; u_int16_t cpu_percentage = 0; double gbit_s = 0, td, pps; ticks tick_start = 0, tick_delta = 0; ticks hz = 0; struct packet *tosend; u_int num_tx_slots = 0; int num_balanced_pkts = 1, watermark = 0; u_int num_pcap_pkts = 0; while((c = getopt(argc,argv,"b:hi:n:g:l:af:r:vm:w:zx:" #if 0 "b:" #endif )) != -1) { switch(c) { case 'b': num_balanced_pkts = atoi(optarg); break; case 'h': printHelp(); break; case 'i': in_dev = strdup(optarg); break; case 'f': pcap_in = strdup(optarg); break; case 'n': num_to_send = atoi(optarg); break; case 'g': bind_core = atoi(optarg); break; case 'l': send_len = atoi(optarg); break; case 'x': if_index = atoi(optarg); break; case 'v': verbose = 1; break; case 'a': active_poll = 1; break; case 'r': sscanf(optarg, "%lf", &gbit_s); break; #if 0 case 'b': cpu_percentage = atoi(optarg); #endif break; case 'm': if(sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", &mac_a, &mac_b, &mac_c, &mac_d, &mac_e, &mac_f) != 6) { printf("Invalid MAC address format (XX:XX:XX:XX:XX:XX)\n"); return(0); } else { reforge_mac = 1; mac_address[0] = mac_a, mac_address[1] = mac_b, mac_address[2] = mac_c; mac_address[3] = mac_d, mac_address[4] = mac_e, mac_address[5] = mac_f; } break; case 'w': watermark = atoi(optarg); if(watermark < 1) watermark = 1; break; case 'z': disable_zero_copy = 1; break; } } if((in_dev == NULL) || (num_balanced_pkts < 1)) printHelp(); printf("Sending packets on %s\n", in_dev); pd = pfring_open(in_dev, 1500, 0 /* PF_RING_PROMISC */); if(pd == NULL) { printf("pfring_open %s error [%s]\n", in_dev, strerror(errno)); return(-1); } else { u_int32_t version; pfring_set_application_name(pd, "pfdnasend"); pfring_version(pd, &version); printf("Using PF_RING v.%d.%d.%d\n", (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); } if (!pd->send && pd->send_ifindex && if_index == -1) { printf("Please use -x <if index>\n"); return -1; } if(watermark > 0) { int rc; if((rc = pfring_set_tx_watermark(pd, watermark)) < 0) printf("pfring_set_tx_watermark() failed [rc=%d]\n", rc); } signal(SIGINT, sigproc); signal(SIGTERM, sigproc); signal(SIGINT, sigproc); if(send_len < 60) send_len = 60; if(gbit_s != 0) { /* cumputing usleep delay */ tick_start = getticks(); usleep(1); tick_delta = getticks() - tick_start; /* cumputing CPU freq */ tick_start = getticks(); usleep(1001); hz = (getticks() - tick_start - tick_delta) * 1000 /*kHz -> Hz*/; printf("Estimated CPU freq: %lu Hz\n", (long unsigned int)hz); } if(pcap_in) { char ebuf[256]; u_char *pkt; struct pcap_pkthdr *h; pcap_t *pt = pcap_open_offline(pcap_in, ebuf); struct timeval beginning = { 0, 0 }; int avg_send_len = 0; if(pt) { struct packet *last = NULL; while(1) { struct packet *p; int rc = pcap_next_ex(pt, &h, (const u_char**)&pkt); if(rc <= 0) break; if (num_pcap_pkts == 0) { beginning.tv_sec = h->ts.tv_sec; beginning.tv_usec = h->ts.tv_usec; } p = (struct packet*)malloc(sizeof(struct packet)); if(p) { p->len = h->caplen; p->ticks_from_beginning = (((h->ts.tv_sec - beginning.tv_sec) * 1000000) + (h->ts.tv_usec - beginning.tv_usec)) * hz / 1000000; p->next = NULL; p->pkt = (char*)malloc(p->len); if(p->pkt == NULL) { printf("Not enough memory\n"); break; } else { memcpy(p->pkt, pkt, p->len); if(reforge_mac) memcpy(p->pkt, mac_address, 6); } if(last) { last->next = p; last = p; } else pkt_head = p, last = p; } else { printf("Not enough memory\n"); break; } if(verbose) printf("Read %d bytes packet from pcap file %s [%lu.%lu Secs = %lu ticks@%luhz from beginning]\n", p->len, pcap_in, h->ts.tv_sec - beginning.tv_sec, h->ts.tv_usec - beginning.tv_usec, (long unsigned int)p->ticks_from_beginning, (long unsigned int)hz); avg_send_len += p->len; num_pcap_pkts++; } /* while */ avg_send_len /= num_pcap_pkts; pcap_close(pt); printf("Read %d packets from pcap file %s\n", num_pcap_pkts, pcap_in); last->next = pkt_head; /* Loop */ send_len = avg_send_len; } else { printf("Unable to open file %s\n", pcap_in); pfring_close(pd); return(-1); } } else { struct packet *p = NULL, *last = NULL; for (i = 0; i < num_balanced_pkts; i++) { forge_udp_packet(buffer, i); p = (struct packet *) malloc(sizeof(struct packet)); if(p) { if (i == 0) pkt_head = p; p->len = send_len; p->ticks_from_beginning = 0; p->next = pkt_head; p->pkt = (char*)malloc(p->len); if (p->pkt == NULL) { printf("Not enough memory\n"); break; } memcpy(p->pkt, buffer, send_len); if (last != NULL) last->next = p; last = p; } } } if(gbit_s > 0) { /* computing max rate */ pps = ((gbit_s * 1000000000) / 8 /*byte*/) / (8 /*Preamble*/ + send_len + 4 /*CRC*/ + 12 /*IFG*/); td = (double)(hz / pps); tick_delta = (ticks)td; printf("Number of %d-byte Packet Per Second at %.2f Gbit/s: %.2f\n", (send_len + 4 /*CRC*/), gbit_s, pps); } if(bind_core >= 0) bind2core(bind_core); if(wait_for_packet && (cpu_percentage > 0)) { if(cpu_percentage > 99) cpu_percentage = 99; pfring_config(cpu_percentage); } if(!verbose) { signal(SIGALRM, my_sigalarm); alarm(1); } gettimeofday(&startTime, NULL); memcpy(&lastTime, &startTime, sizeof(startTime)); pfring_set_socket_mode(pd, send_only_mode); if(pfring_enable_ring(pd) != 0) { printf("Unable to enable ring :-(\n"); pfring_close(pd); return(-1); } use_zero_copy_tx = 0; if((!disable_zero_copy) && (pd->dna_get_num_tx_slots != NULL) && (pd->dna_get_next_free_tx_slot != NULL) && (pd->dna_copy_tx_packet_into_slot != NULL)) { tosend = pkt_head; num_tx_slots = pd->dna_get_num_tx_slots(pd); if(num_tx_slots > 0 && (((num_to_send > 0) && (num_to_send <= num_tx_slots)) || ( pcap_in && (num_pcap_pkts <= num_tx_slots) && (num_tx_slots % num_pcap_pkts == 0)) || (!pcap_in && (num_balanced_pkts <= num_tx_slots) && (num_tx_slots % num_balanced_pkts == 0)))) { int ret; u_int first_free_slot = pd->dna_get_next_free_tx_slot(pd); for(i=0; i<num_tx_slots; i++) { ret = pfring_copy_tx_packet_into_slot(pd, (first_free_slot+i)%num_tx_slots, tosend->pkt, tosend->len); if(ret < 0) break; tosend = tosend->next; } use_zero_copy_tx = 1; printf("Using zero-copy TX\n"); } else { printf("NOT using zero-copy: TX ring size (%u) is not a multiple of the number of unique packets to send (%u)\n", num_tx_slots, pcap_in ? num_pcap_pkts : num_balanced_pkts); } } else { if (!disable_zero_copy) printf("NOT using zero-copy: not supported by the driver\n"); } tosend = pkt_head; i = 0; if(gbit_s != 0) tick_start = getticks(); while((num_to_send == 0) || (i < num_to_send)) { int rc; redo: if (if_index != -1) rc = pfring_send_ifindex(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */, if_index); else if(use_zero_copy_tx) /* We pre-filled the TX slots */ rc = pfring_send(pd, NULL, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */); else rc = pfring_send(pd, tosend->pkt, tosend->len, gbit_s < 0 ? 1 : 0 /* Don't flush (it does PF_RING automatically) */); if(verbose) printf("[%d] pfring_send(%d) returned %d\n", i, tosend->len, rc); if(rc == PF_RING_ERROR_INVALID_ARGUMENT) { printf("Attempting to send invalid packet [len: %u][MTU: %u]%s\n", tosend->len, pd->mtu_len, if_index != -1 ? " or using a wrong interface id" : ""); } else if(rc < 0) { /* Not enough space in buffer */ if(!active_poll) { #if 1 usleep(1); #else if(bind_core >= 0) usleep(1); else pfring_poll(pd, 0); //sched_yield(); #endif } goto redo; } num_pkt_good_sent++; num_bytes_good_sent += tosend->len + 24 /* 8 Preamble + 4 CRC + 12 IFG */; tosend = tosend->next; if (use_zero_copy_tx && (num_pkt_good_sent == num_tx_slots)) tosend = pkt_head; if(gbit_s > 0) { /* rate set */ while((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ; } else if (gbit_s < 0) { /* real pcap rate */ if (tosend->ticks_from_beginning == 0) tick_start = getticks(); /* first packet, resetting time */ while((getticks() - tick_start) < tosend->ticks_from_beginning) ; } if(num_to_send > 0) i++; } /* for */ print_stats(0); pfring_close(pd); return(0); }