All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tianli Lai <laitianli@tom.com>
To: dev@dpdk.org
Cc: stephen@networkplumber.org
Subject: [PATCH v4] examples/kni: add interrupt mode to receive packets
Date: Sat,  9 Apr 2022 18:13:46 +0800	[thread overview]
Message-ID: <20220409101346.3621-1-laitianli@tom.com> (raw)
In-Reply-To: <20220407161205.8633-1-laitianli@tom.com>

kni application have two main-loop threads that they
CPU utilization are up to 100 percent, this two theads are
writing thread and reading thread. I thank set interrupt mode
at reading thread would reduce this thread CPU utilization.

Signed-off-by: Tianli Lai <laitianli@tom.com>
---
 examples/kni/main.c | 91 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 84 insertions(+), 7 deletions(-)

diff --git a/examples/kni/main.c b/examples/kni/main.c
index e99ef5c38a..d4d7a3daa9 100644
--- a/examples/kni/main.c
+++ b/examples/kni/main.c
@@ -73,6 +73,7 @@
 
 #define KNI_US_PER_SECOND       1000000
 #define KNI_SECOND_PER_DAY      86400
+#define MIN_ZERO_POLL_COUNT     100
 
 #define KNI_MAX_KTHREAD 32
 /*
@@ -107,6 +108,8 @@ static uint32_t ports_mask = 0;
 static int promiscuous_on = 0;
 /* Monitor link status continually. off by default. */
 static int monitor_links;
+/* rx set in interrupt mode off by default. */
+static int intr_rx_en;
 
 /* Structure type for recording kni interface specific stats */
 struct kni_interface_stats {
@@ -206,7 +209,7 @@ kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
 /**
  * Interface to burst rx and enqueue mbufs into rx_q
  */
-static void
+static int
 kni_ingress(struct kni_port_params *p)
 {
 	uint8_t i;
@@ -214,9 +217,9 @@ kni_ingress(struct kni_port_params *p)
 	unsigned nb_rx, num;
 	uint32_t nb_kni;
 	struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
-
+	int ret = 0;
 	if (p == NULL)
-		return;
+		return -1;
 
 	nb_kni = p->nb_kni;
 	port_id = p->port_id;
@@ -225,8 +228,10 @@ kni_ingress(struct kni_port_params *p)
 		nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
 		if (unlikely(nb_rx > PKT_BURST_SZ)) {
 			RTE_LOG(ERR, APP, "Error receiving from eth\n");
-			return;
+			return -1;
 		}
+		if (nb_rx == 0)
+			ret = 1;
 		/* Burst tx to kni */
 		num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx);
 		if (num)
@@ -239,6 +244,7 @@ kni_ingress(struct kni_port_params *p)
 			kni_stats[port_id].rx_dropped += nb_rx - num;
 		}
 	}
