From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3BCD36C9E6 for ; Wed, 8 Apr 2026 02:52:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616753; cv=none; b=miFJQ6LJe1NWvGB9ZZxE+hCNQ64L1t7hMWx6AT5ArxLTtjTJRibt5QmadvfvQMMErL/ihxqxvpOztNL+15cY3vlvve0Cq4b6vNJtDLNsllTvQjvE1ohKAn/nh65yliSLr5/qgmpfrf4wergj+7OCfZdv/DW61pPcVzHn7nak4gk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616753; c=relaxed/simple; bh=Xc9JIcJ5tZ/hkJqVabouvK2yaEMKFNhceFeC8ZkDcNI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=M+pOE1JvYRSOf2UvdrXrucWd8L/Cw76PZDTcpB3Roz2LeLZiwmHOfIXWBjkfYvwBDiYwb0xZBrvKRwyvB+o5FbIyArNEPLAFt2qqPxn1OFJD7Exh7RAXq/zhmwoYkhiQpUcfjiuy3xKN6A+KMm7k1nfnFdLn8SCFkHUyHU93nAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Mn4+cd0x; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Mn4+cd0x" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2bdc1b30ac8so34275042eec.1 for ; Tue, 07 Apr 2026 19:52:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616751; x=1776221551; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/2f0Yof1DLXmda+Ua8QZmvkVah9DOsLozAWk9vmUBRA=; b=Mn4+cd0xpBy7ek4ATccBqepKgfmxBtiItjN22LRHilvyWWxidt7/meYupouRTlRJGa 7cuezWpoEhPrs8awJWz5DEQdjB3TZBphBLwDoQvGhKh4Df5fKK8Rs3BP38ju6w5fBtc+ Y+tji1yqz4a9ZZbyENhDLbcfC760f2GBdwimF7rL3+2opdNgJqpv3pOGP91E19U2GiGq MJ9Kr9fGEbN4ioli20X4zu8nZMu0kZEDp35PBYl0qzF83nesMGRwzzazgHcx3ocL6QMS wQtIEYGI3H5e/H2NcYh4GY+wLuHDdSwWbhdEKPD6tfHPWJBI8/9cN26twQPjYYfllTNW ETSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616751; x=1776221551; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/2f0Yof1DLXmda+Ua8QZmvkVah9DOsLozAWk9vmUBRA=; b=GQSfOq0fIWCGP1P9iGNUa2Y4mKQxRFT026YwyulS/d75k0INxJOsWV2JT34VTNUq3E dsZe9KWZgRqmEp/Uy8vHU9+Hn4fU8i+EiuURap6FIZnaBehj8fFjj31th736c+SL8WrN qt3x5ugmxPybKf5i/MY5ByO5jXQRIouffYku3PPx4kXaMQE/aCESCCR7mbs0idJxbjaW mzxN7pgcHWN+DJG5oTznPE0ayKux4h8KwgaJ6SJ9tzvDcsi+YQxmepWAOCbXDVUBcfO+ tzbkted8ALGy8ic4nZN9yEO4ArrGlWY6ts7iwSrQ+OEHiQX90AEBno29dN+GRDGm8ejq MXsg== X-Forwarded-Encrypted: i=1; AJvYcCVWPExvseO+OmfBbO6CW9qje0abyRt0Gq09tYhr3noA0m3pfwsJNpaVkoQ8UpY9lx6UqMhzQ49dapOdtNU=@vger.kernel.org X-Gm-Message-State: AOJu0YyjmCfrpX10j60cUw+gtBVCASdyvX0VEYYOhuF3WBjjFvGRxqjp iebrZVyAEwRmQRsMjQWSuo7p7WI6I6Yh1qiqxKoEJoPlw3eG3UrWnWlHUBYwfTVRSR0C22o5sKP 4H2+x1Ak4euK5ybJNtKArvQ== X-Received: from dyaw3-n1.prod.google.com ([2002:a05:693c:4143:10b0:2c5:2b09:16ef]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:dc88:b0:2c5:3b87:2fec with SMTP id 5a478bee46e88-2cbfca5c3c3mr9675586eec.31.1775616750606; Tue, 07 Apr 2026 19:52:30 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:20 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=3679; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=Xc9JIcJ5tZ/hkJqVabouvK2yaEMKFNhceFeC8ZkDcNI=; b=2tGrfq8QKie9svHpoZm/C1pa+XSVE0HMxc1jYKrhz70twfNKSQhHWJRvLkTuv0kq3x5+Hgsi+ kor24m5SRTIB1P9bELhgNUVWD/lPC+lQ5lKtsKq2LOIwElTCus7ofAl X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-1-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 01/10] net: team: Annotate reads and writes for mixed lock accessed values From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The team_port's "index" and the team's "en_port_count" are read in the hot transmit path, but are only written to when holding the rtnl lock. Use READ_ONCE() for all lockless reads of these values, and use WRITE_ONCE() for all writes. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- drivers/net/team/team_core.c | 11 ++++++----- drivers/net/team/team_mode_random.c | 2 +- include/linux/if_team.h | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index 566a5d102c23..becd066279a6 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -938,7 +938,8 @@ static void team_port_enable(struct team *team, { if (team_port_enabled(port)) return; - port->index =3D team->en_port_count++; + WRITE_ONCE(port->index, team->en_port_count); + WRITE_ONCE(team->en_port_count, team->en_port_count + 1); hlist_add_head_rcu(&port->hlist, team_port_index_hash(team, port->index)); team_adjust_ops(team); @@ -958,7 +959,7 @@ static void __reconstruct_port_hlist(struct team *team,= int rm_index) for (i =3D rm_index + 1; i < team->en_port_count; i++) { port =3D team_get_port_by_index(team, i); hlist_del_rcu(&port->hlist); - port->index--; + WRITE_ONCE(port->index, port->index - 1); hlist_add_head_rcu(&port->hlist, team_port_index_hash(team, port->index)); } @@ -973,8 +974,8 @@ static void team_port_disable(struct team *team, team->ops.port_disabled(team, port); hlist_del_rcu(&port->hlist); __reconstruct_port_hlist(team, port->index); - port->index =3D -1; - team->en_port_count--; + WRITE_ONCE(port->index, -1); + WRITE_ONCE(team->en_port_count, team->en_port_count - 1); team_queue_override_port_del(team, port); team_adjust_ops(team); team_lower_state_changed(port); @@ -1245,7 +1246,7 @@ static int team_port_add(struct team *team, struct ne= t_device *port_dev, netif_addr_unlock_bh(dev); } =20 - port->index =3D -1; + WRITE_ONCE(port->index, -1); list_add_tail_rcu(&port->list, &team->port_list); team_port_enable(team, port); netdev_compute_master_upper_features(dev, true); diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mo= de_random.c index 53d0ce34b8ce..169a7bc865b2 100644 --- a/drivers/net/team/team_mode_random.c +++ b/drivers/net/team/team_mode_random.c @@ -16,7 +16,7 @@ static bool rnd_transmit(struct team *team, struct sk_buf= f *skb) struct team_port *port; int port_index; =20 - port_index =3D get_random_u32_below(team->en_port_count); + port_index =3D get_random_u32_below(READ_ONCE(team->en_port_count)); port =3D team_get_port_by_index_rcu(team, port_index); if (unlikely(!port)) goto drop; diff --git a/include/linux/if_team.h b/include/linux/if_team.h index ccb5327de26d..06f4d7400c1e 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -77,7 +77,7 @@ static inline struct team_port *team_port_get_rcu(const s= truct net_device *dev) =20 static inline bool team_port_enabled(struct team_port *port) { - return port->index !=3D -1; + return READ_ONCE(port->index) !=3D -1; } =20 static inline bool team_port_txable(struct team_port *port) @@ -272,7 +272,7 @@ static inline struct team_port *team_get_port_by_index_= rcu(struct team *team, struct hlist_head *head =3D team_port_index_hash(team, port_index); =20 hlist_for_each_entry_rcu(port, head, hlist) - if (port->index =3D=3D port_index) + if (READ_ONCE(port->index) =3D=3D port_index) return port; return NULL; } --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A09436E468 for ; Wed, 8 Apr 2026 02:52:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616754; cv=none; b=QwGwKx9Tny29S4xUAWtUP+Zr9pJP51BVUIzMvSTLO8iQuk/tOnfC5lLMHfNDg3KPJic07lxGSMeN1Et7y56BSiBPKCCIc6G/4pu0xRJQUvP6Jpzge3uKPEi697y1GeiUPLc77K0YLljVXaEwJH1Y1k64/xH7IZNNG7nUw7fuQWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616754; c=relaxed/simple; bh=ABDDARZ3LBRa/K2R4lTmrc2M2fscQVtdq2vQFlp7tVs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=i/qqNpuHR7AnkXKTyaSVoneEU1Kzi5ItRZkmmDv2+R56pYAtcDtQGCJbsjjzj9hSBAHNJ5OcM1absf1nieKSScvLm3kWYnJBsni38uEfqEcXY7+nFHWGJ/qo415Xrm0wsuMgOLHA7vZElLyJ6IQ1gFwf6JQKpK0G8vlL8HpDdQU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=RNGo464d; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="RNGo464d" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2ceef8e793fso10244156eec.0 for ; Tue, 07 Apr 2026 19:52:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616752; x=1776221552; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ItnT3gTeM/wZiruuzHdFs4ZevuvK/cu62n/SK5ptp+Q=; b=RNGo464dwhE9MNdS9B8R5Fas3/YW0m6G6Pm2fQsC//Kf3jQX3gbuVzngG5uhuRP4v8 H11N0T/HdKUN6e8oB/kEj9B1rJwW75UOIbj2XCvzhfmzCQw/Y6izhcXLjibXyurD0FiJ RGUw9Bd07YA/vuXQ+ku8y+It3iYchTJMlOes4Ia2cuPlHoBB+sIafemDTL4JqtJK4B9v DMVxjWsbvixGvEzZsTwsOmhuPbPu7xKptbtTHQR8taEy4F+2GSMW7KHOdNCrZfirYYFR 4EScjjX0qeKtT5/BCBTJC89VpS1zcedoj4wcQ7/qTxT8efIvEnEEVIgPcXPlXLAucqLy Speg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616752; x=1776221552; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ItnT3gTeM/wZiruuzHdFs4ZevuvK/cu62n/SK5ptp+Q=; b=OU8eJiR7zTxVKYtjuUBEaK2lgu6/1VIE6a8yCC3ZcVdRjj/wj13fQbrDMN2CC3fVsL 8ICbvwR0Gy3jKIv0G/7iZUlEjR6lGw0hi1hqwjsq/DYINFqC1uVOnvJSUX7b6k0qD8yE 2GulrtLiiik0c/ckYyKNrmRuKa6FyjCMvVbdacVtql6KGTYGofj2El8Qt894eIe6sBRY XUnE28Iz0eaF0utQSWRlZm/JHMCGh7J0OXiiV8bE+jxecklG2MKYUe+cfFgtvkFUShgz i1wtpqFtZgBXiKZ3VTvy2ho6yeX8cA49A2CkRKNLXoxRHs6UC5NPkdrM1/6As7z9ZKkY YDmg== X-Forwarded-Encrypted: i=1; AJvYcCVQrw5hqYw2Ax6CSWdHyMEZfdQv09AR37FZmQWnM7yz57UnH96VOpqjoQBBowoHZ8fzRkjC402wn0i8XmQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyDRduEC5uyehA177NYbAx83pAh2HxEonoYZYmvGbkbmmrNSCZP jwMLJJ8+rCKZKOIwHF5DAzhBnnRNBWRMm/d6EEOUszy4zTM9rYWCrhcq3rLkEgGqBAf43IJguy1 LKWS3TPmpbOjKgoIFs1akXQ== X-Received: from dybma11.prod.google.com ([2002:a05:7301:168b:b0:2cc:9049:2bf6]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:3c9b:b0:2d3:d3f:2429 with SMTP id 5a478bee46e88-2d30d3f2ce0mr394310eec.0.1775616752127; Tue, 07 Apr 2026 19:52:32 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:21 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=1423; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=ABDDARZ3LBRa/K2R4lTmrc2M2fscQVtdq2vQFlp7tVs=; b=r8cB68lfooR/1QW4AS+aBeHw0DbnRNjdO87i6cEXF/Acqd5qIrPf4eNSGhRzdGV/Z/oo96MIo yIGXIDlBRm6C+KwLRmMIBbs9OW0KXroMNL8Rxs6JMfMBHs1L3lun8yT X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-2-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 02/10] net: team: Remove unused team_mode_op, port_enabled From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This team_mode_op wasn't used by any of the team modes, so remove it. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- drivers/net/team/team_core.c | 2 -- include/linux/if_team.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index becd066279a6..e54bd21bd068 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -944,8 +944,6 @@ static void team_port_enable(struct team *team, team_port_index_hash(team, port->index)); team_adjust_ops(team); team_queue_override_port_add(team, port); - if (team->ops.port_enabled) - team->ops.port_enabled(team, port); team_notify_peers(team); team_mcast_rejoin(team); team_lower_state_changed(port); diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 06f4d7400c1e..a761f5282bcf 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -121,7 +121,6 @@ struct team_mode_ops { int (*port_enter)(struct team *team, struct team_port *port); void (*port_leave)(struct team *team, struct team_port *port); void (*port_change_dev_addr)(struct team *team, struct team_port *port); - void (*port_enabled)(struct team *team, struct team_port *port); void (*port_disabled)(struct team *team, struct team_port *port); }; =20 --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF36537418A for ; Wed, 8 Apr 2026 02:52:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616756; cv=none; b=HzFynMAkbROKXB6yf9J0U3us8AgdUapZqH7hlvD/fuwUbsPgjoxS5qTUxSrxL9OEiUbiY3hoQP3w4ddmf/+EGTytgpljFdBaVSVDMPNoZFC31RYYb+kh9MPouE02V9mRwuWmq8GchdDUN1P0TKGg7d6+5f/Ap7CkoZ0/ydY2/Cg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616756; c=relaxed/simple; bh=tLf1bkN9uV/Iw7z58TBlDPGRsvBgwjwEW1soOYNlMng=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=XLPGwZsWnP3fv9horTJvsQ+55LL1Ggds+okpjO+fUXtZxvarUmWrmZcPbzcrPbg9jEW1ZSh+hfM4aoiSmNXICJi7ZbmVyJMtM2GqZIL17BRGCtDc+BIrPCmG5PLL4WZdYcEmoAWisBHbY/j7UdTMmDvJPA+1MjPwyTadWqBbzX8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=JIniq80d; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="JIniq80d" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-12711ec96fbso22664095c88.0 for ; Tue, 07 Apr 2026 19:52:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616754; x=1776221554; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Ax5N/AY2QUWPAPxLLKbm2VOEjrgk/KSItcsgBYVbAAY=; b=JIniq80dsUrGfsTfWzz4U55SmKvVKLk42s63/BSktf9VN9Wyou01H7xbAg0HNlcxRk 2Y5yeaemp3ab7FNU2AOg92odKPikfWocm8qvFVcNt+45aqnukO777NY438nlhqLNSSV6 gWTBoIlPNx8vvXCm2BJe3wkRYT1woIj7l04nlJo9Pd91nTGF0PaIu7beurvT9NeuWQuR m9a+wI3l4NosNxItKOOL7Mu2jBf36vgC56VujgF8zKC/gWQrTpjRreSql2WpiYhpA9nz Pdjydd8EAXBaUnlxglirDNnod/qt90XsqxvWTaE1pJ3R8wr6nsvmUQmmD5UZipWs2TpV 7pwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616754; x=1776221554; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Ax5N/AY2QUWPAPxLLKbm2VOEjrgk/KSItcsgBYVbAAY=; b=MyYX7GRnBzKUDJrV4sfyoRdfl7w4BSED7OTho+0c6GFYOBKA5r+VvjguE50EM/b1no Mk5nQzt3DKx1n4wFMbtwmDJYV+HnMrfc/0cmtEAgwqve2wIIZXDMPHZjv5QRAu2gjwtG 7YTVQ+HQVpajHKN2GZotTYk3Pe0lMEb2LZRMn9pa32nBsg4BQ0KPHE8KdYsnDXfuUI5E N2gjD74knFPlVN0m/i6dCWvBiIWOX77fjlb3Ta4VfM/peW/zQh9lhzkx6ff/hJsVRg9e AKgScnCAoHRNtfMN74H7WaxAlQjNzD1VrJJUak1slCyFHCVadtlpIwiGl1YP7QmSxkez 4NrA== X-Forwarded-Encrypted: i=1; AJvYcCUNppLW/E4SgmIDGUSVqd3GtwKcow5esfH9hbKYG6tvrjYePEWAgVdeNC3q6H6mVLrYa6HuIu9M7GW8XJc=@vger.kernel.org X-Gm-Message-State: AOJu0YwCc1aXE0yjEOfiztqsrIHRcZnibjEpk0cyRJk3YLEV9DKECARH zs7pJWk+CCS5DuIFHOSOFxL6Kh0Hq9frgD9usNIsfunOgJ+yhhGYouS/4Mg3dJAOJFKHoWxskQL QkPMHv/tK2lGlQPwkRq5Ckw== X-Received: from dlaj20.prod.google.com ([2002:a05:701b:2814:b0:12a:6c32:ffce]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:4396:b0:128:d2a5:709c with SMTP id a92af1059eb24-12bfb76f887mr9974725c88.33.1775616753732; Tue, 07 Apr 2026 19:52:33 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:22 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=2504; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=tLf1bkN9uV/Iw7z58TBlDPGRsvBgwjwEW1soOYNlMng=; b=z/hty/splzkDAHFuVlNKIT9qqTuMq3/lMpSVznb6sXy8z5QUeqtOlQ20UqrB5K3Trejhd+ocB MFSJECD/SaeC90xQho4F/lLItmaTaC2pShaV/vS6BFWsZVL4j3cDZof X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-3-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 03/10] net: team: Rename port_disabled team mode op to port_tx_disabled From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This team mode op is only used by the load balance mode, and it only uses it in the tx path. Signed-off-by: Marc Harvey Reviewed-by: Jiri Pirko --- drivers/net/team/team_core.c | 4 ++-- drivers/net/team/team_mode_loadbalance.c | 4 ++-- include/linux/if_team.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index e54bd21bd068..2ce31999c99f 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -968,8 +968,8 @@ static void team_port_disable(struct team *team, { if (!team_port_enabled(port)) return; - if (team->ops.port_disabled) - team->ops.port_disabled(team, port); + if (team->ops.port_tx_disabled) + team->ops.port_tx_disabled(team, port); hlist_del_rcu(&port->hlist); __reconstruct_port_hlist(team, port->index); WRITE_ONCE(port->index, -1); diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/te= am_mode_loadbalance.c index 684954c2a8de..840f409d250b 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -655,7 +655,7 @@ static void lb_port_leave(struct team *team, struct tea= m_port *port) free_percpu(lb_port_priv->pcpu_stats); } =20 -static void lb_port_disabled(struct team *team, struct team_port *port) +static void lb_port_tx_disabled(struct team *team, struct team_port *port) { lb_tx_hash_to_port_mapping_null_port(team, port); } @@ -665,7 +665,7 @@ static const struct team_mode_ops lb_mode_ops =3D { .exit =3D lb_exit, .port_enter =3D lb_port_enter, .port_leave =3D lb_port_leave, - .port_disabled =3D lb_port_disabled, + .port_tx_disabled =3D lb_port_tx_disabled, .receive =3D lb_receive, .transmit =3D lb_transmit, }; diff --git a/include/linux/if_team.h b/include/linux/if_team.h index a761f5282bcf..740cb3100dfc 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -121,7 +121,7 @@ struct team_mode_ops { int (*port_enter)(struct team *team, struct team_port *port); void (*port_leave)(struct team *team, struct team_port *port); void (*port_change_dev_addr)(struct team *team, struct team_port *port); - void (*port_disabled)(struct team *team, struct team_port *port); + void (*port_tx_disabled)(struct team *team, struct team_port *port); }; =20 extern int team_modeop_port_enter(struct team *team, struct team_port *por= t); --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4ABAD375AC2 for ; Wed, 8 Apr 2026 02:52:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616760; cv=none; b=IcQHfs9MXqqE7UrE/Krx2kD0XoX3N71TIYJCPwyEbk7WZo5iI/wbllw8T75Mhdy0ADK+Wg5CKXKiOfMCvERcVMxmoR4r6ZQyfEOSdudX0hL0X/7YmTIcLe46ZUh/QUKXyrQkVHJlrtr76KneDcsol+8S6GvQiMuUWNbD/PssOxU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616760; c=relaxed/simple; bh=56indIRElDV0usMzMjHatIwKqE+ETHzgNqfEGPbTnfI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UcPrGcOpxUv+mw1dn2zq0QJKibzI0TV+tmpqKmq49/Hf7G9Vx408MjhYAXnGJYiVnBfmzj5eQntMGTyruF9416sfx0XhsrU5kbMnNoy6SnmvNxo2LGp6mbOpblGMS/c1mtuJwimIpC9m7bpefqekevvJRwGC12gBkdDx+5PaLm8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=h/undASq; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="h/undASq" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2c16233ee11so8106772eec.1 for ; Tue, 07 Apr 2026 19:52:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616755; x=1776221555; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=31MOmavN4EnvwbSfeL7HJH8wgUUfo0sqfPppSBppvUI=; b=h/undASqbR9+mTfUR8jceysG7hARSJylnvj3s3Hol2JVkZaO4wt5nDYkdB8PMKs5Lf 5LjYtXgvmIZ3cTEN4bJZGCpHhL4Vw6tM313EWBSHsHUg12IpZx/twq6mpoExGm1EPV8w AmgkKzgoxDkThyWnjufSwrDRYw79BWJJZO1dktaXcPhLYp32K9+Wx608vOkdqEsFjCXL SUHluMNSlNly9C7vazrc9CUaGgHeQdmjj+Qn2VRHN9J/Wyh9SaVxYFRc/r28JWg94c4t nPy1/UAh90xgbl0v5DZzmP+ZJsY7EZsMQ3yxhJHkT9Z7OmB71yMyFyVwflO5LoVpGsRL zATg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616755; x=1776221555; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=31MOmavN4EnvwbSfeL7HJH8wgUUfo0sqfPppSBppvUI=; b=GN9eFVsM32CZjVkgbMXoU25U6f/ZAb2y4vrXNLP7e8k1lH2GLKioVfzk6b49LwgF0h PGDxUn58zhjpIf8Ack8S/Tq1tgjpvLFbfmyezDgrez+ckGI9Zzftwn6F2+blZ6RXFTXJ G0aEWQBDxAWAtNjxDUYaL8Ga2Eip6z9h9zY7mlgItu8BQ1ohIxNJeEJQtTz+F0bMUCmO iWBLnPK1/dSoYzfbZJS1leKDAQUDsQ/84Clbnb105Kuws0e63MabAKKerwVvjKsyVrT0 D6NI6O3OkWt8c0u9N+m6TAzrxt6ZD9vox2Bzdzmnsq5TlvkFIe9+b1OzrjD+9wS33Xwi AAzg== X-Forwarded-Encrypted: i=1; AJvYcCVeP4ZIy6Jp0HfqoAytQ4HQ22BgEOOmvvIeKufWe5oVbGF2LBMR+ZQVlQV5OsSc+ZSjlbG2FphAQG+sNP4=@vger.kernel.org X-Gm-Message-State: AOJu0YzTAi3Tm3zHyrU2lXVCf3FlWz1MxQKvsWB3Fj+FI+UuRt7kEbIF avq2DaYKIdvcdZtzX+RGlP7E8G2NjFBF1goJdf6hnCjTynRZHGHmX2vwDTQFobZPrW5JB9Z9XT0 Hokuurk2us+r89XcWgezXaw== X-Received: from dyem10.prod.google.com ([2002:a05:7300:818a:b0:2cc:a1bf:2dd9]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:1493:b0:2cf:28e8:d784 with SMTP id 5a478bee46e88-2cf28e8dcd7mr6298319eec.19.1775616755301; Tue, 07 Apr 2026 19:52:35 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:23 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=13139; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=56indIRElDV0usMzMjHatIwKqE+ETHzgNqfEGPbTnfI=; b=XZi23tdvGPXXvI/Xf+0YjO2IPZZc4qDmUVCjhEK5/lSd0rQJmiwvwz0o+vZComeMI5i01N/qb 1p22YyjZmloBs8UylW1tRitoEl3vyyDv3aHa0z1TDTdkEGFOfUd5HoI X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-4-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 04/10] selftests: net: Add tests for failover of team-aggregated ports From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable There are currently no kernel tests that verify the effect of setting the enabled team driver option. In a followup patch, there will be changes to this option, so it will be important to make sure it still behaves as it does now. The test verifies that tcp continues to work across two different team devices in separate network namespaces, even when member links are manually disabled. Signed-off-by: Marc Harvey --- Changes in v6: - Use a tcp port with no associated service. - Make tcpdump helper function not string-replace port numbers with associated service names, even on Fedora, which has a tcpdump patch that changes the required flag. - Link to v5: https://lore.kernel.org/netdev/20260406-teaming-driver-intern= al-v5-4-e8a3f348a1c5@google.com/ Changes in v5: - Use tcpdump for collecting traffic, rather than reading rx counters. - Link to v4: https://lore.kernel.org/netdev/20260403-teaming-driver-intern= al-v4-4-d3032f33ca25@google.com/ Changes in v2: - Fix shellcheck failures. - Remove dependency on net forwarding lib and pipe viewer tools. - Use iperf3 for tcp instead of netcat. - Link to v1: https://lore.kernel.org/all/20260331053353.2504254-5-marcharv= ey@google.com/ --- tools/testing/selftests/drivers/net/team/Makefile | 2 + tools/testing/selftests/drivers/net/team/config | 4 + .../testing/selftests/drivers/net/team/team_lib.sh | 148 +++++++++++++++++= ++ .../drivers/net/team/transmit_failover.sh | 158 +++++++++++++++++= ++++ tools/testing/selftests/net/forwarding/lib.sh | 9 +- 5 files changed, 319 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/team/Makefile b/tools/test= ing/selftests/drivers/net/team/Makefile index 02d6f51d5a06..777da2e0429e 100644 --- a/tools/testing/selftests/drivers/net/team/Makefile +++ b/tools/testing/selftests/drivers/net/team/Makefile @@ -7,9 +7,11 @@ TEST_PROGS :=3D \ options.sh \ propagation.sh \ refleak.sh \ + transmit_failover.sh \ # end of TEST_PROGS =20 TEST_INCLUDES :=3D \ + team_lib.sh \ ../bonding/lag_lib.sh \ ../../../net/forwarding/lib.sh \ ../../../net/in_netns.sh \ diff --git a/tools/testing/selftests/drivers/net/team/config b/tools/testin= g/selftests/drivers/net/team/config index 5d36a22ef080..8f04ae419c53 100644 --- a/tools/testing/selftests/drivers/net/team/config +++ b/tools/testing/selftests/drivers/net/team/config @@ -6,4 +6,8 @@ CONFIG_NETDEVSIM=3Dm CONFIG_NET_IPGRE=3Dy CONFIG_NET_TEAM=3Dy CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=3Dy +CONFIG_NET_TEAM_MODE_BROADCAST=3Dy CONFIG_NET_TEAM_MODE_LOADBALANCE=3Dy +CONFIG_NET_TEAM_MODE_RANDOM=3Dy +CONFIG_NET_TEAM_MODE_ROUNDROBIN=3Dy +CONFIG_VETH=3Dy diff --git a/tools/testing/selftests/drivers/net/team/team_lib.sh b/tools/t= esting/selftests/drivers/net/team/team_lib.sh new file mode 100644 index 000000000000..2057f5edee79 --- /dev/null +++ b/tools/testing/selftests/drivers/net/team/team_lib.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +test_dir=3D"$(dirname "$0")" +export REQUIRE_MZ=3Dno +export NUM_NETIFS=3D0 +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/forwarding/lib.sh" + +TCP_PORT=3D"43434" + +# Create a team interface inside of a given network namespace with a given +# mode, members, and IP address. +# Arguments: +# namespace - Network namespace to put the team interface into. +# team - The name of the team interface to setup. +# mode - The team mode of the interface. +# ip_address - The IP address to assign to the team interface. +# prefix_length - The prefix length for the IP address subnet. +# $@ - members - The member interfaces of the aggregation. +setup_team() +{ + local namespace=3D$1 + local team=3D$2 + local mode=3D$3 + local ip_address=3D$4 + local prefix_length=3D$5 + shift 5 + local members=3D("$@") + + # Prerequisite: team must have no members + for member in "${members[@]}"; do + ip -n "${namespace}" link set "${member}" nomaster + done + + # Prerequisite: team must have no address in order to set it + # shellcheck disable=3DSC2086 + ip -n "${namespace}" addr del "${ip_address}/${prefix_length}" \ + ${NODAD} dev "${team}" + + echo "Setting team in ${namespace} to mode ${mode}" + + if ! ip -n "${namespace}" link set "${team}" down; then + echo "Failed to bring team device down" + return 1 + fi + if ! ip netns exec "${namespace}" teamnl "${team}" setoption mode \ + "${mode}"; then + echo "Failed to set ${team} mode to '${mode}'" + return 1 + fi + + # Aggregate the members into teams. + for member in "${members[@]}"; do + ip -n "${namespace}" link set "${member}" master "${team}" + done + + # Bring team devices up and give them addresses. + if ! ip -n "${namespace}" link set "${team}" up; then + echo "Failed to set ${team} up" + return 1 + fi + + # shellcheck disable=3DSC2086 + if ! ip -n "${namespace}" addr add "${ip_address}/${prefix_length}" \ + ${NODAD} dev "${team}"; then + echo "Failed to give ${team} IP address in ${namespace}" + return 1 + fi +} + +# This is global used to keep track of the sender's iperf3 process, so tha= t it +# can be terminated. +declare sender_pid + +# Start sending and receiving TCP traffic with iperf3. +# Globals: +# sender_pid - The process ID of the iperf3 sender process. Used to kill = it +# later. +start_listening_and_sending() +{ + ip netns exec "${NS2}" iperf3 -s -p "${TCP_PORT}" --logfile /dev/null & + # Wait for server to become reachable before starting client. + slowwait 5 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p \ + "${TCP_PORT}" -t 1 --logfile /dev/null + ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p "${TCP_PORT}" -b 1M -l \ + 1K -t 0 --logfile /dev/null & + sender_pid=3D$! +} + +# Stop sending TCP traffic with iperf3. +# Globals: +# sender_pid - The process ID of the iperf3 sender process. +stop_sending_and_listening() +{ + kill "${sender_pid}" && wait "${sender_pid}" 2>/dev/null || true +} + +# Monitor for TCP traffic with Tcpdump, save results to temp files. +# Arguments: +# namespace - The network namespace to run tcpdump inside of. +# $@ - interfaces - The interfaces to listen to. +save_tcpdump_outputs() +{ + local namespace=3D$1 + shift 1 + local interfaces=3D("$@") + + for interface in "${interfaces[@]}"; do + tcpdump_start "${interface}" "${namespace}" + done + + sleep 1 + + for interface in "${interfaces[@]}"; do + tcpdump_stop_nosleep "${interface}" + done +} + +clear_tcpdump_outputs() +{ + local interfaces=3D("$@") + + for interface in "${interfaces[@]}"; do + tcpdump_cleanup "${interface}" + done +} + +# Read Tcpdump output, determine packet counts. +# Arguments: +# interface - The name of the interface to count packets for. +# ip_address - The destination IP address. +did_interface_receive() +{ + local interface=3D"$1" + local ip_address=3D"$2" + local packet_count + + packet_count=3D$(tcpdump_show "$interface" | grep -c \ + "> ${ip_address}.${TCP_PORT}") + echo "Packet count for ${interface} was ${packet_count}" + + if [[ "${packet_count}" -gt 0 ]]; then + true + else + false + fi +} diff --git a/tools/testing/selftests/drivers/net/team/transmit_failover.sh = b/tools/testing/selftests/drivers/net/team/transmit_failover.sh new file mode 100755 index 000000000000..b2bdcd27bc98 --- /dev/null +++ b/tools/testing/selftests/drivers/net/team/transmit_failover.sh @@ -0,0 +1,158 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# These tests verify the basic failover capability of the team driver via = the +# `enabled` team driver option across different team driver modes. This do= es not +# rely on teamd, and instead just uses teamnl to set the `enabled` option +# directly. +# +# Topology: +# +# +-------------------------+ NS1 +# | test_team1 | +# | + | +# | eth0 | eth1 | +# | +---+---+ | +# | | | | +# +-------------------------+ +# | | +# +-------------------------+ NS2 +# | | | | +# | +-------+ | +# | eth0 | eth1 | +# | + | +# | test_team2 | +# +-------------------------+ + +export ALL_TESTS=3D"team_test_failover" + +test_dir=3D"$(dirname "$0")" +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/lib.sh" +# shellcheck disable=3DSC1091 +source "${test_dir}/team_lib.sh" + +NS1=3D"" +NS2=3D"" +export NODAD=3D"nodad" +PREFIX_LENGTH=3D"64" +NS1_IP=3D"fd00::1" +NS2_IP=3D"fd00::2" +NS1_IP4=3D"192.168.0.1" +NS2_IP4=3D"192.168.0.2" +MEMBERS=3D("eth0" "eth1") + +while getopts "4" opt; do + case $opt in + 4) + echo "IPv4 mode selected." + export NODAD=3D + PREFIX_LENGTH=3D"24" + NS1_IP=3D"${NS1_IP4}" + NS2_IP=3D"${NS2_IP4}" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +# Create the network namespaces, veth pair, and team devices in the specif= ied +# mode. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# mode - The team driver mode to use for the team devices. +environment_create() +{ + trap cleanup_all_ns EXIT + setup_ns ns1 ns2 + NS1=3D"${NS_LIST[0]}" + NS2=3D"${NS_LIST[1]}" + + # Create the interfaces. + ip -n "${NS1}" link add eth0 type veth peer name eth0 netns "${NS2}" + ip -n "${NS1}" link add eth1 type veth peer name eth1 netns "${NS2}" + ip -n "${NS1}" link add test_team1 type team + ip -n "${NS2}" link add test_team2 type team + + # Set up the receiving network namespace's team interface. + setup_team "${NS2}" test_team2 roundrobin "${NS2_IP}" \ + "${PREFIX_LENGTH}" "${MEMBERS[@]}" +} + + +# Check that failover works for a specific team driver mode. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# mode - The mode to set the team interfaces to. +team_test_mode_failover() +{ + local mode=3D"$1" + export RET=3D0 + + # Set up the sender team with the correct mode. + setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ + "${PREFIX_LENGTH}" "${MEMBERS[@]}" + check_err $? "Failed to set up sender team" + + start_listening_and_sending + + ### Scenario 1: All interfaces initially enabled. + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" + did_interface_receive eth0 "${NS2_IP}" + check_err $? "eth0 not transmitting when both links enabled" + did_interface_receive eth1 "${NS2_IP}" + check_err $? "eth1 not transmitting when both links enabled" + clear_tcpdump_outputs "${MEMBERS[@]}" + + ### Scenario 2: One tx-side interface disabled. + ip netns exec "${NS1}" teamnl test_team1 setoption enabled false \ + --port=3Deth1 + slowwait 2 bash -c "ip netns exec ${NS1} teamnl test_team1 getoption \ + enabled --port=3Deth1 | grep -q false" + + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" + did_interface_receive eth0 "${NS2_IP}" + check_err $? "eth0 not transmitting when enabled" + did_interface_receive eth1 "${NS2_IP}" + check_fail $? "eth1 IS transmitting when disabled" + clear_tcpdump_outputs "${MEMBERS[@]}" + + ### Scenario 3: The interface is re-enabled. + ip netns exec "${NS1}" teamnl test_team1 setoption enabled true \ + --port=3Deth1 + slowwait 2 bash -c "ip netns exec ${NS1} teamnl test_team1 getoption \ + enabled --port=3Deth1 | grep -q true" + + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" + did_interface_receive eth0 "${NS2_IP}" + check_err $? "eth0 not transmitting when both links enabled" + did_interface_receive eth1 "${NS2_IP}" + check_err $? "eth1 not transmitting when both links enabled" + clear_tcpdump_outputs "${MEMBERS[@]}" + + log_test "Failover of '${mode}' test" + + # Clean up + stop_sending_and_listening +} + +team_test_failover() +{ + team_test_mode_failover broadcast + team_test_mode_failover roundrobin + team_test_mode_failover random + # Don't test `activebackup` or `loadbalance` modes, since they are too + # complicated for just setting `enabled` to work. They use more than + # the `enabled` option for transmit. +} + +require_command teamnl +require_command iperf3 +require_command tcpdump +environment_create +tests_run +exit "${EXIT_STATUS}" diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/= selftests/net/forwarding/lib.sh index d8cc4c64148d..bb2e9b880343 100644 --- a/tools/testing/selftests/net/forwarding/lib.sh +++ b/tools/testing/selftests/net/forwarding/lib.sh @@ -1749,12 +1749,17 @@ tcpdump_start() sleep 1 } =20 -tcpdump_stop() +tcpdump_stop_nosleep() { local if_name=3D$1 local pid=3D${cappid[$if_name]} =20 $ns_cmd kill "$pid" && wait "$pid" +} + +tcpdump_stop() +{ + tcpdump_stop_nosleep "$1" sleep 1 } =20 @@ -1769,7 +1774,7 @@ tcpdump_show() { local if_name=3D$1 =20 - tcpdump -e -n -r ${capfile[$if_name]} 2>&1 + tcpdump -e -nn -r ${capfile[$if_name]} 2>&1 } =20 # return 0 if the packet wasn't seen on host2_if or 1 if it was --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6E0E373BF7 for ; Wed, 8 Apr 2026 02:52:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616763; cv=none; b=p+PqjnhBp+RJC6YKPEy9b3lRK4ilu0SMAJNJ/BgZQZtUZSN0xVVihabI+o+1NSA/0Pkz4F19AY7ycKGlV/iRYyHIZ3b6a1ZSHNNEQmbIoIduKP4p5N1UoFZEFwtuV7hF4ZnM7o+NFzKhBQgAlb/VnCo0Rc0saNAq+LoE1/Q9H1o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616763; c=relaxed/simple; bh=54WhcsWEBv89XERrl7hjYMlOglMOUs/ISqhCHGqf+vQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=cLQ7xq9DEyoo/eY1M3NfN0fRWDIDetVR6DfzgM4ncB8MGKxSdUobzbWebBZf9El3gWZGFGxD3xyV8UyrWMy/hL+nr6Q5Q7wp2O9he8Ls8RZIj6uXdPlrCiS0MTgu4bPPVc0ECnfjnE6oG8tdhWjYkXfwJMigOJqobBZ5PqJxavY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=aZyJ7MD3; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="aZyJ7MD3" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2ba8013a9e3so6807500eec.0 for ; Tue, 07 Apr 2026 19:52:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616757; x=1776221557; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=VD9hHtRE4Dg4SjmFWUsIyf6/SlMtsUHiRb8Ol9lMtIc=; b=aZyJ7MD3ukDrTFj07qkuitQpVgcGkBlkIC58cxFNfeuHVquiuvcfxZRn98HsYE3wZl n5HsEgxjqlGl5jcEc7zQCH33WIT1ohs93lkbFPf3UZow0w6WZT9Ak8yDKl4PbR9+bs3k xxnDFw6bsi5zFBhwj2BL7Tde1Xe/dzgDlpSe+wCMRqBx86llz/mYK+nY5aw0IUi9W9Qq Y3+k1ovRX8jZW4cbsNbE4iqt6oIvIj3Am13QP0JBPsiJlCtPHFoqcQI1Tn+h3hFjGRRJ MWA5SyPoJxPjGpCPPNgre0YrN+l/J7rA+fPg1X62/be5q86rKQ2fE8J8HA+PXLdtqf2X pDXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616757; x=1776221557; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VD9hHtRE4Dg4SjmFWUsIyf6/SlMtsUHiRb8Ol9lMtIc=; b=fGYbXI3O/Bxh1yQeoWq25CHf4wpYm79HGozMpwNugdyNX2PBkAJAATeH5vslcYSt+1 EC7B3k2pKgtyOjudjdlJCZBvtIngYbSyW0323auztDpnKrU1SwLlJpy7FRxjeT/ZCzTO 7RXozY3eG5LpRNCk/yo+n2KF9KxvU/oaUVlfJXXMsaRqRT0qtz9g7oHwEWen5zO99T9J SgiXH/I7IZU6LRCXcKpPrc9y4xYuMpJRQdwmZ0YNj47IhrIMKAxa7OW4+N6hUK8tDAy8 0Id46JIC0KWNGjPX33kCZtH9jyeCyY/ODs9VerH6B3mz7I5LXLayDztrO6rFX0Wv2Xza i64w== X-Forwarded-Encrypted: i=1; AJvYcCXJS3LwWRzaOVCzfwpfnRFEQTFcs13Bd7aqyl8eIN/Qnoqodr4NG0l15fsEjKpv6CuLU9k6mGQrJ69spgw=@vger.kernel.org X-Gm-Message-State: AOJu0YzzYZ9UGMeX1mPWw26UkzUrNELzZsruL7sHuqGe4xl5IhnLknDw kaHXv5X2iR8teAyI3+Z5FkY90T0RtnX7r2CUaZNQPh32YvVdkG3dhIKU/esssAvrkEZ7kPyHjQH QxHpbODHu0C1d+D2dh1yrdw== X-Received: from dybfx18.prod.google.com ([2002:a05:7300:c392:b0:2c5:89d3:2645]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:d1b:b0:2c0:dc7e:ed17 with SMTP id 5a478bee46e88-2cbf9afb1edmr10454603eec.10.1775616756867; Tue, 07 Apr 2026 19:52:36 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:24 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=11242; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=54WhcsWEBv89XERrl7hjYMlOglMOUs/ISqhCHGqf+vQ=; b=dx+Os/Rg4+dqFHxbQpYI2TSRISx21qmDs17FJqcEDGto/5X9vMCygR5+kCu/XJcCkal/kw5Z4 ePMtJWbQdHiAA3uoySjpG9Folr6nXd/vynoNobl5+lZYMvxJIOq5/jp X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-5-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 05/10] selftests: net: Add test for enablement of ports with teamd From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable There are no tests that verify enablement and disablement of team driver ports with teamd. This should work even with changes to the enablement option, so it is important to test. This test sets up an active-backup network configuration across two network namespaces, and tries to send traffic while changing which link is the active one. Signed-off-by: Marc Harvey --- Changes in v6: - Remove manual changing of member port states to UP, not needed. - Link to v5: https://lore.kernel.org/netdev/20260406-teaming-driver-intern= al-v5-5-e8a3f348a1c5@google.com/ Changes in v5: - Make test wait for inactive link to stop receiving traffic after setting it to inactive, since there was a race condition. - Change test teardown to try graceful shutdown first, then use sigkill if needed. - Manually delete leftover teamd files during teardown. - Use tcpdump instead of checking rx counters. - Link to v4: https://lore.kernel.org/netdev/20260403-teaming-driver-intern= al-v4-5-d3032f33ca25@google.com/ Changed in v3: - Make test cleanup kill teamd instead of terminate. - Link to v2: https://lore.kernel.org/netdev/20260401-teaming-driver-intern= al-v2-5-f80c1291727b@google.com/ Changes in v2: - Fix shellcheck failures. - Remove dependency on net forwarding lib and pipe viewer tools. - Use iperf3 for tcp instead of netcat. - Link to v1: https://lore.kernel.org/all/20260331053353.2504254-6-marcharv= ey@google.com/ --- tools/testing/selftests/drivers/net/team/Makefile | 1 + .../testing/selftests/drivers/net/team/team_lib.sh | 26 +++ .../drivers/net/team/teamd_activebackup.sh | 246 +++++++++++++++++= ++++ tools/testing/selftests/net/lib.sh | 13 ++ 4 files changed, 286 insertions(+) diff --git a/tools/testing/selftests/drivers/net/team/Makefile b/tools/test= ing/selftests/drivers/net/team/Makefile index 777da2e0429e..dab922d7f83d 100644 --- a/tools/testing/selftests/drivers/net/team/Makefile +++ b/tools/testing/selftests/drivers/net/team/Makefile @@ -7,6 +7,7 @@ TEST_PROGS :=3D \ options.sh \ propagation.sh \ refleak.sh \ + teamd_activebackup.sh \ transmit_failover.sh \ # end of TEST_PROGS =20 diff --git a/tools/testing/selftests/drivers/net/team/team_lib.sh b/tools/t= esting/selftests/drivers/net/team/team_lib.sh index 2057f5edee79..02ef0ee02d6a 100644 --- a/tools/testing/selftests/drivers/net/team/team_lib.sh +++ b/tools/testing/selftests/drivers/net/team/team_lib.sh @@ -146,3 +146,29 @@ did_interface_receive() false fi } + +# Return true if the given interface in the given namespace does NOT recei= ve +# traffic over a 1 second period. +# Arguments: +# interface - The name of the interface. +# ip_address - The destination IP address. +# namespace - The name of the namespace that the interface is in. +check_no_traffic() +{ + local interface=3D"$1" + local ip_address=3D"$2" + local namespace=3D"$3" + local rc + + save_tcpdump_outputs "${namespace}" "${interface}" + did_interface_receive "${interface}" "${ip_address}" + rc=3D$? + + clear_tcpdump_outputs "${interface}" + + if [[ "${rc}" -eq 0 ]]; then + return 1 + else + return 0 + fi +} diff --git a/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh= b/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh new file mode 100755 index 000000000000..f1a8639fd83c --- /dev/null +++ b/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh @@ -0,0 +1,246 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# These tests verify that teamd is able to enable and disable ports via the +# active backup runner. +# +# Topology: +# +# +-------------------------+ NS1 +# | test_team1 | +# | + | +# | eth0 | eth1 | +# | +---+---+ | +# | | | | +# +-------------------------+ +# | | +# +-------------------------+ NS2 +# | | | | +# | +-------+ | +# | eth0 | eth1 | +# | + | +# | test_team2 | +# +-------------------------+ + +export ALL_TESTS=3D"teamd_test_active_backup" + +test_dir=3D"$(dirname "$0")" +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/lib.sh" +# shellcheck disable=3DSC1091 +source "${test_dir}/team_lib.sh" + +NS1=3D"" +NS2=3D"" +export NODAD=3D"nodad" +PREFIX_LENGTH=3D"64" +NS1_IP=3D"fd00::1" +NS2_IP=3D"fd00::2" +NS1_IP4=3D"192.168.0.1" +NS2_IP4=3D"192.168.0.2" +NS1_TEAMD_CONF=3D"" +NS2_TEAMD_CONF=3D"" +NS1_TEAMD_PID=3D"" +NS2_TEAMD_PID=3D"" + +while getopts "4" opt; do + case $opt in + 4) + echo "IPv4 mode selected." + export NODAD=3D + PREFIX_LENGTH=3D"24" + NS1_IP=3D"${NS1_IP4}" + NS2_IP=3D"${NS2_IP4}" + ;; + \?) + echo "Invalid option: -${OPTARG}" >&2 + exit 1 + ;; + esac +done + +teamd_config_create() +{ + local runner=3D$1 + local dev=3D$2 + local conf + + conf=3D$(mktemp) + + cat > "${conf}" <<-EOF + { + "device": "${dev}", + "runner": {"name": "${runner}"}, + "ports": { + "eth0": {}, + "eth1": {} + } + } + EOF + echo "${conf}" +} + +# Create the network namespaces, veth pair, and team devices in the specif= ied +# runner. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# runner - The Teamd runner to use for the Team devices. +environment_create() +{ + local runner=3D$1 + + echo "Setting up two-link aggregation for runner ${runner}" + echo "Teamd version is: $(teamd --version)" + trap environment_destroy EXIT + + setup_ns ns1 ns2 + NS1=3D"${NS_LIST[0]}" + NS2=3D"${NS_LIST[1]}" + + for link in $(seq 0 1); do + ip -n "${NS1}" link add "eth${link}" type veth peer name \ + "eth${link}" netns "${NS2}" + check_err $? "Failed to create veth pair" + done + + NS1_TEAMD_CONF=3D$(teamd_config_create "${runner}" "test_team1") + NS2_TEAMD_CONF=3D$(teamd_config_create "${runner}" "test_team2") + echo "Conf files are ${NS1_TEAMD_CONF} and ${NS2_TEAMD_CONF}" + + ip netns exec "${NS1}" teamd -d -f "${NS1_TEAMD_CONF}" + check_err $? "Failed to create team device in ${NS1}" + NS1_TEAMD_PID=3D$(pgrep -f "teamd -d -f ${NS1_TEAMD_CONF}") + + ip netns exec "${NS2}" teamd -d -f "${NS2_TEAMD_CONF}" + check_err $? "Failed to create team device in ${NS2}" + NS2_TEAMD_PID=3D$(pgrep -f "teamd -d -f ${NS2_TEAMD_CONF}") + + echo "Created team devices" + echo "Teamd PIDs are ${NS1_TEAMD_PID} and ${NS2_TEAMD_PID}" + + ip -n "${NS1}" link set test_team1 up + check_err $? "Failed to set test_team1 up in ${NS1}" + ip -n "${NS2}" link set test_team2 up + check_err $? "Failed to set test_team2 up in ${NS2}" + + ip -n "${NS1}" addr add "${NS1_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \ + test_team1 + check_err $? "Failed to add address to team device in ${NS1}" + ip -n "${NS2}" addr add "${NS2_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \ + test_team2 + check_err $? "Failed to add address to team device in ${NS2}" + + slowwait 2 timeout 0.5 ip netns exec "${NS1}" ping -W 1 -c 1 "${NS2_IP}" +} + +# Tear down the environment: kill teamd and delete network namespaces. +environment_destroy() +{ + echo "Tearing down two-link aggregation" + + rm "${NS1_TEAMD_CONF}" + rm "${NS2_TEAMD_CONF}" + + # First, try graceful teamd teardown. + ip netns exec "${NS1}" teamd -k -t test_team1 + ip netns exec "${NS2}" teamd -k -t test_team2 + + # If teamd can't be killed gracefully, then sigkill. + if kill -0 "${NS1_TEAMD_PID}" 2>/dev/null; then + echo "Sending sigkill to teamd for test_team1" + kill -9 "${NS1_TEAMD_PID}" + rm /var/run/teamd/test_team1.{pid,sock} + fi + if kill -0 "${NS2_TEAMD_PID}" 2>/dev/null; then + echo "Sending sigkill to teamd for test_team2" + kill -9 "${NS2_TEAMD_PID}" + rm /var/run/teamd/test_team2.{pid,sock} + fi + cleanup_all_ns +} + +# Change the active port for an active-backup mode team. +# Arguments: +# namespace - The network namespace that the team is in. +# team - The name of the team. +# active_port - The port to make active. +set_active_port() +{ + local namespace=3D$1 + local team=3D$2 + local active_port=3D$3 + + ip netns exec "${namespace}" teamdctl "${team}" state item set \ + runner.active_port "${active_port}" + slowwait 2 bash -c "ip netns exec ${namespace} teamdctl ${team} state \ + item get runner.active_port | grep -q ${active_port}" +} + +# Wait for an interface to stop receiving traffic. If it keeps receiving t= raffic +# for the duration of the timeout, then return an error. +# Arguments: +# - namespace - The network namespace that the interface is in. +# - interface - The name of the interface. +wait_to_stop_receiving() +{ + local namespace=3D$1 + local interface=3D$2 + + echo "Waiting for ${interface} in ${namespace} to stop receiving" + slowwait 10 check_no_traffic "${interface}" "${NS2_IP}" \ + "${namespace}" +} + +# Test that active backup runner can change active ports. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +teamd_test_active_backup() +{ + export RET=3D0 + + start_listening_and_sending + + ### Scenario 1: Don't manually set active port, just make sure team + # works. + save_tcpdump_outputs "${NS2}" test_team2 + did_interface_receive test_team2 "${NS2_IP}" + check_err $? "Traffic did not reach team interface in NS2." + clear_tcpdump_outputs test_team2 + + ### Scenario 2: Choose active port. + set_active_port "${NS1}" test_team1 eth1 + set_active_port "${NS2}" test_team2 eth1 + + wait_to_stop_receiving "${NS2}" eth0 + save_tcpdump_outputs "${NS2}" eth0 eth1 + did_interface_receive eth0 "${NS2_IP}" + check_fail $? "eth0 IS transmitting when inactive" + did_interface_receive eth1 "${NS2_IP}" + check_err $? "eth1 not transmitting when active" + clear_tcpdump_outputs eth0 eth1 + + ### Scenario 3: Change active port. + set_active_port "${NS1}" test_team1 eth0 + set_active_port "${NS2}" test_team2 eth0 + + wait_to_stop_receiving "${NS2}" eth1 + save_tcpdump_outputs "${NS2}" eth0 eth1 + did_interface_receive eth0 "${NS2_IP}" + check_err $? "eth0 not transmitting when active" + did_interface_receive eth1 "${NS2_IP}" + check_fail $? "eth1 IS transmitting when inactive" + clear_tcpdump_outputs eth0 eth1 + + log_test "teamd active backup runner test" + + stop_sending_and_listening +} + +require_command teamd +require_command teamdctl +require_command iperf3 +require_command tcpdump +environment_create activebackup +tests_run +exit "${EXIT_STATUS}" diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/n= et/lib.sh index e915386daf1b..b3827b43782b 100644 --- a/tools/testing/selftests/net/lib.sh +++ b/tools/testing/selftests/net/lib.sh @@ -224,6 +224,19 @@ setup_ns() NS_LIST+=3D("${ns_list[@]}") } =20 +in_all_ns() +{ + local ret=3D0 + local ns_list=3D("${NS_LIST[@]}") + + for ns in "${ns_list[@]}"; do + ip netns exec "${ns}" "$@" + (( ret =3D ret || $? )) + done + + return "${ret}" +} + # Create netdevsim with given id and net namespace. create_netdevsim() { local id=3D"$1" --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BEE6373C0C for ; Wed, 8 Apr 2026 02:52:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616764; cv=none; b=F0Jl6YXCwOU5FKq4wG+beZfle4ystrn6S1KF+S1k3PF+XWGHKAtG35UjNgA+oSAPPBNgtwmSUTBxr7c6mej0xYBRqXn2ajJteN7+ffs4nW17c6cVkGlu9HRUmXSixf1snT0zxHpL+KReu4ky3o9wx8W6zx4AeO3bWIvA2DS5ruI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616764; c=relaxed/simple; bh=oH22fdqSNJSpaqo3JGrJKQygV29uz4pTKSxAP7bGPfQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Uj42+d//VccRdRmZ1z0Zz5Zpe3kiBfEm5Gldmp1KpYrT5VSAgMMbU81vNta+XjZ5bwy0xn3YqW3S3zYp3LmTtbBqPgAhCoM+8JF3nZVrAjGXe/0jNfnYri/mjx35K8URpAeTZREhZjWz4HIRl1LeifHyGZC/lXWQMoo2RDq0G5c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=hIYJ4Gea; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hIYJ4Gea" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-1279caef718so8986255c88.1 for ; Tue, 07 Apr 2026 19:52:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616759; x=1776221559; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=qJ4xpDhza9yvGUIAi+VUP5bjGD/EsXUsUZaTLZUbPU4=; b=hIYJ4Geajq9V/7q4Zu+n9lcOEP6fOKqX1iYDSkh6C4MGFQBxZzJcr+aJ+531/gWLtJ oWfX+lJFIUax1tsS78vRmVjymGGT46DTMHBp4oOgqkbDwxaNEWO5nlFImlYrozauNkjN yBbrmf9feMmZIRYC331UjcmbPmSoWUdKcFZB+stiHPMlUNSVSYZuOkVgihzzwgAnhLMC KuzpJkmPBxy6OsgehpJrJ1D11+DiAXv7fpXx+PZTVmOmpk8Ln5CpzJedTRWPQE48z7le 4s4k8YbYXh1kWd3FewdR6h/cUfEgVdC8J9Jv/GJBBaNSwI1YZHJRkft7IhNJxoel0AOv BcNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616759; x=1776221559; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=qJ4xpDhza9yvGUIAi+VUP5bjGD/EsXUsUZaTLZUbPU4=; b=SWbKg5hCADl3aiibefOAgd0qZSjCjW2q59FPtCBDKmDvqIUL7P1dBhwDOq/6ehfBjN mZPapBpPdvRBUqR4nkxjLV9SpCzrKg/eBHsQpSH6yunpjrMzXsg+rQ/aBqbYLoa8RpTG PI1vR3Ul/EMKWDVirkfGuRPTTXvJtVfk5tYUP71tWBf2mZoZA57k3AbjnBC25iRWg0c2 1BS24UruYDT3AnZPpcUJ4nwBcy/6GmMZX9ipVGSOYApLKeDoXgIr3g7KsbxIpSAGX9Ha UWVL9pk8W8eTvQAavVTdU7hA8hh2wfuDV+AYPesD9v5j1l4xKLzygQHNmPprX7rn19Od jeqg== X-Forwarded-Encrypted: i=1; AJvYcCWlnuCnUaXkIh03zMbnCX3kGHtyEGykI1s4MTguNz6Ai9wfOiune4U88mVVe9N5CRFa4jOIg47Uc0HDQqo=@vger.kernel.org X-Gm-Message-State: AOJu0Yw8nqUfAn0ja7h2rQAcx+89Fg/p4Bytuxjzrtg95+p13Y2bvNKD /25fycH7RCNiAaHsUA1xw5fONVuCFgRTYyjxvpYPoG/pHa5kChYNf5oFJSFkSSK7267DoBLlUNl uGeN5zHfdVgm6hhAEUg89mA== X-Received: from dlaj10.prod.google.com ([2002:a05:701b:280a:b0:12c:580:a828]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:41a3:b0:12a:7181:2eff with SMTP id a92af1059eb24-12bfb6ec49emr8944307c88.4.1775616758530; Tue, 07 Apr 2026 19:52:38 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:25 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=10753; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=oH22fdqSNJSpaqo3JGrJKQygV29uz4pTKSxAP7bGPfQ=; b=2mr8LC0g5CNSv+yuDeTTAGFvkUuSrp7b6OA3/rT10RLlKxf3L9hoC6Yv+aYE2NWNZ+XBdRoiR cW6Ls5OtyY2AGgrje0u896MaSZRVnqHN0NEaeR/udi17467fShE+MN+ X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-6-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 06/10] net: team: Rename enablement functions and struct members to tx From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Add no functional changes, but rename enablement functions, variables etc. that are used in teaming driver transmit decisions. Since rx and tx enablement are still coupled, some of the variables renamed in this patch are still used for the rx path, but that will change in a follow-up patch. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- Changes in v4: - New patch: split from the original monolithic v3 patch "net: team: Decouple rx and tx enablement in the team driver". - Link to v3: https://lore.kernel.org/netdev/20260402-teaming-driver-intern= al-v3-6-e8cfdec3b5c2@google.com/ --- drivers/net/team/team_core.c | 44 +++++++++++++++-------------= -- drivers/net/team/team_mode_loadbalance.c | 2 +- drivers/net/team/team_mode_random.c | 4 +-- drivers/net/team/team_mode_roundrobin.c | 2 +- include/linux/if_team.h | 46 +++++++++++++++++-----------= ---- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index 2ce31999c99f..826769473878 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -532,13 +532,13 @@ static void team_adjust_ops(struct team *team) * correct ops are always set. */ =20 - if (!team->en_port_count || !team_is_mode_set(team) || + if (!team->tx_en_port_count || !team_is_mode_set(team) || !team->mode->ops->transmit) team->ops.transmit =3D team_dummy_transmit; else team->ops.transmit =3D team->mode->ops->transmit; =20 - if (!team->en_port_count || !team_is_mode_set(team) || + if (!team->tx_en_port_count || !team_is_mode_set(team) || !team->mode->ops->receive) team->ops.receive =3D team_dummy_receive; else @@ -831,7 +831,7 @@ static bool team_queue_override_port_has_gt_prio_than(s= truct team_port *port, return true; if (port->priority > cur->priority) return false; - if (port->index < cur->index) + if (port->tx_index < cur->tx_index) return true; return false; } @@ -929,7 +929,7 @@ static bool team_port_find(const struct team *team, =20 /* * Enable/disable port by adding to enabled port hashlist and setting - * port->index (Might be racy so reader could see incorrect ifindex when + * port->tx_index (Might be racy so reader could see incorrect ifindex when * processing a flying packet, but that is not a problem). Write guarded * by RTNL. */ @@ -938,10 +938,10 @@ static void team_port_enable(struct team *team, { if (team_port_enabled(port)) return; - WRITE_ONCE(port->index, team->en_port_count); - WRITE_ONCE(team->en_port_count, team->en_port_count + 1); - hlist_add_head_rcu(&port->hlist, - team_port_index_hash(team, port->index)); + WRITE_ONCE(port->tx_index, team->tx_en_port_count); + WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count + 1); + hlist_add_head_rcu(&port->tx_hlist, + team_tx_port_index_hash(team, port->tx_index)); team_adjust_ops(team); team_queue_override_port_add(team, port); team_notify_peers(team); @@ -951,15 +951,17 @@ static void team_port_enable(struct team *team, =20 static void __reconstruct_port_hlist(struct team *team, int rm_index) { - int i; + struct hlist_head *tx_port_index_hash; struct team_port *port; + int i; =20 - for (i =3D rm_index + 1; i < team->en_port_count; i++) { - port =3D team_get_port_by_index(team, i); - hlist_del_rcu(&port->hlist); - WRITE_ONCE(port->index, port->index - 1); - hlist_add_head_rcu(&port->hlist, - team_port_index_hash(team, port->index)); + for (i =3D rm_index + 1; i < team->tx_en_port_count; i++) { + port =3D team_get_port_by_tx_index(team, i); + hlist_del_rcu(&port->tx_hlist); + WRITE_ONCE(port->tx_index, port->tx_index - 1); + tx_port_index_hash =3D team_tx_port_index_hash(team, + port->tx_index); + hlist_add_head_rcu(&port->tx_hlist, tx_port_index_hash); } } =20 @@ -970,10 +972,10 @@ static void team_port_disable(struct team *team, return; if (team->ops.port_tx_disabled) team->ops.port_tx_disabled(team, port); - hlist_del_rcu(&port->hlist); - __reconstruct_port_hlist(team, port->index); - WRITE_ONCE(port->index, -1); - WRITE_ONCE(team->en_port_count, team->en_port_count - 1); + hlist_del_rcu(&port->tx_hlist); + __reconstruct_port_hlist(team, port->tx_index); + WRITE_ONCE(port->tx_index, -1); + WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1); team_queue_override_port_del(team, port); team_adjust_ops(team); team_lower_state_changed(port); @@ -1244,7 +1246,7 @@ static int team_port_add(struct team *team, struct ne= t_device *port_dev, netif_addr_unlock_bh(dev); } =20 - WRITE_ONCE(port->index, -1); + WRITE_ONCE(port->tx_index, -1); list_add_tail_rcu(&port->list, &team->port_list); team_port_enable(team, port); netdev_compute_master_upper_features(dev, true); @@ -1595,7 +1597,7 @@ static int team_init(struct net_device *dev) return -ENOMEM; =20 for (i =3D 0; i < TEAM_PORT_HASHENTRIES; i++) - INIT_HLIST_HEAD(&team->en_port_hlist[i]); + INIT_HLIST_HEAD(&team->tx_en_port_hlist[i]); INIT_LIST_HEAD(&team->port_list); err =3D team_queue_override_init(team); if (err) diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/te= am_mode_loadbalance.c index 840f409d250b..4833fbfe241e 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -120,7 +120,7 @@ static struct team_port *lb_hash_select_tx_port(struct = team *team, { int port_index =3D team_num_to_port_index(team, hash); =20 - return team_get_port_by_index_rcu(team, port_index); + return team_get_port_by_tx_index_rcu(team, port_index); } =20 /* Hash to port mapping select tx port */ diff --git a/drivers/net/team/team_mode_random.c b/drivers/net/team/team_mo= de_random.c index 169a7bc865b2..370e974f3dca 100644 --- a/drivers/net/team/team_mode_random.c +++ b/drivers/net/team/team_mode_random.c @@ -16,8 +16,8 @@ static bool rnd_transmit(struct team *team, struct sk_buf= f *skb) struct team_port *port; int port_index; =20 - port_index =3D get_random_u32_below(READ_ONCE(team->en_port_count)); - port =3D team_get_port_by_index_rcu(team, port_index); + port_index =3D get_random_u32_below(READ_ONCE(team->tx_en_port_count)); + port =3D team_get_port_by_tx_index_rcu(team, port_index); if (unlikely(!port)) goto drop; port =3D team_get_first_port_txable_rcu(team, port); diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/tea= m_mode_roundrobin.c index dd405d82c6ac..ecbeef28c221 100644 --- a/drivers/net/team/team_mode_roundrobin.c +++ b/drivers/net/team/team_mode_roundrobin.c @@ -27,7 +27,7 @@ static bool rr_transmit(struct team *team, struct sk_buff= *skb) =20 port_index =3D team_num_to_port_index(team, rr_priv(team)->sent_packets++); - port =3D team_get_port_by_index_rcu(team, port_index); + port =3D team_get_port_by_tx_index_rcu(team, port_index); if (unlikely(!port)) goto drop; port =3D team_get_first_port_txable_rcu(team, port); diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 740cb3100dfc..c777170ef552 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -27,10 +27,10 @@ struct team; =20 struct team_port { struct net_device *dev; - struct hlist_node hlist; /* node in enabled ports hash list */ + struct hlist_node tx_hlist; /* node in tx-enabled ports hash list */ struct list_head list; /* node in ordinary list */ struct team *team; - int index; /* index of enabled port. If disabled, it's set to -1 */ + int tx_index; /* index of tx enabled port. If disabled, -1 */ =20 bool linkup; /* either state.linkup or user.linkup */ =20 @@ -77,7 +77,7 @@ static inline struct team_port *team_port_get_rcu(const s= truct net_device *dev) =20 static inline bool team_port_enabled(struct team_port *port) { - return READ_ONCE(port->index) !=3D -1; + return READ_ONCE(port->tx_index) !=3D -1; } =20 static inline bool team_port_txable(struct team_port *port) @@ -190,10 +190,10 @@ struct team { const struct header_ops *header_ops_cache; =20 /* - * List of enabled ports and their count + * List of tx-enabled ports and counts of rx and tx-enabled ports. */ - int en_port_count; - struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES]; + int tx_en_port_count; + struct hlist_head tx_en_port_hlist[TEAM_PORT_HASHENTRIES]; =20 struct list_head port_list; /* list of all ports */ =20 @@ -237,41 +237,43 @@ static inline int team_dev_queue_xmit(struct team *te= am, struct team_port *port, return dev_queue_xmit(skb); } =20 -static inline struct hlist_head *team_port_index_hash(struct team *team, - int port_index) +static inline struct hlist_head *team_tx_port_index_hash(struct team *team, + int tx_port_index) { - return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)]; + unsigned int list_entry =3D tx_port_index & (TEAM_PORT_HASHENTRIES - 1); + + return &team->tx_en_port_hlist[list_entry]; } =20 -static inline struct team_port *team_get_port_by_index(struct team *team, - int port_index) +static inline struct team_port *team_get_port_by_tx_index(struct team *tea= m, + int tx_port_index) { + struct hlist_head *head =3D team_tx_port_index_hash(team, tx_port_index); struct team_port *port; - struct hlist_head *head =3D team_port_index_hash(team, port_index); =20 - hlist_for_each_entry(port, head, hlist) - if (port->index =3D=3D port_index) + hlist_for_each_entry(port, head, tx_hlist) + if (port->tx_index =3D=3D tx_port_index) return port; return NULL; } =20 static inline int team_num_to_port_index(struct team *team, unsigned int n= um) { - int en_port_count =3D READ_ONCE(team->en_port_count); + int tx_en_port_count =3D READ_ONCE(team->tx_en_port_count); =20 - if (unlikely(!en_port_count)) + if (unlikely(!tx_en_port_count)) return 0; - return num % en_port_count; + return num % tx_en_port_count; } =20 -static inline struct team_port *team_get_port_by_index_rcu(struct team *te= am, - int port_index) +static inline struct team_port *team_get_port_by_tx_index_rcu(struct team = *team, + int tx_port_index) { + struct hlist_head *head =3D team_tx_port_index_hash(team, tx_port_index); struct team_port *port; - struct hlist_head *head =3D team_port_index_hash(team, port_index); =20 - hlist_for_each_entry_rcu(port, head, hlist) - if (READ_ONCE(port->index) =3D=3D port_index) + hlist_for_each_entry_rcu(port, head, tx_hlist) + if (READ_ONCE(port->tx_index) =3D=3D tx_port_index) return port; return NULL; } --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BC6537267D for ; Wed, 8 Apr 2026 02:52:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616764; cv=none; b=I0+nBYkxOMEIqqmWBZ71L5ixSG1fVasm/cX4m05fQOU1kvvYUkUj/wsBnvpjPHjuFzWLFFaiGkneV4Zyjc2D7Xl2K3yJ0geni3vMf66ncezxMF67MEoGmnUMRERlVvgxUuNOLY8PG9nUv0nbXNWezqhE1UlqJrvNYd6tr5E8pYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616764; c=relaxed/simple; bh=eMqaikrJDeYNfUMhslQU9p/PNnQcABSE67+YKPMPpAs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T0rrt+rzhIOaj+zKWvs4HBlLXIxJPqPLqJqLmpbjO3m8rv8wUe5USkE8Vid5Tig+Gu0DbDJnhoJ+STLvdQ37930I8mKbPWdNXvBgpzRCiZ5gFZd1uWp1OvzW9hTyVfxng21YRPeH1UVBOrQvNGQnh+TMkteRcKjFw441FI2ZO+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=hkVtwTey; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hkVtwTey" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-12737f276a2so9058162c88.1 for ; Tue, 07 Apr 2026 19:52:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616760; x=1776221560; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=SCOV5PVZ0/9+BmL80DppSiUK4xF2oayBnBsK0SdDfuw=; b=hkVtwTeyYVG1yX7RVL5rlhE+lOgB2OvgQljUdDm6xUuJ/dYefHp4i028gnVOroTC82 MZo5Q/wGzLdZL2XJLH7sZ5sUWrlrS4vM7KTFyZ1t4i+j9jkH4ZR3M+P2v3cFPXRNUcCc edXT8MjU62gjTzSbj5GZrDx3G7HhVDSUiHSBqjqdC4RX/7cBMJOAppEPn8FfcKDwU6lJ mDcagpLOEMQLW6q5F2Q9svhBtmZiY+AczPelXvRkqk58w7GY8T6Kqovs58bMDwQiYLoA alaHhDf1JdUKc9jVwYNjJlQTuI2HV8VHr33Jng5DjO/124+leIAAOS4EIiJr5euzdl+k 6Q+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616760; x=1776221560; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=SCOV5PVZ0/9+BmL80DppSiUK4xF2oayBnBsK0SdDfuw=; b=TdArNyPZFIZ6g/hn4C37KvLW1VDYSZXqPVrA4Z/Z+p8h+rNxQy0YKKu/E54xrhMBcU tLsBvbJgWlmt0ingleWo0buekNr7zt8yJp3xPoVYoDupr5leDUm45ftDnKYQqho0epl0 mFMhfRY0RU+CXgorEyD7RfmXZB6de4ukEfBeX77zA+WTePjCP6hUJH/eWYvivp+at8Xx 2liUBPoOVMIvgyjor0aWjYQpNJ4V3dj8TCrVPVnLAwnjgbQG/iLBKuU8SkkDIygJmgzt dXqputYfWPzbuG3MBFGU1MJoLC3ndPcdW6KVkjs9t2hXQmbyGsPg8h2wikMqyE91VGJq 5C0g== X-Forwarded-Encrypted: i=1; AJvYcCXLqgwBEIYSjJYNJgZqu6CUnVLfqZWfeuLDQYXWc/HbdpHLYK/+OpmRWT3iSZvYBhQgKYIxG40NfSmRSOA=@vger.kernel.org X-Gm-Message-State: AOJu0Yy4EKol4F5NWqeIkl7+oVuDjVAI3RHRWp2ql1huj+mN7VDvHf5O ZMwcPZsXMnJs5Efkr7fVWiYwv/BemNNSTICBsiJL96KRMysn3EkBimSNr6Sxe2EfoBCHfGfnDcT XkU8QiUwZucXPKfwwvCWY9w== X-Received: from dycc15.prod.google.com ([2002:a05:693c:60cf:b0:2c6:415a:9023]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:62aa:b0:12a:72af:83d2 with SMTP id a92af1059eb24-12bfb7109c0mr9410902c88.14.1775616760223; Tue, 07 Apr 2026 19:52:40 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:26 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=9038; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=eMqaikrJDeYNfUMhslQU9p/PNnQcABSE67+YKPMPpAs=; b=Dd/qWxK0iiZ4X3BIMci8eyVnoG1gW8XzIWzDZs6nKEE1TG753dhyJkkrp7f3vLzlLG6xPNi0J zb8u79TiACUAjLZSNqMQlH1oUxeTK6j2RvJlSsAcBi2bCGiWDCQp6iX X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-7-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 07/10] net: team: Track rx enablement separately from tx enablement From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Separate the rx and tx enablement/disablement into different functions so that it is easier to interact with them independently later. Although this patch changes receive and transmit paths, the actual behavior of the teaming driver should remain unchanged, since there is no option introduced yet to change rx or tx enablement independently. Those options will be added in follow-up patches. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- Changes in v5: - Reorder function calls in team_port_enable() to make sure the call order stays the same as before. - Link to v4: https://lore.kernel.org/netdev/20260403-teaming-driver-intern= al-v4-7-d3032f33ca25@google.com/ Changes in v4: - New patch: split from the original monolithic v3 patch "net: team: Decouple rx and tx enablement in the team driver". - Link to v3: https://lore.kernel.org/netdev/20260402-teaming-driver-intern= al-v3-6-e8cfdec3b5c2@google.com/ --- drivers/net/team/team_core.c | 104 ++++++++++++++++++++++++---= ---- drivers/net/team/team_mode_loadbalance.c | 2 +- include/linux/if_team.h | 16 ++++- 3 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index 826769473878..e437099a5a17 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -87,7 +87,7 @@ static void team_lower_state_changed(struct team_port *po= rt) struct netdev_lag_lower_state_info info; =20 info.link_up =3D port->linkup; - info.tx_enabled =3D team_port_enabled(port); + info.tx_enabled =3D team_port_tx_enabled(port); netdev_lower_state_changed(port->dev, &info); } =20 @@ -538,7 +538,7 @@ static void team_adjust_ops(struct team *team) else team->ops.transmit =3D team->mode->ops->transmit; =20 - if (!team->tx_en_port_count || !team_is_mode_set(team) || + if (!team->rx_en_port_count || !team_is_mode_set(team) || !team->mode->ops->receive) team->ops.receive =3D team_dummy_receive; else @@ -734,7 +734,7 @@ static rx_handler_result_t team_handle_frame(struct sk_= buff **pskb) =20 port =3D team_port_get_rcu(skb->dev); team =3D port->team; - if (!team_port_enabled(port)) { + if (!team_port_rx_enabled(port)) { if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) /* link-local packets are mostly useful when stack receives them * with the link they arrive on. @@ -876,7 +876,7 @@ static void __team_queue_override_enabled_check(struct = team *team) static void team_queue_override_port_prio_changed(struct team *team, struct team_port *port) { - if (!port->queue_id || !team_port_enabled(port)) + if (!port->queue_id || !team_port_tx_enabled(port)) return; __team_queue_override_port_del(team, port); __team_queue_override_port_add(team, port); @@ -887,7 +887,7 @@ static void team_queue_override_port_change_queue_id(st= ruct team *team, struct team_port *port, u16 new_queue_id) { - if (team_port_enabled(port)) { + if (team_port_tx_enabled(port)) { __team_queue_override_port_del(team, port); port->queue_id =3D new_queue_id; __team_queue_override_port_add(team, port); @@ -927,26 +927,33 @@ static bool team_port_find(const struct team *team, return false; } =20 +static void __team_port_enable_rx(struct team *team, + struct team_port *port) +{ + team->rx_en_port_count++; + WRITE_ONCE(port->rx_enabled, true); +} + +static void __team_port_disable_rx(struct team *team, + struct team_port *port) +{ + team->rx_en_port_count--; + WRITE_ONCE(port->rx_enabled, false); +} + /* - * Enable/disable port by adding to enabled port hashlist and setting - * port->tx_index (Might be racy so reader could see incorrect ifindex when - * processing a flying packet, but that is not a problem). Write guarded - * by RTNL. + * Enable just TX on the port by adding to tx-enabled port hashlist and + * setting port->tx_index (Might be racy so reader could see incorrect + * ifindex when processing a flying packet, but that is not a problem). + * Write guarded by RTNL. */ -static void team_port_enable(struct team *team, - struct team_port *port) +static void __team_port_enable_tx(struct team *team, + struct team_port *port) { - if (team_port_enabled(port)) - return; WRITE_ONCE(port->tx_index, team->tx_en_port_count); WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count + 1); hlist_add_head_rcu(&port->tx_hlist, team_tx_port_index_hash(team, port->tx_index)); - team_adjust_ops(team); - team_queue_override_port_add(team, port); - team_notify_peers(team); - team_mcast_rejoin(team); - team_lower_state_changed(port); } =20 static void __reconstruct_port_hlist(struct team *team, int rm_index) @@ -965,20 +972,69 @@ static void __reconstruct_port_hlist(struct team *tea= m, int rm_index) } } =20 -static void team_port_disable(struct team *team, - struct team_port *port) +static void __team_port_disable_tx(struct team *team, + struct team_port *port) { - if (!team_port_enabled(port)) - return; if (team->ops.port_tx_disabled) team->ops.port_tx_disabled(team, port); + hlist_del_rcu(&port->tx_hlist); __reconstruct_port_hlist(team, port->tx_index); + WRITE_ONCE(port->tx_index, -1); WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1); - team_queue_override_port_del(team, port); +} + +/* + * Enable TX AND RX on the port. + */ +static void team_port_enable(struct team *team, + struct team_port *port) +{ + bool rx_was_enabled; + bool tx_was_enabled; + + if (team_port_enabled(port)) + return; + + rx_was_enabled =3D team_port_rx_enabled(port); + tx_was_enabled =3D team_port_tx_enabled(port); + + if (!rx_was_enabled) + __team_port_enable_rx(team, port); + if (!tx_was_enabled) + __team_port_enable_tx(team, port); + + team_adjust_ops(team); + if (!tx_was_enabled) + team_queue_override_port_add(team, port); + team_notify_peers(team); + if (!rx_was_enabled) + team_mcast_rejoin(team); + if (!tx_was_enabled) + team_lower_state_changed(port); +} + +static void team_port_disable(struct team *team, + struct team_port *port) +{ + bool rx_was_enabled =3D team_port_rx_enabled(port); + bool tx_was_enabled =3D team_port_tx_enabled(port); + + if (!tx_was_enabled && !rx_was_enabled) + return; + + if (tx_was_enabled) { + __team_port_disable_tx(team, port); + team_queue_override_port_del(team, port); + } + if (rx_was_enabled) + __team_port_disable_rx(team, port); + team_adjust_ops(team); - team_lower_state_changed(port); + + if (tx_was_enabled) + team_lower_state_changed(port); } =20 static int team_port_enter(struct team *team, struct team_port *port) diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/te= am_mode_loadbalance.c index 4833fbfe241e..38a459649569 100644 --- a/drivers/net/team/team_mode_loadbalance.c +++ b/drivers/net/team/team_mode_loadbalance.c @@ -380,7 +380,7 @@ static int lb_tx_hash_to_port_mapping_set(struct team *= team, =20 list_for_each_entry(port, &team->port_list, list) { if (ctx->data.u32_val =3D=3D port->dev->ifindex && - team_port_enabled(port)) { + team_port_tx_enabled(port)) { rcu_assign_pointer(LB_HTPM_PORT_BY_HASH(lb_priv, hash), port); return 0; diff --git a/include/linux/if_team.h b/include/linux/if_team.h index c777170ef552..3d21e06fda67 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -31,6 +31,7 @@ struct team_port { struct list_head list; /* node in ordinary list */ struct team *team; int tx_index; /* index of tx enabled port. If disabled, -1 */ + bool rx_enabled; =20 bool linkup; /* either state.linkup or user.linkup */ =20 @@ -75,14 +76,24 @@ static inline struct team_port *team_port_get_rcu(const= struct net_device *dev) return rcu_dereference(dev->rx_handler_data); } =20 -static inline bool team_port_enabled(struct team_port *port) +static inline bool team_port_rx_enabled(struct team_port *port) +{ + return READ_ONCE(port->rx_enabled); +} + +static inline bool team_port_tx_enabled(struct team_port *port) { return READ_ONCE(port->tx_index) !=3D -1; } =20 +static inline bool team_port_enabled(struct team_port *port) +{ + return team_port_rx_enabled(port) && team_port_tx_enabled(port); +} + static inline bool team_port_txable(struct team_port *port) { - return port->linkup && team_port_enabled(port); + return port->linkup && team_port_tx_enabled(port); } =20 static inline bool team_port_dev_txable(const struct net_device *port_dev) @@ -193,6 +204,7 @@ struct team { * List of tx-enabled ports and counts of rx and tx-enabled ports. */ int tx_en_port_count; + int rx_en_port_count; struct hlist_head tx_en_port_hlist[TEAM_PORT_HASHENTRIES]; =20 struct list_head port_list; /* list of all ports */ --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E8B63750AA for ; Wed, 8 Apr 2026 02:52:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616765; cv=none; b=UO7ZeByevfQiJGNMjJzAnjmGmljMIxo9NN0om/W6mQ1Dgs/cCOmrrn/6h4Ete5QcXnj8oNcRCPKlkWMge1XBQkXrrZwLrqPqq02ccRZz9QSdRKTLI12Xey8lIPl7d9QYvEHo8q4mbCZ0MJEYJjHSiMURq0NpdUEDRD5Fu6eVle4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616765; c=relaxed/simple; bh=dBMLccK+J+0/DzFeaxJbXeK8uOY7wkjClTEHtsz1Xv4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=r4IS0kNodtlRE0FgF8CqP/ndYDuq73PZjIZf/8NRgHzGcdr8lo/L7O06SMpiTxldCrPzzbG98SB+3vK8j4movHK5Rjtz9ZvbgpgiyuXcFBCJQFJ9EUEkDR0Ms921kb8urbvORDzwbD8kNmisjEM60kxsWe3WSlRMerL7bORHMIk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=uw/qXNOj; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="uw/qXNOj" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2bdc1b30ac8so34275523eec.1 for ; Tue, 07 Apr 2026 19:52:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616762; x=1776221562; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=K5z3QxMvishe4U8CjYjl/4RpCskWtOirL2kQpSgWFR0=; b=uw/qXNOjyBAKdVcGb+sPnrr6bK1ZtZ+Igtp8ZXpJNJbBxFFvOucLPFILuQd2WpA2JE jKC3KGhQ1cKMj646dlJ0bY59vMKdyI7Cv+mA8ol+P/W6dg7qRVCRPhqFE8jKLPlN3TjF Pn4YWq7pi/iVxKBNUr6klWMVRCpEvT1t3HnB/euhQHYoIqmwS6DSrAOAXlUvzWWCEQcl YNcVxuaUcSSoltilObN6uH1A/4QpJO8bq74KlNXJ03BOfe99NndvClvmHtk9ObIGM5uB pOBwM2f2oqM98R2W6Ug+lAokh6gxoi5F0AUuVM/xlxIi8HjndedIYUBA78+fbB9SIeNV Bm/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616762; x=1776221562; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K5z3QxMvishe4U8CjYjl/4RpCskWtOirL2kQpSgWFR0=; b=a2Iji0G1+FD5BH+e7gJoE48ybk3kf0qW63bgd0yew6YPIT0Xi6+aaki4EbdM8qOpZR NDXxxUhv5IM2CaFYmdEY9kbxYKhcx+/FcFt2UM5IDO69PXHK1hsK83H9frYjf7KS6iff uiP03+H7Iz3mgRDr9YjRqONlvQIfUjl6Y6daiekVxiSgvKNN3XiTeAGAC7F3drskLS9E GY/kDzkkqWpe8NFsdw2vg9IGSAJS0RoFyB/SGfcHPjIxACbRbJWH9Sl4UVXXFHAdzueA 1cJ6s4eEf9srzUyVdKayjaAXCXxiCBBDnMHbXqHeCIIwOnsObtI6l+b8rB13MKh+OIQB 9a4g== X-Forwarded-Encrypted: i=1; AJvYcCVW89AQa3KreK7YiEcINE55kgJ71dtUXqik84de3nlgHMMGaL3EGSqygaLDmPsI6x9Er/7d4tq1SJ15gbU=@vger.kernel.org X-Gm-Message-State: AOJu0YxmiHSFALqth/i3dMrcQdGIY0ionkeN26EmiOVUltoypkYqP3wi 6nI/L10AS5wTwPpf6mzZ/yX/PY2LHHfg4NY1ecjsQ8j1P9Rc3Y0NSYfRWE5KeVxiiqmkfoQWXfB +1Gux0QELg9rEjg05bt2WIQ== X-Received: from dybmi2.prod.google.com ([2002:a05:7301:f82:b0:2cb:90d4:7906]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:5793:b0:2b0:571a:28a5 with SMTP id 5a478bee46e88-2cbfba8dc09mr10999585eec.18.1775616762001; Tue, 07 Apr 2026 19:52:42 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:27 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=2926; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=dBMLccK+J+0/DzFeaxJbXeK8uOY7wkjClTEHtsz1Xv4=; b=f31grsLfcHIFyaF/YLTciGxq8Kxc5MxTHNUJxKdaCfV6HH/fpD2ElJTVw7GNveoy7tCPAvzB1 QYDxEHQLJUaAjECyq4iILSPjSV4W5amz8sauDx/lkX5ZUP6hFvhjYEC X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-8-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 08/10] net: team: Add new rx_enabled team port option From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Allow independent control over rx enablement via the rx_enabled option without affecting tx enablement. This affects the normal enabled option since a port is only considered enabled if both tx and rx are enabled. If this option is not used, then the enabled option will continue to behave exactly as it did before. Tested in a follow-up patch with a new selftest. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- Changes in v4: - New patch: split from the original monolithic v3 patch "net: team: Decouple rx and tx enablement in the team driver". - Link to v3: https://lore.kernel.org/netdev/20260402-teaming-driver-intern= al-v3-6-e8cfdec3b5c2@google.com/ --- drivers/net/team/team_core.c | 49 ++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 49 insertions(+) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index e437099a5a17..67f77de4cf10 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -941,6 +941,28 @@ static void __team_port_disable_rx(struct team *team, WRITE_ONCE(port->rx_enabled, false); } =20 +static void team_port_enable_rx(struct team *team, + struct team_port *port) +{ + if (team_port_rx_enabled(port)) + return; + + __team_port_enable_rx(team, port); + team_adjust_ops(team); + team_notify_peers(team); + team_mcast_rejoin(team); +} + +static void team_port_disable_rx(struct team *team, + struct team_port *port) +{ + if (!team_port_rx_enabled(port)) + return; + + __team_port_disable_rx(team, port); + team_adjust_ops(team); +} + /* * Enable just TX on the port by adding to tx-enabled port hashlist and * setting port->tx_index (Might be racy so reader could see incorrect @@ -1487,6 +1509,26 @@ static int team_port_en_option_set(struct team *team, return 0; } =20 +static void team_port_rx_en_option_get(struct team *team, + struct team_gsetter_ctx *ctx) +{ + struct team_port *port =3D ctx->info->port; + + ctx->data.bool_val =3D team_port_rx_enabled(port); +} + +static int team_port_rx_en_option_set(struct team *team, + struct team_gsetter_ctx *ctx) +{ + struct team_port *port =3D ctx->info->port; + + if (ctx->data.bool_val) + team_port_enable_rx(team, port); + else + team_port_disable_rx(team, port); + return 0; +} + static void team_user_linkup_option_get(struct team *team, struct team_gsetter_ctx *ctx) { @@ -1608,6 +1650,13 @@ static const struct team_option team_options[] =3D { .getter =3D team_port_en_option_get, .setter =3D team_port_en_option_set, }, + { + .name =3D "rx_enabled", + .type =3D TEAM_OPTION_TYPE_BOOL, + .per_port =3D true, + .getter =3D team_port_rx_en_option_get, + .setter =3D team_port_rx_en_option_set, + }, { .name =3D "user_linkup", .type =3D TEAM_OPTION_TYPE_BOOL, --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA9B037756C for ; Wed, 8 Apr 2026 02:52:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616766; cv=none; b=BYBzNJEJU3q8qwoE7DRiIYOnU1OFbcuEtvjhIWoJSpXpoy+NfZnIQdw0TrlsT13sklZeWh8GaQv0bVvJ9cU7GWXOQwCTTKEEg9xeKH4o1nmxt+JLZWX/XP4CndSWKXAl13eOkSIwUajrkQHW8iAXQ2cglBbSmISyhRNXEeffl/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616766; c=relaxed/simple; bh=ysjEMdXBV3p9t7KlXpwCVPcXO8bpDjU9ioNzjR4UBLc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JtQgsjPQ8TnVHyMCGow04jRe/Lg/RViSQwa0YEUh5nEQDKbiDCan8LlrEjyJ5mtJyBfa6vUW+/ilpsXGpG+Fh7t7JSd87xgZaJGqaWOiTrkQaf08phfXkj2Ke0R6nOBhnfJrWRdlwE5GFFyn+RF95QJwIJV/IdKBGY0+bJI1Rtg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=drY41N2E; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="drY41N2E" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-1279caef718so8986397c88.1 for ; Tue, 07 Apr 2026 19:52:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616764; x=1776221564; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=VrKcMgABSh6GKKrkwrLopmtbIwGc13QpOLpRzfT2BBE=; b=drY41N2E3LXUoirzE6wqMbHrW2gt9FP1ISpFr360Ppd23p4GSeHsC18yY9vJ5vWoyf UNV51Bk8SRVI5Tc9iZgZm7aMqJCp1uNgCZgrECbh2D3D3CUAUWdQpS7/kCzbr+lFb6lm Y3mOJH6fSbDpN/xh4PdEQNcjJ61z2GHeRmsv1pSIwz3XuIEsZgVj5GpZ02F/zupcK7v1 6UbxU/Re+kDNwI9eBdHzkXbHSmliPOhw/oJ1QZbUNucaYzAjPt4LJ3z6Vpv88of1+fV0 48ZDUCtDfIRV5PCgjFxRiEdelpxmOiOiDPeMnLzMTGOc15UqU9dWuTjjgyhoommZc4W7 r6nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616764; x=1776221564; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VrKcMgABSh6GKKrkwrLopmtbIwGc13QpOLpRzfT2BBE=; b=PIckk+vjwDkZfnjISJnDeHbDlJKmwcsyCma4utNDptwhlVrK5LAInPGt3HsCSzc/AQ sHqRaTCun+Zf7AKymXa4C90D35pqGeRxGovjRqg5AJJm8OyX/dFTR5uT21YyDL96RH51 me/zSBzoZi9fbWb9EfZfoQSAc5coJU+slh2iBHZY2i49wV27Hk5cWtlfLK9mlyd1k9A2 6WjJAacMC9rj7vNzUjTcNZBPIw//aHh4OiNiVre5UvyOuOYynDKLrhqp9T3sUJDLGAvz 2GqtNSa+jKPS9bE/EG8Gy7I/WPRT5Dz6UvkQSdBwnBAWaD+xMZKgm9egyiv2UAk2TqO5 j6uw== X-Forwarded-Encrypted: i=1; AJvYcCVjkpUQKBzFHIVHdQmkX7oFtQJRx6sU1jV0Je2PpKwiv08oDPPI3ytlJW6c9KuAlOf31jnuBIvt7cjEE0M=@vger.kernel.org X-Gm-Message-State: AOJu0YzV5pAmA679ixahclbwIlvZ/YPwE710AzZU2vNUK2ShKdxbDFeD zA9hfR+6AP/kkXpEpVhL2yNnvFDXpb3i0STtRqGmWznnw47lLR4VaIx1oewnVHWJ57YOLQ/Hi8a dMgJIUBaQ0C+2JF2uLduGrw== X-Received: from dygg16.prod.google.com ([2002:a05:693c:80d0:b0:2d1:13bb:389c]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:43a9:b0:129:ea6:a3c7 with SMTP id a92af1059eb24-12bfb639e37mr9363933c88.0.1775616763806; Tue, 07 Apr 2026 19:52:43 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:28 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=3270; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=ysjEMdXBV3p9t7KlXpwCVPcXO8bpDjU9ioNzjR4UBLc=; b=WeElomngepKKrGJFaACju/baucu5g7d7uyJDIiedsr2TZFl6fmNCZ5f84LzbH+BS/iv/umn/v guEdVAQ1CpWCBM6f6WPm69vVixdWTS2vfw5TSAkCT45G8SEiyd8iT6h X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-9-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 09/10] net: team: Add new tx_enabled team port option From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey , Jiri Pirko Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This option allows independent control over tx enablement without affecting rx enablement. Like the rx_enabled option, this also implicitly affects the enabled option. If this option is not used, then the enabled option will continue to behave as it did before. Tested in a follow-up patch with a new selftest. Reviewed-by: Jiri Pirko Signed-off-by: Marc Harvey --- Changes in v4: - New patch: split from the original monolithic v3 patch "net: team: Decouple rx and tx enablement in the team driver". - Link to v3: https://lore.kernel.org/netdev/20260402-teaming-driver-intern= al-v3-6-e8cfdec3b5c2@google.com/ --- drivers/net/team/team_core.c | 55 ++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 55 insertions(+) diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c index 67f77de4cf10..0c87f9972457 100644 --- a/drivers/net/team/team_core.c +++ b/drivers/net/team/team_core.c @@ -978,6 +978,21 @@ static void __team_port_enable_tx(struct team *team, team_tx_port_index_hash(team, port->tx_index)); } =20 +static void team_port_enable_tx(struct team *team, + struct team_port *port) +{ + if (team_port_tx_enabled(port)) + return; + + __team_port_enable_tx(team, port); + team_adjust_ops(team); + team_queue_override_port_add(team, port); + + /* Don't rejoin multicast, since this port might not be receiving. */ + team_notify_peers(team); + team_lower_state_changed(port); +} + static void __reconstruct_port_hlist(struct team *team, int rm_index) { struct hlist_head *tx_port_index_hash; @@ -1007,6 +1022,19 @@ static void __team_port_disable_tx(struct team *team, WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1); } =20 +static void team_port_disable_tx(struct team *team, + struct team_port *port) +{ + if (!team_port_tx_enabled(port)) + return; + + __team_port_disable_tx(team, port); + + team_queue_override_port_del(team, port); + team_adjust_ops(team); + team_lower_state_changed(port); +} + /* * Enable TX AND RX on the port. */ @@ -1529,6 +1557,26 @@ static int team_port_rx_en_option_set(struct team *t= eam, return 0; } =20 +static void team_port_tx_en_option_get(struct team *team, + struct team_gsetter_ctx *ctx) +{ + struct team_port *port =3D ctx->info->port; + + ctx->data.bool_val =3D team_port_tx_enabled(port); +} + +static int team_port_tx_en_option_set(struct team *team, + struct team_gsetter_ctx *ctx) +{ + struct team_port *port =3D ctx->info->port; + + if (ctx->data.bool_val) + team_port_enable_tx(team, port); + else + team_port_disable_tx(team, port); + return 0; +} + static void team_user_linkup_option_get(struct team *team, struct team_gsetter_ctx *ctx) { @@ -1657,6 +1705,13 @@ static const struct team_option team_options[] =3D { .getter =3D team_port_rx_en_option_get, .setter =3D team_port_rx_en_option_set, }, + { + .name =3D "tx_enabled", + .type =3D TEAM_OPTION_TYPE_BOOL, + .per_port =3D true, + .getter =3D team_port_tx_en_option_get, + .setter =3D team_port_tx_en_option_set, + }, { .name =3D "user_linkup", .type =3D TEAM_OPTION_TYPE_BOOL, --=20 2.53.0.1213.gd9a14994de-goog From nobody Mon Jun 15 03:52:27 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 625CE372EC4 for ; Wed, 8 Apr 2026 02:52:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616770; cv=none; b=rAPkhIZdkXkYKFJBeIQ9k2g4rXWYK89b6J9SX9FpAaswfBDBM+zKtvezWAKkICrgVFegZxUAi1gOjY/VCT3u4xCO+ZjbKXsVtKNoNY5RoPX+mWJh1OCiBGVkaMiBqoESMFxIfp1J8L3xg8k8qK0acXOrL0UtfdGfnNtrdk01+K4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775616770; c=relaxed/simple; bh=zRiZ3F9ixViqIp/oVJOs2Dr/NZnvNeO1TEoDMXNAr2A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UNhHjedwUkA2yhUeGh1nwJ/9Jyb4vCD8Fsk8QeuAQgu6GwWbfcgmlNbzKUpcEt4/5uvDTWkgeFHisC82Z7z5+ZHT+4xAXDohcpl2Wby3k9GVc5KUc9UOqR4Qwy76NfinzIb1i0qi/gW7jmfkUWwg5ob2fNJNhMY6MGQ0czVNANk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=IqotQjWj; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="IqotQjWj" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2ba9a744f7dso8120705eec.0 for ; Tue, 07 Apr 2026 19:52:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775616766; x=1776221566; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Y/WKVEqvyJ50tKFvDYgDShsP7HGazqsCCeHuDA2/e0s=; b=IqotQjWj4YFMCRGOchph/DY/IdvbEmwpR4YnNt8+GAzQP1MumL7lSb5S/XASfSXWtr aBJ4LfngJWIH1n34Hhqt4zGq8M0h/A/Sbe/sR6gOO+vv65KLj6jyJ7d7TseXVvSUE0cR sScrQOP8IMZfvc2N6yTYPDKmqbnuxTeEH98SOP0ZQHBTvNKYFOikvS3yk98naZCpCIdl O62fT4srTZheSmZxQRK6GkjP5YGMqy0jrt2LXhsN3r40F8qu18A1AoWuzOW+Jw+Aw4rv 6B6bmkij7U2tNDzV3twA3TeTUAG3bJjxZXvr9Kxz0SJEyzkJezm1MqfeOYeqzLqLrybx hNGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775616766; x=1776221566; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Y/WKVEqvyJ50tKFvDYgDShsP7HGazqsCCeHuDA2/e0s=; b=DB+WRyoVOGFssLso1eIcF4/5iVFxzR3ztlebx8pfOvOaTjB1NCK/NIiOTPLQC9ii5E Dpg2N+bWo980qovqPTckr1AzYJKrwNxlFZ3T1Bh5DicXClOWzCeX6pxTSOXHhbe/d5yP chNDlcE5ORomzklovN8qxstTk0ht2EiEbawNosPYJ173vHIEIkafSQLR6z7lqzYjwtJM oI7IS0We1INgL/w2buF6HR/W8ZuA4AG8FIX+Agqxh/MNkpB5QM7eGFHlyiAMgIq5gNT7 jLYv+Sd0t7k58qqhDmDDiybQXI7zUAkDtn65h8Rmun6Hi/MHh5QQXSQSbO7UaTy5tIaC kNqQ== X-Forwarded-Encrypted: i=1; AJvYcCUAexb8C4aduWuQKHmdo92ORtx9Oc4GYCQDoDIv4mk4F5Rvgaa2xvd9mnYhgPweHmwRC6tvN1wvSnFfa9I=@vger.kernel.org X-Gm-Message-State: AOJu0Yyi17H2N6OEu+8Csmt6IBIn12uEAT1CoClNlgbv4VXYOeG77/eJ kZWE5CARoCyDOMk54ELe6FcReRn1MvOcEkeF091g2RNh5CC2Karvp+gZgJXBnE5s+EDEufdi0CM 9rgs5NNPPvS/rnftWUmsQPg== X-Received: from dycmg22.prod.google.com ([2002:a05:693c:2516:b0:2c1:70ef:f2dc]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7301:19a8:b0:2c7:5a7b:e8c0 with SMTP id 5a478bee46e88-2cbfa5c38bdmr9996279eec.12.1775616765364; Tue, 07 Apr 2026 19:52:45 -0700 (PDT) Date: Wed, 08 Apr 2026 02:52:29 +0000 In-Reply-To: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260408-teaming-driver-internal-v6-0-e5bcdcf72504@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775616747; l=13006; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=zRiZ3F9ixViqIp/oVJOs2Dr/NZnvNeO1TEoDMXNAr2A=; b=Gu1tO12NUPBpQK4boVluYuYswtbLzNl429LMV6nfkpcnZOhZadCfG2sz9R0vV0qNOjWCpMesb pLVTFgDf06aAim3R3srsXcL+VvDl1cNqEJPVfyNR2Kr7p1NJOuL6KJ1 X-Mailer: b4 0.14.3 Message-ID: <20260408-teaming-driver-internal-v6-10-e5bcdcf72504@google.com> Subject: [PATCH net-next v6 10/10] selftests: net: Add tests for team driver decoupled tx and rx control From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Use ping and tcpdump to verify that independent rx and tx enablement of team driver member interfaces works as intended. Signed-off-by: Marc Harvey --- Changes in v5: - Minor typo fixes in both test files. - Link to v4: https://lore.kernel.org/netdev/20260403-teaming-driver-intern= al-v4-10-d3032f33ca25@google.com/ Changes in v2: - Fix shellcheck failures. - Link to v1: https://lore.kernel.org/all/20260331053353.2504254-8-marcharv= ey@google.com/ --- tools/testing/selftests/drivers/net/team/Makefile | 1 + .../drivers/net/team/decoupled_enablement.sh | 249 +++++++++++++++++= ++++ .../testing/selftests/drivers/net/team/options.sh | 99 +++++++- 3 files changed, 348 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/drivers/net/team/Makefile b/tools/test= ing/selftests/drivers/net/team/Makefile index dab922d7f83d..7c58cf82121e 100644 --- a/tools/testing/selftests/drivers/net/team/Makefile +++ b/tools/testing/selftests/drivers/net/team/Makefile @@ -2,6 +2,7 @@ # Makefile for net selftests =20 TEST_PROGS :=3D \ + decoupled_enablement.sh \ dev_addr_lists.sh \ non_ether_header_ops.sh \ options.sh \ diff --git a/tools/testing/selftests/drivers/net/team/decoupled_enablement.= sh b/tools/testing/selftests/drivers/net/team/decoupled_enablement.sh new file mode 100755 index 000000000000..0d3d9c98e9f5 --- /dev/null +++ b/tools/testing/selftests/drivers/net/team/decoupled_enablement.sh @@ -0,0 +1,249 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# These tests verify the decoupled RX and TX enablement of team driver mem= ber +# interfaces. +# +# Topology +# +# +---------------------+ NS1 +# | test_team1 | +# | | | +# | eth0 | +# | | | +# | | | +# +---------------------+ +# | +# +---------------------+ NS2 +# | | | +# | | | +# | eth0 | +# | | | +# | test_team2 | +# +---------------------+ + +export ALL_TESTS=3D" + team_test_tx_enablement + team_test_rx_enablement +" + +test_dir=3D"$(dirname "$0")" +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/lib.sh" +# shellcheck disable=3DSC1091 +source "${test_dir}/team_lib.sh" + +NS1=3D"" +NS2=3D"" +export NODAD=3D"nodad" +PREFIX_LENGTH=3D"64" +NS1_IP=3D"fd00::1" +NS2_IP=3D"fd00::2" +NS1_IP4=3D"192.168.0.1" +NS2_IP4=3D"192.168.0.2" +MEMBERS=3D("eth0") +PING_COUNT=3D5 +PING_TIMEOUT_S=3D1 +PING_INTERVAL=3D0.1 + +while getopts "4" opt; do + case $opt in + 4) + echo "IPv4 mode selected." + export NODAD=3D + PREFIX_LENGTH=3D"24" + NS1_IP=3D"${NS1_IP4}" + NS2_IP=3D"${NS2_IP4}" + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +# This has to be sourced after opts are gathered... +export REQUIRE_MZ=3Dno +export NUM_NETIFS=3D0 +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/forwarding/lib.sh" + +# Create the network namespaces, veth pair, and team devices in the specif= ied +# mode. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# mode - The team driver mode to use for the team devices. +environment_create() +{ + trap cleanup_all_ns EXIT + setup_ns ns1 ns2 + NS1=3D"${NS_LIST[0]}" + NS2=3D"${NS_LIST[1]}" + + # Create the interfaces. + ip -n "${NS1}" link add eth0 type veth peer name eth0 netns "${NS2}" + ip -n "${NS1}" link add test_team1 type team + ip -n "${NS2}" link add test_team2 type team + + # Set up the receiving network namespace's team interface. + setup_team "${NS2}" test_team2 roundrobin "${NS2_IP}" \ + "${PREFIX_LENGTH}" "${MEMBERS[@]}" +} + +# Set a particular option value for team or team port. +# Arguments: +# namespace - The namespace name that has the team. +# option_name - The option name to set. +# option_value - The value to set the option to. +# team_name - The name of team to set the option for. +# member_name - The (optional) optional name of the member port. +set_option_value() +{ + local namespace=3D"$1" + local option_name=3D"$2" + local option_value=3D"$3" + local team_name=3D"$4" + local member_name=3D"$5" + local port_flag=3D"--port=3D${member_name}" + + ip netns exec "${namespace}" teamnl "${team_name}" setoption \ + "${option_name}" "${option_value}" "${port_flag}" + return $? +} + +# Send some pings and return the ping command return value. +try_ping() +{ + ip netns exec "${NS1}" ping -i "${PING_INTERVAL}" -c "${PING_COUNT}" \ + "${NS2_IP}" -W "${PING_TIMEOUT_S}" +} + +# Checks tcpdump output from net/forwarding lib, and checks if there are a= ny +# ICMP(4 or 6) packets. +# Arguments: +# interface - The interface name to search for. +# ip_address - The destination IP address (4 or 6) to search for. +did_interface_receive_icmp() +{ + local interface=3D"$1" + local ip_address=3D"$2" + local packet_count + + packet_count=3D$(tcpdump_show "$interface" | grep -c \ + "> ${ip_address}: ICMP") + echo "Packet count for ${interface} was ${packet_count}" + + if [[ "$packet_count" -gt 0 ]]; then + true + else + false + fi +} + +# Test JUST tx enablement with a given mode. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# mode - The mode to set the team interfaces to. +team_test_mode_tx_enablement() +{ + local mode=3D"$1" + export RET=3D0 + + # Set up the sender team with the correct mode. + setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ + "${PREFIX_LENGTH}" "${MEMBERS[@]}" + check_err $? "Failed to set up sender team" + + ### Scenario 1: Member interface initially enabled. + # Expect ping to pass + try_ping + check_err $? "Ping failed when TX enabled" + + ### Scenario 2: One tx-side interface disabled. + # Expect ping to fail. + set_option_value "${NS1}" tx_enabled false test_team1 eth0 + check_err $? "Failed to disable TX" + tcpdump_start eth0 "${NS2}" + try_ping + check_fail $? "Ping succeeded when TX disabled" + tcpdump_stop eth0 + # Expect no packets to be transmitted, since TX is disabled. + did_interface_receive_icmp eth0 "${NS2_IP}" + check_fail $? "eth0 IS transmitting when TX disabled" + tcpdump_cleanup eth0 + + ### Scenario 3: The interface has tx re-enabled. + # Expect ping to pass. + set_option_value "${NS1}" tx_enabled true test_team1 eth0 + check_err $? "Failed to reenable TX" + try_ping + check_err $? "Ping failed when TX reenabled" + + log_test "TX failover of '${mode}' test" +} + +# Test JUST rx enablement with a given mode. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +# Arguments: +# mode - The mode to set the team interfaces to. +team_test_mode_rx_enablement() +{ + local mode=3D"$1" + export RET=3D0 + + # Set up the sender team with the correct mode. + setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ + "${PREFIX_LENGTH}" "${MEMBERS[@]}" + check_err $? "Failed to set up sender team" + + ### Scenario 1: Member interface initially enabled. + # Expect ping to pass + try_ping + check_err $? "Ping failed when RX enabled" + + ### Scenario 2: One rx-side interface disabled. + # Expect ping to fail. + set_option_value "${NS1}" rx_enabled false test_team1 eth0 + check_err $? "Failed to disable RX" + tcpdump_start eth0 "${NS2}" + try_ping + check_fail $? "Ping succeeded when RX disabled" + tcpdump_stop eth0 + # Expect packets to be transmitted, since only RX is disabled. + did_interface_receive_icmp eth0 "${NS2_IP}" + check_err $? "eth0 not transmitting when RX disabled" + tcpdump_cleanup eth0 + + ### Scenario 3: The interface has rx re-enabled. + # Expect ping to pass. + set_option_value "${NS1}" rx_enabled true test_team1 eth0 + check_err $? "Failed to reenable RX" + try_ping + check_err $? "Ping failed when RX reenabled" + + log_test "RX failover of '${mode}' test" +} + +team_test_tx_enablement() +{ + team_test_mode_tx_enablement broadcast + team_test_mode_tx_enablement roundrobin + team_test_mode_tx_enablement random +} + +team_test_rx_enablement() +{ + team_test_mode_rx_enablement broadcast + team_test_mode_rx_enablement roundrobin + team_test_mode_rx_enablement random +} + +require_command teamnl +require_command tcpdump +require_command ping +environment_create +tests_run +exit "${EXIT_STATUS}" diff --git a/tools/testing/selftests/drivers/net/team/options.sh b/tools/te= sting/selftests/drivers/net/team/options.sh index 44888f32b513..66c0cb896dad 100755 --- a/tools/testing/selftests/drivers/net/team/options.sh +++ b/tools/testing/selftests/drivers/net/team/options.sh @@ -11,10 +11,14 @@ if [[ $# -eq 0 ]]; then exit $? fi =20 -ALL_TESTS=3D" +export ALL_TESTS=3D" team_test_options + team_test_enabled_implicit_changes + team_test_rx_enabled_implicit_changes + team_test_tx_enabled_implicit_changes " =20 +# shellcheck disable=3DSC1091 source "${test_dir}/../../../net/lib.sh" =20 TEAM_PORT=3D"team0" @@ -176,12 +180,105 @@ team_test_options() team_test_option mcast_rejoin_count 0 5 team_test_option mcast_rejoin_interval 0 5 team_test_option enabled true false "${MEMBER_PORT}" + team_test_option rx_enabled true false "${MEMBER_PORT}" + team_test_option tx_enabled true false "${MEMBER_PORT}" team_test_option user_linkup true false "${MEMBER_PORT}" team_test_option user_linkup_enabled true false "${MEMBER_PORT}" team_test_option priority 10 20 "${MEMBER_PORT}" team_test_option queue_id 0 1 "${MEMBER_PORT}" } =20 +team_test_enabled_implicit_changes() +{ + export RET=3D0 + + attach_port_if_specified "${MEMBER_PORT}" + check_err $? "Couldn't attach ${MEMBER_PORT} to master" + + # Set enabled to true. + set_and_check_get enabled true "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'enabled' to true" + + # Show that both rx enabled and tx enabled are true. + get_and_check_value rx_enabled true "--port=3D${MEMBER_PORT}" + check_err $? "'Rx_enabled' wasn't implicitly set to true" + get_and_check_value tx_enabled true "--port=3D${MEMBER_PORT}" + check_err $? "'Tx_enabled' wasn't implicitly set to true" + + # Set enabled to false. + set_and_check_get enabled false "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'enabled' to false" + + # Show that both rx enabled and tx enabled are false. + get_and_check_value rx_enabled false "--port=3D${MEMBER_PORT}" + check_err $? "'Rx_enabled' wasn't implicitly set to false" + get_and_check_value tx_enabled false "--port=3D${MEMBER_PORT}" + check_err $? "'Tx_enabled' wasn't implicitly set to false" + + log_test "'Enabled' implicit changes" +} + +team_test_rx_enabled_implicit_changes() +{ + export RET=3D0 + + attach_port_if_specified "${MEMBER_PORT}" + check_err $? "Couldn't attach ${MEMBER_PORT} to master" + + # Set enabled to true. + set_and_check_get enabled true "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'enabled' to true" + + # Set rx_enabled to false. + set_and_check_get rx_enabled false "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'rx_enabled' to false" + + # Show that enabled is false. + get_and_check_value enabled false "--port=3D${MEMBER_PORT}" + check_err $? "'enabled' wasn't implicitly set to false" + + # Set rx_enabled to true. + set_and_check_get rx_enabled true "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'rx_enabled' to true" + + # Show that enabled is true. + get_and_check_value enabled true "--port=3D${MEMBER_PORT}" + check_err $? "'enabled' wasn't implicitly set to true" + + log_test "'Rx_enabled' implicit changes" +} + +team_test_tx_enabled_implicit_changes() +{ + export RET=3D0 + + attach_port_if_specified "${MEMBER_PORT}" + check_err $? "Couldn't attach ${MEMBER_PORT} to master" + + # Set enabled to true. + set_and_check_get enabled true "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'enabled' to true" + + # Set tx_enabled to false. + set_and_check_get tx_enabled false "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'tx_enabled' to false" + + # Show that enabled is false. + get_and_check_value enabled false "--port=3D${MEMBER_PORT}" + check_err $? "'enabled' wasn't implicitly set to false" + + # Set tx_enabled to true. + set_and_check_get tx_enabled true "--port=3D${MEMBER_PORT}" + check_err $? "Failed to set 'tx_enabled' to true" + + # Show that enabled is true. + get_and_check_value enabled true "--port=3D${MEMBER_PORT}" + check_err $? "'enabled' wasn't implicitly set to true" + + log_test "'Tx_enabled' implicit changes" +} + + require_command teamnl setup tests_run --=20 2.53.0.1213.gd9a14994de-goog