提交 ed876af4 编写于 作者: X Xu Kuohai 提交者: Zheng Zengkai

bpf: Add helper bpf_tcp_udpate_seq to synchronize tcp seq/ack

Offering: HULK
hulk inclusion
category: feature
bugzilla: N/A

--------------------------------

In order to process TCP packet with BPF/XDP, it's necessary to
synchronize seq and ack between kernel network stack and bpf prog.
This patch introduces a sample helper to do the sync.

Note that, it's only used for samples, retransmission and congestion
control are not supported.
Signed-off-by: NHe Fengqing <hefengqing@huawei.com>
Signed-off-by: NXu Kuohai <xukuohai@huawei.com>
Signed-off-by: NYang Jihong <yangjihong@huawei.com>
上级 cdeb2751
...@@ -4050,6 +4050,12 @@ union bpf_attr { ...@@ -4050,6 +4050,12 @@ union bpf_attr {
* **-ENOENT** if symbol is not found. * **-ENOENT** if symbol is not found.
* *
* **-EPERM** if caller does not have permission to obtain kernel address. * **-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) \ #define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \ FN(unspec), \
...@@ -4235,6 +4241,7 @@ union bpf_attr { ...@@ -4235,6 +4241,7 @@ union bpf_attr {
FN(btf_find_by_name_kind), \ FN(btf_find_by_name_kind), \
FN(sys_close), \ FN(sys_close), \
FN(kallsyms_lookup_name), \ FN(kallsyms_lookup_name), \
FN(update_tcp_seq), \
/* */ /* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper /* integer value in 'imm' field of BPF_CALL instruction selects which helper
...@@ -4583,6 +4590,10 @@ struct bpf_sock_tuple { ...@@ -4583,6 +4590,10 @@ struct bpf_sock_tuple {
__be16 dport; __be16 dport;
} ipv6; } ipv6;
}; };
__be32 seq;
__be32 delta;
__be32 ack_seq;
}; };
struct bpf_xdp_sock { struct bpf_xdp_sock {
......
...@@ -6239,6 +6239,54 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = { ...@@ -6239,6 +6239,54 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = {
.arg5_type = ARG_ANYTHING, .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, 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) 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) ...@@ -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; return &bpf_xdp_sk_lookup_udp_proto;
case BPF_FUNC_sk_lookup_tcp: case BPF_FUNC_sk_lookup_tcp:
return &bpf_xdp_sk_lookup_tcp_proto; 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: case BPF_FUNC_sk_release:
return &bpf_sk_release_proto; return &bpf_sk_release_proto;
case BPF_FUNC_skc_lookup_tcp: case BPF_FUNC_skc_lookup_tcp:
......
...@@ -4760,6 +4760,12 @@ union bpf_attr { ...@@ -4760,6 +4760,12 @@ union bpf_attr {
* **-ENOENT** if symbol is not found. * **-ENOENT** if symbol is not found.
* *
* **-EPERM** if caller does not have permission to obtain kernel address. * **-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) \ #define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \ FN(unspec), \
...@@ -4945,6 +4951,7 @@ union bpf_attr { ...@@ -4945,6 +4951,7 @@ union bpf_attr {
FN(btf_find_by_name_kind), \ FN(btf_find_by_name_kind), \
FN(sys_close), \ FN(sys_close), \
FN(kallsyms_lookup_name), \ FN(kallsyms_lookup_name), \
FN(update_tcp_seq), \
/* */ /* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper /* integer value in 'imm' field of BPF_CALL instruction selects which helper
...@@ -5292,6 +5299,10 @@ struct bpf_sock_tuple { ...@@ -5292,6 +5299,10 @@ struct bpf_sock_tuple {
__be16 dport; __be16 dport;
} ipv6; } ipv6;
}; };
__be32 seq;
__be32 delta;
__be32 ack_seq;
}; };
struct bpf_xdp_sock { struct bpf_xdp_sock {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册