DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
@ 2024-04-12 12:27 Kamil Vojanec
  2024-04-12 12:27 ` [PATCH v2 2/2] doc/prog_guide: document " Kamil Vojanec
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Kamil Vojanec @ 2024-04-12 12:27 UTC (permalink / raw)
  To: dev; +Cc: Kamil Vojanec, Chas Williams, Min Hu (Connor)

This patch adds a new bonding mode: 'direct'. The purpose of this mode
is to redirect output packets to the same member port on which they were
received. In case the requested port is not among the member ports,
round robin TX mode is used as a fallback.

Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
---
 app/test/test_link_bonding.c            | 205 ++++++++++++++++++++++++
 drivers/net/bonding/rte_eth_bond.h      |   5 +
 drivers/net/bonding/rte_eth_bond_args.c |   1 +
 drivers/net/bonding/rte_eth_bond_pmd.c  |  50 +++++-
 4 files changed, 258 insertions(+), 3 deletions(-)

diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 4d54706c21..254cacf5aa 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -2134,6 +2134,208 @@ test_roundrobin_verify_polling_member_link_status_change(void)
 	return remove_members_and_stop_bonding_device();
 }
 
+/** Direct mode Tests */
+
+static int
+test_direct_tx_burst_single_member(void)
+{
+	unsigned int i;
+	int member_port_id;
+	struct rte_eth_stats port_stats;
+	struct rte_mbuf *pkts[MAX_PKT_BURST];
+	const unsigned int burst_size = 20;
+
+	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
+			"Burst size specified is greater than supported.");
+
+	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
+			BONDING_MODE_DIRECT, 0, 1, 1),
+			"Failed to initialize bonding device with single member");
+
+	/* Generate burst of test packets */
+	TEST_ASSERT_EQUAL(generate_test_burst(pkts, burst_size, 0, 1, 0, 0, 0),
+			(int) burst_size, "Failed to generate test burst");
+
+	member_port_id = test_params->member_port_ids[0];
+
+	/* Set the 'port' mbuf attribute to the appropriate value */
+	for (i = 0; i < burst_size; i++)
+		pkts[i]->port = member_port_id;
+
+	/* Send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+			test_params->bonding_port_id, 0, pkts, burst_size),
+			burst_size,
+			"TX burst failed");
+
+	/* Verify stats on bonding port */
+	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
+	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
+			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
+			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
+			burst_size);
+
+	/* Verify stats on member port */
+	rte_eth_stats_get(member_port_id, &port_stats);
+	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
+			"Member port (%d) opackets value (%u) not as expected (%u)\n",
+			member_port_id, (unsigned int) port_stats.opackets,
+			burst_size);
+
+	/* Put all members down and try to transmit */
+	virtual_ethdev_simulate_link_status_interrupt(member_port_id, 0);
+
+	/* Try to send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
+			pkts, burst_size), 0,
+			"TX burst returned unexpected value");
+
+	/* Clean up and remove members from bonding device */
+	return remove_members_and_stop_bonding_device();
+}
+
+static int
+test_direct_tx_burst_multiple_members_single_tx(void)
+{
+	unsigned int i;
+	struct rte_eth_stats port_stats;
+	struct rte_mbuf *pkts[MAX_PKT_BURST];
+	const unsigned int num_members = 4;
+	const unsigned int burst_size = 20;
+	const int exp_member_port_id = test_params->member_port_ids[0];
+	int cmember_port_id;
+	unsigned int expected_pkts;
+
+
+	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
+			"Burst size specified is greater than supported.");
+
+	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
+			BONDING_MODE_DIRECT, 0, num_members, 1),
+			"Failed to initialize bonding device with single member");
+
+	/* Generate burst of test packets */
+	TEST_ASSERT_EQUAL(generate_test_burst(
+			pkts, burst_size, 0, 1, 0, 0, 0),
+			(int) burst_size,
+			"Failed to generate test burst");
+
+
+	/* Set the 'port' mbuf attribute to the appropriate value */
+	for (i = 0; i < burst_size; i++)
+		pkts[i]->port = exp_member_port_id;
+
+	/* Send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+			test_params->bonding_port_id, 0, pkts, burst_size),
+			burst_size,
+			"TX burst failed");
+
+	/* Verify stats on bonding port */
+	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
+	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
+			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
+			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
+			burst_size);
+
+	/* Verify member ports tx stats */
+	for (i = 0; i < test_params->bonding_member_count; i++) {
+		cmember_port_id = test_params->member_port_ids[i];
+
+		if (cmember_port_id == exp_member_port_id)
+			expected_pkts = burst_size;
+		else
+			expected_pkts = 0;
+
+		rte_eth_stats_get(cmember_port_id, &port_stats);
+		TEST_ASSERT_EQUAL(port_stats.opackets,
+				(uint64_t)expected_pkts,
+				"Member Port (%d) opackets value (%u) not as expected (%u)\n",
+				test_params->bonding_port_id, (unsigned int)port_stats.opackets,
+				expected_pkts);
+	}
+
+	/* Put all members down and try and transmit */
+	for (i = 0; i < test_params->bonding_member_count; i++) {
+		virtual_ethdev_simulate_link_status_interrupt(
+				test_params->member_port_ids[i], 0);
+	}
+
+	/* Try to send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
+			pkts, burst_size), 0,
+			"TX burst returned unexpected value");
+
+	/* Clean up and remove members from bonding device */
+	return remove_members_and_stop_bonding_device();
+}
+
+static int
+test_direct_tx_burst_multiple_members_rr_fallback(void)
+{
+	unsigned int i;
+	struct rte_eth_stats port_stats;
+	struct rte_mbuf *pkts[MAX_PKT_BURST];
+	const unsigned int num_members = 4;
+	const unsigned int pkts_per_member = 20;
+	const unsigned int burst_size = num_members * pkts_per_member;
+
+
+	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
+			"Burst size specified is greater than supported.");
+
+	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
+			BONDING_MODE_DIRECT, 0, num_members, 1),
+			"Failed to initialize bonding device with single member");
+
+	/* Generate burst of test packets */
+	TEST_ASSERT_EQUAL(generate_test_burst(
+			pkts, burst_size, 0, 1, 0, 0, 0),
+			(int) burst_size,
+			"Failed to generate test burst");
+
+
+	/* Set the 'port' mbuf attribute to the appropriate value */
+	for (i = 0; i < burst_size; i++)
+		pkts[i]->port = RTE_MAX_ETHPORTS;
+
+	/* Send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+			test_params->bonding_port_id, 0, pkts, burst_size),
+			burst_size,
+			"TX burst failed");
+
+	/* Verify stats on bonding port */
+	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
+	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
+			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
+			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
+			burst_size);
+
+	/* Verify member ports tx stats */
+	for (i = 0; i < test_params->bonding_member_count; i++) {
+		rte_eth_stats_get(test_params->member_port_ids[i], &port_stats);
+		TEST_ASSERT_EQUAL(port_stats.opackets,
+				(uint64_t)pkts_per_member,
+				"Member Port (%d) opackets value (%u) not as expected (%u)\n",
+				test_params->bonding_port_id, (unsigned int)port_stats.opackets,
+				pkts_per_member);
+	}
+
+	/* Put all members down and try and transmit */
+	for (i = 0; i < test_params->bonding_member_count; i++) {
+		virtual_ethdev_simulate_link_status_interrupt(
+				test_params->member_port_ids[i], 0);
+	}
+
+	/* Try to send burst on bonding port */
+	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
+			pkts, burst_size), 0,
+			"TX burst returned unexpected value");
+
+	/* Clean up and remove members from bonding device */
+	return remove_members_and_stop_bonding_device();
+}
 
 /** Active Backup Mode Tests */
 
@@ -5174,6 +5376,9 @@ static struct unit_test_suite link_bonding_test_suite  = {
 		TEST_CASE(test_roundrobin_verify_mac_assignment),
 		TEST_CASE(test_roundrobin_verify_member_link_status_change_behaviour),
 		TEST_CASE(test_roundrobin_verify_polling_member_link_status_change),
+		TEST_CASE(test_direct_tx_burst_single_member),
+		TEST_CASE(test_direct_tx_burst_multiple_members_single_tx),
+		TEST_CASE(test_direct_tx_burst_multiple_members_rr_fallback),
 		TEST_CASE(test_activebackup_tx_burst),
 		TEST_CASE(test_activebackup_rx_burst),
 		TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h
index f10165f2c6..82d6644500 100644
--- a/drivers/net/bonding/rte_eth_bond.h
+++ b/drivers/net/bonding/rte_eth_bond.h
@@ -83,6 +83,11 @@ extern "C" {
  * information from it. When ARP reply from that peer is received, its MAC is
  * stored, one of member MACs assigned and ARP reply send to that peer.
  */
+#define BONDING_MODE_DIRECT	(7)
+/**< Direct bonding mode (Mode 7)
+ * In this mode, all packets are transmitted using the same member port on which
+ * it was received. This is decided based on the 'port' field of 'rte_mbuf'.
+ */
 
 /* Balance Mode Transmit Policies */
 #define BALANCE_XMIT_POLICY_LAYER2		(0)
diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c
index bdec5d61d4..44e20568db 100644
--- a/drivers/net/bonding/rte_eth_bond_args.c
+++ b/drivers/net/bonding/rte_eth_bond_args.c
@@ -158,6 +158,7 @@ bond_ethdev_parse_member_mode_kvarg(const char *key __rte_unused,
 	case BONDING_MODE_8023AD:
 	case BONDING_MODE_TLB:
 	case BONDING_MODE_ALB:
+	case BONDING_MODE_DIRECT:
 		return 0;
 	default:
 		RTE_BOND_LOG(ERR, "Invalid member mode value (%s) specified", value);
diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
index c40d18d128..57ac5879c4 100644
--- a/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -578,9 +578,14 @@ bond_ethdev_rx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	return nb_recv_pkts;
 }
 
+enum tx_member_populate_mode {
+	RR_ONLY,
+	DIRECT_WITH_RR_FALLBACK,
+};
+
 static uint16_t
-bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
-		uint16_t nb_pkts)
+bond_ethdev_tx_burst_rr_generic(void *queue, struct rte_mbuf **bufs,
+		uint16_t nb_pkts, enum tx_member_populate_mode pop_mode)
 {
 	struct bond_dev_private *internals;
 	struct bond_tx_queue *bd_tx_q;
@@ -594,7 +599,7 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
 	uint16_t num_tx_total = 0, num_tx_member;
 
 	static int member_idx;
-	int i, cmember_idx = 0, tx_fail_total = 0;
+	int i, j, cmember_idx = 0, tx_fail_total = 0;
 
 	bd_tx_q = (struct bond_tx_queue *)queue;
 	internals = bd_tx_q->dev_private;
@@ -611,6 +616,17 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
 	/* Populate members mbuf with which packets are to be sent on it  */
 	for (i = 0; i < nb_pkts; i++) {
 		cmember_idx = (member_idx + i) % num_of_members;
+
+		if (pop_mode == DIRECT_WITH_RR_FALLBACK) {
+			/* Try to find correct member index */
+			for (j = 0; j < num_of_members; j++) {
+				if (bufs[i]->port == members[j]) {
+					cmember_idx = j;
+					break;
+				}
+			}
+		}
+
 		member_bufs[cmember_idx][(member_nb_pkts[cmember_idx])++] = bufs[i];
 	}
 
@@ -646,6 +662,20 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
 	return num_tx_total;
 }
 
+static uint16_t
+bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
+		uint16_t nb_pkts)
+{
+	return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, RR_ONLY);
+}
+
+static uint16_t
+bond_ethdev_tx_burst_direct(void *queue, struct rte_mbuf **bufs,
+		uint16_t nb_pkts)
+{
+	return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, DIRECT_WITH_RR_FALLBACK);
+}
+
 static uint16_t
 bond_ethdev_tx_burst_active_backup(void *queue,
 		struct rte_mbuf **bufs, uint16_t nb_pkts)
@@ -1551,6 +1581,7 @@ mac_address_members_update(struct rte_eth_dev *bonding_eth_dev)
 	case BONDING_MODE_ROUND_ROBIN:
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
+	case BONDING_MODE_DIRECT:
 		for (i = 0; i < internals->member_count; i++) {
 			if (rte_eth_dev_default_mac_addr_set(
 					internals->members[i].port_id,
@@ -1648,6 +1679,10 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, uint8_t mode)
 		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb;
 		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb;
 		break;
+	case BONDING_MODE_DIRECT:
+		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_direct;
+		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
+		break;
 	default:
 		return -1;
 	}
@@ -2581,6 +2616,7 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_TLB:
 	case BONDING_MODE_ALB:
+	case BONDING_MODE_DIRECT:
 	default:
 		/**
 		 * In theses mode the maximum theoretical link speed is the sum
@@ -2678,6 +2714,7 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
 	case BONDING_MODE_ROUND_ROBIN:
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
+	case BONDING_MODE_DIRECT:
 	case BONDING_MODE_8023AD: {
 		unsigned int member_ok = 0;
 
@@ -2732,6 +2769,7 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
 	case BONDING_MODE_ROUND_ROBIN:
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
+	case BONDING_MODE_DIRECT:
 	case BONDING_MODE_8023AD: {
 		unsigned int member_ok = 0;
 
@@ -2790,6 +2828,7 @@ bond_ethdev_promiscuous_update(struct rte_eth_dev *dev)
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
 	case BONDING_MODE_8023AD:
+	case BONDING_MODE_DIRECT:
 		/* As promiscuous mode is propagated to all members for these
 		 * mode, no need to update for bonding device.
 		 */
@@ -2825,6 +2864,7 @@ bond_ethdev_allmulticast_enable(struct rte_eth_dev *eth_dev)
 	case BONDING_MODE_ROUND_ROBIN:
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
+	case BONDING_MODE_DIRECT:
 	case BONDING_MODE_8023AD: {
 		unsigned int member_ok = 0;
 
@@ -2879,6 +2919,7 @@ bond_ethdev_allmulticast_disable(struct rte_eth_dev *eth_dev)
 	case BONDING_MODE_ROUND_ROBIN:
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
+	case BONDING_MODE_DIRECT:
 	case BONDING_MODE_8023AD: {
 		unsigned int member_ok = 0;
 
@@ -2936,6 +2977,7 @@ bond_ethdev_allmulticast_update(struct rte_eth_dev *dev)
 	case BONDING_MODE_BALANCE:
 	case BONDING_MODE_BROADCAST:
 	case BONDING_MODE_8023AD:
+	case BONDING_MODE_DIRECT:
 		/* As allmulticast mode is propagated to all members for these
 		 * mode, no need to update for bonding device.
 		 */
@@ -3365,6 +3407,8 @@ bond_mode_name(uint8_t mode)
 		return "TLB";
 	case BONDING_MODE_ALB:
 		return "ALB";
+	case BONDING_MODE_DIRECT:
+		return "DIRECT";
 	default:
 		return "Unknown";
 	}
-- 
2.39.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 2/2] doc/prog_guide: document direct link bonding mode
  2024-04-12 12:27 [PATCH v2 1/2] net/bonding: introduce direct link bonding mode Kamil Vojanec
@ 2024-04-12 12:27 ` Kamil Vojanec
  2024-07-05 11:27 ` [PATCH v2 1/2] net/bonding: introduce " Ferruh Yigit
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Kamil Vojanec @ 2024-04-12 12:27 UTC (permalink / raw)
  To: dev; +Cc: Kamil Vojanec, Chas Williams, Min Hu (Connor)

This commit introduces documentation for the newly introduced link
bonding mode.

Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
---
 doc/guides/prog_guide/img/bond-mode-7.svg     | 908 ++++++++++++++++++
 .../link_bonding_poll_mode_drv_lib.rst        |  13 +
 2 files changed, 921 insertions(+)
 create mode 100644 doc/guides/prog_guide/img/bond-mode-7.svg

diff --git a/doc/guides/prog_guide/img/bond-mode-7.svg b/doc/guides/prog_guide/img/bond-mode-7.svg
new file mode 100644
index 0000000000..aae0a5132e
--- /dev/null
+++ b/doc/guides/prog_guide/img/bond-mode-7.svg
@@ -0,0 +1,908 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- SPDX-License-Identifier: BSD-3-Clause -->
+
+<svg
+   width="332.15576"
+   height="334.46951"
+   viewBox="0 0 265.725 267.57566"
+   xml:space="preserve"
+   color-interpolation-filters="sRGB"
+   class="st16"
+   id="svg3406"
+   version="1.1"
+   inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
+   sodipodi:docname="bond-mode-7.svg"
+   style="font-size:12px;fill:none;stroke-linecap:square;stroke-miterlimit:3;overflow:visible"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
+     id="metadata3652"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2560"
+     inkscape:window-height="1371"
+     id="namedview3650"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="2.8284271"
+     inkscape:cx="65.230601"
+     inkscape:cy="174.83215"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="shape20-95-0"
+     inkscape:showpageshadow="2"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1" /><style
+     type="text/css"
+     id="style3408">
+		.st1 {visibility:visible}
+		.st2 {fill:#5b9bd5;fill-opacity:0.25;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.25}
+		.st3 {fill:#4f87bb;stroke:#40709c;stroke-width:0.75}
+		.st4 {fill:#feffff;font-family:Calibri;font-size:0.833336em}
+		.st5 {fill:url(#grad0-11);stroke:#4f87bb;stroke-width:0.75}
+		.st6 {fill:#4f87bb;font-family:Calibri;font-size:0.833336em}
+		.st7 {fill:#759fcc;fill-opacity:0.25;filter:url(#filter_2);stroke:#759fcc;stroke-opacity:0.25}
+		.st8 {fill:#668bb3;stroke:#547395;stroke-width:0.75}
+		.st9 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
+		.st10 {fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25}
+		.st11 {fill:#759fcc;fill-opacity:0.22;filter:url(#filter_2);stroke:#759fcc;stroke-opacity:0.22}
+		.st12 {fill:#759fcc;stroke:#c7c8c8;stroke-width:0.25}
+		.st13 {fill:url(#grad0-40);stroke:#a6b6cd;stroke-width:0.75}
+		.st14 {fill:#70ad47;fill-opacity:0.25;filter:url(#filter_2);stroke:#70ad47;stroke-opacity:0.25}
+		.st15 {fill:#61973d;stroke:#507e31;stroke-width:0.75}
+		.st16 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+	</style><defs
+     id="Patterns_And_Gradients"><linearGradient
+       id="grad0-11"
+       x1="-0.24584444"
+       y1="740.8343"
+       x2="167.49742"
+       y2="740.8343"
+       gradientTransform="scale(1.5253548,0.65558519)"
+       gradientUnits="userSpaceOnUse"><stop
+         offset="0"
+         stop-color="#e9eff7"
+         stop-opacity="1"
+         id="stop3412" /><stop
+         offset="0.24"
+         stop-color="#f4f7fb"
+         stop-opacity="1"
+         id="stop3414" /><stop
+         offset="0.54"
+         stop-color="#feffff"
+         stop-opacity="1"
+         id="stop3416" /></linearGradient><linearGradient
+       id="grad0-40"
+       x1="0"
+       y1="0"
+       x2="1"
+       y2="0"
+       gradientTransform="matrix(0.5,0.8660254,-0.8660254,0.5,0.6830127,-0.1830127)"><stop
+         offset="0"
+         stop-color="#f3f6fa"
+         stop-opacity="1"
+         id="stop3419" /><stop
+         offset="0.24"
+         stop-color="#f9fafc"
+         stop-opacity="1"
+         id="stop3421" /><stop
+         offset="0.54"
+         stop-color="#feffff"
+         stop-opacity="1"
+         id="stop3423" /></linearGradient><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40"
+       id="linearGradient3654"
+       gradientTransform="scale(2.9084098,0.3438305)"
+       x1="-0.12893644"
+       y1="1717.1688"
+       x2="28.140807"
+       y2="1717.1688"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40"
+       id="linearGradient3656"
+       gradientTransform="scale(2.093628,0.47763977)"
+       x1="-0.17911492"
+       y1="1233.6389"
+       x2="25.111911"
+       y2="1233.6389"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40"
+       id="linearGradient3658"
+       gradientTransform="scale(2.093628,0.47763977)"
+       x1="-0.17911492"
+       y1="1233.6389"
+       x2="25.111911"
+       y2="1233.6389"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40"
+       id="linearGradient3660"
+       gradientTransform="scale(2.1254139,0.4704966)"
+       x1="-0.17643623"
+       y1="1252.3682"
+       x2="25.498563"
+       y2="1252.3682"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40"
+       id="linearGradient3662"
+       gradientTransform="scale(2.1254139,0.4704966)"
+       x1="-0.17643623"
+       y1="1252.3682"
+       x2="25.498563"
+       y2="1252.3682"
+       gradientUnits="userSpaceOnUse" /><filter
+       id="filter_2-5"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427-9" /></filter><filter
+       id="filter_2-2"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427-93" /></filter><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40-3"
+       id="linearGradient3658-6"
+       gradientTransform="scale(2.093628,0.47763977)"
+       x1="-0.17911492"
+       y1="1233.6389"
+       x2="25.111912"
+       y2="1233.6389"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       id="grad0-40-3"
+       x1="0"
+       y1="0"
+       x2="1"
+       y2="0"
+       gradientTransform="rotate(60,0.5,0.5)"><stop
+         offset="0"
+         stop-color="#f3f6fa"
+         stop-opacity="1"
+         id="stop3419-2" /><stop
+         offset="0.24"
+         stop-color="#f9fafc"
+         stop-opacity="1"
+         id="stop3421-0" /><stop
+         offset="0.54"
+         stop-color="#feffff"
+         stop-opacity="1"
+         id="stop3423-6" /></linearGradient><filter
+       id="filter_2-4"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427-7" /></filter><filter
+       id="filter_2-25"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427-4" /></filter><linearGradient
+       inkscape:collect="always"
+       xlink:href="#grad0-40-3"
+       id="linearGradient3"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(2.093628,0.47763977)"
+       x1="-0.17911492"
+       y1="1233.6389"
+       x2="25.111912"
+       y2="1233.6389" /><filter
+       id="filter_2-9"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427-2" /></filter></defs><defs
+     id="Filters"><filter
+       id="filter_2"
+       color-interpolation-filters="sRGB"
+       x="-0.3739452"
+       y="-0.3739452"
+       width="1.7478904"
+       height="1.7478904"><feGaussianBlur
+         stdDeviation="2"
+         id="feGaussianBlur3427" /></filter></defs><g
+     id="g3429"
+     transform="translate(-13.045598,-14.663414)"><title
+       id="title3431">Page-4</title><g
+       id="shape1-1"
+       transform="translate(18,-516.416)"><title
+   id="title3434">Rectangle.7</title><desc
+   id="desc3436">User Application</desc><g
+   id="shadow1-2"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="534.41602"
+     width="255.118"
+     height="60.859798"
+     class="st2"
+     id="rect3439"
+     style="fill:#5b9bd5;fill-opacity:0.25;stroke:#5b9bd5;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="534.41602"
+   width="255.118"
+   height="60.859798"
+   class="st3"
+   id="rect3441"
+   style="fill:#4f87bb;stroke:#40709c;stroke-width:0.75" /><text
+   x="94"
+   y="567.84998"
+   class="st4"
+   id="text3443"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">User Application</text>
+</g><g
+       id="group2-7"
+       transform="translate(18,-355.662)"><title
+         id="title3446">Sheet.2</title><g
+         id="shape3-8"><title
+   id="title3449">Rectangle.38</title><desc
+   id="desc3451">DPDK</desc><rect
+   x="0"
+   y="486.05499"
+   width="255.118"
+   height="109.22"
+   class="st5"
+   id="rect3453"
+   style="fill:url(#grad0-11);stroke:#4f87bb;stroke-width:0.75" /><text
+   x="228.45"
+   y="499.06"
+   class="st6"
+   id="text3455"
+   style="line-height:0%;font-family:Calibri;fill:#4f87bb">DPDK</text>
+</g><g
+         id="shape4-13"
+         transform="translate(6.87402,-7.17304)"><title
+   id="title3458">Rectangle.16</title><desc
+   id="desc3460">bonding ethdev</desc><g
+   id="shadow4-14"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="523.16803"
+     width="241.157"
+     height="72.107201"
+     class="st7"
+     id="rect3463"
+     style="fill:#759fcc;fill-opacity:0.25;stroke:#759fcc;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="523.16803"
+   width="241.157"
+   height="72.107201"
+   class="st8"
+   id="rect3465"
+   style="fill:#668bb3;stroke:#547395;stroke-width:0.75" /><text
+   x="89.650002"
+   y="536.16998"
+   class="st4"
+   id="text3467"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">bonding ethdev</text>
+</g><g
+         id="shape5-19"
+         transform="translate(13.9606,-14.1732)"><title
+   id="title3470">Rectangle.11</title><desc
+   id="desc3472">ethdev port</desc><g
+   id="shadow5-20"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="559.75598"
+     width="70.866096"
+     height="35.519501"
+     class="st9"
+     id="rect3475"
+     style="fill:#5b9bd5;fill-opacity:0.22000002;stroke:#5b9bd5;stroke-opacity:0.22000002;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="559.75598"
+   width="70.866096"
+   height="35.519501"
+   class="st10"
+   id="rect3477"
+   style="fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25" /><text
+   x="11.46"
+   y="580.52002"
+   class="st4"
+   id="text3479"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">ethdev port</text>
+</g><g
+         id="shape6-25"
+         transform="translate(91.9134,-14.1732)"><title
+   id="title3482">Rectangle.14</title><desc
+   id="desc3484">ethdev port</desc><g
+   id="shadow6-26"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="559.75598"
+     width="70.866096"
+     height="35.519501"
+     class="st11"
+     id="rect3487"
+     style="fill:#759fcc;fill-opacity:0.22000002;stroke:#759fcc;stroke-opacity:0.22000002;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="559.75598"
+   width="70.866096"
+   height="35.519501"
+   class="st12"
+   id="rect3489"
+   style="fill:#759fcc;stroke:#c7c8c8;stroke-width:0.25" /><text
+   x="11.46"
+   y="580.52002"
+   class="st4"
+   id="text3491"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">ethdev port</text>
+</g><g
+         id="shape7-31"
+         transform="translate(169.866,-14.1732)"><title
+   id="title3494">Rectangle.15</title><desc
+   id="desc3496">ethdev port</desc><g
+   id="shadow7-32"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="559.75598"
+     width="70.866096"
+     height="35.519501"
+     class="st11"
+     id="rect3499"
+     style="fill:#759fcc;fill-opacity:0.22000002;stroke:#759fcc;stroke-opacity:0.22000002;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="559.75598"
+   width="70.866096"
+   height="35.519501"
+   class="st12"
+   id="rect3501"
+   style="fill:#759fcc;stroke:#c7c8c8;stroke-width:0.25" /><text
+   x="11.46"
+   y="580.52002"
+   class="st4"
+   id="text3503"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">ethdev port</text>
+</g></g><g
+       id="shape8-37"
+       transform="matrix(0.00130551,-0.99999915,0.99999915,0.00130551,-449.822,159.557)"><title
+         id="title3506">Simple Double Arrow.14</title><path
+         d="m 0,595.28 11.34,-4.49 0,2.24 58.8,0 0,-2.24 11.33,4.49 -11.33,4.48 0,-2.24 -58.8,0 0,2.24 L 0,595.28 z"
+         class="st13"
+         id="path3508"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3654);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape9-41"
+       transform="rotate(-89.355,-121.47494,397.4472)"><title
+         id="title3511">Simple Arrow</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 H 52.2 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3513"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3656);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape10-44"
+       transform="rotate(90.645,214.4765,442.71488)"><title
+         id="title3516">Simple Arrow.37</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 H 52.2 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3518"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3658);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape10-44-1"
+       transform="rotate(90.645,253.20638,480.85796)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+         id="title3516-5">Simple Arrow.37</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 H 52.2 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3518-5"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3658-6);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape10-44-1-3"
+       transform="rotate(90.645,292.36043,519.86224)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+         id="title3516-5-1">Simple Arrow.37</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 H 52.2 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3518-5-4"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape11-47"
+       transform="rotate(-89.1701,-83.073075,359.30327)"><title
+         id="title3521">Simple Arrow.38</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 h 42.48 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3523"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3660);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape12-50"
+       transform="rotate(-90.679,-39.709348,322.23657)"><title
+         id="title3526">Simple Arrow.39</title><path
+         d="m 0,595.28 11.34,-5.67 v 2.83 h 42.48 v 2.84 2.83 H 11.34 v 2.83 z"
+         class="st13"
+         id="path3528"
+         inkscape:connector-curvature="0"
+         style="fill:url(#linearGradient3662);stroke:#a6b6cd;stroke-width:0.75" /></g><g
+       id="shape13-53"
+       transform="translate(124.724,-436.365)"><title
+   id="title3531">Square.114</title><desc
+   id="desc3533">1</desc><g
+   id="shadow13-54"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3536"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3538"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3540"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">1</text>
+</g><g
+       id="shape14-59"
+       transform="translate(124.724,-455.698)"><title
+   id="title3543">Square.115</title><desc
+   id="desc3545">2</desc><g
+   id="shadow14-60"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3548"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3550"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3552"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">2</text>
+</g><g
+       id="shape15-65"
+       transform="translate(124.724,-474.406)"><title
+   id="title3555">Square.116</title><desc
+   id="desc3557">3</desc><g
+   id="shadow15-66"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3560"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3562"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3564"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">3</text>
+</g><g
+       id="shape16-71"
+       transform="translate(124.724,-493.739)"><title
+   id="title3567">Square.117</title><desc
+   id="desc3569">4</desc><g
+   id="shadow16-72"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3572"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3574"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3576"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">4</text>
+</g><g
+       id="shape17-77"
+       transform="translate(124.724,-513.071)"><title
+   id="title3579">Square.118</title><desc
+   id="desc3581">5</desc><g
+   id="shadow17-78"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3584"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3586"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3588"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">5</text>
+</g><g
+       id="shape18-83"
+       transform="translate(39.685,-320.315)"><title
+   id="title3591">Square.120</title><desc
+   id="desc3593">1</desc><g
+   id="shadow18-84"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3596"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3598"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3600"
+   style="line-height:0%;font-family:Calibri;fill:#feffff">1</text>
+</g><g
+       id="shape18-83-1"
+       transform="translate(86.600881,-320.26392)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+   id="title3591-9">Square.120</title><desc
+   id="desc3593-4">1</desc><g
+   id="shadow18-84-7"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3596-8"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2-2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3598-4"
+   style="fill:#d8d200;stroke:#afa600;stroke-width:0.75;fill-opacity:1;stroke-opacity:1" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3600-5"
+   style="font-size:10px;line-height:0%;font-family:Calibri;fill:#feffff">1</text>
+</g><g
+       id="shape19-89"
+       transform="translate(119.055,-320.315)"><title
+   id="title3603">Square.121</title><desc
+   id="desc3605">2</desc><g
+   id="shadow19-90"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3608"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3610"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3612"
+   style="line-height:0%;font-family:Calibri;fill:#feffff;-inkscape-font-specification:'Calibri, Normal';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"><tspan
+     sodipodi:role="line"
+     id="tspan2">3</tspan></text>
+</g><g
+       id="shape19-89-6"
+       transform="translate(162.66037,-320.37407)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+   id="title3603-5">Square.121</title><desc
+   id="desc3605-6">2</desc><g
+   id="shadow19-90-9"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3608-3"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2-4)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3610-7"
+   style="fill:#d8d200;fill-opacity:1;stroke:#afa600;stroke-width:0.75;stroke-opacity:1" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3612-4"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:0%;font-family:Calibri;-inkscape-font-specification:'Calibri, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#feffff"><tspan
+     sodipodi:role="line"
+     id="tspan2-5"
+     x="4.5500002"
+     y="591.19">3</tspan></text>
+</g><g
+       id="shape20-95"
+       transform="translate(198.425,-320.315)"><title
+   id="title3615">Square.122</title><desc
+   id="desc3617">3</desc><g
+   id="shadow20-96"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3620"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3622"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3624"
+   style="line-height:0%;font-family:Calibri;fill:#feffff;-inkscape-font-specification:'Calibri, Normal';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"><tspan
+     sodipodi:role="line"
+     id="tspan4">5</tspan></text>
+</g><g
+       id="shape20-95-0"
+       transform="translate(241.29563,-320.14712)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+   id="title3615-6">Square.122</title><desc
+   id="desc3617-8">3</desc><g
+   id="shadow20-96-9"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3620-2"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2-9)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3622-6"
+   style="fill:#d8d200;stroke:#afa600;stroke-width:0.75;fill-opacity:1;stroke-opacity:1" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3624-6"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:0%;font-family:Calibri;-inkscape-font-specification:'Calibri, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#feffff"><tspan
+     sodipodi:role="line"
+     id="tspan4-4"
+     x="4.5500002"
+     y="591.19">5</tspan></text>
+</g><g
+       id="shape21-101"
+       transform="translate(39.685,-338.74)"><title
+   id="title3627">Square.123</title><desc
+   id="desc3629">4</desc><g
+   id="shadow21-102"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3632"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3634"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3636"
+   style="line-height:0%;font-family:Calibri;fill:#feffff;-inkscape-font-specification:'Calibri, Normal';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"><tspan
+     sodipodi:role="line"
+     id="tspan1">2</tspan></text>
+</g><g
+       id="shape21-101-2"
+       transform="translate(86.545022,-338.5491)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+   id="title3627-2">Square.123</title><desc
+   id="desc3629-8">4</desc><g
+   id="shadow21-102-9"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3632-7"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2-5)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3634-3"
+   style="fill:#d8d200;stroke:#afa600;stroke-width:0.75;fill-opacity:1;stroke-opacity:1" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3636-6"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:0%;font-family:Calibri;-inkscape-font-specification:'Calibri, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#feffff"><tspan
+     sodipodi:role="line"
+     id="tspan1-1"
+     x="4.5500002"
+     y="591.19">2</tspan></text>
+</g><g
+       id="shape22-107"
+       transform="translate(119.055,-338.74)"><title
+   id="title3639">Square.124</title><desc
+   id="desc3641">5</desc><g
+   id="shadow22-108"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3644"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3646"
+   style="fill:#61973d;stroke:#507e31;stroke-width:0.75" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3648"
+   style="line-height:0%;font-family:Sans;fill:#feffff;-inkscape-font-specification:'Sans, Normal';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:10px;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal"><tspan
+     sodipodi:role="line"
+     id="tspan3">4</tspan></text>
+</g><g
+       id="shape22-107-7"
+       transform="translate(162.49787,-338.73386)"
+       style="font-size:12px;overflow:visible;fill:none;stroke-linecap:square;stroke-miterlimit:3"><title
+   id="title3639-4">Square.124</title><desc
+   id="desc3641-4">5</desc><g
+   id="shadow22-108-3"
+   transform="translate(0.345598,1.97279)"
+   class="st1"
+   style="visibility:visible"><rect
+     x="0"
+     y="581.10199"
+     width="14.1732"
+     height="14.1732"
+     class="st14"
+     id="rect3644-0"
+     style="fill:#70ad47;fill-opacity:0.25;stroke:#70ad47;stroke-opacity:0.25;filter:url(#filter_2-25)" /></g><rect
+   x="0"
+   y="581.10199"
+   width="14.1732"
+   height="14.1732"
+   class="st15"
+   id="rect3646-7"
+   style="fill:#d8d200;fill-opacity:1;stroke:#afa600;stroke-width:0.75;stroke-opacity:1" /><text
+   x="4.5500002"
+   y="591.19"
+   class="st4"
+   id="text3648-8"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10px;line-height:0%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#feffff"><tspan
+     sodipodi:role="line"
+     id="tspan3-6"
+     x="4.5500002"
+     y="591.19">4</tspan></text>
+</g></g></svg>
diff --git a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
index 60717a3587..146add35a5 100644
--- a/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
+++ b/doc/guides/prog_guide/link_bonding_poll_mode_drv_lib.rst
@@ -129,6 +129,19 @@ Currently the Link Bonding PMD library supports following modes of operation:
     changes the transmitting member, according to the computed load. Statistics
     are collected in 100ms intervals and scheduled every 10ms.
 
+*   **Transmit Load Balancing (Mode 7):**
+
+.. figure:: img/bond-mode-7.*
+
+   Direct TX (Mode 7)
+
+
+    This mode is a specialized version of round robin bonding mode. It transmits
+    packets to the same member ports on which they were received (based on the
+    ``port`` attribute of ``struct rte_mbuf``). In case the port attribute does
+    not belong to any managed bonding members, this mode reverts back to round
+    robin TX mode. Note that this mode does not implement a specific RX mode,
+    instead using a round robin approach.
 
 Implementation Details
 ----------------------
-- 
2.39.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-04-12 12:27 [PATCH v2 1/2] net/bonding: introduce direct link bonding mode Kamil Vojanec
  2024-04-12 12:27 ` [PATCH v2 2/2] doc/prog_guide: document " Kamil Vojanec
