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
struct vxlan_encap_conf vxlan_encap_conf = {
.select_ipv4 = 1,
.select_vlan = 0,
+ .select_tos_ttl = 0,
.vni = "\x00\x00\x00",
.udp_src = 0,
.udp_dst = RTE_BE16(4789),
.ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x11\x11",
.vlan_tci = 0,
+ .ip_tos = 0,
+ .ip_ttl = 255,
.eth_src = "\x00\x00\x00\x00\x00\x00",
.eth_dst = "\xff\xff\xff\xff\xff\xff",
};
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(const char *device_name,
+static void dev_event_callback(const char *device_name,
enum rte_dev_event_type type,
void *param);
return 0;
}
-static inline uint32_t
-bsf64(uint64_t v)
-{
- return (uint32_t)__builtin_ctzll(v);
-}
-
-static inline uint32_t
-log2_u64(uint64_t v)
-{
- if (v == 0)
- return 0;
- v = rte_align64pow2(v);
- return bsf64(v);
-}
-
static int
pagesz_flags(uint64_t page_sz)
{
/* as per mmap() manpage, all page sizes are log2 of page size
* shifted by MAP_HUGE_SHIFT
*/
- int log2 = log2_u64(page_sz);
+ int log2 = rte_log2_u64(page_sz);
return (log2 << HUGE_SHIFT);
}
"%-14u Rx- bad outer L4 checksum: %-14u\n",
fs->rx_bad_ip_csum, fs->rx_bad_l4_csum,
fs->rx_bad_outer_l4_csum);
+ } else {
+ printf("\n");
}
#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
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;
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)
void
attach_port(char *identifier)
{
- portid_t pi = 0;
+ portid_t pi;
struct rte_dev_iterator iterator;
printf("Attaching a new port...\n");
return;
}
- RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator)
+ /* 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
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;
printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
if (ports != NULL) {
no_link_check = 1;
RTE_ETH_FOREACH_DEV(pt_id) {
- printf("\nShutting down port %d...\n", pt_id);
+ printf("\nStopping port %d...\n", pt_id);
fflush(stdout);
stop_port(pt_id);
+ }
+ RTE_ETH_FOREACH_DEV(pt_id) {
+ printf("\nShutting down port %d...\n", pt_id);
+ fflush(stdout);
close_port(pt_id);
/*
}
ret = rte_dev_event_callback_unregister(NULL,
- eth_dev_event_callback, NULL);
+ dev_event_callback, NULL);
if (ret < 0) {
RTE_LOG(ERR, EAL,
"fail to unregister device event callback.\n");
}
}
+/*
+ * This callback is for remove a port for a device. It has limitation because
+ * it is not for multiple port removal for a device.
+ * TODO: the device detach invoke will plan to be removed from user side to
+ * eal. And convert all PMDs to free port resources on ether device closing.
+ */
static void
-rmv_event_callback(void *arg)
+rmv_port_callback(void *arg)
{
int need_to_start = 0;
int org_no_link_check = no_link_check;
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);
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))
+ rmv_port_callback, (void *)(intptr_t)port_id))
fprintf(stderr, "Could not set up deferred device removal\n");
break;
default:
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(const char *device_name, enum rte_dev_event_type type,
+dev_event_callback(const char *device_name, enum rte_dev_event_type type,
__rte_unused void *arg)
{
uint16_t port_id;
switch (type) {
case RTE_DEV_EVENT_REMOVE:
- RTE_LOG(ERR, EAL, "The device: %s has been removed!\n",
+ RTE_LOG(DEBUG, EAL, "The device: %s has been removed!\n",
device_name);
ret = rte_eth_dev_get_port_by_name(device_name, &port_id);
if (ret) {
device_name);
return;
}
- rmv_event_callback((void *)(intptr_t)port_id);
+ /*
+ * Because the user's callback is invoked in eal interrupt
+ * callback, the interrupt callback need to be finished before
+ * it can be unregistered when detaching device. So finish
+ * callback soon and use a deferred removal to detach device
+ * is need. It is a workaround, once the device detaching be
+ * moved into the eal in the future, the deferred removal could
+ * be deleted.
+ */
+ if (rte_eal_alarm_set(100000,
+ rmv_port_callback, (void *)(intptr_t)port_id))
+ RTE_LOG(ERR, EAL,
+ "Could not set up deferred device removal\n");
break;
case RTE_DEV_EVENT_ADD:
RTE_LOG(ERR, EAL, "The device: %s has been added!\n",
printf("\nPort statistics ====================================");
for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
nic_stats_display(fwd_ports_ids[i]);
+
+ fflush(stdout);
}
static void
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);
+ rte_pdump_init();
#endif
count = 0;
#endif
/* on FreeBSD, mlockall() is disabled by default */
-#ifdef RTE_EXEC_ENV_BSDAPP
+#ifdef RTE_EXEC_ENV_FREEBSD
do_mlockall = 0;
#else
do_mlockall = 1;
}
ret = rte_dev_event_callback_register(NULL,
- eth_dev_event_callback, NULL);
+ dev_event_callback, NULL);
if (ret) {
RTE_LOG(ERR, EAL,
"fail to register device event callback\n");