static sendpacket_t * sendpacket_open_quick_tx(const char *device, char *errbuf) { sendpacket_t *sp; struct quick_tx* dev; const char *ifname; char full_dev_name[256]; unsigned int map_size = QTX_MASTER_PAGE_NUM * PAGE_SIZE; unsigned int *map; int blocks; int i, fd; assert(device); assert(errbuf); if (strlen(device) > MAX_IFNAMELEN - 8) { snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Interface name is to long: %s\n", device); goto ifacename_invalid; } /* * Sort out interface names */ if (!strncmp(device, "qtx:", 4)) ifname = &device[4]; else ifname = device; /* open device name */ snprintf(full_dev_name, sizeof(full_dev_name), "%s%s", QTX_FULL_PATH_PREFIX, ifname); if ((fd = open(full_dev_name, O_RDWR | O_SYNC)) < 0) { snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while opening device\n" "Check that the QuickTX module is loaded and the interface name is correct \n"); goto open_failed; } /* create a memory map to Quick TX kernel module */ map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while attempting to map memory from device"); goto map_create_failed; } /* create device */ dev = safe_malloc(sizeof(struct quick_tx)); dev->map_length = map_size; dev->fd = fd; dev->data = (struct quick_tx_shared_data*)map; dev->stop_auto_mapping = false; if (quick_tx_mmap_mem_block(dev) < 0) { snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while mapping block"); goto map_failed; } if ((blocks = quick_tx_alloc_mem_space(dev, QTX_QUEUE_SIZE)) < 0) { snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "[quick_tx] error while allocating memory"); goto map_alloc_failed; } dbgx(1, "[quick_tx] mapped %d blocks of memory\n", blocks); /* store results */ sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t)); strncpy(sp->device, full_dev_name, sizeof(sp->device)); sp->handle.fd = fd; sp->qtx_dev = dev; sp->handle_type = SP_TYPE_QUICK_TX; return sp; map_alloc_failed: for (i = (dev->data->num_mem_blocks - 1); i >= 0; i--) { struct quick_tx_mem_block_entry* mem_block = &dev->data->mem_blocks[i]; if (munmap (mem_block->user_addr, mem_block->length) == -1) { dbgx(1, "[quick_tx] error while calling munmap for block %d\n", i); } } munmap ((void*)dev->data, dev->map_length); map_failed: free(dev); map_create_failed: close(fd); open_failed: ifacename_invalid: return NULL; }
int main (int argc, char* argv[]) { int i; void* buffer; long length; int loops; __u64 packets_sent = 0; __u64 packet_bytes = 0; struct timeval tv_start; struct pcap_pkthdr* pcap_hdr; struct quick_tx qtx; if (argc != 3 && argc != 4) { printf("Usage: ./pcapsend <path-to-pcap> <interface> [loops]\n"); exit(-1); } if (!read_pcap_file(argv[1], &buffer, &length)) { perror("Failed to read file! "); exit(-1); } if (argc == 4) { loops = atoi(argv[3]); } else { loops = 1; } memset(&qtx, 0, sizeof(qtx)); int ret = quick_tx_open(argv[2], &qtx); if (ret == 0) { int blocks = quick_tx_alloc_mem_space(&qtx, length * loops); if (blocks >= 0) { printf("quick_tx mapped %d blocks of memory\n", blocks); } else { printf("quick_tx_alloc_mem_space failure\n"); exit(-1); } } else { exit(-1); } gettimeofday(&tv_start,NULL); for (i = 0; i < loops; i++) { void* offset = buffer + sizeof(struct pcap_file_header); while(offset < buffer + length) { pcap_hdr = (struct pcap_pkthdr*) offset; offset += sizeof(struct pcap_pkthdr); if ((quick_tx_send_packet(&qtx, (const void*)offset, pcap_hdr->caplen)) < 0) { printf("An error occurred while trying to send a packet\n"); goto quick_tx_error; } offset += pcap_hdr->caplen; packets_sent++; packet_bytes+= pcap_hdr->caplen; } } printf("Done, closing everything!\n"); printf("\n"); quick_tx_error: quick_tx_close(&qtx); free(buffer); return 0; }