[dpdk-dev] [PATCH v4 2/2] app/testpmd: use uevent to monitor hot removal

Jeff Guo jia.guo at intel.com
Sun Sep 3 17:49:45 CEST 2017


use testpmd for example, to show app how to request and use
uevent monitoring to handle an event of device hot removal.

Signed-off-by: Jeff Guo <jia.guo at intel.com>
---
 app/test-pmd/testpmd.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 9a36e66..b5ff7d7 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -393,6 +393,10 @@ static void check_all_ports_link_status(uint32_t port_mask);
 static int eth_event_callback(uint8_t port_id,
 			      enum rte_eth_event_type type,
 			      void *param, void *ret_param);
+static int eth_uevent_callback(struct rte_device *dev,
+			      enum rte_eal_uevent_type type,
+			      void *param, void *ret_param);
+
 
 /*
  * Check if all the ports are started.
@@ -1413,6 +1417,7 @@ start_port(portid_t pid)
 	struct rte_port *port;
 	struct ether_addr mac_addr;
 	enum rte_eth_event_type event_type;
+	enum rte_eal_uevent_type uevent_type;
 
 	if (port_id_is_invalid(pid, ENABLED_WARN))
 		return 0;
@@ -1548,6 +1553,18 @@ start_port(portid_t pid)
 			}
 		}
 
+		for (uevent_type = RTE_EAL_UEVENT_UNKNOWN;
+		     uevent_type < RTE_EAL_UEVENT_MAX;
+		     uevent_type++) {
+			diag = rte_eal_uev_callback_register(&port->dev_info.pci_dev->device,uevent_type,
+							eth_uevent_callback, NULL);
+			if (diag) {
+				printf("Failed to setup uevent callback for uevent %d\n",
+					uevent_type);
+				return -1;
+			}
+		}
+
 		/* start port */
 		if (rte_eth_dev_start(pi) < 0) {
 			printf("Fail to start port %d\n", pi);
@@ -1842,6 +1859,16 @@ rmv_event_callback(void *arg)
 			dev->device->name);
 }
 
+static void
+rmv_uevent_callback(void *arg)
+{
+	struct rte_device *dev = (struct rte_device *)arg;
+	printf("removing device %s\n", dev->name);
+	if (rte_eal_dev_detach(dev))
+		RTE_LOG(ERR, USER1, "Failed to detach device %s\n",
+			dev->name);
+}
+
 /* This function is used by the interrupt thread */
 static int
 eth_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param,
@@ -1883,6 +1910,41 @@ eth_event_callback(uint8_t port_id, enum rte_eth_event_type type, void *param,
 	return 0;
 }
 
+/* This function is used by the interrupt thread */
+static int
+eth_uevent_callback(struct rte_device *dev, enum rte_eal_uevent_type type, void *param,
+		  void *ret_param)
+{
+	static const char * const event_desc[] = {
+		[RTE_EAL_UEVENT_UNKNOWN] = "Unknown",
+		[RTE_EAL_UEVENT_REMOVE] = "remove",
+	};
+
+	RTE_SET_USED(param);
+	RTE_SET_USED(ret_param);
+
+	if (type >= RTE_EAL_UEVENT_MAX) {
+		fprintf(stderr, "%s called upon invalid event %d\n",
+			__func__, type);
+		fflush(stderr);
+	} else if (event_print_mask & (UINT32_C(1) << type)) {
+		printf("%s event\n",
+			event_desc[type]);
+		fflush(stdout);
+	}
+
+	switch (type) {
+	case RTE_EAL_UEVENT_REMOVE:
+		if (rte_eal_alarm_set(100000,
+				rmv_uevent_callback, (void *)dev))
+			fprintf(stderr, "Could not set up deferred device removal\n");
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
 static int
 set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port)
 {
-- 
2.7.4



More information about the dev mailing list