git: 2c6ff1d6320d - main - LRO: fix BPF filters for lagg in the hpts path

From: Andrew Gallatin <gallatin_at_FreeBSD.org>
Date: Sat, 13 Aug 2022 21:34:02 UTC
The branch main has been updated by gallatin:

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

commit 2c6ff1d6320d57a9d0dc62c10c83145ed49a51dd
Author:     Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2022-08-13 00:15:46 +0000
Commit:     Andrew Gallatin <gallatin@FreeBSD.org>
CommitDate: 2022-08-13 21:33:36 +0000

    LRO: fix BPF filters for lagg in the hpts path
    
    When in the hpts path, we need to handle BPF filters since aggregated
    packets do not pass up the stack in the normal way. This is already
    done for most interfaces, but lagg needs special handling. This is
    because packets received via a lagg are passed up the stack with
    the leaf interface's ifp stored in m_pkthdr.rcvif.
    
    To handle lagg packets, we must identify that the passed rcvif is
    currently a lagg port by checking for IFT_IEEE8023ADLAG or
    IFT_INFINIBANDLAG (since lagg changes the lagg port's type to that
    when an interface becomes a lagg member). Then we need to find the
    lagg's ifp, and handle any BPF listeners on the lagg.
    
    Note: It is possible to have multiple BPF filters, one on a member
    port and one on the lagg itself. That is why we have to have 2
    checks and 2 ETHER_BPF_MTAPs.
    
    Reviewed by: jhb, rrs
    Sponsored by: Netflix
    Differential Revision: https://reviews.freebsd.org/D36136
---
 sys/netinet/tcp_lro.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 2633ccd12afc..fcde002bac53 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -53,6 +53,11 @@ __FBSDID("$FreeBSD$");
 #include <net/ethernet.h>
 #include <net/bpf.h>
 #include <net/vnet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/infiniband.h>
+#include <net/if_lagg.h>
 
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
@@ -85,7 +90,8 @@ static int	tcp_lro_rx_common(struct lro_ctrl *lc, struct mbuf *m,
 
 #ifdef TCPHPTS
 static bool	do_bpf_strip_and_compress(struct inpcb *, struct lro_ctrl *,
-		struct lro_entry *, struct mbuf **, struct mbuf **, struct mbuf **, bool *, bool);
+		struct lro_entry *, struct mbuf **, struct mbuf **, struct mbuf **,
+		bool *, bool, bool, struct ifnet *);
 
 #endif
 
@@ -1283,7 +1289,8 @@ tcp_lro_flush_tcphpts(struct lro_ctrl *lc, struct lro_entry *le)
 	struct inpcb *inp;
 	struct tcpcb *tp;
 	struct mbuf **pp, *cmp, *mv_to;
-	bool bpf_req, should_wake;
+	struct ifnet *lagg_ifp;
+	bool bpf_req, lagg_bpf_req, should_wake;
 
 	/* Check if packet doesn't belongs to our network interface. */
 	if ((tcplro_stacks_wanting_mbufq == 0) ||
@@ -1341,13 +1348,25 @@ tcp_lro_flush_tcphpts(struct lro_ctrl *lc, struct lro_entry *le)
 		should_wake = true;
 	/* Check if packets should be tapped to BPF. */
 	bpf_req = bpf_peers_present(lc->ifp->if_bpf);
+	lagg_bpf_req = false;
+	lagg_ifp = NULL;
+	if (lc->ifp->if_type == IFT_IEEE8023ADLAG ||
+	    lc->ifp->if_type == IFT_INFINIBANDLAG) {
+		struct lagg_port *lp = lc->ifp->if_lagg;
+		struct lagg_softc *sc = lp->lp_softc;
+
+		lagg_ifp = sc->sc_ifp;
+		if (lagg_ifp != NULL)
+			lagg_bpf_req = bpf_peers_present(lagg_ifp->if_bpf);
+	}
 
 	/* Strip and compress all the incoming packets. */
 	cmp = NULL;
 	for (pp = &le->m_head; *pp != NULL; ) {
 		mv_to = NULL;
 		if (do_bpf_strip_and_compress(inp, lc, le, pp,
-			 &cmp, &mv_to, &should_wake, bpf_req ) == false) {
+			&cmp, &mv_to, &should_wake, bpf_req,
+			lagg_bpf_req, lagg_ifp) == false) {
 			/* Advance to next mbuf. */
 			pp = &(*pp)->m_nextpkt;
 		} else if (mv_to != NULL) {
@@ -1593,7 +1612,7 @@ build_ack_entry(struct tcp_ackent *ae, struct tcphdr *th, struct mbuf *m,
 static bool
 do_bpf_strip_and_compress(struct inpcb *inp, struct lro_ctrl *lc,
     struct lro_entry *le, struct mbuf **pp, struct mbuf **cmp, struct mbuf **mv_to,
-    bool *should_wake, bool bpf_req)
+    bool *should_wake, bool bpf_req, bool lagg_bpf_req, struct ifnet *lagg_ifp)
 {
 	union {
 		void *ptr;
@@ -1619,6 +1638,9 @@ do_bpf_strip_and_compress(struct inpcb *inp, struct lro_ctrl *lc,
 	if (__predict_false(bpf_req))
 		ETHER_BPF_MTAP(lc->ifp, m);
 
+	if (__predict_false(lagg_bpf_req))
+		ETHER_BPF_MTAP(lagg_ifp, m);
+
 	tcp_hdr_offset = m->m_pkthdr.lro_tcp_h_off;
 	lro_type = le->inner.data.lro_type;
 	switch (lro_type) {