git: 2c6ff1d6320d - main - LRO: fix BPF filters for lagg in the hpts path
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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) {