All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: Robin Jarry <rjarry@redhat.com>
Cc: dev@dpdk.org
Subject: Re: [PATCH dpdk v3] net/tap: add software MAC address filtering
Date: Sat, 21 Mar 2026 16:20:57 -0700	[thread overview]
Message-ID: <20260321162057.09dbd5fc@phoenix.local> (raw)
In-Reply-To: <20260321144840.863746-2-rjarry@redhat.com>

On Sat, 21 Mar 2026 15:48:40 +0100
Robin Jarry <rjarry@redhat.com> wrote:

> Linux TAP devices deliver all packets to userspace regardless of the
> PROMISC/ALLMULTI flags on the interface. When promiscuous mode is
> disabled, drop received packets whose destination MAC does not match
> any configured unicast or multicast address.
> 
> The receive path checks the destination MAC against the device's
> unicast address table (managed by the ethdev layer), the multicast
> address list (stored by the driver since the ethdev layer does not keep
> a copy), and accepts broadcast unconditionally. Promiscuous and
> all-multicast modes bypass the respective checks.
> 
> To support multiple unicast addresses via rte_eth_dev_mac_addr_add(),
> allocate mac_addrs with rte_zmalloc (TAP_MAX_MAC_ADDRS=16) instead of
> pointing into dev_private, and advertise the new limit in dev_infos_get.
> 
> Dropped packets are reported via per-queue xstats
> (rx_q<N>_mac_filter_drops).
> 
> Signed-off-by: Robin Jarry <rjarry@redhat.com>
> ---

Here is a test for this.

From f1f093323a713abdfeb36a486a16b4b816095953 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Sat, 21 Mar 2026 16:14:00 -0700
Subject: [PATCH 2/2] net/tap: add tests for software MAC address filtering

Extend the TAP PMD test suite to cover the new MAC filtering API.
Verify that dev_info advertises multiple unicast addresses,
mac_addr_add/remove and set_mc_addr_list work correctly,
and mac_filter_drops xstats are present and reset properly.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/test_pmd_tap.c | 133 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/app/test/test_pmd_tap.c b/app/test/test_pmd_tap.c
index dabd7d3506..bd3d4a64cc 100644
--- a/app/test/test_pmd_tap.c
+++ b/app/test/test_pmd_tap.c
@@ -757,6 +757,135 @@ test_tap_setup(void)
 	return 0;
 }
 
+/*
+ * MAC address filtering tests.
+ *
+ * These exercise the new software MAC filtering paths added to TAP:
+ * mac_addr_add/remove, set_mc_addr_list, xstats for mac_filter_drops,
+ * and the increased max_mac_addrs reported in dev_info.
+ */
+
+static int
+test_tap_mac_filter_info(void)
+{
+	struct rte_eth_dev_info dev_info;
+
+	TEST_ASSERT_SUCCESS(rte_eth_dev_info_get(tap_port0, &dev_info),
+			    "failed to get dev info");
+	TEST_ASSERT(dev_info.max_mac_addrs >= 16,
+		    "max_mac_addrs=%u, expected >= 16",
+		    dev_info.max_mac_addrs);
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_tap_mac_addr_ops(void)
+{
+	struct rte_ether_addr addr, addr2;
+
+	rte_eth_random_addr(addr.addr_bytes);
+	rte_eth_random_addr(addr2.addr_bytes);
+
+	TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(tap_port0, &addr, 0),
+			    "mac_addr_add first address failed");
+	TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(tap_port0, &addr2, 0),
+			    "mac_addr_add second address failed");
+
+	rte_eth_dev_mac_addr_remove(tap_port0, &addr2);
+	rte_eth_dev_mac_addr_remove(tap_port0, &addr);
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_tap_mc_addr_list(void)
+{
+	struct rte_ether_addr mc_addrs[3];
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		rte_eth_random_addr(mc_addrs[i].addr_bytes);
+		mc_addrs[i].addr_bytes[0] |= RTE_ETHER_GROUP_ADDR;
+	}
+
+	TEST_ASSERT_SUCCESS(rte_eth_dev_set_mc_addr_list(tap_port0, mc_addrs, 3),
+			    "set_mc_addr_list(3) failed");
+	TEST_ASSERT_SUCCESS(rte_eth_dev_set_mc_addr_list(tap_port0, mc_addrs, 1),
+			    "set_mc_addr_list(1) failed");
+	TEST_ASSERT_SUCCESS(rte_eth_dev_set_mc_addr_list(tap_port0, NULL, 0),
+			    "set_mc_addr_list(0) failed");
+
+	return TEST_SUCCESS;
+}
+
+static int
+test_tap_xstats_mac_filter(void)
+{
+	struct rte_eth_xstat_name *names = NULL;
+	struct rte_eth_xstat *xstats = NULL;
+	int nb_xstats, ret, i;
+	int found = 0;
+	int result = TEST_FAILED;
+
+	nb_xstats = rte_eth_xstats_get_names(tap_port0, NULL, 0);
+	TEST_ASSERT(nb_xstats > 0,
+		    "expected at least 1 xstat, got %d", nb_xstats);
+
+	names = calloc(nb_xstats, sizeof(*names));
+	xstats = calloc(nb_xstats, sizeof(*xstats));
+	if (names == NULL || xstats == NULL) {
+		printf("Error: failed to allocate xstats arrays\n");
+		goto out;
+	}
+
+	ret = rte_eth_xstats_get_names(tap_port0, names, nb_xstats);
+	if (ret != nb_xstats) {
+		printf("Error: xstats_get_names returned %d, expected %d\n",
+		       ret, nb_xstats);
+		goto out;
+	}
+
+	/* Verify at least one mac_filter_drops counter exists */
+	for (i = 0; i < nb_xstats; i++) {
+		if (strstr(names[i].name, "mac_filter_drops") != NULL)
+			found++;
+	}
+	if (found == 0) {
+		printf("Error: no mac_filter_drops xstat found\n");
+		goto out;
+	}
+
+	/* Reset and verify the mac_filter_drops counters are zero */
+	if (rte_eth_xstats_reset(tap_port0) != 0) {
+		printf("Error: xstats_reset failed\n");
+		goto out;
+	}
+
+	ret = rte_eth_xstats_get(tap_port0, xstats, nb_xstats);
+	if (ret != nb_xstats) {
+		printf("Error: xstats_get after reset returned %d\n", ret);
+		goto out;
+	}
+
+	for (i = 0; i < nb_xstats; i++) {
+		if (strstr(names[i].name, "mac_filter_drops") == NULL)
+			continue;
+		if (xstats[i].value != 0) {
+			printf("Error: %s not zero after reset\n",
+			       names[i].name);
+			goto out;
+		}
+	}
+
+	result = TEST_SUCCESS;
+
+out:
+	free(names);
+	free(xstats);
+	return result;
+}
+
 /* Individual test case wrappers */
 
 static int
@@ -1128,6 +1257,10 @@ static struct unit_test_suite test_pmd_tap_suite = {
 		TEST_CASE(test_tap_multiqueue),
 		TEST_CASE(test_tap_rx_queue_setup),
 		TEST_CASE(test_tap_tx_burst),
+		TEST_CASE(test_tap_mac_filter_info),
+		TEST_CASE(test_tap_mac_addr_ops),
+		TEST_CASE(test_tap_mc_addr_list),
+		TEST_CASE(test_tap_xstats_mac_filter),
 		TEST_CASES_END()
 	}
 };
-- 
2.53.0


  parent reply	other threads:[~2026-03-21 23:21 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-19 22:10 [PATCH dpdk] net/tap: add software MAC address filtering Robin Jarry
2026-03-19 22:43 ` Stephen Hemminger
2026-03-20  8:26   ` Robin Jarry
2026-03-20 10:10 ` Morten Brørup
2026-03-20 16:45 ` [PATCH dpdk v2] " Robin Jarry
2026-03-21  2:58   ` Stephen Hemminger
2026-03-21  5:48     ` Morten Brørup
2026-03-21 14:48 ` [PATCH dpdk v3] " Robin Jarry
2026-03-21 17:06   ` Stephen Hemminger
2026-03-21 23:20   ` Stephen Hemminger [this message]
2026-03-23  8:42 ` [PATCH dpdk v4] " Robin Jarry
2026-03-23 18:52   ` Stephen Hemminger
2026-03-24 19:09 ` [PATCH dpdk v5] " Robin Jarry
2026-03-25 16:40   ` Stephen Hemminger
2026-03-26  9:15     ` Robin Jarry

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20260321162057.09dbd5fc@phoenix.local \
    --to=stephen@networkplumber.org \
    --cc=dev@dpdk.org \
    --cc=rjarry@redhat.com \
    /path/to/YOUR_REPLY

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

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