X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Ftestpmd.c;h=9c0edcaed12f614be18678825d935e3a6618c389;hb=a72a1ef34e75f40efc0a2051f55d555af9138e9c;hp=8a50ddeef0704c574faad9ec9eb255fb0adb4940;hpb=f431e0104df89aa9f53b20448530baec18f3d39a;p=dpdk.git diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 8a50ddeef0..9c0edcaed1 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -178,6 +178,7 @@ struct fwd_engine * fwd_engines[] = { &tx_only_engine, &csum_fwd_engine, &icmp_echo_engine, + &noisy_vnf_engine, #if defined RTE_LIBRTE_PMD_SOFTNIC &softnic_fwd_engine, #endif @@ -273,6 +274,40 @@ int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET; */ int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET; +/* + * Configurable value of buffered packets before sending. + */ +uint16_t noisy_tx_sw_bufsz; + +/* + * Configurable value of packet buffer timeout. + */ +uint16_t noisy_tx_sw_buf_flush_time; + +/* + * Configurable value for size of VNF internal memory area + * used for simulating noisy neighbour behaviour + */ +uint64_t noisy_lkup_mem_sz; + +/* + * Configurable value of number of random writes done in + * VNF simulation memory area. + */ +uint64_t noisy_lkup_num_writes; + +/* + * Configurable value of number of random reads done in + * VNF simulation memory area. + */ +uint64_t noisy_lkup_num_reads; + +/* + * Configurable value of number of random reads/writes done in + * VNF simulation memory area. + */ +uint64_t noisy_lkup_num_reads_writes; + /* * Receive Side Scaling (RSS) configuration. */ @@ -310,6 +345,24 @@ uint8_t rmv_interrupt = 1; /* enabled by default */ uint8_t hot_plug = 0; /**< hotplug disabled by default. */ +/* After attach, port setup is called on event or by iterator */ +bool setup_on_probe_event = true; + +/* Pretty printing of ethdev events */ +static const char * const eth_event_desc[] = { + [RTE_ETH_EVENT_UNKNOWN] = "unknown", + [RTE_ETH_EVENT_INTR_LSC] = "link state change", + [RTE_ETH_EVENT_QUEUE_STATE] = "queue state", + [RTE_ETH_EVENT_INTR_RESET] = "reset", + [RTE_ETH_EVENT_VF_MBOX] = "VF mbox", + [RTE_ETH_EVENT_IPSEC] = "IPsec", + [RTE_ETH_EVENT_MACSEC] = "MACsec", + [RTE_ETH_EVENT_INTR_RMV] = "device removal", + [RTE_ETH_EVENT_NEW] = "device probed", + [RTE_ETH_EVENT_DESTROY] = "device released", + [RTE_ETH_EVENT_MAX] = NULL, +}; + /* * Display or mask ether events * Default to all events except VF_MBOX @@ -446,18 +499,16 @@ struct nvgre_encap_conf nvgre_encap_conf = { }; /* Forward function declarations */ +static void setup_attached_port(portid_t pi); static void map_port_queue_stats_mapping_registers(portid_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); static int eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, void *ret_param); -static void eth_dev_event_callback(char *device_name, +static void eth_dev_event_callback(const char *device_name, enum rte_dev_event_type type, void *param); -static int eth_dev_event_callback_register(void); -static int eth_dev_event_callback_unregister(void); - /* * Check if all the ports are started. @@ -533,9 +584,21 @@ set_default_fwd_ports_config(void) portid_t pt_id; int i = 0; - RTE_ETH_FOREACH_DEV(pt_id) + RTE_ETH_FOREACH_DEV(pt_id) { fwd_ports_ids[i++] = pt_id; + /* Update sockets info according to the attached device */ + int socket_id = rte_eth_dev_socket_id(pt_id); + if (socket_id >= 0 && new_socket_id(socket_id)) { + if (num_sockets >= RTE_MAX_NUMA_NODES) { + rte_exit(EXIT_FAILURE, + "Total sockets greater than %u\n", + RTE_MAX_NUMA_NODES); + } + socket_ids[num_sockets++] = socket_id; + } + } + nb_cfg_ports = nb_ports; nb_fwd_ports = nb_ports; } @@ -989,12 +1052,6 @@ init_config(void) memset(port_per_socket,0,RTE_MAX_NUMA_NODES); - if (numa_support) { - memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); - memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); - memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); - } - /* Configuration of logical cores. */ fwd_lcores = rte_zmalloc("testpmd: fwd_lcores", sizeof(struct fwd_lcore *) * nb_lcores, @@ -1025,15 +1082,22 @@ init_config(void) DEV_TX_OFFLOAD_MBUF_FAST_FREE)) port->dev_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MBUF_FAST_FREE; + if (!(port->dev_info.tx_offload_capa & + DEV_TX_OFFLOAD_MATCH_METADATA)) + port->dev_conf.txmode.offloads &= + ~DEV_TX_OFFLOAD_MATCH_METADATA; if (numa_support) { if (port_numa[pid] != NUMA_NO_CONFIG) port_per_socket[port_numa[pid]]++; else { uint32_t socket_id = rte_eth_dev_socket_id(pid); - /* if socket_id is invalid, set to 0 */ + /* + * if socket_id is invalid, + * set to the first available socket. + */ if (check_socket_id(socket_id) < 0) - socket_id = 0; + socket_id = socket_ids[0]; port_per_socket[socket_id]++; } } @@ -1050,6 +1114,7 @@ init_config(void) /* set flag to initialize port/queue */ port->need_reconfig = 1; port->need_reconfig_queues = 1; + port->tx_metadata = 0; } /* @@ -1189,9 +1254,12 @@ init_fwd_streams(void) else { port->socket_id = rte_eth_dev_socket_id(pid); - /* if socket_id is invalid, set to 0 */ + /* + * if socket_id is invalid, + * set to the first available socket. + */ if (check_socket_id(port->socket_id) < 0) - port->socket_id = 0; + port->socket_id = socket_ids[0]; } } else { @@ -1564,31 +1632,6 @@ launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore) } } -/* - * Update the forward ports list. - */ -void -update_fwd_ports(portid_t new_pid) -{ - unsigned int i; - unsigned int new_nb_fwd_ports = 0; - int move = 0; - - for (i = 0; i < nb_fwd_ports; ++i) { - if (port_id_is_invalid(fwd_ports_ids[i], DISABLED_WARN)) - move = 1; - else if (move) - fwd_ports_ids[new_nb_fwd_ports++] = fwd_ports_ids[i]; - else - new_nb_fwd_ports++; - } - if (new_pid < RTE_MAX_ETHPORTS) - fwd_ports_ids[new_nb_fwd_ports++] = new_pid; - - nb_fwd_ports = new_nb_fwd_ports; - nb_cfg_ports = new_nb_fwd_ports; -} - /* * Launch packet forwarding configuration. */ @@ -1906,18 +1949,6 @@ port_is_started(portid_t port_id) return 1; } -static int -port_is_closed(portid_t port_id) -{ - if (port_id_is_invalid(port_id, ENABLED_WARN)) - return 0; - - if (ports[port_id].port_status != RTE_PORT_CLOSED) - return 0; - - return 1; -} - int start_port(portid_t pid) { @@ -1926,7 +1957,6 @@ start_port(portid_t pid) queueid_t qi; struct rte_port *port; struct ether_addr mac_addr; - enum rte_eth_event_type event_type; if (port_id_is_invalid(pid, ENABLED_WARN)) return 0; @@ -1956,7 +1986,7 @@ start_port(portid_t pid) return -1; } } - + configure_rxtx_dump_callbacks(0); printf("Configuring Port %d (socket %u)\n", pi, port->socket_id); /* configure port */ @@ -2055,7 +2085,7 @@ start_port(portid_t pid) return -1; } } - + configure_rxtx_dump_callbacks(verbose_level); /* start port */ if (rte_eth_dev_start(pi) < 0) { printf("Fail to start port %d\n", pi); @@ -2082,20 +2112,6 @@ start_port(portid_t pid) need_check_link_status = 1; } - for (event_type = RTE_ETH_EVENT_UNKNOWN; - event_type < RTE_ETH_EVENT_MAX; - event_type++) { - diag = rte_eth_dev_callback_register(RTE_ETH_ALL, - event_type, - eth_event_callback, - NULL); - if (diag) { - printf("Failed to setup even callback for event %d\n", - event_type); - return -1; - } - } - if (need_check_link_status == 1 && !no_link_check) check_all_ports_link_status(RTE_PORT_ALL); else if (need_check_link_status == 0) @@ -2154,6 +2170,28 @@ stop_port(portid_t pid) printf("Done\n"); } +static void +remove_invalid_ports_in(portid_t *array, portid_t *total) +{ + portid_t i; + portid_t new_total = 0; + + for (i = 0; i < *total; i++) + if (!port_id_is_invalid(array[i], DISABLED_WARN)) { + array[new_total] = array[i]; + new_total++; + } + *total = new_total; +} + +static void +remove_invalid_ports(void) +{ + remove_invalid_ports_in(ports_ids, &nb_ports); + remove_invalid_ports_in(fwd_ports_ids, &nb_fwd_ports); + nb_cfg_ports = nb_fwd_ports; +} + void close_port(portid_t pid) { @@ -2196,6 +2234,8 @@ close_port(portid_t pid) port_flow_flush(pi); rte_eth_dev_close(pi); + remove_invalid_ports(); + if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) printf("Port %d cannot be set to closed\n", pi); @@ -2245,44 +2285,11 @@ reset_port(portid_t pid) printf("Done\n"); } -static int -eth_dev_event_callback_register(void) -{ - int ret; - - /* register the device event callback */ - ret = rte_dev_event_callback_register(NULL, - eth_dev_event_callback, NULL); - if (ret) { - printf("Failed to register device event callback\n"); - return -1; - } - - return 0; -} - - -static int -eth_dev_event_callback_unregister(void) -{ - int ret; - - /* unregister the device event callback */ - ret = rte_dev_event_callback_unregister(NULL, - eth_dev_event_callback, NULL); - if (ret < 0) { - printf("Failed to unregister device event callback\n"); - return -1; - } - - return 0; -} - void attach_port(char *identifier) { - portid_t pi = 0; - unsigned int socket_id; + portid_t pi; + struct rte_dev_iterator iterator; printf("Attaching a new port...\n"); @@ -2291,61 +2298,97 @@ attach_port(char *identifier) return; } - if (rte_eth_dev_attach(identifier, &pi)) + if (rte_dev_probe(identifier) != 0) { + TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier); return; + } + + /* first attach mode: event */ + if (setup_on_probe_event) { + /* new ports are detected on RTE_ETH_EVENT_NEW event */ + for (pi = 0; pi < RTE_MAX_ETHPORTS; pi++) + if (ports[pi].port_status == RTE_PORT_HANDLING && + ports[pi].need_setup != 0) + setup_attached_port(pi); + return; + } + + /* second attach mode: iterator */ + RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator) { + /* setup ports matching the devargs used for probing */ + if (port_is_forwarding(pi)) + continue; /* port was already attached before */ + setup_attached_port(pi); + } +} + +static void +setup_attached_port(portid_t pi) +{ + unsigned int socket_id; socket_id = (unsigned)rte_eth_dev_socket_id(pi); - /* if socket_id is invalid, set to 0 */ + /* if socket_id is invalid, set to the first available socket. */ if (check_socket_id(socket_id) < 0) - socket_id = 0; + socket_id = socket_ids[0]; reconfig(pi, socket_id); rte_eth_promiscuous_enable(pi); - ports_ids[nb_ports] = pi; - nb_ports = rte_eth_dev_count_avail(); - + ports_ids[nb_ports++] = pi; + fwd_ports_ids[nb_fwd_ports++] = pi; + nb_cfg_ports = nb_fwd_ports; + ports[pi].need_setup = 0; ports[pi].port_status = RTE_PORT_STOPPED; - update_fwd_ports(pi); - printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports); printf("Done\n"); } void -detach_port(portid_t port_id) +detach_port_device(portid_t port_id) { - char name[RTE_ETH_NAME_MAX_LEN]; - uint16_t i; + struct rte_device *dev; + portid_t sibling; - printf("Detaching a port...\n"); + printf("Removing a device...\n"); - if (!port_is_closed(port_id)) { - printf("Please close port first\n"); + dev = rte_eth_devices[port_id].device; + if (dev == NULL) { + printf("Device already removed\n"); return; } - if (ports[port_id].flow_list) - port_flow_flush(port_id); + if (ports[port_id].port_status != RTE_PORT_CLOSED) { + if (ports[port_id].port_status != RTE_PORT_STOPPED) { + printf("Port not stopped\n"); + return; + } + printf("Port was not closed\n"); + if (ports[port_id].flow_list) + port_flow_flush(port_id); + } - if (rte_eth_dev_detach(port_id, name)) { - TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id); + if (rte_dev_remove(dev) != 0) { + TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name); return; } - for (i = 0; i < nb_ports; i++) { - if (ports_ids[i] == port_id) { - ports_ids[i] = ports_ids[nb_ports-1]; - ports_ids[nb_ports-1] = 0; - break; + for (sibling = 0; sibling < RTE_MAX_ETHPORTS; sibling++) { + if (rte_eth_devices[sibling].device != dev) + continue; + /* reset mapping between old ports and removed device */ + rte_eth_devices[sibling].device = NULL; + if (ports[sibling].port_status != RTE_PORT_CLOSED) { + /* sibling ports are forced to be closed */ + ports[sibling].port_status = RTE_PORT_CLOSED; + printf("Port %u is closed\n", sibling); } } - nb_ports = rte_eth_dev_count_avail(); - update_fwd_ports(RTE_MAX_ETHPORTS); + remove_invalid_ports(); - printf("Port %u is detached. Now total ports is %d\n", - port_id, nb_ports); + printf("Device of port %u is detached\n", port_id); + printf("Now total ports is %d\n", nb_ports); printf("Done\n"); return; } @@ -2378,20 +2421,32 @@ pmd_test_exit(void) */ device = rte_eth_devices[pt_id].device; if (device && !strcmp(device->driver->name, "net_virtio_user")) - detach_port(pt_id); + detach_port_device(pt_id); } } if (hot_plug) { ret = rte_dev_event_monitor_stop(); - if (ret) + if (ret) { RTE_LOG(ERR, EAL, "fail to stop device event monitor."); + return; + } - ret = eth_dev_event_callback_unregister(); - if (ret) + ret = rte_dev_event_callback_unregister(NULL, + eth_dev_event_callback, NULL); + if (ret < 0) { RTE_LOG(ERR, EAL, - "fail to unregister all event callbacks."); + "fail to unregister device event callback.\n"); + return; + } + + ret = rte_dev_hotplug_handle_disable(); + if (ret) { + RTE_LOG(ERR, EAL, + "fail to disable hotplug handling.\n"); + return; + } } printf("\nBye...\n"); @@ -2478,7 +2533,7 @@ rmv_event_callback(void *arg) stop_port(port_id); no_link_check = org_no_link_check; close_port(port_id); - detach_port(port_id); + detach_port_device(port_id); if (need_to_start) start_packet_forwarding(0); } @@ -2488,20 +2543,6 @@ static int eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, void *ret_param) { - static const char * const event_desc[] = { - [RTE_ETH_EVENT_UNKNOWN] = "Unknown", - [RTE_ETH_EVENT_INTR_LSC] = "LSC", - [RTE_ETH_EVENT_QUEUE_STATE] = "Queue state", - [RTE_ETH_EVENT_INTR_RESET] = "Interrupt reset", - [RTE_ETH_EVENT_VF_MBOX] = "VF Mbox", - [RTE_ETH_EVENT_IPSEC] = "IPsec", - [RTE_ETH_EVENT_MACSEC] = "MACsec", - [RTE_ETH_EVENT_INTR_RMV] = "device removal", - [RTE_ETH_EVENT_NEW] = "device probed", - [RTE_ETH_EVENT_DESTROY] = "device released", - [RTE_ETH_EVENT_MAX] = NULL, - }; - RTE_SET_USED(param); RTE_SET_USED(ret_param); @@ -2511,15 +2552,18 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, fflush(stderr); } else if (event_print_mask & (UINT32_C(1) << type)) { printf("\nPort %" PRIu16 ": %s event\n", port_id, - event_desc[type]); + eth_event_desc[type]); fflush(stdout); } - if (port_id_is_invalid(port_id, DISABLED_WARN)) - return 0; - switch (type) { + case RTE_ETH_EVENT_NEW: + ports[port_id].need_setup = 1; + ports[port_id].port_status = RTE_PORT_HANDLING; + break; case RTE_ETH_EVENT_INTR_RMV: + if (port_id_is_invalid(port_id, DISABLED_WARN)) + break; if (rte_eal_alarm_set(100000, rmv_event_callback, (void *)(intptr_t)port_id)) fprintf(stderr, "Could not set up deferred device removal\n"); @@ -2530,11 +2574,36 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, return 0; } +static int +register_eth_event_callback(void) +{ + int ret; + enum rte_eth_event_type event; + + for (event = RTE_ETH_EVENT_UNKNOWN; + event < RTE_ETH_EVENT_MAX; event++) { + ret = rte_eth_dev_callback_register(RTE_ETH_ALL, + event, + eth_event_callback, + NULL); + if (ret != 0) { + TESTPMD_LOG(ERR, "Failed to register callback for " + "%s event\n", eth_event_desc[event]); + return -1; + } + } + + return 0; +} + /* This function is used by the interrupt thread */ static void -eth_dev_event_callback(char *device_name, enum rte_dev_event_type type, +eth_dev_event_callback(const char *device_name, enum rte_dev_event_type type, __rte_unused void *arg) { + uint16_t port_id; + int ret; + if (type >= RTE_DEV_EVENT_MAX) { fprintf(stderr, "%s called upon invalid event %d\n", __func__, type); @@ -2545,9 +2614,13 @@ eth_dev_event_callback(char *device_name, enum rte_dev_event_type type, case RTE_DEV_EVENT_REMOVE: RTE_LOG(ERR, EAL, "The device: %s has been removed!\n", device_name); - /* TODO: After finish failure handle, begin to stop - * packet forward, stop port, close port, detach port. - */ + ret = rte_eth_dev_get_port_by_name(device_name, &port_id); + if (ret) { + RTE_LOG(ERR, EAL, "can not get port by device %s!\n", + device_name); + return; + } + rmv_event_callback((void *)(intptr_t)port_id); break; case RTE_DEV_EVENT_ADD: RTE_LOG(ERR, EAL, "The device: %s has been added!\n", @@ -2936,6 +3009,11 @@ init_port(void) "rte_zmalloc(%d struct rte_port) failed\n", RTE_MAX_ETHPORTS); } + + /* Initialize ports NUMA structures */ + memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); + memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); + memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); } static void @@ -3002,6 +3080,10 @@ main(int argc, char** argv) rte_panic("Cannot register log type"); rte_log_set_level(testpmd_logtype, RTE_LOG_DEBUG); + ret = register_eth_event_callback(); + if (ret != 0) + rte_panic("Cannot register for ethdev events"); + #ifdef RTE_LIBRTE_PDUMP /* initialize packet capture framework */ rte_pdump_init(NULL); @@ -3070,14 +3152,27 @@ main(int argc, char** argv) init_config(); if (hot_plug) { - /* enable hot plug monitoring */ + ret = rte_dev_hotplug_handle_enable(); + if (ret) { + RTE_LOG(ERR, EAL, + "fail to enable hotplug handling."); + return -1; + } + ret = rte_dev_event_monitor_start(); if (ret) { - rte_errno = EINVAL; + RTE_LOG(ERR, EAL, + "fail to start device event monitoring."); return -1; } - eth_dev_event_callback_register(); + ret = rte_dev_event_callback_register(NULL, + eth_dev_event_callback, NULL); + if (ret) { + RTE_LOG(ERR, EAL, + "fail to register device event callback\n"); + return -1; + } } if (start_port(RTE_PORT_ALL) != 0)