mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
tcp: Use a struct to represent a saved_syn
The TCP_SAVE_SYN has both the network header and tcp header. The total length of the saved syn packet is currently stored in the first 4 bytes (u32) of an array and the actual packet data is stored after that. A later patch will add a bpf helper that allows to get the tcp header alone from the saved syn without the network header. It will be more convenient to have a direct offset to a specific header instead of re-parsing it. This requires to separately store the network hdrlen. The total header length (i.e. network + tcp) is still needed for the current usage in getsockopt. Although this total length can be obtained by looking into the tcphdr and then get the (th->doff << 2), this patch chooses to directly store the tcp hdrlen in the second four bytes of this newly created "struct saved_syn". By using a new struct, it can give a readable name to each individual header length. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20200820190014.2883694-1-kafai@fb.com
This commit is contained in:
parent
9c0f8cbdc0
commit
70a217f197
5 changed files with 28 additions and 14 deletions
|
@ -406,7 +406,7 @@ struct tcp_sock {
|
||||||
* socket. Used to retransmit SYNACKs etc.
|
* socket. Used to retransmit SYNACKs etc.
|
||||||
*/
|
*/
|
||||||
struct request_sock __rcu *fastopen_rsk;
|
struct request_sock __rcu *fastopen_rsk;
|
||||||
u32 *saved_syn;
|
struct saved_syn *saved_syn;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum tsq_enum {
|
enum tsq_enum {
|
||||||
|
@ -484,6 +484,11 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp)
|
||||||
tp->saved_syn = NULL;
|
tp->saved_syn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 tcp_saved_syn_len(const struct saved_syn *saved_syn)
|
||||||
|
{
|
||||||
|
return saved_syn->network_hdrlen + saved_syn->tcp_hdrlen;
|
||||||
|
}
|
||||||
|
|
||||||
struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
|
struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
|
||||||
const struct sk_buff *orig_skb);
|
const struct sk_buff *orig_skb);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,12 @@ struct request_sock_ops {
|
||||||
|
|
||||||
int inet_rtx_syn_ack(const struct sock *parent, struct request_sock *req);
|
int inet_rtx_syn_ack(const struct sock *parent, struct request_sock *req);
|
||||||
|
|
||||||
|
struct saved_syn {
|
||||||
|
u32 network_hdrlen;
|
||||||
|
u32 tcp_hdrlen;
|
||||||
|
u8 data[];
|
||||||
|
};
|
||||||
|
|
||||||
/* struct request_sock - mini sock to represent a connection request
|
/* struct request_sock - mini sock to represent a connection request
|
||||||
*/
|
*/
|
||||||
struct request_sock {
|
struct request_sock {
|
||||||
|
@ -60,7 +66,7 @@ struct request_sock {
|
||||||
struct timer_list rsk_timer;
|
struct timer_list rsk_timer;
|
||||||
const struct request_sock_ops *rsk_ops;
|
const struct request_sock_ops *rsk_ops;
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
u32 *saved_syn;
|
struct saved_syn *saved_syn;
|
||||||
u32 secid;
|
u32 secid;
|
||||||
u32 peer_secid;
|
u32 peer_secid;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4550,9 +4550,9 @@ static int _bpf_getsockopt(struct sock *sk, int level, int optname,
|
||||||
tp = tcp_sk(sk);
|
tp = tcp_sk(sk);
|
||||||
|
|
||||||
if (optlen <= 0 || !tp->saved_syn ||
|
if (optlen <= 0 || !tp->saved_syn ||
|
||||||
optlen > tp->saved_syn[0])
|
optlen > tcp_saved_syn_len(tp->saved_syn))
|
||||||
goto err_clear;
|
goto err_clear;
|
||||||
memcpy(optval, tp->saved_syn + 1, optlen);
|
memcpy(optval, tp->saved_syn->data, optlen);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto err_clear;
|
goto err_clear;
|
||||||
|
|
|
@ -3788,20 +3788,21 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
if (tp->saved_syn) {
|
if (tp->saved_syn) {
|
||||||
if (len < tp->saved_syn[0]) {
|
if (len < tcp_saved_syn_len(tp->saved_syn)) {
|
||||||
if (put_user(tp->saved_syn[0], optlen)) {
|
if (put_user(tcp_saved_syn_len(tp->saved_syn),
|
||||||
|
optlen)) {
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
len = tp->saved_syn[0];
|
len = tcp_saved_syn_len(tp->saved_syn);
|
||||||
if (put_user(len, optlen)) {
|
if (put_user(len, optlen)) {
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
if (copy_to_user(optval, tp->saved_syn + 1, len)) {
|
if (copy_to_user(optval, tp->saved_syn->data, len)) {
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6599,13 +6599,15 @@ static void tcp_reqsk_record_syn(const struct sock *sk,
|
||||||
{
|
{
|
||||||
if (tcp_sk(sk)->save_syn) {
|
if (tcp_sk(sk)->save_syn) {
|
||||||
u32 len = skb_network_header_len(skb) + tcp_hdrlen(skb);
|
u32 len = skb_network_header_len(skb) + tcp_hdrlen(skb);
|
||||||
u32 *copy;
|
struct saved_syn *saved_syn;
|
||||||
|
|
||||||
copy = kmalloc(len + sizeof(u32), GFP_ATOMIC);
|
saved_syn = kmalloc(struct_size(saved_syn, data, len),
|
||||||
if (copy) {
|
GFP_ATOMIC);
|
||||||
copy[0] = len;
|
if (saved_syn) {
|
||||||
memcpy(©[1], skb_network_header(skb), len);
|
saved_syn->network_hdrlen = skb_network_header_len(skb);
|
||||||
req->saved_syn = copy;
|
saved_syn->tcp_hdrlen = tcp_hdrlen(skb);
|
||||||
|
memcpy(saved_syn->data, skb_network_header(skb), len);
|
||||||
|
req->saved_syn = saved_syn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue