extern "C" { #include #include #include #include #include #include #include #include #include } #include static char appsym[64] = "vxlan_inject"; static char dev_symbol[64] = "vxlan_user"; static char str_pcap_file[2048] = "dumpfile"; uint64_t cpu_mask = 0x1; unsigned int nr_thread = 1; uint64_t link_id = 0; struct mr_instance * mr_instance = NULL; struct mr_vdev * dev_handler = NULL; struct mr_sendpath * sendpath = NULL; #define BURST_MAX 64 unsigned int nr_burst = 1; unsigned int self_loop = 0; class PacketLoader { private: pcap_t * pcap_handle_{nullptr}; public: static constexpr unsigned int PKTLEN_MAX = 4096; void LoadFromPcapFile(const std::string & path) { char error_buffer[PCAP_ERRBUF_SIZE]; pcap_handle_ = pcap_open_offline(path.c_str(), error_buffer); assert(pcap_handle_ != nullptr); } virtual ~PacketLoader() { if (pcap_handle_) pcap_close(pcap_handle_); } const unsigned char * FetchPacket(unsigned & pkt_len) { struct pcap_pkthdr header { }; auto * pkt_content = pcap_next(pcap_handle_, &header); pkt_len = header.caplen; return pkt_content; } }; class PacketLoader * packet_loader = nullptr; void * txonly_loop(void * arg) { uintptr_t sid = (uintptr_t)arg; marsio_buff_t * tx_buff[BURST_MAX]; marsio_thread_init(mr_instance); struct mr_tunnat_ctrlzone tx_ctrlzone; memset(&tx_ctrlzone, 0, sizeof(struct mr_tunnat_ctrlzone)); tx_ctrlzone.virtual_link_id = link_id; tx_ctrlzone.action = TUNNAT_CZ_ACTION_ENCAP_VIRTUAL_LINK_ID; for (;;) { unsigned pkt_len; auto * pkt_ptr = packet_loader->FetchPacket(pkt_len); if (pkt_ptr == nullptr) break; int ret = marsio_buff_malloc_global(mr_instance, tx_buff, 1, MARSIO_SOCKET_ID_ANY, MARSIO_LCORE_ID_ANY); if (ret < 0) { fprintf(stderr, "marsio_buff_malloc_global execution failed."); exit(0); } marsio_buff_t * tx_buff_ptr = tx_buff[0]; char * tx_buff_begin = marsio_buff_append(tx_buff_ptr, pkt_len); memcpy(tx_buff_begin, pkt_ptr, pkt_len); marsio_buff_ctrlzone_set(tx_buff_ptr, 0, &tx_ctrlzone, sizeof(tx_ctrlzone)); marsio_send_burst_with_options(sendpath, sid, tx_buff, 1, MARSIO_SEND_OPT_FAST); } return (void *)NULL; } int help() { return 0; } int main(int argc, char * argv[]) { int opt = 0; while ((opt = getopt(argc, argv, "s:t:r:a:c:b:d:h?rl")) != -1) { char * endptr = NULL; switch (opt) { case '?': case 'h': { help(); break; } case 'd': { snprintf(dev_symbol, sizeof(dev_symbol), "%s", optarg); break; } case 'a': { snprintf(appsym, sizeof(appsym), "%s", optarg); break; } case 'c': { cpu_mask = strtoull(optarg, &endptr, 0); if (cpu_mask == 0 && endptr == optarg) help(); break; } case 'r': { snprintf(str_pcap_file, sizeof(str_pcap_file), "%s", optarg); break; } case 't': { link_id = strtoull(optarg, &endptr, 0); if (cpu_mask == 0 && endptr == optarg) help(); break; } default: help(); break; } } mr_instance = marsio_create(); if (mr_instance == nullptr) { fprintf(stderr, "Marsio instance create failed. "); abort(); } unsigned int opt_value = 1; marsio_option_set(mr_instance, MARSIO_OPT_EXIT_WHEN_ERR, &opt_value, sizeof(opt_value)); marsio_option_set(mr_instance, MARSIO_OPT_THREAD_MASK, &cpu_mask, sizeof(cpu_mask)); marsio_init(mr_instance, appsym); nr_thread = __builtin_popcountll(cpu_mask); dev_handler = marsio_open_device(mr_instance, dev_symbol, 0, nr_thread); fprintf(stdout, "Thread Count = %d\n", nr_thread); sendpath = marsio_sendpath_create_by_vdev(dev_handler); assert(sendpath != nullptr); packet_loader = new PacketLoader(); packet_loader->LoadFromPcapFile(str_pcap_file); pthread_t __tmp_pid[nr_thread]; for (unsigned int i = 0; i < nr_thread; i++) { pthread_create(&__tmp_pid[i], nullptr, txonly_loop, (void *)(uintptr_t)i); } for (unsigned int i = 0; i < nr_thread; i++) { pthread_join(__tmp_pid[i], nullptr); } marsio_destory(mr_instance); fprintf(stdout, "RXONLY is terminated. "); return 0; }