static inline int atq_nb_event_queues(struct evt_options *opt) { /* nb_queues = number of producers */ return opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ? rte_eth_dev_count_avail() : evt_nr_active_lcores(opt->plcores); }
/* * The main function, which does initialization and calls the per-lcore * functions. */ int main(int argc, char *argv[]) { struct rte_mempool *mbuf_pool; unsigned nb_ports; uint16_t portid; /* Initialize the Environment Abstraction Layer (EAL). */ int ret = rte_eal_init(argc, argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); argc -= ret; argv += ret; /* Check that there is an even number of ports to send/receive on. */ nb_ports = rte_eth_dev_count_avail(); if (nb_ports < 2 || (nb_ports & 1)) rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n"); /* Creates a new mempool in memory to hold the mbufs. */ mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); /* Initialize all ports. */ RTE_ETH_FOREACH_DEV(portid) if (port_init(portid, mbuf_pool) != 0) rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu16 "\n", portid); if (rte_lcore_count() > 1) printf("\nWARNING: Too many lcores enabled. Only 1 used.\n"); /* Call lcore_main on the master core only. */ lcore_main(); return 0; }
/*----------------------------------------------------------------------------*/ int SetNetEnv(char *dev_name_list, char *port_stat_list) { int eidx = 0; int i, j; int set_all_inf = (strncmp(dev_name_list, ALL_STRING, sizeof(ALL_STRING))==0); TRACE_CONFIG("Loading interface setting\n"); CONFIG.eths = (struct eth_table *) calloc(MAX_DEVICES, sizeof(struct eth_table)); if (!CONFIG.eths) { TRACE_ERROR("Can't allocate space for CONFIG.eths\n"); exit(EXIT_FAILURE); } if (current_iomodule_func == &ps_module_func) { #ifndef DISABLE_PSIO struct ifreq ifr; /* calculate num_devices now! */ num_devices = ps_list_devices(devices); if (num_devices == -1) { perror("ps_list_devices"); exit(EXIT_FAILURE); } /* Create socket */ int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock == -1) { TRACE_ERROR("socket"); exit(EXIT_FAILURE); } /* To Do: Parse dev_name_list rather than use strstr */ for (i = 0; i < num_devices; i++) { strcpy(ifr.ifr_name, devices[i].name); /* getting interface information */ if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { if (!set_all_inf && strstr(dev_name_list, ifr.ifr_name) == NULL) continue; /* Setting informations */ eidx = CONFIG.eths_num++; strcpy(CONFIG.eths[eidx].dev_name, ifr.ifr_name); CONFIG.eths[eidx].ifindex = devices[i].ifindex; /* getting address */ if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin; } if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0 ) { for (j = 0; j < ETH_ALEN; j ++) { CONFIG.eths[eidx].haddr[j] = ifr.ifr_addr.sa_data[j]; } } /* Net MASK */ if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].netmask = *(uint32_t *)&sin; } /* add to attached devices */ for (j = 0; j < num_devices_attached; j++) { if (devices_attached[j] == devices[i].ifindex) { break; } } devices_attached[num_devices_attached] = devices[i].ifindex; num_devices_attached++; } else { perror("SIOCGIFFLAGS"); } } num_queues = GetNumQueues(); if (num_queues <= 0) { TRACE_CONFIG("Failed to find NIC queues!\n"); close(sock); return -1; } if (num_queues > num_cpus) { TRACE_CONFIG("Too many NIC queues available.\n"); close(sock); return -1; } close(sock); #endif /* !PSIO_MODULE */ } else if (current_iomodule_func == &dpdk_module_func) { #ifndef DISABLE_DPDK int cpu = CONFIG.num_cores; mpz_t _cpumask; char cpumaskbuf[32] = ""; char mem_channels[8] = ""; char socket_mem_str[32] = ""; // int i; int ret, socket_mem; static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; /* STEP 1: first determine CPU mask */ mpz_init(_cpumask); if (!mpz_cmp(_cpumask, CONFIG._cpumask)) { /* get the cpu mask */ for (ret = 0; ret < cpu; ret++) mpz_setbit(_cpumask, ret); gmp_sprintf(cpumaskbuf, "%ZX", _cpumask); } else gmp_sprintf(cpumaskbuf, "%ZX", CONFIG._cpumask); mpz_clear(_cpumask); /* STEP 2: determine memory channels per socket */ /* get the mem channels per socket */ if (CONFIG.num_mem_ch == 0) { TRACE_ERROR("DPDK module requires # of memory channels " "per socket parameter!\n"); exit(EXIT_FAILURE); } sprintf(mem_channels, "%d", CONFIG.num_mem_ch); /* STEP 3: determine socket memory */ /* get socket memory threshold (in MB) */ socket_mem = RTE_ALIGN_CEIL((unsigned long)ceil((CONFIG.num_cores * (CONFIG.rcvbuf_size + CONFIG.sndbuf_size + sizeof(struct tcp_stream) + sizeof(struct tcp_recv_vars) + sizeof(struct tcp_send_vars) + sizeof(struct fragment_ctx)) * CONFIG.max_concurrency)/RTE_SOCKET_MEM_SHIFT), RTE_CACHE_LINE_SIZE); /* initialize the rte env, what a waste of implementation effort! */ int argc = 6;//8; char *argv[RTE_ARGC_MAX] = {"", "-c", cpumaskbuf, "-n", mem_channels, #if 0 "--socket-mem", socket_mem_str, #endif "--proc-type=auto" }; ret = probe_all_rte_devices(argv, &argc, dev_name_list); /* STEP 4: build up socket mem parameter */ sprintf(socket_mem_str, "%d", socket_mem); #if 0 char *smsptr = socket_mem_str + strlen(socket_mem_str); for (i = 1; i < ret + 1; i++) { sprintf(smsptr, ",%d", socket_mem); smsptr += strlen(smsptr); } TRACE_DBG("socket_mem: %s\n", socket_mem_str); #endif /* * re-set getopt extern variable optind. * this issue was a bitch to debug * rte_eal_init() internally uses getopt() syscall * mtcp applications that also use an `external' getopt * will cause a violent crash if optind is not reset to zero * prior to calling the func below... * see man getopt(3) for more details */ optind = 0; #ifdef DEBUG /* print argv's */ for (i = 0; i < argc; i++) TRACE_INFO("argv[%d]: %s\n", i, argv[i]); #endif /* initialize the dpdk eal env */ ret = rte_eal_init(argc, argv); if (ret < 0) { TRACE_ERROR("Invalid EAL args!\n"); exit(EXIT_FAILURE); } /* give me the count of 'detected' ethernet ports */ #if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0) num_devices = rte_eth_dev_count(); #else num_devices = rte_eth_dev_count_avail(); #endif if (num_devices == 0) { TRACE_ERROR("No Ethernet port!\n"); exit(EXIT_FAILURE); } /* get mac addr entries of 'detected' dpdk ports */ for (ret = 0; ret < num_devices; ret++) rte_eth_macaddr_get(ret, &ports_eth_addr[ret]); num_queues = MIN(CONFIG.num_cores, MAX_CPUS); struct ifaddrs *ifap; struct ifaddrs *iter_if; char *seek; if (getifaddrs(&ifap) != 0) { perror("getifaddrs: "); exit(EXIT_FAILURE); } iter_if = ifap; do { if (iter_if->ifa_addr && iter_if->ifa_addr->sa_family == AF_INET && !set_all_inf && (seek=strstr(dev_name_list, iter_if->ifa_name)) != NULL && /* check if the interface was not aliased */ *(seek + strlen(iter_if->ifa_name)) != ':') { struct ifreq ifr; /* Setting informations */ eidx = CONFIG.eths_num++; strcpy(CONFIG.eths[eidx].dev_name, iter_if->ifa_name); strcpy(ifr.ifr_name, iter_if->ifa_name); /* Create socket */ int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock == -1) { perror("socket"); exit(EXIT_FAILURE); } /* getting address */ if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin; } if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0 ) { for (j = 0; j < ETH_ALEN; j ++) { CONFIG.eths[eidx].haddr[j] = ifr.ifr_addr.sa_data[j]; } } /* Net MASK */ if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].netmask = *(uint32_t *)&sin; } close(sock); for (j = 0; j < num_devices; j++) { if (!memcmp(&CONFIG.eths[eidx].haddr[0], &ports_eth_addr[j], ETH_ALEN)) CONFIG.eths[eidx].ifindex = j; } /* add to attached devices */ for (j = 0; j < num_devices_attached; j++) { if (devices_attached[j] == CONFIG.eths[eidx].ifindex) { break; } } devices_attached[num_devices_attached] = CONFIG.eths[eidx].ifindex; num_devices_attached++; fprintf(stderr, "Total number of attached devices: %d\n", num_devices_attached); fprintf(stderr, "Interface name: %s\n", iter_if->ifa_name); } iter_if = iter_if->ifa_next; } while (iter_if != NULL); freeifaddrs(ifap); #if 0 /* * XXX: It seems that there is a bug in the RTE SDK. * The dynamically allocated rte_argv params are left * as dangling pointers. Freeing them causes program * to crash. */ /* free up all resources */ for (; rte_argc >= 9; rte_argc--) { if (rte_argv[rte_argc] != NULL) { fprintf(stderr, "Cleaning up rte_argv[%d]: %s (%p)\n", rte_argc, rte_argv[rte_argc], rte_argv[rte_argc]); free(rte_argv[rte_argc]); rte_argv[rte_argc] = NULL; } } #endif /* check if process is primary or secondary */ CONFIG.multi_process_is_master = (eal_proc_type_detect() == RTE_PROC_PRIMARY) ? 1 : 0; #endif /* !DISABLE_DPDK */ } else if (current_iomodule_func == &netmap_module_func) { #ifndef DISABLE_NETMAP struct ifaddrs *ifap; struct ifaddrs *iter_if; char *seek; num_queues = MIN(CONFIG.num_cores, MAX_CPUS); if (getifaddrs(&ifap) != 0) { perror("getifaddrs: "); exit(EXIT_FAILURE); } iter_if = ifap; do { if (iter_if->ifa_addr && iter_if->ifa_addr->sa_family == AF_INET && !set_all_inf && (seek=strstr(dev_name_list, iter_if->ifa_name)) != NULL && /* check if the interface was not aliased */ *(seek + strlen(iter_if->ifa_name)) != ':') { struct ifreq ifr; /* Setting informations */ eidx = CONFIG.eths_num++; strcpy(CONFIG.eths[eidx].dev_name, iter_if->ifa_name); strcpy(ifr.ifr_name, iter_if->ifa_name); /* Create socket */ int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock == -1) { perror("socket"); exit(EXIT_FAILURE); } /* getting address */ if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin; } if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0 ) { for (j = 0; j < ETH_ALEN; j ++) { CONFIG.eths[eidx].haddr[j] = ifr.ifr_addr.sa_data[j]; } } /* Net MASK */ if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].netmask = *(uint32_t *)&sin; } close(sock); #if 0 for (j = 0; j < num_devices; j++) { if (!memcmp(&CONFIG.eths[eidx].haddr[0], &ports_eth_addr[j], ETH_ALEN)) CONFIG.eths[eidx].ifindex = ifr.ifr_ifindex; #endif CONFIG.eths[eidx].ifindex = eidx; TRACE_INFO("Ifindex of interface %s is: %d\n", ifr.ifr_name, CONFIG.eths[eidx].ifindex); #if 0 } #endif /* add to attached devices */ for (j = 0; j < num_devices_attached; j++) { if (devices_attached[j] == CONFIG.eths[eidx].ifindex) { break; } } devices_attached[num_devices_attached] = if_nametoindex(ifr.ifr_name); num_devices_attached++; fprintf(stderr, "Total number of attached devices: %d\n", num_devices_attached); fprintf(stderr, "Interface name: %s\n", iter_if->ifa_name); } iter_if = iter_if->ifa_next; } while (iter_if != NULL); freeifaddrs(ifap); #endif /* !DISABLE_NETMAP */ } else if (current_iomodule_func == &onvm_module_func) { #ifdef ENABLE_ONVM int cpu = CONFIG.num_cores; mpz_t cpumask; char cpumaskbuf[32]; char mem_channels[8]; char service[6]; char instance[6]; int ret; mpz_init(cpumask); /* get the cpu mask */ for (ret = 0; ret < cpu; ret++) mpz_setbit(cpumask, ret); gmp_sprintf(cpumaskbuf, "%ZX", cpumask); mpz_clear(cpumask); /* get the mem channels per socket */ if (CONFIG.num_mem_ch == 0) { TRACE_ERROR("DPDK module requires # of memory channels " "per socket parameter!\n"); exit(EXIT_FAILURE); } sprintf(mem_channels, "%d", CONFIG.num_mem_ch); sprintf(service, "%d", CONFIG.onvm_serv); sprintf(instance, "%d", CONFIG.onvm_inst); /* initialize the rte env first, what a waste of implementation effort! */ char *argv[] = {"", "-c", cpumaskbuf, "-n", mem_channels, "--proc-type=secondary", "--", "-r", service, instance, "" }; const int argc = 10; /* * re-set getopt extern variable optind. * this issue was a bitch to debug * rte_eal_init() internally uses getopt() syscall * mtcp applications that also use an `external' getopt * will cause a violent crash if optind is not reset to zero * prior to calling the func below... * see man getopt(3) for more details */ optind = 0; /* initialize the dpdk eal env */ ret = onvm_nflib_init(argc, argv, "mtcp_nf", &CONFIG.nf_info); if (ret < 0) { TRACE_ERROR("Invalid EAL args!\n"); exit(EXIT_FAILURE); } /* give me the count of 'detected' ethernet ports */ num_devices = ports->num_ports; if (num_devices == 0) { TRACE_ERROR("No Ethernet port!\n"); exit(EXIT_FAILURE); } num_queues = MIN(CONFIG.num_cores, MAX_CPUS); struct ifaddrs *ifap; struct ifaddrs *iter_if; char *seek; if (getifaddrs(&ifap) != 0) { perror("getifaddrs: "); exit(EXIT_FAILURE); } iter_if = ifap; do { if (iter_if->ifa_addr && iter_if->ifa_addr->sa_family == AF_INET && !set_all_inf && (seek=strstr(dev_name_list, iter_if->ifa_name)) != NULL && /* check if the interface was not aliased */ *(seek + strlen(iter_if->ifa_name)) != ':') { struct ifreq ifr; /* Setting informations */ eidx = CONFIG.eths_num++; strcpy(CONFIG.eths[eidx].dev_name, iter_if->ifa_name); strcpy(ifr.ifr_name, iter_if->ifa_name); /* Create socket */ int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock == -1) { perror("socket"); } /* getting address */ if (ioctl(sock, SIOCGIFADDR, &ifr) == 0 ) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].ip_addr = *(uint32_t *)&sin; } for (j = 0; j < ETH_ALEN; j ++) { CONFIG.eths[eidx].haddr[j] = ports->mac[eidx].addr_bytes[j]; }; /* Net MASK */ if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) { struct in_addr sin = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; CONFIG.eths[eidx].netmask = *(uint32_t *)&sin; } close(sock); CONFIG.eths[eidx].ifindex = ports->id[eidx]; devices_attached[num_devices_attached] = CONFIG.eths[eidx].ifindex; num_devices_attached++; fprintf(stderr, "Total number of attached devices: %d\n", num_devices_attached); fprintf(stderr, "Interface name: %s\n", iter_if->ifa_name); } iter_if = iter_if->ifa_next; } while (iter_if != NULL); freeifaddrs(ifap); #endif /* ENABLE_ONVM */ } CONFIG.nif_to_eidx = (int*)calloc(MAX_DEVICES, sizeof(int)); if (!CONFIG.nif_to_eidx) { exit(EXIT_FAILURE); } for (i = 0; i < MAX_DEVICES; ++i) { CONFIG.nif_to_eidx[i] = -1; } for (i = 0; i < CONFIG.eths_num; ++i) { j = CONFIG.eths[i].ifindex; if (j >= MAX_DEVICES) { TRACE_ERROR("ifindex of eths_%d exceed the limit: %d\n", i, j); exit(EXIT_FAILURE); } /* the physic port index of the i-th port listed in the config file is j*/ CONFIG.nif_to_eidx[j] = i; /* finally set the port stats option `on' */ if (strcmp(CONFIG.eths[i].dev_name, port_stat_list) == 0) CONFIG.eths[i].stat_print = TRUE; } return 0; }
int init(int argc, char *argv[]) { int retval; const struct rte_memzone *mz_nf; const struct rte_memzone *mz_port; const struct rte_memzone *mz_cores; const struct rte_memzone *mz_scp; const struct rte_memzone *mz_services; const struct rte_memzone *mz_nf_per_service; uint8_t i, total_ports, port_id; /* init EAL, parsing EAL args */ retval = rte_eal_init(argc, argv); if (retval < 0) return -1; argc -= retval; argv += retval; #ifdef RTE_LIBRTE_PDUMP rte_pdump_init(NULL); #endif /* get total number of ports */ total_ports = rte_eth_dev_count_avail(); /* set up array for NF tx data */ mz_nf = rte_memzone_reserve(MZ_NF_INFO, sizeof(*nfs) * MAX_NFS, rte_socket_id(), NO_FLAGS); if (mz_nf == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for nf information\n"); memset(mz_nf->addr, 0, sizeof(*nfs) * MAX_NFS); nfs = mz_nf->addr; /* set up ports info */ mz_port = rte_memzone_reserve(MZ_PORT_INFO, sizeof(*ports), rte_socket_id(), NO_FLAGS); if (mz_port == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for port information\n"); ports = mz_port->addr; /* set up core status */ mz_cores = rte_memzone_reserve(MZ_CORES_STATUS, sizeof(*cores) * onvm_threading_get_num_cores(), rte_socket_id(), NO_FLAGS); if (mz_cores == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for core information\n"); memset(mz_cores->addr, 0, sizeof(*cores) * 64); cores = mz_cores->addr; /* set up array for NF tx data */ mz_services = rte_memzone_reserve(MZ_SERVICES_INFO, sizeof(uint16_t *) * num_services, rte_socket_id(), NO_FLAGS); if (mz_services == NULL) rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for services information\n"); services = mz_services->addr; for (i = 0; i < num_services; i++) { services[i] = rte_calloc("one service NFs", MAX_NFS_PER_SERVICE, sizeof(uint16_t), 0); } mz_nf_per_service = rte_memzone_reserve(MZ_NF_PER_SERVICE_INFO, sizeof(uint16_t) * num_services, rte_socket_id(), NO_FLAGS); if (mz_nf_per_service == NULL) { rte_exit(EXIT_FAILURE, "Cannot reserve memory zone for NF per service information.\n"); } nf_per_service_count = mz_nf_per_service->addr; /* parse additional, application arguments */ retval = parse_app_args(total_ports, argc, argv); if (retval != 0) return -1; /* initialise mbuf pools */ retval = init_mbuf_pools(); if (retval != 0) rte_exit(EXIT_FAILURE, "Cannot create needed mbuf pools\n"); /* initialise nf info pool */ retval = init_nf_info_pool(); if (retval != 0) { rte_exit(EXIT_FAILURE, "Cannot create nf info mbuf pool: %s\n", rte_strerror(rte_errno)); } /* initialise pool for NF messages */ retval = init_nf_msg_pool(); if (retval != 0) { rte_exit(EXIT_FAILURE, "Cannot create nf message pool: %s\n", rte_strerror(rte_errno)); } /* now initialise the ports we will use */ for (i = 0; i < ports->num_ports; i++) { port_id = ports->id[i]; rte_eth_macaddr_get(port_id, &ports->mac[port_id]); retval = init_port(port_id); if (retval != 0) rte_exit(EXIT_FAILURE, "Cannot initialise port %u\n", port_id); char event_msg_buf[20]; sprintf(event_msg_buf, "Port %d initialized", port_id); onvm_stats_add_event(event_msg_buf, NULL); } check_all_ports_link_status(ports->num_ports, (~0x0)); /* initialise the NF queues/rings for inter-eu comms */ init_shm_rings(); /* initialise a queue for newly created NFs */ init_info_queue(); /*initialize a default service chain*/ default_chain = onvm_sc_create(); retval = onvm_sc_append_entry(default_chain, ONVM_NF_ACTION_TONF, 1); if (retval == ENOSPC) { printf("chain length can not be larger than the maximum chain length\n"); exit(1); } printf("Default service chain: send to sdn NF\n"); /* set up service chain pointer shared to NFs*/ mz_scp = rte_memzone_reserve(MZ_SCP_INFO, sizeof(struct onvm_service_chain *), rte_socket_id(), NO_FLAGS); if (mz_scp == NULL) rte_exit(EXIT_FAILURE, "Canot reserve memory zone for service chain pointer\n"); memset(mz_scp->addr, 0, sizeof(struct onvm_service_chain *)); default_sc_p = mz_scp->addr; *default_sc_p = default_chain; onvm_sc_print(default_chain); onvm_flow_dir_init(); return 0; }