diff mbox series

[dpdk-dev,19/20] eventdev: add routine to launch eventmode workers

Message ID 1528478659-15859-20-git-send-email-anoob.joseph@caviumnetworks.com (mailing list archive)
State Changes Requested, archived
Delegated to: Jerin Jacob
Headers show
Series add eventmode helper functions | expand

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail apply issues

Commit Message

Anoob Joseph June 8, 2018, 5:24 p.m. UTC
With eventmode, workers could be drafted differently according to the
capabilities of the underlying event device. The added function would
receive an array of such workers and probes the eventmode properties to
choose the worker.

Signed-off-by: Anoob Joseph <anoob.joseph@caviumnetworks.com>
---
 lib/librte_eventdev/rte_eventmode_helper.c         | 299 +++++++++++++++++++++
 lib/librte_eventdev/rte_eventmode_helper.h         |  57 ++++
 .../rte_eventmode_helper_internal.h                |  23 ++
 3 files changed, 379 insertions(+)
diff mbox series

Patch

diff --git a/lib/librte_eventdev/rte_eventmode_helper.c b/lib/librte_eventdev/rte_eventmode_helper.c
index 7f2d269..25cb4a9 100644
--- a/lib/librte_eventdev/rte_eventmode_helper.c
+++ b/lib/librte_eventdev/rte_eventmode_helper.c
@@ -2,6 +2,7 @@ 
  * Copyright(c) 2018 Cavium, Inc
  */
 #include <getopt.h>
+#include <stdbool.h>
 
 #include <rte_ethdev.h>
 #include <rte_eventdev.h>
@@ -13,6 +14,9 @@ 
 
 #define CMD_LINE_OPT_TRANSFER_MODE	"transfer-mode"
 
+static volatile bool rx_core_running;
+static volatile bool eventmode_worker_stop;
+
 static const char short_options[] =
 	""
 	;
@@ -110,6 +114,16 @@  internal_get_next_active_core(struct eventmode_conf *em_conf,
 	return next_core;
 }
 
+static inline bool
+internal_dev_has_burst_mode(uint8_t dev_id)
+{
+	struct rte_event_dev_info dev_info;
+
+	rte_event_dev_info_get(dev_id, &dev_info);
+	return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE) ?
+			true : false;
+}
+
 /* Global functions */
 
 void
@@ -992,3 +1006,288 @@  rte_eventmode_helper_get_tx_queue(struct rte_eventmode_helper_conf *mode_conf,
 	return eventdev_config->nb_eventqueue;
 }
 
