#include #include #include #include #include #include #include #include static char appsym[64] = "mrfwd"; static char dev_1_symbol[64] = "meth0"; uint64_t cpu_mask = 0x3c; unsigned int nr_thread; struct mr_instance * mr_instance = NULL; struct mr_vdev * dev_1_handler = NULL; struct mr_sendpath * to_dev_1_sendpath = NULL; #define BURST_MAX 64 unsigned int nr_burst = 32; /* options */ unsigned int opt_dump_packet_metadata = 1; unsigned int opt_inject_by_deep_copy = 0; void dump_packet_metadata(marsio_buff_t * buff) { #if 0 sid_t sids[MR_SID_LIST_MAXLEN]; int nr_sids = marsio_buff_get_sid_list(buff, sids, MR_SID_LIST_MAXLEN); fprintf(stderr, "packet buf = %p, is_vlan_tci_set = %u, vlan_tci = %u\n", buff, is_vlan_tci_set, vlan_tci); #endif } void * l2fwd_loop(void * arg) { uintptr_t sid = (uintptr_t)arg; marsio_buff_t * rx_buff[BURST_MAX]; marsio_buff_t * tx_buff[BURST_MAX]; int ret = 0; marsio_thread_init(mr_instance); for (;;) { ret = marsio_recv_burst(dev_1_handler, sid, rx_buff, (int)nr_burst); if (ret == 0) { marsio_poll_wait(mr_instance, &dev_1_handler, 1, sid, -1); } for (int i = 0; i < ret; i++) { if (opt_dump_packet_metadata) { dump_packet_metadata(rx_buff[i]); } if (opt_inject_by_deep_copy) { marsio_buff_t * orin_buff = rx_buff[i]; marsio_buff_t * deep_copy_buff = NULL; marsio_buff_malloc_global(mr_instance, &deep_copy_buff, 1, MARSIO_SOCKET_ID_ANY, MARSIO_LCORE_ID_ANY); /* copy the packet body */ unsigned int orin_pkt_len = marsio_buff_datalen(orin_buff); const char * orin_pkt_ptr = marsio_buff_mtod(orin_buff); char * deep_copy_ptr = marsio_buff_append(deep_copy_buff, orin_pkt_len); memcpy(deep_copy_ptr, orin_pkt_ptr, orin_pkt_len); /* get the route ctx */ char route_ctx[64]; marsio_buff_get_metadata(orin_buff, MR_BUFF_ROUTE_CTX, route_ctx, sizeof(route_ctx)); /* get the sids */ sid_t sids[MR_SID_LIST_MAXLEN]; int nr_sids = marsio_buff_get_sid_list(orin_buff, sids, MR_SID_LIST_MAXLEN); #if 0 struct rte_ether_hdr * ether_hdr = (struct rte_ether_hdr *)orin_pkt_ptr; if(ether_hdr->ether_type != 0xAAAA) { assert(nr_sids != 0); } #endif /* set route ctx and sids for deep copy buff */ marsio_buff_set_metadata(deep_copy_buff, MR_BUFF_ROUTE_CTX, route_ctx, sizeof(route_ctx)); marsio_buff_set_sid_list(deep_copy_buff, sids, nr_sids); tx_buff[i] = deep_copy_buff; } } if (opt_inject_by_deep_copy) { marsio_buff_free(mr_instance, rx_buff, ret, MARSIO_SOCKET_ID_ANY, MARSIO_LCORE_ID_ANY); marsio_send_burst(to_dev_1_sendpath, sid, tx_buff, (int)ret); } else { marsio_send_burst(to_dev_1_sendpath, sid, rx_buff, (int)ret); } } } int help() { return 0; } int main(int argc, char * argv[]) { int opt = 0; while ((opt = getopt(argc, argv, "s:d:a:c:b:h?")) != -1) { char * endptr = NULL; switch (opt) { case '?': case 'h': { help(); break; } case 's': { snprintf(dev_1_symbol, sizeof(dev_1_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 'b': { nr_burst = strtoull(optarg, &endptr, 0); if (nr_burst == 0 && endptr == optarg) help(); break; } default: help(); break; } } mr_instance = marsio_create(); if (mr_instance == NULL) { 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_1_handler = marsio_open_device(mr_instance, dev_1_symbol, nr_thread, nr_thread); to_dev_1_sendpath = marsio_sendpath_create_by_vdev(dev_1_handler); fprintf(stdout, "Thread Count = %d\n", nr_thread); pthread_t tmp_pid[nr_thread]; for (int i = 0; i < nr_thread; i++) { pthread_create(&tmp_pid[i], NULL, l2fwd_loop, (void *)(uintptr_t)i); } for (int i = 0; i < nr_thread; i++) { pthread_join(tmp_pid[i], NULL); } marsio_destory(mr_instance); fprintf(stdout, "L2FWD is terminated. "); return 0; }