static void enter_mode_pcap_to_tx(struct mode *mode) { int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct tx_stats stats; uint8_t *out = NULL; if (!device_up_and_running(mode->device_out)) panic("Device not up and running!\n"); set_memcpy(); tx_sock = pf_socket(); if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } memset(&tx_ring, 0, sizeof(tx_ring)); memset(&bpf_ops, 0, sizeof(bpf_ops)); memset(&stats, 0, sizeof(stats)); ifindex = device_ifindex(mode->device_out); size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: TX %luus %s\n\n", interval, pcap_ops[mode->pcap]->name); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { struct pcap_pkthdr phdr; hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); do { ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h); stats.tx_bytes += hdr->tp_h.tp_len;; stats.tx_packets++; show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, hdr->tp_h.tp_snaplen, mode->link_type); kernel_may_pull_from_tx(&hdr->tp_h); next_slot(&it, &tx_ring); if (unlikely(sigint == 1)) break; if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } } out: fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); close(tx_sock); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); }
static void enter_mode_rx_only_or_dump(struct mode *mode) { int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long fcnt = 0; short ifflags = 0; uint8_t *packet; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; if (!device_up_and_running(mode->device_in)) panic("Device not up and running!\n"); set_memcpy(); sock = pf_socket(); if (mode->dump) { struct stat tmp; memset(&tmp, 0, sizeof(tmp)); ret = stat(mode->device_out, &tmp); if (ret < 0) { mode->dump_dir = 0; goto try_file; } mode->dump_dir = !!S_ISDIR(tmp.st_mode); if (mode->dump_dir) { fd = begin_multi_pcap_file(mode); } else { try_file: fd = begin_single_pcap_file(mode); } } memset(&rx_ring, 0, sizeof(rx_ring)); memset(&rx_poll, 0, sizeof(rx_poll)); memset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(mode->device_in); size = ring_size(mode->device_in, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support); create_rx_ring(sock, &rx_ring); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_in); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq, mode->cpu); } if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RX %s\n\n", mode->dump ? pcap_ops[mode->pcap]->name : ""); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(rx_ring.layout.tp_frame_size < hdr->tp_h.tp_snaplen)) { fprintf(stderr, "Skipping too large packet! " "No jumbo support selected?\n"); fflush(stderr); goto next; } if (mode->dump) { struct pcap_pkthdr phdr; tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr); ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr, packet, phdr.len); if (unlikely(ret != sizeof(phdr) + phdr.len)) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, mode->link_type); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr->tp_h); next_slot(&it, &rx_ring); if (unlikely(sigint == 1)) break; if (mode->dump && next_dump) { struct tpacket_stats kstats; socklen_t slen = sizeof(kstats); memset(&kstats, 0, sizeof(kstats)); getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); fd = next_multi_pcap_file(mode, fd); next_dump = false; if (mode->print_mode == FNTTYPE_PRINT_NONE) { printf(".(+%u/-%u)", kstats.tp_packets - kstats.tp_drops, kstats.tp_drops); fflush(stdout); } } } poll(&rx_poll, 1, -1); poll_error_maybe_die(sock, &rx_poll); } if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) sock_print_net_stats(sock); else { printf("\n\n"); fflush(stdout); } dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); close(sock); if (mode->dump) { if (mode->dump_dir) finish_multi_pcap_file(mode, fd); else finish_single_pcap_file(mode, fd); } }
static void pcap_to_xmit(struct ctx *ctx) { __label__ out; uint8_t *out = NULL; int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long trunced = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; pcap_pkthdr_t phdr; if (!device_up_and_running(ctx->device_out) && !ctx->rfraw) panic("Device not up and running!\n"); bug_on(!__pcap_io); tx_sock = pf_socket(); if (!strncmp("-", ctx->device_in, strlen("-"))) { fd = dup_or_die(fileno(stdin)); close(fileno(stdin)); if (ctx->pcap == PCAP_OPS_MM) ctx->pcap = PCAP_OPS_SG; } else { fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); } if (__pcap_io->init_once_pcap) __pcap_io->init_once_pcap(); ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type); if (ret) panic("Error reading pcap header!\n"); if (__pcap_io->prepare_access_pcap) { ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo); if (ret) panic("Error prepare reading pcap!\n"); } fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_out); xfree(ctx->device_out); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_out); if (ctx->link_type != LINKTYPE_IEEE802_11) panic("Wrong linktype of pcap!\n"); } ifindex = device_ifindex(ctx->device_out); size = ring_size(ctx->device_out, ctx->reserve_size); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); set_packet_loss_discard(tx_sock); setup_tx_ring_layout(tx_sock, &tx_ring, size, ctx->jumbo); create_tx_ring(tx_sock, &tx_ring, ctx->verbose); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(tx_sock, &tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_out); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_out, irq, ctx->cpu); } if (ctx->kpull) interval = ctx->kpull; set_itimer_interval_value(&itimer, 0, interval); setitimer(ITIMER_REAL, &itimer, NULL); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { hdr = tx_ring.frames[it].iov_base; out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); do { ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; if (ring_frame_size(&tx_ring) < pcap_get_length(&phdr, ctx->magic)) { pcap_set_length(&phdr, ctx->magic, ring_frame_size(&tx_ring)); trunced++; } } while (ctx->filter && !bpf_run_filter(&bpf_ops, out, pcap_get_length(&phdr, ctx->magic))); pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &hdr->tp_h, &hdr->s_ll); ctx->tx_bytes += hdr->tp_h.tp_len;; ctx->tx_packets++; show_frame_hdr(hdr, ctx->print_mode); dissector_entry_point(out, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode); kernel_may_pull_from_tx(&hdr->tp_h); it++; if (it >= tx_ring.layout.tp_frame_nr) it = 0; if (unlikely(sigint == 1)) break; if (frame_count_max != 0) { if (ctx->tx_packets >= frame_count_max) { sigint = 1; break; } } } } out: bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); timer_purge(); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_out); if (__pcap_io->prepare_close_pcap) __pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD); if (!strncmp("-", ctx->device_in, strlen("-"))) dup2(fd, fileno(stdin)); close(fd); close(tx_sock); fflush(stdout); printf("\n"); printf("\r%12lu packets outgoing\n", ctx->tx_packets); printf("\r%12lu packets truncated in file\n", trunced); printf("\r%12lu bytes outgoing\n", ctx->tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); }
static void recv_only_or_dump(struct ctx *ctx) { short ifflags = 0; int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; struct timeval start, end, diff; struct block_desc *pbd; unsigned long frame_count = 0; sock = pf_socket(); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_in); xfree(ctx->device_in); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in); ctx->link_type = LINKTYPE_IEEE802_11; } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); ret = set_sockopt_hwtimestamp(sock, ctx->device_in); if (ret == 0 && ctx->verbose) printf("HW timestamping enabled\n"); setup_rx_ring_layout(sock, &rx_ring, size, true, true); create_rx_ring(sock, &rx_ring, ctx->verbose); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(sock, &rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_in); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = enter_promiscuous_mode(ctx->device_in); if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap) __pcap_io->init_once_pcap(); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { __label__ try_file; struct stat stats; fmemset(&stats, 0, sizeof(stats)); ret = stat(ctx->device_out, &stats); if (ret < 0) { ctx->dump_dir = 0; goto try_file; } ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) { fd = begin_multi_pcap_file(ctx); } else { try_file: fd = begin_single_pcap_file(ctx); } } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_rx_block((pbd = (void *) rx_ring.frames[it].iov_base))) { walk_t3_block(pbd, ctx, sock, &fd, &frame_count); kernel_may_pull_from_rx_block(pbd); it = (it + 1) % rx_ring.layout3.tp_block_nr; if (unlikely(sigint == 1)) break; } poll(&rx_poll, 1, -1); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) { sock_rx_net_stats(sock, frame_count); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
static void recv_only_or_dump(struct ctx *ctx) { short ifflags = 0; int sock, ifindex, fd = 0, ret; size_t size; unsigned int it = 0; struct ring rx_ring; struct pollfd rx_poll; struct sock_fprog bpf_ops; struct timeval start, end, diff; bool is_v3 = is_defined(HAVE_TPACKET3); sock = pf_socket_type(ctx->link_type); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); if (ctx->hwtimestamp) { ret = set_sockopt_hwtimestamp(sock, ctx->device_in); if (ret == 0 && ctx->verbose) printf("HW timestamping enabled\n"); } ring_rx_setup(&rx_ring, sock, size, ifindex, &rx_poll, is_v3, true, ctx->verbose, ctx->fanout_group, ctx->fanout_type); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { int irq = device_irq_number(ctx->device_in); device_set_irq_affinity(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = device_enter_promiscuous_mode(ctx->device_in); if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap) __pcap_io->init_once_pcap(true); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { struct stat stats; ret = stat(ctx->device_out, &stats); if (ret < 0) ctx->dump_dir = 0; else ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) fd = begin_multi_pcap_file(ctx); else fd = begin_single_pcap_file(ctx); } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { #ifdef HAVE_TPACKET3 struct block_desc *pbd; while (user_may_pull_from_rx_block((pbd = rx_ring.frames[it].iov_base))) { walk_t3_block(pbd, ctx, sock, &fd); kernel_may_pull_from_rx_block(pbd); it = (it + 1) % rx_ring.layout3.tp_block_nr; if (unlikely(sigint == 1)) break; } #else while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { struct frame_map *hdr = rx_ring.frames[it].iov_base; uint8_t *packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; pcap_pkthdr_t phdr; if (ctx->packet_type != -1) if (ctx->packet_type != hdr->s_ll.sll_pkttype) goto next; ctx->pkts_seen++; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { /* XXX: silently ignore for now. We used to * report them with dump_rx_stats() */ goto next; } if (dump_to_pcap(ctx)) { tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic); ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet, pcap_get_length(&phdr, ctx->magic)); if (unlikely(ret != (int) pcap_get_total_length(&phdr, ctx->magic))) panic("Write error to pcap!\n"); } show_frame_hdr(packet, hdr->tp_h.tp_snaplen, ctx->link_type, hdr, ctx->print_mode, ctx->pkts_seen); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode, &hdr->s_ll); if (frame_count_max != 0) { if (unlikely(ctx->pkts_seen >= frame_count_max)) { sigint = 1; break; } } next: kernel_may_pull_from_rx(&hdr->tp_h); it = (it + 1) % rx_ring.layout.tp_frame_nr; if (unlikely(sigint == 1)) break; update_pcap_next_dump(ctx, hdr->tp_h.tp_snaplen, &fd, sock, is_v3); } #endif /* HAVE_TPACKET3 */ ret = poll(&rx_poll, 1, -1); if (unlikely(ret < 0)) { if (errno != EINTR) panic("Poll failed!\n"); } } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); dump_rx_stats(ctx, sock, is_v3); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) device_leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
int main(int argc, char **argv) { bool slow = false, invoke_cpp = false, reseed = true; int c, opt_index, i, j, vals[4] = {0}, irq; char *confname = NULL, *ptr; unsigned long cpus_tmp, orig_num = 0; unsigned long long tx_packets, tx_bytes; struct ctx ctx; fmemset(&ctx, 0, sizeof(ctx)); ctx.cpus = get_number_cpus_online(); ctx.uid = getuid(); ctx.gid = getgid(); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'h': help(); break; case 'v': version(); break; case 'e': example(); break; case 'p': invoke_cpp = true; break; case 'V': ctx.verbose = true; break; case 'P': cpus_tmp = strtoul(optarg, NULL, 0); if (cpus_tmp > 0 && cpus_tmp < ctx.cpus) ctx.cpus = cpus_tmp; break; case 'd': case 'o': ctx.device = xstrndup(optarg, IFNAMSIZ); break; case 'r': ctx.rand = true; break; case 's': slow = true; ctx.cpus = 1; ctx.smoke_test = true; ctx.rhost = xstrdup(optarg); break; case 'R': ctx.rfraw = true; break; case 'J': ctx.jumbo_support = true; break; case 'c': case 'i': confname = xstrdup(optarg); if (!strncmp("-", confname, strlen("-"))) ctx.cpus = 1; break; case 'u': ctx.uid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'g': ctx.gid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'k': ctx.kpull = strtoul(optarg, NULL, 0); break; case 'E': seed = strtoul(optarg, NULL, 0); reseed = false; break; case 'n': orig_num = strtoul(optarg, NULL, 0); ctx.num = orig_num; break; case 't': slow = true; ctx.gap = strtoul(optarg, NULL, 0); if (ctx.gap > 0) /* Fall back to single core to not * mess up correct timing. We are slow * anyway! */ ctx.cpus = 1; break; case 'S': ptr = optarg; ctx.reserve_size = 0; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) ctx.reserve_size = 1 << 10; else if (!strncmp(ptr, "MiB", strlen("MiB"))) ctx.reserve_size = 1 << 20; else if (!strncmp(ptr, "GiB", strlen("GiB"))) ctx.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); *ptr = 0; ctx.reserve_size *= strtol(optarg, NULL, 0); break; case '?': switch (optopt) { case 'd': case 'c': case 'n': case 'S': case 's': case 'P': case 'o': case 'E': case 'i': case 'k': case 'u': case 'g': case 't': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (argc < 5) help(); if (ctx.device == NULL) panic("No networking device given!\n"); if (confname == NULL) panic("No configuration file given!\n"); if (device_mtu(ctx.device) == 0) panic("This is no networking device!\n"); register_signal(SIGINT, signal_handler); register_signal(SIGHUP, signal_handler); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); set_system_socket_memory(vals, array_size(vals)); xlockme(); if (ctx.rfraw) { ctx.device_trans = xstrdup(ctx.device); xfree(ctx.device); enter_rfmon_mac80211(ctx.device_trans, &ctx.device); sleep(0); } irq = device_irq_number(ctx.device); device_set_irq_affinity_list(irq, 0, ctx.cpus - 1); stats = setup_shared_var(ctx.cpus); for (i = 0; i < ctx.cpus; i++) { pid_t pid = fork(); switch (pid) { case 0: if (reseed) seed = generate_srand_seed(); srand(seed); cpu_affinity(i); main_loop(&ctx, confname, slow, i, invoke_cpp, orig_num); goto thread_out; case -1: panic("Cannot fork processes!\n"); } } for (i = 0; i < ctx.cpus; i++) { int status; wait(&status); if (WEXITSTATUS(status) == EXIT_FAILURE) die(); } if (ctx.rfraw) leave_rfmon_mac80211(ctx.device_trans, ctx.device); reset_system_socket_memory(vals, array_size(vals)); for (i = 0, tx_packets = tx_bytes = 0; i < ctx.cpus; i++) { while ((__get_state(i) & CPU_STATS_STATE_RES) == 0) sched_yield(); tx_packets += stats[i].tx_packets; tx_bytes += stats[i].tx_bytes; } fflush(stdout); printf("\n"); printf("\r%12llu packets outgoing\n", tx_packets); printf("\r%12llu bytes outgoing\n", tx_bytes); for (i = 0; i < ctx.cpus; i++) { printf("\r%12lu sec, %lu usec on CPU%d (%llu packets)\n", stats[i].tv_sec, stats[i].tv_usec, i, stats[i].tx_packets); } thread_out: xunlockme(); destroy_shared_var(stats, ctx.cpus); device_restore_irq_affinity_list(); free(ctx.device); free(ctx.device_trans); free(ctx.rhost); free(confname); return 0; }
static void enter_mode_rx_only_or_dump(struct mode *mode) { int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long fcnt = 0, skipped = 0; short ifflags = 0; uint8_t *packet; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; if (!device_up_and_running(mode->device_in)) panic("Device not up and running!\n"); sock = pf_socket(); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device_in); xfree(mode->device_in); enter_rfmon_mac80211(mode->device_trans, &mode->device_in); mode->link_type = LINKTYPE_IEEE802_11; } if (mode->dump) { struct stat tmp; fmemset(&tmp, 0, sizeof(tmp)); ret = stat(mode->device_out, &tmp); if (ret < 0) { mode->dump_dir = 0; goto try_file; } mode->dump_dir = !!S_ISDIR(tmp.st_mode); if (mode->dump_dir) { fd = begin_multi_pcap_file(mode); } else { try_file: fd = begin_single_pcap_file(mode); } } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(mode->device_in); size = ring_size(mode->device_in, mode->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(mode->filter, &bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); set_sockopt_hwtimestamp(sock, mode->device_in); setup_rx_ring_layout(sock, &rx_ring, size, mode->jumbo_support); create_rx_ring(sock, &rx_ring); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_in); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_in, irq, mode->cpu); } if (mode->promiscuous == true) { ifflags = enter_promiscuous_mode(mode->device_in); printf("PROMISC\n"); } printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: RX %s ", mode->dump ? pcap_ops[mode->pcap]->name : ""); if (mode->rfraw) printf("802.11 raw via %s ", mode->device_in); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); gettimeofday(&start, NULL); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; fcnt++; if (mode->packet_type != PACKET_ALL) if (mode->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { skipped++; goto next; } if (mode->dump) { struct pcap_pkthdr phdr; tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &phdr); ret = pcap_ops[mode->pcap]->write_pcap_pkt(fd, &phdr, packet, phdr.len); if (unlikely(ret != sizeof(phdr) + phdr.len)) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, mode->print_mode, RING_MODE_INGRESS); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, mode->link_type, mode->print_mode); if (frame_cnt_max != 0 && fcnt >= frame_cnt_max) { sigint = 1; break; } next: kernel_may_pull_from_rx(&hdr->tp_h); next_slot_prerd(&it, &rx_ring); if (unlikely(sigint == 1)) break; if (mode->dump && next_dump) { struct tpacket_stats kstats; socklen_t slen = sizeof(kstats); fmemset(&kstats, 0, sizeof(kstats)); getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); fd = next_multi_pcap_file(mode, fd); next_dump = false; if (mode->print_mode == FNTTYPE_PRINT_NONE) { printf(".(+%lu/-%lu)", 1UL * kstats.tp_packets - kstats.tp_drops - skipped, 1UL * kstats.tp_drops + skipped); fflush(stdout); } } } poll(&rx_poll, 1, -1); poll_error_maybe_die(sock, &rx_poll); } gettimeofday(&end, NULL); diff = tv_subtract(end, start); if (!(mode->dump_dir && mode->print_mode == FNTTYPE_PRINT_NONE)) { sock_print_net_stats(sock, skipped); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (mode->promiscuous == true) leave_promiscuous_mode(mode->device_in, ifflags); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device_in); close(sock); if (mode->dump) { if (mode->dump_dir) finish_multi_pcap_file(mode, fd); else finish_single_pcap_file(mode, fd); } }
static void enter_mode_pcap_to_tx(struct mode *mode) { int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct tx_stats stats; uint8_t *out = NULL; unsigned long trunced = 0; struct timeval start, end, diff; if (!device_up_and_running(mode->device_out)) panic("Device not up and running!\n"); tx_sock = pf_socket(); if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type); if (ret) panic("error reading pcap header!\n"); if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) panic("error prepare reading pcap!\n"); } fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); fmemset(&stats, 0, sizeof(stats)); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device_out); xfree(mode->device_out); enter_rfmon_mac80211(mode->device_trans, &mode->device_out); if (mode->link_type != LINKTYPE_IEEE802_11) panic("Wrong linktype of pcap!\n"); } ifindex = device_ifindex(mode->device_out); size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); set_sockopt_hwtimestamp(tx_sock, mode->device_out); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: TX %luus %s ", interval, pcap_ops[mode->pcap]->name); if (mode->rfraw) printf("802.11 raw via %s ", mode->device_out); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); gettimeofday(&start, NULL); while (likely(sigint == 0)) { while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) { struct pcap_pkthdr phdr; hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); do { memset(&phdr, 0, sizeof(phdr)); ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr, out, ring_frame_size(&tx_ring)); if (unlikely(ret <= 0)) goto out; if (ring_frame_size(&tx_ring) < phdr.len) { phdr.len = ring_frame_size(&tx_ring); trunced++; } } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h); stats.tx_bytes += hdr->tp_h.tp_len;; stats.tx_packets++; show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, hdr->tp_h.tp_snaplen, mode->link_type, mode->print_mode); kernel_may_pull_from_tx(&hdr->tp_h); next_slot_prewr(&it, &tx_ring); if (unlikely(sigint == 1)) break; if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { sigint = 1; break; } } } out: gettimeofday(&end, NULL); diff = tv_subtract(end, start); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu frames truncated (larger than frame)\n", trunced); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device_out); close(tx_sock); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); }
static void recv_only_or_dump(struct ctx *ctx) { uint8_t *packet; short ifflags = 0; int sock, irq, ifindex, fd = 0, ret; unsigned int size, it = 0; unsigned long frame_count = 0, skipped = 0; struct ring rx_ring; struct pollfd rx_poll; struct frame_map *hdr; struct sock_fprog bpf_ops; struct timeval start, end, diff; pcap_pkthdr_t phdr; if (!device_up_and_running(ctx->device_in) && !ctx->rfraw) panic("Device not up and running!\n"); sock = pf_socket(); if (ctx->rfraw) { ctx->device_trans = xstrdup(ctx->device_in); xfree(ctx->device_in); enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in); ctx->link_type = LINKTYPE_IEEE802_11; } fmemset(&rx_ring, 0, sizeof(rx_ring)); fmemset(&rx_poll, 0, sizeof(rx_poll)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); ifindex = device_ifindex(ctx->device_in); size = ring_size(ctx->device_in, ctx->reserve_size); enable_kernel_bpf_jit_compiler(); bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type); if (ctx->dump_bpf) bpf_dump_all(&bpf_ops); bpf_attach_to_sock(sock, &bpf_ops); set_sockopt_hwtimestamp(sock, ctx->device_in); setup_rx_ring_layout(sock, &rx_ring, size, ctx->jumbo); create_rx_ring(sock, &rx_ring, ctx->verbose); mmap_rx_ring(sock, &rx_ring); alloc_rx_ring_frames(&rx_ring); bind_rx_ring(sock, &rx_ring, ifindex); prepare_polling(sock, &rx_poll); dissector_init_all(ctx->print_mode); if (ctx->cpu >= 0 && ifindex > 0) { irq = device_irq_number(ctx->device_in); device_bind_irq_to_cpu(irq, ctx->cpu); if (ctx->verbose) printf("IRQ: %s:%d > CPU%d\n", ctx->device_in, irq, ctx->cpu); } if (ctx->promiscuous) ifflags = enter_promiscuous_mode(ctx->device_in); drop_privileges(ctx->enforce, ctx->uid, ctx->gid); if (dump_to_pcap(ctx)) { __label__ try_file; struct stat stats; fmemset(&stats, 0, sizeof(stats)); ret = stat(ctx->device_out, &stats); if (ret < 0) { ctx->dump_dir = 0; goto try_file; } ctx->dump_dir = S_ISDIR(stats.st_mode); if (ctx->dump_dir) { fd = begin_multi_pcap_file(ctx); } else { try_file: fd = begin_single_pcap_file(ctx); } } printf("Running! Hang up with ^C!\n\n"); fflush(stdout); bug_on(gettimeofday(&start, NULL)); while (likely(sigint == 0)) { while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) { __label__ next; hdr = rx_ring.frames[it].iov_base; packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac; frame_count++; if (ctx->packet_type != -1) if (ctx->packet_type != hdr->s_ll.sll_pkttype) goto next; if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) { skipped++; goto next; } if (dump_to_pcap(ctx)) { tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic); ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet, pcap_get_length(&phdr, ctx->magic)); if (unlikely(ret != pcap_get_total_length(&phdr, ctx->magic))) panic("Write error to pcap!\n"); } show_frame_hdr(hdr, ctx->print_mode); dissector_entry_point(packet, hdr->tp_h.tp_snaplen, ctx->link_type, ctx->print_mode); if (frame_count_max != 0) { if (frame_count >= frame_count_max) { sigint = 1; break; } } next: kernel_may_pull_from_rx(&hdr->tp_h); it++; if (it >= rx_ring.layout.tp_frame_nr) it = 0; if (unlikely(sigint == 1)) break; if (dump_to_pcap(ctx)) { if (ctx->dump_mode == DUMP_INTERVAL_SIZE) { interval += hdr->tp_h.tp_snaplen; if (interval > ctx->dump_interval) { next_dump = true; interval = 0; } } if (next_dump) { fd = next_multi_pcap_file(ctx, fd); next_dump = false; if (ctx->verbose) print_pcap_file_stats(sock, ctx, skipped); } } } poll(&rx_poll, 1, -1); } bug_on(gettimeofday(&end, NULL)); timersub(&end, &start, &diff); if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) { sock_print_net_stats(sock, skipped); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); } else { printf("\n\n"); fflush(stdout); } bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_rx_ring(sock, &rx_ring); if (ctx->promiscuous) leave_promiscuous_mode(ctx->device_in, ifflags); if (ctx->rfraw) leave_rfmon_mac80211(ctx->device_trans, ctx->device_in); if (dump_to_pcap(ctx)) { if (ctx->dump_dir) finish_multi_pcap_file(ctx, fd); else finish_single_pcap_file(ctx, fd); } close(sock); }
int main(int argc, char **argv) { bool slow = false, invoke_cpp = false, reseed = true, cpustats = true; bool prio_high = false, set_irq_aff = true, set_sock_mem = true; int c, opt_index, vals[4] = {0}, irq; uint64_t gap = 0; unsigned int i, j; char *confname = NULL, *ptr; unsigned long cpus_tmp, orig_num = 0; unsigned long long tx_packets, tx_bytes; struct ctx ctx; fmemset(&ctx, 0, sizeof(ctx)); ctx.cpus = get_number_cpus_online(); ctx.uid = getuid(); ctx.gid = getgid(); ctx.qdisc_path = false; /* Keep an initial small default size to reduce cache-misses. */ ctx.reserve_size = 512 * (1 << 10); while ((c = getopt_long(argc, argv, short_options, long_options, &opt_index)) != EOF) { switch (c) { case 'h': help(); break; case 'v': version(); break; case 'C': cpustats = false; break; case 'e': example(); break; case 'p': invoke_cpp = true; break; case 'V': ctx.verbose = true; break; case 'P': cpus_tmp = strtoul(optarg, NULL, 0); if (cpus_tmp > 0 && cpus_tmp < ctx.cpus) ctx.cpus = cpus_tmp; break; case 'd': case 'o': ctx.device = xstrndup(optarg, IFNAMSIZ); break; case 'H': prio_high = true; break; case 'A': set_sock_mem = false; break; case 'Q': set_irq_aff = false; break; case 'q': ctx.qdisc_path = true; break; case 'r': ctx.rand = true; break; case 's': slow = true; ctx.cpus = 1; ctx.smoke_test = true; ctx.rhost = xstrdup(optarg); break; case 'R': ctx.rfraw = true; break; case 'J': ctx.jumbo_support = true; break; case 'c': case 'i': confname = xstrdup(optarg); if (!strncmp("-", confname, strlen("-"))) ctx.cpus = 1; break; case 'u': ctx.uid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'g': ctx.gid = strtoul(optarg, NULL, 0); ctx.enforce = true; break; case 'k': printf("Option -k/--kernel-pull is no longer used and " "will be removed in a future release!\n"); break; case 'E': seed = strtoul(optarg, NULL, 0); reseed = false; break; case 'n': orig_num = strtoul(optarg, NULL, 0); ctx.num = orig_num; break; case 't': slow = true; ptr = optarg; prctl(PR_SET_TIMERSLACK, 1UL); gap = strtoul(optarg, NULL, 0); for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "ns", strlen("ns"))) { ctx.gap.tv_sec = gap / 1000000000; ctx.gap.tv_nsec = gap % 1000000000; } else if (*ptr == '\0' || !strncmp(ptr, "us", strlen("us"))) { /* Default to microseconds for backwards * compatibility if no postfix is given. */ ctx.gap.tv_sec = gap / 1000000; ctx.gap.tv_nsec = (gap % 1000000) * 1000; } else if (!strncmp(ptr, "ms", strlen("ms"))) { ctx.gap.tv_sec = gap / 1000; ctx.gap.tv_nsec = (gap % 1000) * 1000000; } else if (!strncmp(ptr, "s", strlen("s"))) { ctx.gap.tv_sec = gap; ctx.gap.tv_nsec = 0; } else panic("Syntax error in time param!\n"); if (gap > 0) /* Fall back to single core to not mess up * correct timing. We are slow anyway! */ ctx.cpus = 1; break; case 'S': ptr = optarg; for (j = i = strlen(optarg); i > 0; --i) { if (!isdigit(optarg[j - i])) break; ptr++; } if (!strncmp(ptr, "KiB", strlen("KiB"))) ctx.reserve_size = 1 << 10; else if (!strncmp(ptr, "MiB", strlen("MiB"))) ctx.reserve_size = 1 << 20; else if (!strncmp(ptr, "GiB", strlen("GiB"))) ctx.reserve_size = 1 << 30; else panic("Syntax error in ring size param!\n"); ctx.reserve_size *= strtoul(optarg, NULL, 0); break; case '?': switch (optopt) { case 'd': case 'c': case 'n': case 'S': case 's': case 'P': case 'o': case 'E': case 'i': case 'k': case 'u': case 'g': case 't': panic("Option -%c requires an argument!\n", optopt); default: if (isprint(optopt)) printf("Unknown option character `0x%X\'!\n", optopt); die(); } default: break; } } if (argc < 5) help(); if (ctx.device == NULL) panic("No networking device given!\n"); if (confname == NULL) panic("No configuration file given!\n"); if (device_mtu(ctx.device) == 0) panic("This is no networking device!\n"); register_signal(SIGINT, signal_handler); register_signal(SIGQUIT, signal_handler); register_signal(SIGTERM, signal_handler); register_signal(SIGHUP, signal_handler); if (prio_high) { set_proc_prio(-20); set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO)); } if (set_sock_mem) set_system_socket_memory(vals, array_size(vals)); xlockme(); if (ctx.rfraw) { ctx.device_trans = xstrdup(ctx.device); xfree(ctx.device); enter_rfmon_mac80211(ctx.device_trans, &ctx.device); panic_handler_add(on_panic_del_rfmon, ctx.device); sleep(0); } /* * If number of packets is smaller than number of CPUs use only as * many CPUs as there are packets. Otherwise we end up sending more * packets than intended or none at all. */ if (ctx.num) ctx.cpus = min_t(unsigned int, ctx.num, ctx.cpus); irq = device_irq_number(ctx.device); if (set_irq_aff) device_set_irq_affinity_list(irq, 0, ctx.cpus - 1); stats = setup_shared_var(ctx.cpus); for (i = 0; i < ctx.cpus; i++) { pid_t pid = fork(); switch (pid) { case 0: if (reseed) seed = generate_srand_seed(); srand(seed); cpu_affinity(i); main_loop(&ctx, confname, slow, i, invoke_cpp, orig_num); goto thread_out; case -1: panic("Cannot fork processes!\n"); } } for (i = 0; i < ctx.cpus; i++) { int status; wait(&status); if (WEXITSTATUS(status) == EXIT_FAILURE) die(); } if (ctx.rfraw) leave_rfmon_mac80211(ctx.device); if (set_sock_mem) reset_system_socket_memory(vals, array_size(vals)); for (i = 0, tx_packets = tx_bytes = 0; i < ctx.cpus; i++) { while ((__get_state(i) & CPU_STATS_STATE_RES) == 0) sched_yield(); tx_packets += stats[i].tx_packets; tx_bytes += stats[i].tx_bytes; } fflush(stdout); printf("\n"); printf("\r%12llu packets outgoing\n", tx_packets); printf("\r%12llu bytes outgoing\n", tx_bytes); for (i = 0; cpustats && i < ctx.cpus; i++) { printf("\r%12lu sec, %lu usec on CPU%d (%llu packets)\n", stats[i].tv_sec, stats[i].tv_usec, i, stats[i].tx_packets); } thread_out: xunlockme(); destroy_shared_var(stats, ctx.cpus); if (set_irq_aff) device_restore_irq_affinity_list(); free(ctx.device); free(ctx.device_trans); free(ctx.rhost); free(confname); return 0; }
static void enter_mode_pcap_to_tx(struct mode *mode) { int irq, ifindex, fd = 0, ret; unsigned int size, it = 0; struct ring tx_ring; struct frame_map *hdr; struct sock_fprog bpf_ops; struct tx_stats stats; uint8_t *out = NULL; unsigned long trunced = 0; struct timeval start, end, diff; int filen = 0; struct pcap_timeval *pcap_time; /* if (!device_up_and_running(mode->device_out)) panic("Device not up and running!\n"); */ if (!pcap_ops[mode->pcap]) panic("pcap group not supported!\n"); //Moved here /* ifindex = device_ifindex(mode->device_out); //Make n devices out of it. From here size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); set_sockopt_hwtimestamp(tx_sock, mode->device_out); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } //Till here. Make n TXRings. One for each NIC. */ //Moved to here end int x = 0; for (filen = 0; filen < num_of_pcaps; filen++) { tx_sock = pf_socket(); mode->device_in = pcaplist[filen]; printf("\n \n File selected is: %s \n", mode->device_in); fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME); //Need to do for each file ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type); if (ret) { panic("error reading pcap header!\n"); continue; } if (pcap_ops[mode->pcap]->prepare_reading_pcap) { ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd); if (ret) { panic("error prepare reading pcap!\n"); continue; } } fmemset(&tx_ring, 0, sizeof(tx_ring)); fmemset(&bpf_ops, 0, sizeof(bpf_ops)); fmemset(&stats, 0, sizeof(stats)); if (mode->rfraw) { mode->device_trans = xstrdup(mode->device_out); xfree(mode->device_out); enter_rfmon_mac80211(mode->device_trans, &mode->device_out); if (mode->link_type != LINKTYPE_IEEE802_11) panic("Wrong linktype of pcap!\n"); continue; } ifindex = device_ifindex(mode->device_out); //Make n devices out of it. From here size = ring_size(mode->device_out, mode->reserve_size); bpf_parse_rules(mode->filter, &bpf_ops); set_packet_loss_discard(tx_sock); set_sockopt_hwtimestamp(tx_sock, mode->device_out); setup_tx_ring_layout(tx_sock, &tx_ring, size, mode->jumbo_support); create_tx_ring(tx_sock, &tx_ring); mmap_tx_ring(tx_sock, &tx_ring); alloc_tx_ring_frames(&tx_ring); bind_tx_ring(tx_sock, &tx_ring, ifindex); //Till here. Make n TXRings. One for each NIC. dissector_init_all(mode->print_mode); if (mode->cpu >= 0 && ifindex > 0) { irq = device_irq_number(mode->device_out); device_bind_irq_to_cpu(mode->cpu, irq); printf("IRQ: %s:%d > CPU%d\n", mode->device_out, irq, mode->cpu); } if (mode->kpull) interval = mode->kpull; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; //for fixed delay need to SET this setitimer(ITIMER_REAL, &itimer, NULL); printf("BPF:\n"); bpf_dump_all(&bpf_ops); printf("MD: TX %luus %s ", interval, pcap_ops[mode->pcap]->name); if (mode->rfraw) printf("802.11 raw via %s ", mode->device_out); #ifdef _LARGEFILE64_SOURCE printf("lf64 "); #endif ioprio_print(); printf("\n"); gettimeofday(&start, NULL); sigint = 0; while (likely(sigint == 0)) { while (user_may_pull_from_tx (tx_ring.frames[it].iov_base)) { struct pcap_pkthdr phdr; hdr = tx_ring.frames[it].iov_base; /* Kernel assumes: data = ph.raw + po->tp_hdrlen - * sizeof(struct sockaddr_ll); */ out = ((uint8_t *) hdr) + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); do { memset(&phdr, 0, sizeof(phdr)); ret = pcap_ops[mode->pcap]-> read_pcap_pkt(fd, &phdr, out, ring_frame_size (&tx_ring)); if (unlikely(ret <= 0)) goto out; if (ring_frame_size(&tx_ring) < phdr.len) { phdr.len = ring_frame_size(&tx_ring); trunced++; } } while (mode->filter && !bpf_run_filter(&bpf_ops, out, phdr.len)); pcap_pkthdr_to_tpacket_hdr(&phdr, &hdr->tp_h); if (stats.tx_packets == 0) { pcap_time = &phdr.ts; beginning_tv_sec = pcap_time->tv_sec; beginning_tv_usec = pcap_time->tv_usec; } /* * START OF BLOCK The below routines are only if Speed or PPS is set else they won't execute * */ if (gbit_s > 0) { /* computing max rate */ pps = ((gbit_s * 1000000000) / 8 /*byte */ ) / (8 /*Preamble */ + avg_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", (avg_send_len + 4 /*CRC*/), gbit_s, pps); } else if (pps > 0) { td = (double)(hz / pps); tick_delta = (ticks) td; } //END OF BLOCK /* show_frame_hdr(hdr, mode->print_mode, RING_MODE_EGRESS); dissector_entry_point(out, hdr->tp_h.tp_snaplen, mode->link_type, mode->print_mode); */ //x++; kernel_may_pull_from_tx(&hdr->tp_h); next_slot_prewr(&it, &tx_ring); stats.tx_bytes += hdr->tp_h.tp_len;; stats.tx_packets++; send_len += hdr->tp_h.tp_len; avg_send_len = send_len / stats.tx_packets; if (unlikely(sigint == 1)) break; if (frame_cnt_max != 0 && stats.tx_packets >= frame_cnt_max) { //sigint = 1; break; } //START OF BLOCK if (gbit_s != 0 || pps > 0) tick_start = getticks(); if (gbit_s > 0 || pps > 0) { /* rate set */ while ((getticks() - tick_start) < (num_pkt_good_sent * tick_delta)) ; } else if (gbit_s < 0) { /* real pcap rate --FULL SYNC MODE */ pcap_time = &phdr.ts; ticks ticks_from_beginning = (((pcap_time->tv_sec - beginning_tv_sec) * 1000000) + (pcap_time->tv_usec - beginning_tv_usec)) * hz / 1000000; //delta time of this pkt from beginning of pcap /* h-> is this packet header and beginning is 1st packet's header */ if (ticks_from_beginning == 0) tick_start = getticks(); /* first packet, resetting time */ while ((getticks() - tick_start) < ticks_from_beginning) ; } //pps routine end //END OF BLOCK } } out: gettimeofday(&end, NULL); diff = tv_subtract(end, start); fflush(stdout); printf("\n"); printf("\r%12lu frames outgoing\n", stats.tx_packets); printf("\r%12lu frames truncated (larger than frame)\n", trunced); printf("\r%12lu bytes outgoing\n", stats.tx_bytes); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); bpf_release(&bpf_ops); dissector_cleanup_all(); destroy_tx_ring(tx_sock, &tx_ring); if (mode->rfraw) leave_rfmon_mac80211(mode->device_trans, mode->device_out); close(tx_sock); if (pcap_ops[mode->pcap]->prepare_close_pcap) pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ); close(fd); } }