Skip to content

Commit f19397a

Browse files
Lawrence Brakmoborkmann
authored andcommitted
bpf: Add access to snd_cwnd and others in sock_ops
Adds read access to snd_cwnd and srtt_us fields of tcp_sock. Since these fields are only valid if the socket associated with the sock_ops program call is a full socket, the field is_fullsock is also added to the bpf_sock_ops struct. If the socket is not a full socket, reading these fields returns 0. Note that in most cases it will not be necessary to check is_fullsock to know if there is a full socket. The context of the call, as specified by the 'op' field, can sometimes determine whether there is a full socket. The struct bpf_sock_ops has the following fields added: __u32 is_fullsock; /* Some TCP fields are only valid if * there is a full socket. If not, the * fields read as zero. */ __u32 snd_cwnd; __u32 srtt_us; /* Averaged RTT << 3 in usecs */ There is a new macro, SOCK_OPS_GET_TCP32(NAME), to make it easier to add read access to more 32 bit tcp_sock fields. Signed-off-by: Lawrence Brakmo <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent 792f3dd commit f19397a

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

include/linux/filter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,7 @@ struct bpf_sock_ops_kern {
985985
u32 reply;
986986
u32 replylong[4];
987987
};
988+
u32 is_fullsock;
988989
};
989990

990991
#endif /* __LINUX_FILTER_H__ */

include/net/tcp.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,10 +2012,12 @@ static inline int tcp_call_bpf(struct sock *sk, int op)
20122012
struct bpf_sock_ops_kern sock_ops;
20132013
int ret;
20142014

2015-
if (sk_fullsock(sk))
2015+
memset(&sock_ops, 0, sizeof(sock_ops));
2016+
if (sk_fullsock(sk)) {
2017+
sock_ops.is_fullsock = 1;
20162018
sock_owned_by_me(sk);
2019+
}
20172020

2018-
memset(&sock_ops, 0, sizeof(sock_ops));
20192021
sock_ops.sk = sk;
20202022
sock_ops.op = op;
20212023

include/uapi/linux/bpf.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,12 @@ struct bpf_sock_ops {
941941
__u32 local_ip6[4]; /* Stored in network byte order */
942942
__u32 remote_port; /* Stored in network byte order */
943943
__u32 local_port; /* stored in host byte order */
944+
__u32 is_fullsock; /* Some TCP fields are only valid if
945+
* there is a full socket. If not, the
946+
* fields read as zero.
947+
*/
948+
__u32 snd_cwnd;
949+
__u32 srtt_us; /* Averaged RTT << 3 in usecs */
944950
};
945951

946952
/* List of known BPF sock_ops operators.

net/core/filter.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4437,6 +4437,42 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
44374437
*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
44384438
offsetof(struct sock_common, skc_num));
44394439
break;
4440+
4441+
case offsetof(struct bpf_sock_ops, is_fullsock):
4442+
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
4443+
struct bpf_sock_ops_kern,
4444+
is_fullsock),
4445+
si->dst_reg, si->src_reg,
4446+
offsetof(struct bpf_sock_ops_kern,
4447+
is_fullsock));
4448+
break;
4449+
4450+
/* Helper macro for adding read access to tcp_sock fields. */
4451+
#define SOCK_OPS_GET_TCP32(FIELD_NAME) \
4452+
do { \
4453+
BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, FIELD_NAME) != 4); \
4454+
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
4455+
struct bpf_sock_ops_kern, \
4456+
is_fullsock), \
4457+
si->dst_reg, si->src_reg, \
4458+
offsetof(struct bpf_sock_ops_kern, \
4459+
is_fullsock)); \
4460+
*insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 2); \
4461+
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
4462+
struct bpf_sock_ops_kern, sk),\
4463+
si->dst_reg, si->src_reg, \
4464+
offsetof(struct bpf_sock_ops_kern, sk));\
4465+
*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg, \
4466+
offsetof(struct tcp_sock, FIELD_NAME)); \
4467+
} while (0)
4468+
4469+
case offsetof(struct bpf_sock_ops, snd_cwnd):
4470+
SOCK_OPS_GET_TCP32(snd_cwnd);
4471+
break;
4472+
4473+
case offsetof(struct bpf_sock_ops, srtt_us):
4474+
SOCK_OPS_GET_TCP32(srtt_us);
4475+
break;
44404476
}
44414477
return insn - insn_buf;
44424478
}

0 commit comments

Comments
 (0)