@ 2024-07-05 11:27 ` Ferruh Yigit
  2024-12-04 22:21   ` Stephen Hemminger
  2024-07-10  3:49 ` lihuisong (C)
  2024-12-12 18:07 ` Stephen Hemminger
  3 siblings, 1 reply; 9+ messages in thread
From: Ferruh Yigit @ 2024-07-05 11:27 UTC (permalink / raw)
  To: Kamil Vojanec, dev; +Cc: Chas Williams, Min Hu (Connor)

On 4/12/2024 1:27 PM, Kamil Vojanec wrote:
> This patch adds a new bonding mode: 'direct'. The purpose of this mode
> is to redirect output packets to the same member port on which they were
> received. In case the requested port is not among the member ports,
> round robin TX mode is used as a fallback.
> 
> Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
>

Hi Chas, Connor,

Reminder of this patch, can you please review it?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-04-12 12:27 [PATCH v2 1/2] net/bonding: introduce direct link bonding mode Kamil Vojanec
  2024-04-12 12:27 ` [PATCH v2 2/2] doc/prog_guide: document " Kamil Vojanec
  2024-07-05 11:27 ` [PATCH v2 1/2] net/bonding: introduce " Ferruh Yigit
@ 2024-07-10  3:49 ` lihuisong (C)
  2024-07-10  5:16   ` Kamil Vojanec
  2024-12-12 18:07 ` Stephen Hemminger
  3 siblings, 1 reply; 9+ messages in thread
From: lihuisong (C) @ 2024-07-10  3:49 UTC (permalink / raw)
  To: Kamil Vojanec, dev; +Cc: Chas Williams, Min Hu (Connor), Ferruh Yigit

Hi Kamil,

在 2024/4/12 20:27, Kamil Vojanec 写道:
> This patch adds a new bonding mode: 'direct'. The purpose of this mode
> is to redirect output packets to the same member port on which they were
> received. In case the requested port is not among the member ports,
> round robin TX mode is used as a fallback.
I don't find the 'direct' mode in latest Linux. Do you have a plan to do 
this in Linux?
In addition, all the bonding mode have been supported in DPDK.
I am not sure if it is ok for us to add any new mode for our application.

IIUC, the 'direct' mode just to let the packets from one port send out 
at the same port, right?
If it is, why do you introduce this new mode? It doesn't seem to have 
anything to do with bonding.
Application also can very simply do that anyway.

/Huisong
>
> Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
> ---
>   app/test/test_link_bonding.c            | 205 ++++++++++++++++++++++++
>   drivers/net/bonding/rte_eth_bond.h      |   5 +
>   drivers/net/bonding/rte_eth_bond_args.c |   1 +
>   drivers/net/bonding/rte_eth_bond_pmd.c  |  50 +++++-
>   4 files changed, 258 insertions(+), 3 deletions(-)
>
> diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
> index 4d54706c21..254cacf5aa 100644
> --- a/app/test/test_link_bonding.c
> +++ b/app/test/test_link_bonding.c
> @@ -2134,6 +2134,208 @@ test_roundrobin_verify_polling_member_link_status_change(void)
>   	return remove_members_and_stop_bonding_device();
>   }
>   
> +/** Direct mode Tests */
> +
> +static int
> +test_direct_tx_burst_single_member(void)
> +{
> +	unsigned int i;
> +	int member_port_id;
> +	struct rte_eth_stats port_stats;
> +	struct rte_mbuf *pkts[MAX_PKT_BURST];
> +	const unsigned int burst_size = 20;
> +
> +	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
> +			"Burst size specified is greater than supported.");
> +
> +	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
> +			BONDING_MODE_DIRECT, 0, 1, 1),
> +			"Failed to initialize bonding device with single member");
> +
> +	/* Generate burst of test packets */
> +	TEST_ASSERT_EQUAL(generate_test_burst(pkts, burst_size, 0, 1, 0, 0, 0),
> +			(int) burst_size, "Failed to generate test burst");
> +
> +	member_port_id = test_params->member_port_ids[0];
> +
> +	/* Set the 'port' mbuf attribute to the appropriate value */
> +	for (i = 0; i < burst_size; i++)
> +		pkts[i]->port = member_port_id;
> +
> +	/* Send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
> +			test_params->bonding_port_id, 0, pkts, burst_size),
> +			burst_size,
> +			"TX burst failed");
> +
> +	/* Verify stats on bonding port */
> +	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
> +	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
> +			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
> +			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
> +			burst_size);
> +
> +	/* Verify stats on member port */
> +	rte_eth_stats_get(member_port_id, &port_stats);
> +	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
> +			"Member port (%d) opackets value (%u) not as expected (%u)\n",
> +			member_port_id, (unsigned int) port_stats.opackets,
> +			burst_size);
> +
> +	/* Put all members down and try to transmit */
> +	virtual_ethdev_simulate_link_status_interrupt(member_port_id, 0);
> +
> +	/* Try to send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
> +			pkts, burst_size), 0,
> +			"TX burst returned unexpected value");
> +
> +	/* Clean up and remove members from bonding device */
> +	return remove_members_and_stop_bonding_device();
> +}
> +
> +static int
> +test_direct_tx_burst_multiple_members_single_tx(void)
> +{
> +	unsigned int i;
> +	struct rte_eth_stats port_stats;
> +	struct rte_mbuf *pkts[MAX_PKT_BURST];
> +	const unsigned int num_members = 4;
> +	const unsigned int burst_size = 20;
> +	const int exp_member_port_id = test_params->member_port_ids[0];
> +	int cmember_port_id;
> +	unsigned int expected_pkts;
> +
> +
> +	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
> +			"Burst size specified is greater than supported.");
> +
> +	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
> +			BONDING_MODE_DIRECT, 0, num_members, 1),
> +			"Failed to initialize bonding device with single member");
> +
> +	/* Generate burst of test packets */
> +	TEST_ASSERT_EQUAL(generate_test_burst(
> +			pkts, burst_size, 0, 1, 0, 0, 0),
> +			(int) burst_size,
> +			"Failed to generate test burst");
> +
> +
> +	/* Set the 'port' mbuf attribute to the appropriate value */
> +	for (i = 0; i < burst_size; i++)
> +		pkts[i]->port = exp_member_port_id;
> +
> +	/* Send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
> +			test_params->bonding_port_id, 0, pkts, burst_size),
> +			burst_size,
> +			"TX burst failed");
> +
> +	/* Verify stats on bonding port */
> +	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
> +	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
> +			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
> +			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
> +			burst_size);
> +
> +	/* Verify member ports tx stats */
> +	for (i = 0; i < test_params->bonding_member_count; i++) {
> +		cmember_port_id = test_params->member_port_ids[i];
> +
> +		if (cmember_port_id == exp_member_port_id)
> +			expected_pkts = burst_size;
> +		else
> +			expected_pkts = 0;
> +
> +		rte_eth_stats_get(cmember_port_id, &port_stats);
> +		TEST_ASSERT_EQUAL(port_stats.opackets,
> +				(uint64_t)expected_pkts,
> +				"Member Port (%d) opackets value (%u) not as expected (%u)\n",
> +				test_params->bonding_port_id, (unsigned int)port_stats.opackets,
> +				expected_pkts);
> +	}
> +
> +	/* Put all members down and try and transmit */
> +	for (i = 0; i < test_params->bonding_member_count; i++) {
> +		virtual_ethdev_simulate_link_status_interrupt(
> +				test_params->member_port_ids[i], 0);
> +	}
> +
> +	/* Try to send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
> +			pkts, burst_size), 0,
> +			"TX burst returned unexpected value");
> +
> +	/* Clean up and remove members from bonding device */
> +	return remove_members_and_stop_bonding_device();
> +}
> +
> +static int
> +test_direct_tx_burst_multiple_members_rr_fallback(void)
> +{
> +	unsigned int i;
> +	struct rte_eth_stats port_stats;
> +	struct rte_mbuf *pkts[MAX_PKT_BURST];
> +	const unsigned int num_members = 4;
> +	const unsigned int pkts_per_member = 20;
> +	const unsigned int burst_size = num_members * pkts_per_member;
> +
> +
> +	TEST_ASSERT(burst_size <= MAX_PKT_BURST,
> +			"Burst size specified is greater than supported.");
> +
> +	TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
> +			BONDING_MODE_DIRECT, 0, num_members, 1),
> +			"Failed to initialize bonding device with single member");
> +
> +	/* Generate burst of test packets */
> +	TEST_ASSERT_EQUAL(generate_test_burst(
> +			pkts, burst_size, 0, 1, 0, 0, 0),
> +			(int) burst_size,
> +			"Failed to generate test burst");
> +
> +
> +	/* Set the 'port' mbuf attribute to the appropriate value */
> +	for (i = 0; i < burst_size; i++)
> +		pkts[i]->port = RTE_MAX_ETHPORTS;
> +
> +	/* Send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(
> +			test_params->bonding_port_id, 0, pkts, burst_size),
> +			burst_size,
> +			"TX burst failed");
> +
> +	/* Verify stats on bonding port */
> +	rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
> +	TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
> +			"Bonding port (%d) opackets value (%u) not as expected (%u)\n",
> +			test_params->bonding_port_id, (unsigned int) port_stats.opackets,
> +			burst_size);
> +
> +	/* Verify member ports tx stats */
> +	for (i = 0; i < test_params->bonding_member_count; i++) {
> +		rte_eth_stats_get(test_params->member_port_ids[i], &port_stats);
> +		TEST_ASSERT_EQUAL(port_stats.opackets,
> +				(uint64_t)pkts_per_member,
> +				"Member Port (%d) opackets value (%u) not as expected (%u)\n",
> +				test_params->bonding_port_id, (unsigned int)port_stats.opackets,
> +				pkts_per_member);
> +	}
> +
> +	/* Put all members down and try and transmit */
> +	for (i = 0; i < test_params->bonding_member_count; i++) {
> +		virtual_ethdev_simulate_link_status_interrupt(
> +				test_params->member_port_ids[i], 0);
> +	}
> +
> +	/* Try to send burst on bonding port */
> +	TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
> +			pkts, burst_size), 0,
> +			"TX burst returned unexpected value");
> +
> +	/* Clean up and remove members from bonding device */
> +	return remove_members_and_stop_bonding_device();
> +}
>   
>   /** Active Backup Mode Tests */
>   
> @@ -5174,6 +5376,9 @@ static struct unit_test_suite link_bonding_test_suite  = {
>   		TEST_CASE(test_roundrobin_verify_mac_assignment),
>   		TEST_CASE(test_roundrobin_verify_member_link_status_change_behaviour),
>   		TEST_CASE(test_roundrobin_verify_polling_member_link_status_change),
> +		TEST_CASE(test_direct_tx_burst_single_member),
> +		TEST_CASE(test_direct_tx_burst_multiple_members_single_tx),
> +		TEST_CASE(test_direct_tx_burst_multiple_members_rr_fallback),
>   		TEST_CASE(test_activebackup_tx_burst),
>   		TEST_CASE(test_activebackup_rx_burst),
>   		TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
> diff --git a/drivers/net/bonding/rte_eth_bond.h b/drivers/net/bonding/rte_eth_bond.h
> index f10165f2c6..82d6644500 100644
> --- a/drivers/net/bonding/rte_eth_bond.h
> +++ b/drivers/net/bonding/rte_eth_bond.h
> @@ -83,6 +83,11 @@ extern "C" {
>    * information from it. When ARP reply from that peer is received, its MAC is
>    * stored, one of member MACs assigned and ARP reply send to that peer.
>    */
> +#define BONDING_MODE_DIRECT	(7)
> +/**< Direct bonding mode (Mode 7)
> + * In this mode, all packets are transmitted using the same member port on which
> + * it was received. This is decided based on the 'port' field of 'rte_mbuf'.
> + */
>   
>   /* Balance Mode Transmit Policies */
>   #define BALANCE_XMIT_POLICY_LAYER2		(0)
> diff --git a/drivers/net/bonding/rte_eth_bond_args.c b/drivers/net/bonding/rte_eth_bond_args.c
> index bdec5d61d4..44e20568db 100644
> --- a/drivers/net/bonding/rte_eth_bond_args.c
> +++ b/drivers/net/bonding/rte_eth_bond_args.c
> @@ -158,6 +158,7 @@ bond_ethdev_parse_member_mode_kvarg(const char *key __rte_unused,
>   	case BONDING_MODE_8023AD:
>   	case BONDING_MODE_TLB:
>   	case BONDING_MODE_ALB:
> +	case BONDING_MODE_DIRECT:
>   		return 0;
>   	default:
>   		RTE_BOND_LOG(ERR, "Invalid member mode value (%s) specified", value);
> diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c b/drivers/net/bonding/rte_eth_bond_pmd.c
> index c40d18d128..57ac5879c4 100644
> --- a/drivers/net/bonding/rte_eth_bond_pmd.c
> +++ b/drivers/net/bonding/rte_eth_bond_pmd.c
> @@ -578,9 +578,14 @@ bond_ethdev_rx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
>   	return nb_recv_pkts;
>   }
>   
> +enum tx_member_populate_mode {
> +	RR_ONLY,
> +	DIRECT_WITH_RR_FALLBACK,
> +};
> +
>   static uint16_t
> -bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
> -		uint16_t nb_pkts)
> +bond_ethdev_tx_burst_rr_generic(void *queue, struct rte_mbuf **bufs,
> +		uint16_t nb_pkts, enum tx_member_populate_mode pop_mode)
>   {
>   	struct bond_dev_private *internals;
>   	struct bond_tx_queue *bd_tx_q;
> @@ -594,7 +599,7 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
>   	uint16_t num_tx_total = 0, num_tx_member;
>   
>   	static int member_idx;
> -	int i, cmember_idx = 0, tx_fail_total = 0;
> +	int i, j, cmember_idx = 0, tx_fail_total = 0;
>   
>   	bd_tx_q = (struct bond_tx_queue *)queue;
>   	internals = bd_tx_q->dev_private;
> @@ -611,6 +616,17 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
>   	/* Populate members mbuf with which packets are to be sent on it  */
>   	for (i = 0; i < nb_pkts; i++) {
>   		cmember_idx = (member_idx + i) % num_of_members;
> +
> +		if (pop_mode == DIRECT_WITH_RR_FALLBACK) {
> +			/* Try to find correct member index */
> +			for (j = 0; j < num_of_members; j++) {
> +				if (bufs[i]->port == members[j]) {
> +					cmember_idx = j;
> +					break;
> +				}
> +			}
> +		}
> +
>   		member_bufs[cmember_idx][(member_nb_pkts[cmember_idx])++] = bufs[i];
>   	}
>   
> @@ -646,6 +662,20 @@ bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
>   	return num_tx_total;
>   }
>   
> +static uint16_t
> +bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
> +		uint16_t nb_pkts)
> +{
> +	return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, RR_ONLY);
> +}
> +
> +static uint16_t
> +bond_ethdev_tx_burst_direct(void *queue, struct rte_mbuf **bufs,
> +		uint16_t nb_pkts)
> +{
> +	return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, DIRECT_WITH_RR_FALLBACK);
> +}
> +
>   static uint16_t
>   bond_ethdev_tx_burst_active_backup(void *queue,
>   		struct rte_mbuf **bufs, uint16_t nb_pkts)
> @@ -1551,6 +1581,7 @@ mac_address_members_update(struct rte_eth_dev *bonding_eth_dev)
>   	case BONDING_MODE_ROUND_ROBIN:
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
> +	case BONDING_MODE_DIRECT:
>   		for (i = 0; i < internals->member_count; i++) {
>   			if (rte_eth_dev_default_mac_addr_set(
>   					internals->members[i].port_id,
> @@ -1648,6 +1679,10 @@ bond_ethdev_mode_set(struct rte_eth_dev *eth_dev, uint8_t mode)
>   		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb;
>   		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb;
>   		break;
> +	case BONDING_MODE_DIRECT:
> +		eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_direct;
> +		eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
> +		break;
>   	default:
>   		return -1;
>   	}
> @@ -2581,6 +2616,7 @@ bond_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_TLB:
>   	case BONDING_MODE_ALB:
> +	case BONDING_MODE_DIRECT:
>   	default:
>   		/**
>   		 * In theses mode the maximum theoretical link speed is the sum
> @@ -2678,6 +2714,7 @@ bond_ethdev_promiscuous_enable(struct rte_eth_dev *eth_dev)
>   	case BONDING_MODE_ROUND_ROBIN:
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
> +	case BONDING_MODE_DIRECT:
>   	case BONDING_MODE_8023AD: {
>   		unsigned int member_ok = 0;
>   
> @@ -2732,6 +2769,7 @@ bond_ethdev_promiscuous_disable(struct rte_eth_dev *dev)
>   	case BONDING_MODE_ROUND_ROBIN:
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
> +	case BONDING_MODE_DIRECT:
>   	case BONDING_MODE_8023AD: {
>   		unsigned int member_ok = 0;
>   
> @@ -2790,6 +2828,7 @@ bond_ethdev_promiscuous_update(struct rte_eth_dev *dev)
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
>   	case BONDING_MODE_8023AD:
> +	case BONDING_MODE_DIRECT:
>   		/* As promiscuous mode is propagated to all members for these
>   		 * mode, no need to update for bonding device.
>   		 */
> @@ -2825,6 +2864,7 @@ bond_ethdev_allmulticast_enable(struct rte_eth_dev *eth_dev)
>   	case BONDING_MODE_ROUND_ROBIN:
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
> +	case BONDING_MODE_DIRECT:
>   	case BONDING_MODE_8023AD: {
>   		unsigned int member_ok = 0;
>   
> @@ -2879,6 +2919,7 @@ bond_ethdev_allmulticast_disable(struct rte_eth_dev *eth_dev)
>   	case BONDING_MODE_ROUND_ROBIN:
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
> +	case BONDING_MODE_DIRECT:
>   	case BONDING_MODE_8023AD: {
>   		unsigned int member_ok = 0;
>   
> @@ -2936,6 +2977,7 @@ bond_ethdev_allmulticast_update(struct rte_eth_dev *dev)
>   	case BONDING_MODE_BALANCE:
>   	case BONDING_MODE_BROADCAST:
>   	case BONDING_MODE_8023AD:
> +	case BONDING_MODE_DIRECT:
>   		/* As allmulticast mode is propagated to all members for these
>   		 * mode, no need to update for bonding device.
>   		 */
> @@ -3365,6 +3407,8 @@ bond_mode_name(uint8_t mode)
>   		return "TLB";
>   	case BONDING_MODE_ALB:
>   		return "ALB";
> +	case BONDING_MODE_DIRECT:
> +		return "DIRECT";
>   	default:
>   		return "Unknown";
>   	}

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-07-10  3:49 ` lihuisong (C)
@ 2024-07-10  5:16   ` Kamil Vojanec
  2024-12-03 18:18     ` Stephen Hemminger
  0 siblings, 1 reply; 9+ messages in thread
