bpf: tcp: Add bpf_skops_established()
In tcp_init_transfer(), it currently calls the bpf prog to give it a chance to handle the just "ESTABLISHED" event (e.g. do setsockopt on the newly established sk). Right now, it is done by calling the general purpose tcp_call_bpf(). In the later patch, it also needs to pass the just-received skb which concludes the 3 way handshake. E.g. the SYNACK received at the active side. The bpf prog can then learn some specific header options written by the peer's bpf-prog and potentially do setsockopt on the newly established sk. Thus, instead of reusing the general purpose tcp_call_bpf(), a new function bpf_skops_established() is added to allow passing the "skb" to the bpf prog. The actual skb passing from bpf_skops_established() to the bpf prog will happen together in a later patch which has the necessary bpf pieces. A "skb" arg is also added to tcp_init_transfer() such that it can then be passed to bpf_skops_established(). Calling the new bpf_skops_established() instead of tcp_call_bpf() should be a noop in this patch. Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20200820190039.2884750-1-kafai@fb.com
This commit is contained in:
parent
7656d68455
commit
72be0fe6ba
@ -394,7 +394,7 @@ void tcp_metrics_init(void);
|
|||||||
bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst);
|
bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst);
|
||||||
void tcp_close(struct sock *sk, long timeout);
|
void tcp_close(struct sock *sk, long timeout);
|
||||||
void tcp_init_sock(struct sock *sk);
|
void tcp_init_sock(struct sock *sk);
|
||||||
void tcp_init_transfer(struct sock *sk, int bpf_op);
|
void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb);
|
||||||
__poll_t tcp_poll(struct file *file, struct socket *sock,
|
__poll_t tcp_poll(struct file *file, struct socket *sock,
|
||||||
struct poll_table_struct *wait);
|
struct poll_table_struct *wait);
|
||||||
int tcp_getsockopt(struct sock *sk, int level, int optname,
|
int tcp_getsockopt(struct sock *sk, int level, int optname,
|
||||||
|
@ -295,7 +295,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
|||||||
refcount_set(&req->rsk_refcnt, 2);
|
refcount_set(&req->rsk_refcnt, 2);
|
||||||
|
|
||||||
/* Now finish processing the fastopen child socket. */
|
/* Now finish processing the fastopen child socket. */
|
||||||
tcp_init_transfer(child, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB);
|
tcp_init_transfer(child, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, skb);
|
||||||
|
|
||||||
tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
|
tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
|
||||||
|
|
||||||
|
@ -138,6 +138,29 @@ void clean_acked_data_flush(void)
|
|||||||
EXPORT_SYMBOL_GPL(clean_acked_data_flush);
|
EXPORT_SYMBOL_GPL(clean_acked_data_flush);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CGROUP_BPF
|
||||||
|
static void bpf_skops_established(struct sock *sk, int bpf_op,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct bpf_sock_ops_kern sock_ops;
|
||||||
|
|
||||||
|
sock_owned_by_me(sk);
|
||||||
|
|
||||||
|
memset(&sock_ops, 0, offsetof(struct bpf_sock_ops_kern, temp));
|
||||||
|
sock_ops.op = bpf_op;
|
||||||
|
sock_ops.is_fullsock = 1;
|
||||||
|
sock_ops.sk = sk;
|
||||||
|
/* skb will be passed to the bpf prog in a later patch. */
|
||||||
|
|
||||||
|
BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void bpf_skops_established(struct sock *sk, int bpf_op,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb,
|
static void tcp_gro_dev_warn(struct sock *sk, const struct sk_buff *skb,
|
||||||
unsigned int len)
|
unsigned int len)
|
||||||
{
|
{
|
||||||
@ -5808,7 +5831,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tcp_rcv_established);
|
EXPORT_SYMBOL(tcp_rcv_established);
|
||||||
|
|
||||||
void tcp_init_transfer(struct sock *sk, int bpf_op)
|
void tcp_init_transfer(struct sock *sk, int bpf_op, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
struct tcp_sock *tp = tcp_sk(sk);
|
struct tcp_sock *tp = tcp_sk(sk);
|
||||||
@ -5829,7 +5852,7 @@ void tcp_init_transfer(struct sock *sk, int bpf_op)
|
|||||||
tp->snd_cwnd = tcp_init_cwnd(tp, __sk_dst_get(sk));
|
tp->snd_cwnd = tcp_init_cwnd(tp, __sk_dst_get(sk));
|
||||||
tp->snd_cwnd_stamp = tcp_jiffies32;
|
tp->snd_cwnd_stamp = tcp_jiffies32;
|
||||||
|
|
||||||
tcp_call_bpf(sk, bpf_op, 0, NULL);
|
bpf_skops_established(sk, bpf_op, skb);
|
||||||
tcp_init_congestion_control(sk);
|
tcp_init_congestion_control(sk);
|
||||||
tcp_init_buffer_space(sk);
|
tcp_init_buffer_space(sk);
|
||||||
}
|
}
|
||||||
@ -5848,7 +5871,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
|
|||||||
sk_mark_napi_id(sk, skb);
|
sk_mark_napi_id(sk, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp_init_transfer(sk, BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB);
|
tcp_init_transfer(sk, BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, skb);
|
||||||
|
|
||||||
/* Prevent spurious tcp_cwnd_restart() on first data
|
/* Prevent spurious tcp_cwnd_restart() on first data
|
||||||
* packet.
|
* packet.
|
||||||
@ -6320,7 +6343,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
|||||||
} else {
|
} else {
|
||||||
tcp_try_undo_spurious_syn(sk);
|
tcp_try_undo_spurious_syn(sk);
|
||||||
tp->retrans_stamp = 0;
|
tp->retrans_stamp = 0;
|
||||||
tcp_init_transfer(sk, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB);
|
tcp_init_transfer(sk, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB,
|
||||||
|
skb);
|
||||||
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
|
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
|
||||||
}
|
}
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
Loading…
Reference in New Issue
Block a user