Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 06 Feb 2026 03:38:51 +0000
From:      Zhenlei Huang <zlei@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: a622030b4bae - main - lagg: Make the none protocol a first-class citizen
Message-ID:  <6985624b.42e7d.c91bd19@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=a622030b4baec2136984cea7bd25c2985a2ae9b3

commit a622030b4baec2136984cea7bd25c2985a2ae9b3
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2026-02-06 03:37:43 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2026-02-06 03:37:43 +0000

    lagg: Make the none protocol a first-class citizen
    
    All the other protocols have corresponding start and input routines,
    which are used in the fast path. Currently the none protocol is
    treated specially. In the fast path it is checked to indicate whether
    a working protocol is configured. There are two issues raised by this
    design:
    
    1. In production, other protocols are commonly used, but not the
    none protocol. It smells like an overkill to always check it in the
    fast path. It is unfair to other commonly used protocols.
    
    2. PR 289017 reveals that there's a small window between checking the
    protocol and calling lagg_proto_start(). lagg_proto_start() is possible
    to see the none protocol and do NULL deferencing.
    
    Fix them by making the none protocol a first-class citizen so that it
    has start and input routines just the same as other protocols. Then we
    can stop checking it in the fast path, since lagg_proto_start() and
    lagg_proto_input() will never fail to work.
    
    The error ENETDOWN is chosen for the start routine. Obviously no active
    ports are available, and the packets will go nowhere. It is also a
    better error than ENXIO, since indeed the interface is configured and
    has a TX algorithm (the none protocol).
    
    PR:             289017
    Diagnosed by:   Qiu-ji Chen <chenqiuji666@gmail.com>
    Tested by:      Gui-Dong Han <hanguidong02@gmail.com>
    Reviewed by:    glebius
    MFC after:      5 days
    Differential Revision:  https://reviews.freebsd.org/D55123
---
 sys/net/if_lagg.c | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 5b52bfa80e3b..21ea2b30459b 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -169,6 +169,11 @@ static void	lagg_media_status(struct ifnet *, struct ifmediareq *);
 static struct lagg_port *lagg_link_active(struct lagg_softc *,
 		    struct lagg_port *);
 
+/* No proto */
+static int	lagg_none_start(struct lagg_softc *, struct mbuf *);
+static struct mbuf *lagg_none_input(struct lagg_softc *, struct lagg_port *,
+		    struct mbuf *);
+
 /* Simple round robin */
 static void	lagg_rr_attach(struct lagg_softc *);
 static int	lagg_rr_start(struct lagg_softc *, struct mbuf *);
@@ -219,7 +224,9 @@ static const struct lagg_proto {
 	void		(*pr_portreq)(struct lagg_port *, void *);
 } lagg_protos[] = {
     {
-	.pr_num = LAGG_PROTO_NONE
+	.pr_num = LAGG_PROTO_NONE,
+	.pr_start = lagg_none_start,
+	.pr_input = lagg_none_input,
     },
     {
 	.pr_num = LAGG_PROTO_ROUNDROBIN,
@@ -2129,8 +2136,8 @@ lagg_transmit_ethernet(struct ifnet *ifp, struct mbuf *m)
 	if (m->m_pkthdr.csum_flags & CSUM_SND_TAG)
 		MPASS(m->m_pkthdr.snd_tag->ifp == ifp);
 #endif
-	/* We need a Tx algorithm and at least one port */
-	if (sc->sc_proto == LAGG_PROTO_NONE || sc->sc_count == 0) {
+	/* We need at least one port */
+	if (sc->sc_count == 0) {
 		m_freem(m);
 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		return (ENXIO);
@@ -2151,8 +2158,8 @@ lagg_transmit_infiniband(struct ifnet *ifp, struct mbuf *m)
 	if (m->m_pkthdr.csum_flags & CSUM_SND_TAG)
 		MPASS(m->m_pkthdr.snd_tag->ifp == ifp);
 #endif
-	/* We need a Tx algorithm and at least one port */
-	if (sc->sc_proto == LAGG_PROTO_NONE || sc->sc_count == 0) {
+	/* We need at least one port */
+	if (sc->sc_count == 0) {
 		m_freem(m);
 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		return (ENXIO);
@@ -2180,8 +2187,7 @@ lagg_input_ethernet(struct ifnet *ifp, struct mbuf *m)
 
 	NET_EPOCH_ASSERT();
 	if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
-	    lp->lp_detaching != 0 ||
-	    sc->sc_proto == LAGG_PROTO_NONE) {
+	    lp->lp_detaching != 0) {
 		m_freem(m);
 		return (NULL);
 	}
@@ -2215,8 +2221,7 @@ lagg_input_infiniband(struct ifnet *ifp, struct mbuf *m)
 
 	NET_EPOCH_ASSERT();
 	if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
-	    lp->lp_detaching != 0 ||
-	    sc->sc_proto == LAGG_PROTO_NONE) {
+	    lp->lp_detaching != 0) {
 		m_freem(m);
 		return (NULL);
 	}
@@ -2390,6 +2395,25 @@ lagg_enqueue(struct ifnet *ifp, struct mbuf *m)
 	return (ifp->if_transmit)(ifp, m);
 }
 
+/*
+ * No proto
+ */
+static int
+lagg_none_start(struct lagg_softc *sc, struct mbuf *m)
+{
+	m_freem(m);
+	if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
+	/* No active ports available */
+	return (ENETDOWN);
+}
+
+static struct mbuf *
+lagg_none_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
+{
+	m_freem(m);
+	return (NULL);
+}
+
 /*
  * Simple round robin aggregation
  */


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6985624b.42e7d.c91bd19>