From: Kamil Vojanec @ 2024-07-10  5:16 UTC (permalink / raw)
  To: lihuisong (C), dev; +Cc: Chas Williams, Min Hu (Connor), Ferruh Yigit

[-- Attachment #1: Type: text/plain, Size: 21267 bytes --]

Hi,

> I don't find the 'direct' mode in latest Linux. Do you have a plan to 
> do this in Linux
No, I was not planning on any Linux kernel contributions.
> IIUC, the 'direct' mode just to let the packets from one port send out 
> at the same port, right?
> If it is, why do you introduce this new mode? It doesn't seem to have 
> anything to do with bonding. 
Indeed, the base functionality is to forward packets to the same port 
they were received on. The main use-case is to allow applications use 
one aggregated (bonding) port ensure that packet forwarding is always 
the same.

I find it a lot simpler to use a bonding port whenever I have an 
application that uses multiple ports. It means I don't have to 
configure, start and stop all the ports; the bonding PMD is a perfect 
abstraction for that.

Kamil

On 7/10/24 05:49, lihuisong (C) wrote:
> Hi Kamil,
>
> 在 2024/4/12 20:27, Kamil Vojanec 写道:
>> This patch adds a new bonding mode: 'direct'. The purpose of this mode
>> is to redirect output packets to the same member port on which they were
>> received. In case the requested port is not among the member ports,
>> round robin TX mode is used as a fallback.
> I don't find the 'direct' mode in latest Linux. Do you have a plan to 
> do this in Linux?
> In addition, all the bonding mode have been supported in DPDK.
> I am not sure if it is ok for us to add any new mode for our application.
>
> IIUC, the 'direct' mode just to let the packets from one port send out 
> at the same port, right?
> If it is, why do you introduce this new mode? It doesn't seem to have 
> anything to do with bonding.
> Application also can very simply do that anyway.
>
> /Huisong
>>
>> Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
>> ---
>>   app/test/test_link_bonding.c            | 205 ++++++++++++++++++++++++
>>   drivers/net/bonding/rte_eth_bond.h      |   5 +
>>   drivers/net/bonding/rte_eth_bond_args.c |   1 +
>>   drivers/net/bonding/rte_eth_bond_pmd.c  |  50 +++++-
>>   4 files changed, 258 insertions(+), 3 deletions(-)
>>
>> diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
>> index 4d54706c21..254cacf5aa 100644
>> --- a/app/test/test_link_bonding.c
>> +++ b/app/test/test_link_bonding.c
>> @@ -2134,6 +2134,208 @@ 
>> test_roundrobin_verify_polling_member_link_status_change(void)
>>       return remove_members_and_stop_bonding_device();
>>   }
>>   +/** Direct mode Tests */
>> +
>> +static int
>> +test_direct_tx_burst_single_member(void)
>> +{
>> +    unsigned int i;
>> +    int member_port_id;
>> +    struct rte_eth_stats port_stats;
>> +    struct rte_mbuf *pkts[MAX_PKT_BURST];
>> +    const unsigned int burst_size = 20;
>> +
>> +    TEST_ASSERT(burst_size <= MAX_PKT_BURST,
>> +            "Burst size specified is greater than supported.");
>> +
>> +    TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
>> +            BONDING_MODE_DIRECT, 0, 1, 1),
>> +            "Failed to initialize bonding device with single member");
>> +
>> +    /* Generate burst of test packets */
>> +    TEST_ASSERT_EQUAL(generate_test_burst(pkts, burst_size, 0, 1, 0, 
>> 0, 0),
>> +            (int) burst_size, "Failed to generate test burst");
>> +
>> +    member_port_id = test_params->member_port_ids[0];
>> +
>> +    /* Set the 'port' mbuf attribute to the appropriate value */
>> +    for (i = 0; i < burst_size; i++)
>> +        pkts[i]->port = member_port_id;
>> +
>> +    /* Send burst on bonding port */
>> +    TEST_ASSERT_EQUAL(rte_eth_tx_burst(
>> +            test_params->bonding_port_id, 0, pkts, burst_size),
>> +            burst_size,
>> +            "TX burst failed");
>> +
>> +    /* Verify stats on bonding port */
>> +    rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
>> +    TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
>> +            "Bonding port (%d) opackets value (%u) not as expected 
>> (%u)\n",
>> +            test_params->bonding_port_id, (unsigned int) 
>> port_stats.opackets,
>> +            burst_size);
>> +
>> +    /* Verify stats on member port */
>> +    rte_eth_stats_get(member_port_id, &port_stats);
>> +    TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
>> +            "Member port (%d) opackets value (%u) not as expected 
>> (%u)\n",
>> +            member_port_id, (unsigned int) port_stats.opackets,
>> +            burst_size);
>> +
>> +    /* Put all members down and try to transmit */
>> + virtual_ethdev_simulate_link_status_interrupt(member_port_id, 0);
>> +
>> +    /* Try to send burst on bonding port */
>> + TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
>> +            pkts, burst_size), 0,
>> +            "TX burst returned unexpected value");
>> +
>> +    /* Clean up and remove members from bonding device */
>> +    return remove_members_and_stop_bonding_device();
>> +}
>> +
>> +static int
>> +test_direct_tx_burst_multiple_members_single_tx(void)
>> +{
>> +    unsigned int i;
>> +    struct rte_eth_stats port_stats;
>> +    struct rte_mbuf *pkts[MAX_PKT_BURST];
>> +    const unsigned int num_members = 4;
>> +    const unsigned int burst_size = 20;
>> +    const int exp_member_port_id = test_params->member_port_ids[0];
>> +    int cmember_port_id;
>> +    unsigned int expected_pkts;
>> +
>> +
>> +    TEST_ASSERT(burst_size <= MAX_PKT_BURST,
>> +            "Burst size specified is greater than supported.");
>> +
>> +    TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
>> +            BONDING_MODE_DIRECT, 0, num_members, 1),
>> +            "Failed to initialize bonding device with single member");
>> +
>> +    /* Generate burst of test packets */
>> +    TEST_ASSERT_EQUAL(generate_test_burst(
>> +            pkts, burst_size, 0, 1, 0, 0, 0),
>> +            (int) burst_size,
>> +            "Failed to generate test burst");
>> +
>> +
>> +    /* Set the 'port' mbuf attribute to the appropriate value */
>> +    for (i = 0; i < burst_size; i++)
>> +        pkts[i]->port = exp_member_port_id;
>> +
>> +    /* Send burst on bonding port */
>> +    TEST_ASSERT_EQUAL(rte_eth_tx_burst(
>> +            test_params->bonding_port_id, 0, pkts, burst_size),
>> +            burst_size,
>> +            "TX burst failed");
>> +
>> +    /* Verify stats on bonding port */
>> +    rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
>> +    TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
>> +            "Bonding port (%d) opackets value (%u) not as expected 
>> (%u)\n",
>> +            test_params->bonding_port_id, (unsigned int) 
>> port_stats.opackets,
>> +            burst_size);
>> +
>> +    /* Verify member ports tx stats */
>> +    for (i = 0; i < test_params->bonding_member_count; i++) {
>> +        cmember_port_id = test_params->member_port_ids[i];
>> +
>> +        if (cmember_port_id == exp_member_port_id)
>> +            expected_pkts = burst_size;
>> +        else
>> +            expected_pkts = 0;
>> +
>> +        rte_eth_stats_get(cmember_port_id, &port_stats);
>> +        TEST_ASSERT_EQUAL(port_stats.opackets,
>> +                (uint64_t)expected_pkts,
>> +                "Member Port (%d) opackets value (%u) not as 
>> expected (%u)\n",
>> +                test_params->bonding_port_id, (unsigned 
>> int)port_stats.opackets,
>> +                expected_pkts);
>> +    }
>> +
>> +    /* Put all members down and try and transmit */
>> +    for (i = 0; i < test_params->bonding_member_count; i++) {
>> +        virtual_ethdev_simulate_link_status_interrupt(
>> +                test_params->member_port_ids[i], 0);
>> +    }
>> +
>> +    /* Try to send burst on bonding port */
>> + TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
>> +            pkts, burst_size), 0,
>> +            "TX burst returned unexpected value");
>> +
>> +    /* Clean up and remove members from bonding device */
>> +    return remove_members_and_stop_bonding_device();
>> +}
>> +
>> +static int
>> +test_direct_tx_burst_multiple_members_rr_fallback(void)
>> +{
>> +    unsigned int i;
>> +    struct rte_eth_stats port_stats;
>> +    struct rte_mbuf *pkts[MAX_PKT_BURST];
>> +    const unsigned int num_members = 4;
>> +    const unsigned int pkts_per_member = 20;
>> +    const unsigned int burst_size = num_members * pkts_per_member;
>> +
>> +
>> +    TEST_ASSERT(burst_size <= MAX_PKT_BURST,
>> +            "Burst size specified is greater than supported.");
>> +
>> +    TEST_ASSERT_SUCCESS(initialize_bonding_device_with_members(
>> +            BONDING_MODE_DIRECT, 0, num_members, 1),
>> +            "Failed to initialize bonding device with single member");
>> +
>> +    /* Generate burst of test packets */
>> +    TEST_ASSERT_EQUAL(generate_test_burst(
>> +            pkts, burst_size, 0, 1, 0, 0, 0),
>> +            (int) burst_size,
>> +            "Failed to generate test burst");
>> +
>> +
>> +    /* Set the 'port' mbuf attribute to the appropriate value */
>> +    for (i = 0; i < burst_size; i++)
>> +        pkts[i]->port = RTE_MAX_ETHPORTS;
>> +
>> +    /* Send burst on bonding port */
>> +    TEST_ASSERT_EQUAL(rte_eth_tx_burst(
>> +            test_params->bonding_port_id, 0, pkts, burst_size),
>> +            burst_size,
>> +            "TX burst failed");
>> +
>> +    /* Verify stats on bonding port */
>> +    rte_eth_stats_get(test_params->bonding_port_id, &port_stats);
>> +    TEST_ASSERT_EQUAL(port_stats.opackets, burst_size,
>> +            "Bonding port (%d) opackets value (%u) not as expected 
>> (%u)\n",
>> +            test_params->bonding_port_id, (unsigned int) 
>> port_stats.opackets,
>> +            burst_size);
>> +
>> +    /* Verify member ports tx stats */
>> +    for (i = 0; i < test_params->bonding_member_count; i++) {
>> +        rte_eth_stats_get(test_params->member_port_ids[i], 
>> &port_stats);
>> +        TEST_ASSERT_EQUAL(port_stats.opackets,
>> +                (uint64_t)pkts_per_member,
>> +                "Member Port (%d) opackets value (%u) not as 
>> expected (%u)\n",
>> +                test_params->bonding_port_id, (unsigned 
>> int)port_stats.opackets,
>> +                pkts_per_member);
>> +    }
>> +
>> +    /* Put all members down and try and transmit */
>> +    for (i = 0; i < test_params->bonding_member_count; i++) {
>> +        virtual_ethdev_simulate_link_status_interrupt(
>> +                test_params->member_port_ids[i], 0);
>> +    }
>> +
>> +    /* Try to send burst on bonding port */
>> + TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonding_port_id, 0,
>> +            pkts, burst_size), 0,
>> +            "TX burst returned unexpected value");
>> +
>> +    /* Clean up and remove members from bonding device */
>> +    return remove_members_and_stop_bonding_device();
>> +}
>>     /** Active Backup Mode Tests */
>>   @@ -5174,6 +5376,9 @@ static struct unit_test_suite 
>> link_bonding_test_suite  = {
>>           TEST_CASE(test_roundrobin_verify_mac_assignment),
>> TEST_CASE(test_roundrobin_verify_member_link_status_change_behaviour),
>> TEST_CASE(test_roundrobin_verify_polling_member_link_status_change),
>> +        TEST_CASE(test_direct_tx_burst_single_member),
>> + TEST_CASE(test_direct_tx_burst_multiple_members_single_tx),
>> + TEST_CASE(test_direct_tx_burst_multiple_members_rr_fallback),
>>           TEST_CASE(test_activebackup_tx_burst),
>>           TEST_CASE(test_activebackup_rx_burst),
>> TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
>> diff --git a/drivers/net/bonding/rte_eth_bond.h 
>> b/drivers/net/bonding/rte_eth_bond.h
>> index f10165f2c6..82d6644500 100644
>> --- a/drivers/net/bonding/rte_eth_bond.h
>> +++ b/drivers/net/bonding/rte_eth_bond.h
>> @@ -83,6 +83,11 @@ extern "C" {
>>    * information from it. When ARP reply from that peer is received, 
>> its MAC is
>>    * stored, one of member MACs assigned and ARP reply send to that 
>> peer.
>>    */
>> +#define BONDING_MODE_DIRECT    (7)
>> +/**< Direct bonding mode (Mode 7)
>> + * In this mode, all packets are transmitted using the same member 
>> port on which
>> + * it was received. This is decided based on the 'port' field of 
>> 'rte_mbuf'.
>> + */
>>     /* Balance Mode Transmit Policies */
>>   #define BALANCE_XMIT_POLICY_LAYER2        (0)
>> diff --git a/drivers/net/bonding/rte_eth_bond_args.c 
>> b/drivers/net/bonding/rte_eth_bond_args.c
>> index bdec5d61d4..44e20568db 100644
>> --- a/drivers/net/bonding/rte_eth_bond_args.c
>> +++ b/drivers/net/bonding/rte_eth_bond_args.c
>> @@ -158,6 +158,7 @@ bond_ethdev_parse_member_mode_kvarg(const char 
>> *key __rte_unused,
>>       case BONDING_MODE_8023AD:
>>       case BONDING_MODE_TLB:
>>       case BONDING_MODE_ALB:
>> +    case BONDING_MODE_DIRECT:
>>           return 0;
>>       default:
>>           RTE_BOND_LOG(ERR, "Invalid member mode value (%s) 
>> specified", value);
>> diff --git a/drivers/net/bonding/rte_eth_bond_pmd.c 
>> b/drivers/net/bonding/rte_eth_bond_pmd.c
>> index c40d18d128..57ac5879c4 100644
>> --- a/drivers/net/bonding/rte_eth_bond_pmd.c
>> +++ b/drivers/net/bonding/rte_eth_bond_pmd.c
>> @@ -578,9 +578,14 @@ bond_ethdev_rx_burst_alb(void *queue, struct 
>> rte_mbuf **bufs, uint16_t nb_pkts)
>>       return nb_recv_pkts;
>>   }
>>   +enum tx_member_populate_mode {
>> +    RR_ONLY,
>> +    DIRECT_WITH_RR_FALLBACK,
>> +};
>> +
>>   static uint16_t
>> -bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
>> -        uint16_t nb_pkts)
>> +bond_ethdev_tx_burst_rr_generic(void *queue, struct rte_mbuf **bufs,
>> +        uint16_t nb_pkts, enum tx_member_populate_mode pop_mode)
>>   {
>>       struct bond_dev_private *internals;
>>       struct bond_tx_queue *bd_tx_q;
>> @@ -594,7 +599,7 @@ bond_ethdev_tx_burst_round_robin(void *queue, 
>> struct rte_mbuf **bufs,
>>       uint16_t num_tx_total = 0, num_tx_member;
>>         static int member_idx;
>> -    int i, cmember_idx = 0, tx_fail_total = 0;
>> +    int i, j, cmember_idx = 0, tx_fail_total = 0;
>>         bd_tx_q = (struct bond_tx_queue *)queue;
>>       internals = bd_tx_q->dev_private;
>> @@ -611,6 +616,17 @@ bond_ethdev_tx_burst_round_robin(void *queue, 
>> struct rte_mbuf **bufs,
>>       /* Populate members mbuf with which packets are to be sent on 
>> it  */
>>       for (i = 0; i < nb_pkts; i++) {
>>           cmember_idx = (member_idx + i) % num_of_members;
>> +
>> +        if (pop_mode == DIRECT_WITH_RR_FALLBACK) {
>> +            /* Try to find correct member index */
>> +            for (j = 0; j < num_of_members; j++) {
>> +                if (bufs[i]->port == members[j]) {
>> +                    cmember_idx = j;
>> +                    break;
>> +                }
>> +            }
>> +        }
>> +
>> member_bufs[cmember_idx][(member_nb_pkts[cmember_idx])++] = bufs[i];
>>       }
>>   @@ -646,6 +662,20 @@ bond_ethdev_tx_burst_round_robin(void *queue, 
>> struct rte_mbuf **bufs,
>>       return num_tx_total;
>>   }
>>   +static uint16_t
>> +bond_ethdev_tx_burst_round_robin(void *queue, struct rte_mbuf **bufs,
>> +        uint16_t nb_pkts)
>> +{
>> +    return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, 
>> RR_ONLY);
>> +}
>> +
>> +static uint16_t
>> +bond_ethdev_tx_burst_direct(void *queue, struct rte_mbuf **bufs,
>> +        uint16_t nb_pkts)
>> +{
>> +    return bond_ethdev_tx_burst_rr_generic(queue, bufs, nb_pkts, 
>> DIRECT_WITH_RR_FALLBACK);
>> +}
>> +
>>   static uint16_t
>>   bond_ethdev_tx_burst_active_backup(void *queue,
>>           struct rte_mbuf **bufs, uint16_t nb_pkts)
>> @@ -1551,6 +1581,7 @@ mac_address_members_update(struct rte_eth_dev 
>> *bonding_eth_dev)
>>       case BONDING_MODE_ROUND_ROBIN:
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>> +    case BONDING_MODE_DIRECT:
>>           for (i = 0; i < internals->member_count; i++) {
>>               if (rte_eth_dev_default_mac_addr_set(
>>                       internals->members[i].port_id,
>> @@ -1648,6 +1679,10 @@ bond_ethdev_mode_set(struct rte_eth_dev 
>> *eth_dev, uint8_t mode)
>>           eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_alb;
>>           eth_dev->rx_pkt_burst = bond_ethdev_rx_burst_alb;
>>           break;
>> +    case BONDING_MODE_DIRECT:
>> +        eth_dev->tx_pkt_burst = bond_ethdev_tx_burst_direct;
>> +        eth_dev->rx_pkt_burst = bond_ethdev_rx_burst;
>> +        break;
>>       default:
>>           return -1;
>>       }
>> @@ -2581,6 +2616,7 @@ bond_ethdev_link_update(struct rte_eth_dev 
>> *ethdev, int wait_to_complete)
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_TLB:
>>       case BONDING_MODE_ALB:
>> +    case BONDING_MODE_DIRECT:
>>       default:
>>           /**
>>            * In theses mode the maximum theoretical link speed is the 
>> sum
>> @@ -2678,6 +2714,7 @@ bond_ethdev_promiscuous_enable(struct 
>> rte_eth_dev *eth_dev)
>>       case BONDING_MODE_ROUND_ROBIN:
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>> +    case BONDING_MODE_DIRECT:
>>       case BONDING_MODE_8023AD: {
>>           unsigned int member_ok = 0;
>>   @@ -2732,6 +2769,7 @@ bond_ethdev_promiscuous_disable(struct 
>> rte_eth_dev *dev)
>>       case BONDING_MODE_ROUND_ROBIN:
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>> +    case BONDING_MODE_DIRECT:
>>       case BONDING_MODE_8023AD: {
>>           unsigned int member_ok = 0;
>>   @@ -2790,6 +2828,7 @@ bond_ethdev_promiscuous_update(struct 
>> rte_eth_dev *dev)
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>>       case BONDING_MODE_8023AD:
>> +    case BONDING_MODE_DIRECT:
>>           /* As promiscuous mode is propagated to all members for these
>>            * mode, no need to update for bonding device.
>>            */
>> @@ -2825,6 +2864,7 @@ bond_ethdev_allmulticast_enable(struct 
>> rte_eth_dev *eth_dev)
>>       case BONDING_MODE_ROUND_ROBIN:
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>> +    case BONDING_MODE_DIRECT:
>>       case BONDING_MODE_8023AD: {
>>           unsigned int member_ok = 0;
>>   @@ -2879,6 +2919,7 @@ bond_ethdev_allmulticast_disable(struct 
>> rte_eth_dev *eth_dev)
>>       case BONDING_MODE_ROUND_ROBIN:
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>> +    case BONDING_MODE_DIRECT:
>>       case BONDING_MODE_8023AD: {
>>           unsigned int member_ok = 0;
>>   @@ -2936,6 +2977,7 @@ bond_ethdev_allmulticast_update(struct 
>> rte_eth_dev *dev)
>>       case BONDING_MODE_BALANCE:
>>       case BONDING_MODE_BROADCAST:
>>       case BONDING_MODE_8023AD:
>> +    case BONDING_MODE_DIRECT:
>>           /* As allmulticast mode is propagated to all members for these
>>            * mode, no need to update for bonding device.
>>            */
>> @@ -3365,6 +3407,8 @@ bond_mode_name(uint8_t mode)
>>           return "TLB";
>>       case BONDING_MODE_ALB:
>>           return "ALB";
>> +    case BONDING_MODE_DIRECT:
>> +        return "DIRECT";
>>       default:
>>           return "Unknown";
>>       }

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4319 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-07-10  5:16   ` Kamil Vojanec
@ 2024-12-03 18:18     ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2024-12-03 18:18 UTC (permalink / raw)
  To: Kamil Vojanec
  Cc: lihuisong (C), dev, Chas Williams, Min Hu (Connor), Ferruh Yigit

On Wed, 10 Jul 2024 07:16:58 +0200
Kamil Vojanec <vojanec@cesnet.cz> wrote:

> Hi,
> 
> > I don't find the 'direct' mode in latest Linux. Do you have a plan to 
> > do this in Linux  
> No, I was not planning on any Linux kernel contributions.
> > IIUC, the 'direct' mode just to let the packets from one port send out 
> > at the same port, right?
> > If it is, why do you introduce this new mode? It doesn't seem to have 
> > anything to do with bonding.   
> Indeed, the base functionality is to forward packets to the same port 
> they were received on. The main use-case is to allow applications use 
> one aggregated (bonding) port ensure that packet forwarding is always 
> the same.
> 
> I find it a lot simpler to use a bonding port whenever I have an 
> application that uses multiple ports. It means I don't have to 
> configure, start and stop all the ports; the bonding PMD is a perfect 
> abstraction for that.
> 
> Kamil

There is overlap between bonding and bridging especially when used as leaf.
This use case sounds like a new driver, rather than dog piling more features
on already complex bridge device. Maybe a new simple bridge PMD would
be more appropriate.

Alternatively, the user transmit policy callback could be an option?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-07-05 11:27 ` [PATCH v2 1/2] net/bonding: introduce " Ferruh Yigit
@ 2024-12-04 22:21   ` Stephen Hemminger
  0 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2024-12-04 22:21 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: Kamil Vojanec, dev, Chas Williams, Min Hu (Connor)

On Fri, 5 Jul 2024 12:27:55 +0100
Ferruh Yigit <ferruh.yigit@amd.com> wrote:

> On 4/12/2024 1:27 PM, Kamil Vojanec wrote:
> > This patch adds a new bonding mode: 'direct'. The purpose of this mode
> > is to redirect output packets to the same member port on which they were
> > received. In case the requested port is not among the member ports,
> > round robin TX mode is used as a fallback.
> > 
> > Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
> >  
> 
> Hi Chas, Connor,
> 
> Reminder of this patch, can you please review it?

Is one of the bonding maintainers available to look at this?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-04-12 12:27 [PATCH v2 1/2] net/bonding: introduce direct link bonding mode Kamil Vojanec
                   ` (2 preceding siblings ...)
  2024-07-10  3:49 ` lihuisong (C)
@ 2024-12-12 18:07 ` Stephen Hemminger
  2024-12-13  2:37   ` lihuisong (C)
  3 siblings, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2024-12-12 18:07 UTC (permalink / raw)
  To: Kamil Vojanec; +Cc: dev, Chas Williams, Min Hu (Connor)

On Fri, 12 Apr 2024 14:27:39 +0200
Kamil Vojanec <vojanec@cesnet.cz> wrote:

> This patch adds a new bonding mode: 'direct'. The purpose of this mode
> is to redirect output packets to the same member port on which they were
> received. In case the requested port is not among the member ports,
> round robin TX mode is used as a fallback.
> 
> Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
> ---

This patch appears stuck. It is introducing a special new mode which really
doesn't exactly fit the normal use of a bonding type device.

Could the bonding maintainers review please.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/2] net/bonding: introduce direct link bonding mode
  2024-12-12 18:07 ` Stephen Hemminger
@ 2024-12-13  2:37   ` lihuisong (C)
  0 siblings, 0 replies; 9+ messages in thread
From: lihuisong (C) @ 2024-12-13  2:37 UTC (permalink / raw)
  To: Kamil Vojanec; +Cc: dev, Chas Williams, Min Hu (Connor), Stephen Hemminger


在 2024/12/13 2:07, Stephen Hemminger 写道:
> On Fri, 12 Apr 2024 14:27:39 +0200
> Kamil Vojanec <vojanec@cesnet.cz> wrote:
>
>> This patch adds a new bonding mode: 'direct'. The purpose of this mode
>> is to redirect output packets to the same member port on which they were
>> received. In case the requested port is not among the member ports,
>> round robin TX mode is used as a fallback.
>>
>> Signed-off-by: Kamil Vojanec <vojanec@cesnet.cz>
>> ---
> This patch appears stuck. It is introducing a special new mode which really
> doesn't exactly fit the normal use of a bonding type device.
I also reviewed this patch before.
The 'direct' mode is just to let the packets from one port send out at 
the same port.
It doesn't seem to have anything to do with bonding, because application 
also can do it.
In addition, it is not a well-known bonding mode and has no plan on 
Linux kernel.
If it is needed, I agree with Stephen's proposal that using transmit 
policy callback.
>
> Could the bonding maintainers review please.
> .

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-12-13  2:37 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-12 12:27 [PATCH v2 1/2] net/bonding: introduce direct link bonding mode Kamil Vojanec
2024-04-12 12:27 ` [PATCH v2 2/2] doc/prog_guide: document " Kamil Vojanec
2024-07-05 11:27 ` [PATCH v2 1/2] net/bonding: introduce " Ferruh Yigit
2024-12-04 22:21   ` Stephen Hemminger
2024-07-10  3:49 ` lihuisong (C)
2024-07-10  5:16   ` Kamil Vojanec
2024-12-03 18:18     ` Stephen Hemminger
2024-12-12 18:07 ` Stephen Hemminger
2024-12-13  2:37   ` lihuisong (C)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).