+	return ret;
 }
 
 /**
@@ -277,12 +283,56 @@ kni_egress(struct kni_port_params *p)
 	}
 }
 
+static int
+sleep_until_rx_interrupt(int num, int lcore)
+{
+	static struct {
+		bool wakeup;
+	} __rte_cache_aligned status[RTE_MAX_LCORE];
+	struct rte_epoll_event event[num];
+	int n;
+
+	if (status[lcore].wakeup) {
+		RTE_LOG(DEBUG, APP,
+				"lcore %u sleeps until interrupt triggers\n",
+				rte_lcore_id());
+	}
+	n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, 10);
+	status[lcore].wakeup = n != 0;
+
+	return 0;
+}
+
+static void
+turn_on_off_intr(uint16_t port_id, uint16_t queue_id, bool on)
+{
+	if (on)
+		rte_eth_dev_rx_intr_enable(port_id, queue_id);
+	else
+		rte_eth_dev_rx_intr_disable(port_id, queue_id);
+}
+
+static int event_register(void)
+{
+	int ret;
+
+	ret = rte_eth_dev_rx_intr_ctl_q(0, 0,
+					RTE_EPOLL_PER_THREAD,
+					RTE_INTR_EVENT_ADD, NULL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int
 main_loop(__rte_unused void *arg)
 {
 	uint16_t i;
 	int32_t f_stop;
 	int32_t f_pause;
+	int ret = 0;
+	uint32_t zero_rx_packet_count = 0;
 	const unsigned lcore_id = rte_lcore_id();
 	enum lcore_rxtx {
 		LCORE_NONE,
@@ -291,12 +341,17 @@ main_loop(__rte_unused void *arg)
 		LCORE_MAX
 	};
 	enum lcore_rxtx flag = LCORE_NONE;
+	int intr_en = 0;
 
 	RTE_ETH_FOREACH_DEV(i) {
 		if (!kni_port_params_array[i])
 			continue;
 		if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) {
 			flag = LCORE_RX;
+			if (intr_rx_en && !event_register())
+				intr_en = 1;
+			else
+				RTE_LOG(DEBUG, APP, "RX interrupt won't enable.\n");
 			break;
 		} else if (kni_port_params_array[i]->lcore_tx ==
 						(uint8_t)lcore_id) {
@@ -316,7 +371,23 @@ main_loop(__rte_unused void *arg)
 				break;
 			if (f_pause)
 				continue;
-			kni_ingress(kni_port_params_array[i]);
+			ret = kni_ingress(kni_port_params_array[i]);
+			if (ret == 1) {
+				zero_rx_packet_count++;
+				if (zero_rx_packet_count <=
+						MIN_ZERO_POLL_COUNT)
+					continue;
+			} else
+				zero_rx_packet_count = 0;
+
+			if (zero_rx_packet_count > 0) {
+				zero_rx_packet_count = 0;
+				if (unlikely(intr_en)) {
+					turn_on_off_intr(i, 0, 1);
+					sleep_until_rx_interrupt(1, lcore_id);
+					turn_on_off_intr(i, 0, 0);
+				}
+			}
 		}
 	} else if (flag == LCORE_TX) {
 		RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
@@ -341,12 +412,13 @@ main_loop(__rte_unused void *arg)
 static void
 print_usage(const char *prgname)
 {
-	RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m "
+	RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m -I "
 		   "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)"
 		   "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n"
 		   "    -p PORTMASK: hex bitmask of ports to use\n"
 		   "    -P : enable promiscuous mode\n"
 		   "    -m : enable monitoring of port carrier state\n"
+		   "    -I : enable rx interrupt mode\n"
 		   "    --config (port,lcore_rx,lcore_tx,lcore_kthread...): "
 		   "port and lcore configurations\n",
 	           prgname);
@@ -527,7 +599,7 @@ parse_args(int argc, char **argv)
 	opterr = 0;
 
 	/* Parse command line */
-	while ((opt = getopt_long(argc, argv, "p:Pm", longopts,
+	while ((opt = getopt_long(argc, argv, "p:PmI", longopts,
 						&longindex)) != EOF) {
 		switch (opt) {
 		case 'p':
@@ -539,6 +611,9 @@ parse_args(int argc, char **argv)
 		case 'm':
 			monitor_links = 1;
 			break;
+		case 'I':
+			intr_rx_en = 1;
+			break;
 		case 0:
 			if (!strncmp(longopts[longindex].name,
 				     CMDLINE_OPT_CONFIG,
@@ -610,6 +685,8 @@ init_port(uint16_t port)
 	if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
 		local_port_conf.txmode.offloads |=
 			RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
+	if (intr_rx_en)
+		local_port_conf.intr_conf.rxq = 1;
 	ret = rte_eth_dev_configure(port, 1, 1, &local_port_conf);
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n",
-- 
2.27.0


  parent reply	other threads:[~2022-04-09  2:14 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-07 16:12 [PATCH] examples/kni: add interrupt mode to receive packets Tianli Lai
2022-04-08  9:02 ` Tianli Lai
2022-04-08  9:12 ` [PATCH v3] " Tianli Lai
2022-04-08 15:15   ` Stephen Hemminger
2022-04-09 10:13 ` Tianli Lai [this message]
2023-07-04  2:58   ` [PATCH v4] " Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220409101346.3621-1-laitianli@tom.com \
    --to=laitianli@tom.com \
    --cc=dev@dpdk.org \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.