+/* Helper functions for launching workers */
+
+static int32_t
+rte_eventmode_helper_start_worker_rx_core(struct eventmode_conf *em_conf,
+		uint32_t lcore_id)
+{
+	uint32_t service_id[EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE];
+	struct rx_adapter_conf *adapter;
+	int service_count = 0;
+	int adapter_id;
+	int32_t ret;
+	int i;
+
+	RTE_EM_HLPR_LOG_INFO(
+		"Entering rx_core processing on lcore %u", lcore_id);
+
+	/*
+	 * Need to parse adapter conf to see which all adapters need to be
+	 * handled this core.
+	 */
+	for (i = 0; i < em_conf->nb_rx_adapter; i++) {
+		/* Check if we have exceeded the max allowed */
+		if (service_count > EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE) {
+			RTE_EM_HLPR_LOG_ERR(
+				"Exceeded the max allowed adapters per rx core");
+			break;
+		}
+
+		adapter = &(em_conf->adapter[i]);
+		if (adapter->rx_core_id != lcore_id)
+			continue;
+
+		/* Adapter need to be handled by this core */
+		adapter_id = adapter->adapter_id;
+
+		/* Get the service ID for the adapters */
+		ret = rte_event_eth_rx_adapter_service_id_get(adapter_id,
+				&(service_id[service_count]));
+
+		if (ret != -ESRCH && ret != 0) {
+			RTE_EM_HLPR_LOG_ERR(
+				"Error getting service ID used by adapter");
+			return ret;
+		}
+
+		/* Update service count */
+		service_count++;
+	}
+
+	rx_core_running = true;
+
+	while (rx_core_running) {
+		for (i = 0; i < service_count; i++) {
+			/* Initiate rx_adapter service */
+			rte_service_run_iter_on_app_lcore(service_id[i], 0);
+		}
+	}
+
+	return 0;
+}
+
+static int32_t
+rte_eventmode_helper_stop_worker_rx_core(void)
+{
+	if (rx_core_running) {
+		RTE_EM_HLPR_LOG_INFO("Stopping rx cores\n");
+		rx_core_running = false;
+	}
+	return 0;
+}
+
+static struct rte_eventmode_helper_app_worker_params *
+rte_eventmode_helper_find_worker(uint32_t lcore_id,
+		struct eventmode_conf *em_conf,
+		struct rte_eventmode_helper_app_worker_params *app_wrkrs,
+		uint8_t nb_wrkr_param)
+{
+	struct rte_eventmode_helper_event_link_info *link = NULL;
+	uint8_t eventdev_id;
+	struct eventdev_params *eventdev_config;
+	int i;
+	struct rte_eventmode_helper_app_worker_params curr_conf = {0};
+	struct rte_eventmode_helper_app_worker_params *tmp_wrkr;
+
+	/*
+	 * Event device to be used will be derived from the first lcore-event
+	 * link.
+	 *
+	 * Assumption: All lcore-event link tied to a core would be using the
+	 * same event device. in other words, one core would be polling on
+	 * queues of a single event device only.
+	 */
+
+	/* Get a link for this lcore */
+	for (i = 0; i < em_conf->nb_link; i++) {
+		link = &(em_conf->link[i]);
+		if (link->lcore_id == lcore_id)
+			break;
+	}
+
+	if (link == NULL) {
+		RTE_EM_HLPR_LOG_ERR(
+			"No valid link found for lcore(%d)", lcore_id);
+		return NULL;
+	}
+
+	/* Get event dev ID */
+	eventdev_id = link->eventdev_id;
+
+	/* Get the corresponding eventdev config */
+	eventdev_config = internal_get_eventdev_params(em_conf, eventdev_id);
+
+	/* Populate the curr_conf with the capabilities */
+
+	/* Check for burst mode */
+	if (internal_dev_has_burst_mode(eventdev_id))
+		curr_conf.cap.burst = RTE_EVENTMODE_HELPER_RX_TYPE_BURST;
+	else
+		curr_conf.cap.burst = RTE_EVENTMODE_HELPER_RX_TYPE_NON_BURST;
+
+	curr_conf.cap.s1_sched_type =
+			rte_eventmode_helper_get_s1_sched_type(em_conf);
+
+	curr_conf.cap.s2_sched_type =
+			rte_eventmode_helper_get_s2_sched_type(em_conf);
+
+	/* TODO make this part of em_conf */
+	curr_conf.nb_stage = 1;
+
+	/* Now parse the passed list and see if we have matching capabilties */
+
+	/* Initialize the pointer used to traverse the list */
+	tmp_wrkr = app_wrkrs;
+
+	for (i = 0; i < nb_wrkr_param; i++, tmp_wrkr++) {
+
+		/* Skip this if capabilities are not matching */
+		if (tmp_wrkr->cap.u64 != curr_conf.cap.u64)
+			continue;
+
+		/* Skip if the number of stages is not matching */
+		if (tmp_wrkr->nb_stage != curr_conf.nb_stage)
+			continue;
+
+		/* If the checks pass, we have a match */
+		return tmp_wrkr;
+	}
+
+	/* TODO required for ATQ */
+	RTE_SET_USED(eventdev_config);
+
+	return NULL;
+}
+
+static int
+rte_eventmode_helper_verify_match_worker(
+	struct rte_eventmode_helper_app_worker_params *match_wrkr)
+{
+	if (match_wrkr->nb_stage == 0) {
+		RTE_EM_HLPR_LOG_ERR("App stages cannot be 0");
+		return 0;
+	}
+
+	/* Verify the stages registered */
+	switch (match_wrkr->nb_stage) {
+	case 2:
+		if (match_wrkr->s2_worker_thread == NULL) {
+			RTE_EM_HLPR_LOG_ERR(
+				"No worker registered for second stage");
+			return 0;
+		}
+		/* Fall through */
+	case 1:
+		if (match_wrkr->s1_worker_thread == NULL) {
+			RTE_EM_HLPR_LOG_ERR(
+				"No worker registered for first stage");
+			return 0;
+		}
+		break;
+	default:
+		RTE_EM_HLPR_LOG_ERR("Only two stages are supported now");
+		return 0;
+	}
+
+	/* Success */
+	return 1;
+}
+
+void
+rte_eventmode_helper_launch_worker(struct rte_eventmode_helper_conf *mode_conf,
+		struct rte_eventmode_helper_app_worker_params *app_wrkr,
+		uint8_t nb_wrkr_param)
+{
+	struct rte_eventmode_helper_app_worker_params *match_wrkr;
+	uint32_t lcore_id;
+	int i;
+	struct eventmode_conf *em_conf;
+
+	if (mode_conf == NULL) {
+		RTE_EM_HLPR_LOG_ERR("Invalid conf");
+		return;
+	}
+
+	if (mode_conf->mode_params == NULL) {
+		RTE_EM_HLPR_LOG_ERR("Invalid mode params");
+		return;
+	}
+
+	/* Get eventmode conf */
+	em_conf = (struct eventmode_conf *)(mode_conf->mode_params);
+
+	/* Get core ID */
+	lcore_id = rte_lcore_id();
+
+	/* TODO check capability for rx core */
+
+	/* Check if this is rx core */
+	if (em_conf->rx_core_mask & (1 << lcore_id)) {
+		rte_eventmode_helper_start_worker_rx_core(em_conf, lcore_id);
+		return;
+	}
+
+	if (app_wrkr == NULL || nb_wrkr_param == 0) {
+		RTE_EM_HLPR_LOG_ERR("Invalid args");
+		return;
+	}
+
+	/*
+	 * This is a regular worker thread. The application would be
+	 * registering multiple workers with various capabilities. The
+	 * worker to be run will be selected by the capabilities of the
+	 * event device configured.
+	 */
+
+	/* Get the first matching worker for the event device */
+	match_wrkr = rte_eventmode_helper_find_worker(lcore_id,
+			em_conf,
+			app_wrkr,
+			nb_wrkr_param);
+
+	if (match_wrkr == NULL) {
+		RTE_EM_HLPR_LOG_ERR(
+			"No matching worker registered for lcore %d", lcore_id);
+		goto clean_and_exit;
+	}
+
+	/* Verify sanity of the matched worker */
+	if (rte_eventmode_helper_verify_match_worker(match_wrkr) != 1) {
+		RTE_EM_HLPR_LOG_ERR("Error in validating the matched worker");
+		goto clean_and_exit;
+	}
+
+	/*
+	 * If single stage, then the worker thread will have the loop,
+	 * thereby avoiding the dereferencing of the function pointer.
+	 */
+	if (match_wrkr->nb_stage == 1) {
+		match_wrkr->s1_worker_thread((void *)mode_conf);
+		goto clean_and_exit;
+	}
+
+	/* TODO write worker stop API */
+	eventmode_worker_stop = false;
+
+	/* Run the worker threads */
+	while (!eventmode_worker_stop) {
+
+		/* Launch the stages registered */
+		for (i = 1; i <= match_wrkr->nb_stage; i++) {
+			switch (i) {
+			case 1:
+				match_wrkr->s1_worker_thread((void *)em_conf);
+				break;
+			case 2:
+				match_wrkr->s2_worker_thread((void *)em_conf);
+				break;
+			}
+		}
+	}
+
+clean_and_exit:
+
+	/* Flag rx_cores to stop, if started */
+	rte_eventmode_helper_stop_worker_rx_core();
+}
diff --git a/lib/librte_eventdev/rte_eventmode_helper.h b/lib/librte_eventdev/rte_eventmode_helper.h
index be2fe8d..25b1180 100644
--- a/lib/librte_eventdev/rte_eventmode_helper.h
+++ b/lib/librte_eventdev/rte_eventmode_helper.h
@@ -12,6 +12,22 @@  enum rte_eventmode_helper_pkt_transfer_mode {
 	RTE_EVENTMODE_HELPER_PKT_TRANSFER_MODE_EVENT,
 };
 
