diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0a3e0424999931390a4f474650e98c5e2728088b..dd54acedc646efef06b29aff19e91d8aa4713375 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -4050,6 +4050,12 @@ union bpf_attr { * **-ENOENT** if symbol is not found. * * **-EPERM** if caller does not have permission to obtain kernel address. + * + * int bpf_update_tcp_seq(struct xdp_buff *ctx, struct bpf_sock_tuple *tuple, u32 len, u32 netns_id, u64 flags) + * Description + * Update tcp seq + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -4235,6 +4241,7 @@ union bpf_attr { FN(btf_find_by_name_kind), \ FN(sys_close), \ FN(kallsyms_lookup_name), \ + FN(update_tcp_seq), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper @@ -4583,6 +4590,10 @@ struct bpf_sock_tuple { __be16 dport; } ipv6; }; + + __be32 seq; + __be32 delta; + __be32 ack_seq; }; struct bpf_xdp_sock { diff --git a/net/core/filter.c b/net/core/filter.c index 4d2290004325943db675e0ce05077ae7b295e70c..3065b103f65ee8e53f23c177210fd9b7f1cc2764 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -6239,6 +6239,54 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = { .arg5_type = ARG_ANYTHING, }; +/* If we update tp->rcv_nxt, also update tp->bytes_received */ +static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) +{ + u32 delta = seq - tp->rcv_nxt; + + sock_owned_by_me((struct sock *)tp); + tp->bytes_received += delta; + WRITE_ONCE(tp->rcv_nxt, seq); +} + +BPF_CALL_5(bpf_xdp_update_tcp_seq, struct xdp_buff *, ctx, + struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags) +{ + struct net *caller_net = dev_net(ctx->rxq->dev); + int ifindex = ctx->rxq->dev->ifindex; + struct sock *sk; + struct tcp_sock *tp; + + sk = __bpf_sk_lookup(NULL, tuple, len, caller_net, + ifindex, IPPROTO_TCP, netns_id, + flags); + if (!sk) + return -1; + + tp = tcp_sk(sk); + tcp_rcv_nxt_update(tp, tuple->seq + tuple->delta); + + WRITE_ONCE(tp->snd_nxt, tuple->ack_seq); + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); + WRITE_ONCE(tp->bytes_sent, tuple->ack_seq); + WRITE_ONCE(tp->bytes_acked, tuple->ack_seq); + WRITE_ONCE(tp->write_seq, tuple->ack_seq); + + return 0; +} + +static const struct bpf_func_proto bpf_xdp_update_tcp_seq_proto = { + .func = bpf_xdp_update_tcp_seq, + .gpl_only = false, + .pkt_access = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_CTX, + .arg2_type = ARG_PTR_TO_MEM, + .arg3_type = ARG_CONST_SIZE, + .arg4_type = ARG_ANYTHING, + .arg5_type = ARG_ANYTHING, +}; + BPF_CALL_5(bpf_sock_addr_skc_lookup_tcp, struct bpf_sock_addr_kern *, ctx, struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags) { @@ -7317,6 +7365,8 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_xdp_sk_lookup_udp_proto; case BPF_FUNC_sk_lookup_tcp: return &bpf_xdp_sk_lookup_tcp_proto; + case BPF_FUNC_update_tcp_seq: + return &bpf_xdp_update_tcp_seq_proto; case BPF_FUNC_sk_release: return &bpf_sk_release_proto; case BPF_FUNC_skc_lookup_tcp: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 82cfa82231b509dbab31e7a380579d59f7dd294b..4f86c2187adab6f31c3865bb94c7e2a0fb896814 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -4760,6 +4760,12 @@ union bpf_attr { * **-ENOENT** if symbol is not found. * * **-EPERM** if caller does not have permission to obtain kernel address. + * + * int bpf_update_tcp_seq(struct xdp_buff *ctx, struct bpf_sock_tuple *tuple, u32 len, u32 netns_id, u64 flags) + * Description + * Update tcp seq + * Return + * 0 on success, or a negative error in case of failure. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -4945,6 +4951,7 @@ union bpf_attr { FN(btf_find_by_name_kind), \ FN(sys_close), \ FN(kallsyms_lookup_name), \ + FN(update_tcp_seq), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper @@ -5292,6 +5299,10 @@ struct bpf_sock_tuple { __be16 dport; } ipv6; }; + + __be32 seq; + __be32 delta; + __be32 ack_seq; }; struct bpf_xdp_sock {