On Fri, Apr 11, 2025 at 03:10:21PM +0200, Laurent Vivier wrote: > Use packet_base() and extract headers using IOV_REMOVE_HEADER() > and iov_peek_header_() rather than packet_get(). > > Signed-off-by: Laurent Vivier > --- > tcp.c | 31 ++++++++++++++++++++++++------- > 1 file changed, 24 insertions(+), 7 deletions(-) > > diff --git a/tcp.c b/tcp.c > index 35626c914c6a..1838b73cf766 100644 > --- a/tcp.c > +++ b/tcp.c > @@ -310,6 +310,16 @@ > #include "tcp_buf.h" > #include "tcp_vu.h" > > +/* > + * The size of TCP header (including options) is given by doff (Data Offset) > + * that is a 4-bit value specifying the number of 32-bit words in the header. > + * The maximum value of doff is 15 [(1 << 4) - 1]. > + * The maximum length in bytes of options is 15 minus the number of 32-bit > + * words in the minimal TCP header (5) multiplied by the length of a 32-bit > + * word (4). > + */ > +#define OPTLEN_MAX (((1UL << 4) - 6) * 4UL) > + > #ifndef __USE_MISC > /* From Linux UAPI, missing in netinet/tcp.h provided by musl */ > struct tcp_repair_opt { > @@ -1957,7 +1967,10 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, > { > struct tcp_tap_conn *conn; > const struct tcphdr *th; > - size_t optlen, len; > + char optsc[OPTLEN_MAX]; > + struct iov_tail data; > + size_t optlen, l4len; > + struct tcphdr thc; > const char *opts; > union flow *flow; > flow_sidx_t sidx; > @@ -1966,15 +1979,19 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, > > (void)pif; > > - th = packet_get(p, idx, 0, sizeof(*th), &len); > + if (!packet_base(p, idx, &data)) > + return 1; > + > + l4len = iov_tail_size(&data); > + > + th = IOV_REMOVE_HEADER(&data, thc); > if (!th) > return 1; > - len += sizeof(*th); > > optlen = th->doff * 4UL - sizeof(*th); > /* Static checkers might fail to see this: */ > - optlen = MIN(optlen, ((1UL << 4) /* from doff width */ - 6) * 4UL); > - opts = packet_get(p, idx, sizeof(*th), optlen, NULL); > + optlen = MIN(optlen, OPTLEN_MAX); > + opts = (char *)iov_peek_header_(&data, &optsc[0], optlen, 1); Can you use remove_header here? AFAICT it makes logical sense to move the tail on to covering just the payload at this point. > sidx = flow_lookup_af(c, IPPROTO_TCP, PIF_TAP, af, saddr, daddr, > ntohs(th->source), ntohs(th->dest)); > @@ -1986,7 +2003,7 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, > tcp_conn_from_tap(c, af, saddr, daddr, th, > opts, optlen, now); > else > - tcp_rst_no_conn(c, af, saddr, daddr, flow_lbl, th, len); > + tcp_rst_no_conn(c, af, saddr, daddr, flow_lbl, th, l4len); > return 1; > } > > @@ -1994,7 +2011,7 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af, > ASSERT(pif_at_sidx(sidx) == PIF_TAP); > conn = &flow->tcp; > > - flow_trace(conn, "packet length %zu from tap", len); > + flow_trace(conn, "packet length %zu from tap", l4len); > > if (th->rst) { > conn_event(c, conn, CLOSED); -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson