diff --git a/include/net/tcp.h b/include/net/tcp.h
index 48487135c076..7f4ab50f08c7 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -3054,6 +3054,12 @@ struct bpf_tcp_ops {
struct request_sock *req, struct sk_buff *syn_skb,
enum tcp_synack_type synack_type,
u32 opt_off);
+
+ /* Called when an incoming skb is enqueued to sk->sk_receive_queue. */
+ void (*enqueue_rcvq)(struct sock *sk, struct sk_buff *skb);
+
+ /* Called after data is dequeued from sk->sk_receive_queue. */
+ void (*dequeue_rcvq)(struct sock *sk);
};
#define bpf_tcp_ops_call(op, sk, ...) \@@ -3146,6 +3152,18 @@ static inline void tcp_bpf_rtt(struct sock *sk, long mrtt, u32 srtt)
bpf_tcp_ops_call(rtt, sk, mrtt, srtt);
}
+static inline void bpf_tcp_ops_enqueue_rcvq(struct sock *sk, struct sk_buff *skb)
+{
+ if (BPF_TCP_OPS_TEST_FLAG(tcp_sk(sk), RCVQ))
+ bpf_tcp_ops_call(enqueue_rcvq, sk, skb);
+}
+
+static inline void bpf_tcp_ops_dequeue_rcvq(struct sock *sk)
+{
+ if (BPF_TCP_OPS_TEST_FLAG(tcp_sk(sk), RCVQ))
+ bpf_tcp_ops_call(dequeue_rcvq, sk);
+}
+
#if IS_ENABLED(CONFIG_SMC)
extern struct static_key_false tcp_have_smc;
#endifdiff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 6ff90b73dd38..ded3ac8df9ac 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -7339,7 +7339,8 @@ enum {
BPF_TCP_OPS_FLAG_PARSE_HDR_OPT_ALL = (1 << 1),
BPF_TCP_OPS_FLAG_PARSE_HDR_OPT_UNKNOWN = (1 << 2),
BPF_TCP_OPS_FLAG_WRITE_HDR_OPT = (1 << 3),
- BPF_TCP_OPS_FLAG_ALL = (1 << 4) - 1,
+ BPF_TCP_OPS_FLAG_RCVQ = (1 << 4),
+ BPF_TCP_OPS_FLAG_ALL = (1 << 5) - 1,
};
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detectdiff --git a/net/ipv4/bpf_tcp_ops.c b/net/ipv4/bpf_tcp_ops.c
index 5693857e764e..dafe2337f9fc 100644
--- a/net/ipv4/bpf_tcp_ops.c
+++ b/net/ipv4/bpf_tcp_ops.c
@@ -76,6 +76,14 @@ static void write_hdr_opt_stub(struct sock *sk, struct sk_buff *skb,
{
}
+static void enqueue_rcvq_stub(struct sock *sk, struct sk_buff *skb)
+{
+}
+
+static void dequeue_rcvq_stub(struct sock *sk)
+{
+}
+
static struct bpf_tcp_ops __bpf_tcp_ops = {
.timeout_init = timeout_init_stub,
.rwnd_init = rwnd_init_stub,@@ -90,6 +98,8 @@ static struct bpf_tcp_ops __bpf_tcp_ops = {
.parse_hdr = parse_hdr_stub,
.hdr_opt_len = hdr_opt_len_stub,
.write_hdr_opt = write_hdr_opt_stub,
+ .enqueue_rcvq = enqueue_rcvq_stub,
+ .dequeue_rcvq = dequeue_rcvq_stub,
};
BPF_CALL_4(bpf_tcp_ops_store_hdr_opt, void *, ctx, const void *, from,diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index fa69961c47d3..a1e2bb3974ce 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1609,6 +1609,8 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
"cleanup rbuf bug: copied %X seq %X rcvnxt %X\n",
tp->copied_seq, TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt);
__tcp_cleanup_rbuf(sk, copied);
+
+ bpf_tcp_ops_dequeue_rcvq(sk);
}
static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb)
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index 471c78be5513..4939bcbc81d1 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -281,6 +281,8 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)
TCP_SKB_CB(skb)->seq++;
TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
+ bpf_tcp_ops_enqueue_rcvq(sk, skb);
+
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
tcp_add_receive_queue(sk, skb);
tp->syn_data_acked = 1;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 79d721215f52..8518c744aa17 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5351,6 +5351,8 @@ static void tcp_ofo_queue(struct sock *sk)
continue;
}
+ bpf_tcp_ops_enqueue_rcvq(sk, skb);
+
tail = skb_peek_tail(&sk->sk_receive_queue);
eaten = tail && tcp_try_coalesce(sk, tail, skb, &fragstolen);
tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
@@ -5554,6 +5556,8 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb,
int eaten;
struct sk_buff *tail = skb_peek_tail(&sk->sk_receive_queue);
+ bpf_tcp_ops_enqueue_rcvq(sk, skb);
+
eaten = (tail &&
tcp_try_coalesce(sk, tail,
skb, fragstolen)) ? 1 : 0;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 6ff90b73dd38..ded3ac8df9ac 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -7339,7 +7339,8 @@ enum {
BPF_TCP_OPS_FLAG_PARSE_HDR_OPT_ALL = (1 << 1),
BPF_TCP_OPS_FLAG_PARSE_HDR_OPT_UNKNOWN = (1 << 2),
BPF_TCP_OPS_FLAG_WRITE_HDR_OPT = (1 << 3),
- BPF_TCP_OPS_FLAG_ALL = (1 << 4) - 1,
+ BPF_TCP_OPS_FLAG_RCVQ = (1 << 4),
+ BPF_TCP_OPS_FLAG_ALL = (1 << 5) - 1,
};
/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect--
2.56.0.rc1.315.gc6ed9934b7-goog