+/* Event mode packet rx types */
+enum rte_eventmode_helper_rx_types {
+	RTE_EVENTMODE_HELPER_RX_TYPE_INVALID = 0,
+	RTE_EVENTMODE_HELPER_RX_TYPE_NON_BURST,
+	RTE_EVENTMODE_HELPER_RX_TYPE_BURST,
+	RTE_EVENTMODE_HELPER_RX_TYPE_MAX = 16
+};
+
+/* Event mode packet tx types */
+enum rte_eventmode_helper_tx_types {
+	RTE_EVETNMODE_HELPER_TX_TYPE_INVALID = 0,
+	RTE_EVENTMODE_HELPER_TX_TYPE_LOCKED,
+	RTE_EVENTMODE_HELPER_TX_TYPE_LOCKLESS,
+	RTE_EVENTMODE_HELPER_TX_TYPE_MAX = 16
+};
+
 struct rte_eventmode_helper_conf {
 	enum rte_eventmode_helper_pkt_transfer_mode mode;
 		/**< Packet transfer mode of the application */
@@ -36,6 +52,27 @@  struct rte_eventmode_helper_event_link_info {
 		/**< Lcore to be polling on this port */
 };
 
+/* Workers registered by the application */
+struct rte_eventmode_helper_app_worker_params {
+	union {
+		struct {
+			uint64_t burst : 4;
+			/**< Specify status of rx type burst */
+			uint64_t s1_sched_type : 2;
+			/**< Stage 1 scheduling type for the thread */
+			uint64_t s2_sched_type : 2;
+			/**< Stage 2 scheduling type for the thread */
+		};
+		uint64_t u64;
+	} cap;
+			/**< Capabilities of this worker */
+	uint8_t nb_stage;
+	void (*s1_worker_thread)(void *);
+			/**< Stage 1 worker thread */
+	void (*s2_worker_thread)(void *);
+			/**< Stage 2 worker thread */
+};
+
 /* Common helper functions for command line parsing */
 
 /**
@@ -152,5 +189,25 @@  uint8_t
 rte_eventmode_helper_get_tx_queue(struct rte_eventmode_helper_conf *mode_conf,
 		uint8_t eventdev_id);
 
+/**
+ * Launch eventmode worker
+ *
+ * The application can request the eventmode helper subsystem to launch the
+ * worker based on the capabilities of event device and the options selected
+ * while initializing the eventmode.
+ *
+ * @param mode_conf
+ *   Configuration of the mode in which app is doing packet handling
+ * @param app_wrkr
+ *   List of all the workers registered by application, along with it's
+ *   capabilties
+ * @param nb_wrkr_param
+ *   Number of workers passed by the application
+ *
+ */
+void
+rte_eventmode_helper_launch_worker(struct rte_eventmode_helper_conf *mode_conf,
+		struct rte_eventmode_helper_app_worker_params *app_wrkr,
+		uint8_t nb_wrkr_param);
 
 #endif /* _RTE_EVENTMODE_HELPER_H_ */
diff --git a/lib/librte_eventdev/rte_eventmode_helper_internal.h b/lib/librte_eventdev/rte_eventmode_helper_internal.h
index 3a4e52f..996c654 100644
--- a/lib/librte_eventdev/rte_eventmode_helper_internal.h
+++ b/lib/librte_eventdev/rte_eventmode_helper_internal.h
@@ -43,6 +43,9 @@ 
 #define EVENT_MODE_MAX_LCORE_LINKS \
 	(EVENT_MODE_MAX_EVENT_DEVS * EVENT_MODE_MAX_EVENT_QUEUES_PER_DEV)
 
+/* Max adapters that one rx core can handle */
+#define EVENT_MODE_MAX_ADAPTERS_PER_RX_CORE EVENT_MODE_MAX_RX_ADAPTERS
+
 /* Event dev params */
 struct eventdev_params {
 	uint8_t eventdev_id;
@@ -104,4 +107,24 @@  struct eventmode_conf {
 		/**< 64 bit field to specify extended params */
 };
 
+/*
+ * Get sched type of the first stage of app
+ *
+ */
+static inline uint8_t
+rte_eventmode_helper_get_s1_sched_type(struct eventmode_conf *em_conf)
+{
+	return em_conf->ext_params.s1_sched_type;
+}
+
+/*
+ * Get sched type of the first stage of app
+ *
+ */
+static inline uint8_t
+rte_eventmode_helper_get_s2_sched_type(struct eventmode_conf *em_conf)
+{
+	return em_conf->ext_params.s2_sched_type;
+}
+
 #endif /* _RTE_EVENTMODE_HELPER_INTERNAL_H_ */