On Fri, Jun 26, 2020 at 10:55 AM Martin KaFai Lau <kafai@xxxxxx> wrote: > > The total length of the saved syn packet is currently stored in > the first 4 bytes (u32) and the actual packet data is stored after that. > > A latter patch will also want to store an offset (bpf_hdr_opt_off) to > a TCP header option which the bpf program will be interested in parsing. > Instead of anonymously storing this offset into the second 4 bytes, > this patch creates a struct for the existing saved_syn. > It can give a readable name to the stored lengths instead of implicitly > using the first few u32(s) to do that. > > The new TCP bpf header offset (bpf_hdr_opt_off) added in a latter patch is > an offset from the tcp header instead of from the network header. > It will make the bpf programming side easier. Thus, this patch stores > the network header length instead of the total length of the syn > header. The total length can be obtained by the > "network header len + tcp_hdrlen". The latter patch can > then also gets the offset to the TCP bpf header option by > "network header len + bpf_hdr_opt_off". > > Signed-off-by: Martin KaFai Lau <kafai@xxxxxx> > --- > include/linux/tcp.h | 11 ++++++++++- > include/net/request_sock.h | 7 ++++++- > net/core/filter.c | 4 ++-- > net/ipv4/tcp.c | 9 +++++---- > net/ipv4/tcp_input.c | 12 ++++++------ > 5 files changed, 29 insertions(+), 14 deletions(-) > > diff --git a/include/linux/tcp.h b/include/linux/tcp.h > index 3bdec31ce8f4..9d50132d95e6 100644 > --- a/include/linux/tcp.h > +++ b/include/linux/tcp.h > @@ -404,7 +404,7 @@ struct tcp_sock { > * socket. Used to retransmit SYNACKs etc. > */ > struct request_sock __rcu *fastopen_rsk; > - u32 *saved_syn; > + struct saved_syn *saved_syn; > }; > > enum tsq_enum { > @@ -482,6 +482,15 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp) > tp->saved_syn = NULL; > } > > +static inline u32 tcp_saved_syn_len(const struct saved_syn *saved_syn) > +{ > + const struct tcphdr *th; > + > + th = (void *)saved_syn->data + saved_syn->network_hdrlen; > + > + return saved_syn->network_hdrlen + __tcp_hdrlen(th); > +} Ah... We have a patch extending TCP_SAVE_SYN to save all headers, so keeping the length in a proper field would be better than going back to TCP header to get __tcp_hdrlen(th) I am not sure why trying to save 4 bytes in this saved_syn would matter ;) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index c9fcfa4ec43f3f0d75763e2bc6773e15bd38d68f..8ecdc5f87788439c7a08d3b72f9567e6369e7c4e 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -258,7 +258,7 @@ struct tcp_sock { fastopen_connect:1, /* FASTOPEN_CONNECT sockopt */ fastopen_no_cookie:1, /* Allow send/recv SYN+data without a cookie */ is_sack_reneg:1, /* in recovery from loss with SACK reneg? */ - unused:2; + save_syn:2; /* Save headers of SYN packet */ u8 nonagle : 4,/* Disable Nagle algorithm? */ thin_lto : 1,/* Use linear timeouts for thin streams */ recvmsg_inq : 1,/* Indicate # of bytes in queue upon recvmsg */ @@ -270,7 +270,7 @@ struct tcp_sock { syn_fastopen_exp:1,/* SYN includes Fast Open exp. option */ syn_fastopen_ch:1, /* Active TFO re-enabling probe */ syn_data_acked:1,/* data in SYN is acked by SYN-ACK */ - save_syn:1, /* Save headers of SYN packet */ + unused_save_syn:1, /* Moved above */ is_cwnd_limited:1,/* forward progress limited by snd_cwnd? */ syn_smc:1; /* SYN includes SMC */ u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fa62baf509c8075cb7da30ee0f65059ac35c1c60..7e108de07fb4e45a994d3d75331489ad82f9deb7 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3097,7 +3097,8 @@ static int do_tcp_setsockopt(struct sock *sk, int level, break; case TCP_SAVE_SYN: - if (val < 0 || val > 1) + /* 0: disable, 1: enable, 2: start from ether_header */ + if (val < 0 || val > 2) err = -EINVAL; else tp->save_syn = val; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7ce5bad2308134954133f612ec129cf56946d9a1..5513f8aaae9f6c0303fac4d2c590ead1a6076502 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6708,11 +6708,19 @@ static void tcp_reqsk_record_syn(const struct sock *sk, if (tcp_sk(sk)->save_syn) { u32 len = skb_network_header_len(skb) + tcp_hdrlen(skb); u32 *copy; + void *base; + + if (tcp_sk(sk)->save_syn == 2) { /* Save full header. */ + len += skb->network_header - skb->mac_header; + base = skb_mac_header(skb); + } else { + base = skb_network_header(skb); + } copy = kmalloc(len + sizeof(u32), GFP_ATOMIC); if (copy) { copy[0] = len; - memcpy(©[1], skb_network_header(skb), len); + memcpy(©[1], base, len); req->saved_syn = copy; } }