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) {