diff options
| author | Martin KaFai Lau <kafai@fb.com> | 2019-02-10 02:22:23 -0500 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2019-02-10 22:46:17 -0500 |
| commit | 9b1f3d6e5af295a72deb5e3f04db07a6a58be72e (patch) | |
| tree | ed930951a91c0ebc2d278c6f50e19955cee9d714 | |
| parent | aa65d6960a98fc15a96ce361b26e9fd55c9bccc5 (diff) | |
bpf: Refactor sock_ops_convert_ctx_access
The next patch will introduce a new "struct bpf_tcp_sock" which
exposes the same tcp_sock's fields already exposed in
"struct bpf_sock_ops".
This patch refactor the existing convert_ctx_access() codes for
"struct bpf_sock_ops" to get them ready to be reused for
"struct bpf_tcp_sock". The "rtt_min" is not refactored
in this patch because its handling is different from other
fields.
The SOCK_OPS_GET_TCP_SOCK_FIELD is new. All other SOCK_OPS_XXX_FIELD
changes are code move only.
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
| -rw-r--r-- | net/core/filter.c | 287 |
1 files changed, 127 insertions, 160 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 01bb64bf2b5e..c0d7b9ef279f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -5030,6 +5030,54 @@ static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = { | |||
| 5030 | }; | 5030 | }; |
| 5031 | #endif /* CONFIG_IPV6_SEG6_BPF */ | 5031 | #endif /* CONFIG_IPV6_SEG6_BPF */ |
| 5032 | 5032 | ||
| 5033 | #define CONVERT_COMMON_TCP_SOCK_FIELDS(md_type, CONVERT) \ | ||
| 5034 | do { \ | ||
| 5035 | switch (si->off) { \ | ||
| 5036 | case offsetof(md_type, snd_cwnd): \ | ||
| 5037 | CONVERT(snd_cwnd); break; \ | ||
| 5038 | case offsetof(md_type, srtt_us): \ | ||
| 5039 | CONVERT(srtt_us); break; \ | ||
| 5040 | case offsetof(md_type, snd_ssthresh): \ | ||
| 5041 | CONVERT(snd_ssthresh); break; \ | ||
| 5042 | case offsetof(md_type, rcv_nxt): \ | ||
| 5043 | CONVERT(rcv_nxt); break; \ | ||
| 5044 | case offsetof(md_type, snd_nxt): \ | ||
| 5045 | CONVERT(snd_nxt); break; \ | ||
| 5046 | case offsetof(md_type, snd_una): \ | ||
| 5047 | CONVERT(snd_una); break; \ | ||
| 5048 | case offsetof(md_type, mss_cache): \ | ||
| 5049 | CONVERT(mss_cache); break; \ | ||
| 5050 | case offsetof(md_type, ecn_flags): \ | ||
| 5051 | CONVERT(ecn_flags); break; \ | ||
| 5052 | case offsetof(md_type, rate_delivered): \ | ||
| 5053 | CONVERT(rate_delivered); break; \ | ||
| 5054 | case offsetof(md_type, rate_interval_us): \ | ||
| 5055 | CONVERT(rate_interval_us); break; \ | ||
| 5056 | case offsetof(md_type, packets_out): \ | ||
| 5057 | CONVERT(packets_out); break; \ | ||
| 5058 | case offsetof(md_type, retrans_out): \ | ||
| 5059 | CONVERT(retrans_out); break; \ | ||
| 5060 | case offsetof(md_type, total_retrans): \ | ||
| 5061 | CONVERT(total_retrans); break; \ | ||
| 5062 | case offsetof(md_type, segs_in): \ | ||
| 5063 | CONVERT(segs_in); break; \ | ||
| 5064 | case offsetof(md_type, data_segs_in): \ | ||
| 5065 | CONVERT(data_segs_in); break; \ | ||
| 5066 | case offsetof(md_type, segs_out): \ | ||
| 5067 | CONVERT(segs_out); break; \ | ||
| 5068 | case offsetof(md_type, data_segs_out): \ | ||
| 5069 | CONVERT(data_segs_out); break; \ | ||
| 5070 | case offsetof(md_type, lost_out): \ | ||
| 5071 | CONVERT(lost_out); break; \ | ||
| 5072 | case offsetof(md_type, sacked_out): \ | ||
| 5073 | CONVERT(sacked_out); break; \ | ||
| 5074 | case offsetof(md_type, bytes_received): \ | ||
| 5075 | CONVERT(bytes_received); break; \ | ||
| 5076 | case offsetof(md_type, bytes_acked): \ | ||
| 5077 | CONVERT(bytes_acked); break; \ | ||
| 5078 | } \ | ||
| 5079 | } while (0) | ||
| 5080 | |||
| 5033 | #ifdef CONFIG_INET | 5081 | #ifdef CONFIG_INET |
| 5034 | static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, | 5082 | static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, |
| 5035 | int dif, int sdif, u8 family, u8 proto) | 5083 | int dif, int sdif, u8 family, u8 proto) |
| @@ -7196,6 +7244,85 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, | |||
| 7196 | struct bpf_insn *insn = insn_buf; | 7244 | struct bpf_insn *insn = insn_buf; |
| 7197 | int off; | 7245 | int off; |
| 7198 | 7246 | ||
| 7247 | /* Helper macro for adding read access to tcp_sock or sock fields. */ | ||
| 7248 | #define SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \ | ||
| 7249 | do { \ | ||
| 7250 | BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \ | ||
| 7251 | FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \ | ||
| 7252 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7253 | struct bpf_sock_ops_kern, \ | ||
| 7254 | is_fullsock), \ | ||
| 7255 | si->dst_reg, si->src_reg, \ | ||
| 7256 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7257 | is_fullsock)); \ | ||
| 7258 | *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 2); \ | ||
| 7259 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7260 | struct bpf_sock_ops_kern, sk),\ | ||
| 7261 | si->dst_reg, si->src_reg, \ | ||
| 7262 | offsetof(struct bpf_sock_ops_kern, sk));\ | ||
| 7263 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(OBJ, \ | ||
| 7264 | OBJ_FIELD), \ | ||
| 7265 | si->dst_reg, si->dst_reg, \ | ||
| 7266 | offsetof(OBJ, OBJ_FIELD)); \ | ||
| 7267 | } while (0) | ||
| 7268 | |||
| 7269 | #define SOCK_OPS_GET_TCP_SOCK_FIELD(FIELD) \ | ||
| 7270 | SOCK_OPS_GET_FIELD(FIELD, FIELD, struct tcp_sock) | ||
| 7271 | |||
| 7272 | /* Helper macro for adding write access to tcp_sock or sock fields. | ||
| 7273 | * The macro is called with two registers, dst_reg which contains a pointer | ||
| 7274 | * to ctx (context) and src_reg which contains the value that should be | ||
| 7275 | * stored. However, we need an additional register since we cannot overwrite | ||
| 7276 | * dst_reg because it may be used later in the program. | ||
| 7277 | * Instead we "borrow" one of the other register. We first save its value | ||
| 7278 | * into a new (temp) field in bpf_sock_ops_kern, use it, and then restore | ||
| 7279 | * it at the end of the macro. | ||
| 7280 | */ | ||
| 7281 | #define SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \ | ||
| 7282 | do { \ | ||
| 7283 | int reg = BPF_REG_9; \ | ||
| 7284 | BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \ | ||
| 7285 | FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \ | ||
| 7286 | if (si->dst_reg == reg || si->src_reg == reg) \ | ||
| 7287 | reg--; \ | ||
| 7288 | if (si->dst_reg == reg || si->src_reg == reg) \ | ||
| 7289 | reg--; \ | ||
| 7290 | *insn++ = BPF_STX_MEM(BPF_DW, si->dst_reg, reg, \ | ||
| 7291 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7292 | temp)); \ | ||
| 7293 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7294 | struct bpf_sock_ops_kern, \ | ||
| 7295 | is_fullsock), \ | ||
| 7296 | reg, si->dst_reg, \ | ||
| 7297 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7298 | is_fullsock)); \ | ||
| 7299 | *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \ | ||
| 7300 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7301 | struct bpf_sock_ops_kern, sk),\ | ||
| 7302 | reg, si->dst_reg, \ | ||
| 7303 | offsetof(struct bpf_sock_ops_kern, sk));\ | ||
| 7304 | *insn++ = BPF_STX_MEM(BPF_FIELD_SIZEOF(OBJ, OBJ_FIELD), \ | ||
| 7305 | reg, si->src_reg, \ | ||
| 7306 | offsetof(OBJ, OBJ_FIELD)); \ | ||
| 7307 | *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->dst_reg, \ | ||
| 7308 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7309 | temp)); \ | ||
| 7310 | } while (0) | ||
| 7311 | |||
| 7312 | #define SOCK_OPS_GET_OR_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ, TYPE) \ | ||
| 7313 | do { \ | ||
| 7314 | if (TYPE == BPF_WRITE) \ | ||
| 7315 | SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \ | ||
| 7316 | else \ | ||
| 7317 | SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \ | ||
| 7318 | } while (0) | ||
| 7319 | |||
| 7320 | CONVERT_COMMON_TCP_SOCK_FIELDS(struct bpf_sock_ops, | ||
| 7321 | SOCK_OPS_GET_TCP_SOCK_FIELD); | ||
| 7322 | |||
| 7323 | if (insn > insn_buf) | ||
| 7324 | return insn - insn_buf; | ||
| 7325 | |||
| 7199 | switch (si->off) { | 7326 | switch (si->off) { |
| 7200 | case offsetof(struct bpf_sock_ops, op) ... | 7327 | case offsetof(struct bpf_sock_ops, op) ... |
| 7201 | offsetof(struct bpf_sock_ops, replylong[3]): | 7328 | offsetof(struct bpf_sock_ops, replylong[3]): |
| @@ -7353,175 +7480,15 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, | |||
| 7353 | FIELD_SIZEOF(struct minmax_sample, t)); | 7480 | FIELD_SIZEOF(struct minmax_sample, t)); |
| 7354 | break; | 7481 | break; |
| 7355 | 7482 | ||
| 7356 | /* Helper macro for adding read access to tcp_sock or sock fields. */ | ||
| 7357 | #define SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \ | ||
| 7358 | do { \ | ||
| 7359 | BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \ | ||
| 7360 | FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \ | ||
| 7361 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7362 | struct bpf_sock_ops_kern, \ | ||
| 7363 | is_fullsock), \ | ||
| 7364 | si->dst_reg, si->src_reg, \ | ||
| 7365 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7366 | is_fullsock)); \ | ||
| 7367 | *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 2); \ | ||
| 7368 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7369 | struct bpf_sock_ops_kern, sk),\ | ||
| 7370 | si->dst_reg, si->src_reg, \ | ||
| 7371 | offsetof(struct bpf_sock_ops_kern, sk));\ | ||
| 7372 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(OBJ, \ | ||
| 7373 | OBJ_FIELD), \ | ||
| 7374 | si->dst_reg, si->dst_reg, \ | ||
| 7375 | offsetof(OBJ, OBJ_FIELD)); \ | ||
| 7376 | } while (0) | ||
| 7377 | |||
| 7378 | /* Helper macro for adding write access to tcp_sock or sock fields. | ||
| 7379 | * The macro is called with two registers, dst_reg which contains a pointer | ||
| 7380 | * to ctx (context) and src_reg which contains the value that should be | ||
| 7381 | * stored. However, we need an additional register since we cannot overwrite | ||
| 7382 | * dst_reg because it may be used later in the program. | ||
| 7383 | * Instead we "borrow" one of the other register. We first save its value | ||
| 7384 | * into a new (temp) field in bpf_sock_ops_kern, use it, and then restore | ||
| 7385 | * it at the end of the macro. | ||
| 7386 | */ | ||
| 7387 | #define SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \ | ||
| 7388 | do { \ | ||
| 7389 | int reg = BPF_REG_9; \ | ||
| 7390 | BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \ | ||
| 7391 | FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \ | ||
| 7392 | if (si->dst_reg == reg || si->src_reg == reg) \ | ||
| 7393 | reg--; \ | ||
| 7394 | if (si->dst_reg == reg || si->src_reg == reg) \ | ||
| 7395 | reg--; \ | ||
| 7396 | *insn++ = BPF_STX_MEM(BPF_DW, si->dst_reg, reg, \ | ||
| 7397 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7398 | temp)); \ | ||
| 7399 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7400 | struct bpf_sock_ops_kern, \ | ||
| 7401 | is_fullsock), \ | ||
| 7402 | reg, si->dst_reg, \ | ||
| 7403 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7404 | is_fullsock)); \ | ||
| 7405 | *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \ | ||
| 7406 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \ | ||
| 7407 | struct bpf_sock_ops_kern, sk),\ | ||
| 7408 | reg, si->dst_reg, \ | ||
| 7409 | offsetof(struct bpf_sock_ops_kern, sk));\ | ||
| 7410 | *insn++ = BPF_STX_MEM(BPF_FIELD_SIZEOF(OBJ, OBJ_FIELD), \ | ||
| 7411 | reg, si->src_reg, \ | ||
| 7412 | offsetof(OBJ, OBJ_FIELD)); \ | ||
| 7413 | *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->dst_reg, \ | ||
| 7414 | offsetof(struct bpf_sock_ops_kern, \ | ||
| 7415 | temp)); \ | ||
| 7416 | } while (0) | ||
| 7417 | |||
| 7418 | #define SOCK_OPS_GET_OR_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ, TYPE) \ | ||
| 7419 | do { \ | ||
| 7420 | if (TYPE == BPF_WRITE) \ | ||
| 7421 | SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \ | ||
| 7422 | else \ | ||
| 7423 | SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \ | ||
| 7424 | } while (0) | ||
| 7425 | |||
| 7426 | case offsetof(struct bpf_sock_ops, snd_cwnd): | ||
| 7427 | SOCK_OPS_GET_FIELD(snd_cwnd, snd_cwnd, struct tcp_sock); | ||
| 7428 | break; | ||
| 7429 | |||
| 7430 | case offsetof(struct bpf_sock_ops, srtt_us): | ||
| 7431 | SOCK_OPS_GET_FIELD(srtt_us, srtt_us, struct tcp_sock); | ||
| 7432 | break; | ||
| 7433 | |||
| 7434 | case offsetof(struct bpf_sock_ops, bpf_sock_ops_cb_flags): | 7483 | case offsetof(struct bpf_sock_ops, bpf_sock_ops_cb_flags): |
| 7435 | SOCK_OPS_GET_FIELD(bpf_sock_ops_cb_flags, bpf_sock_ops_cb_flags, | 7484 | SOCK_OPS_GET_FIELD(bpf_sock_ops_cb_flags, bpf_sock_ops_cb_flags, |
| 7436 | struct tcp_sock); | 7485 | struct tcp_sock); |
| 7437 | break; | 7486 | break; |
| 7438 | 7487 | ||
| 7439 | case offsetof(struct bpf_sock_ops, snd_ssthresh): | ||
| 7440 | SOCK_OPS_GET_FIELD(snd_ssthresh, snd_ssthresh, struct tcp_sock); | ||
| 7441 | break; | ||
| 7442 | |||
| 7443 | case offsetof(struct bpf_sock_ops, rcv_nxt): | ||
| 7444 | SOCK_OPS_GET_FIELD(rcv_nxt, rcv_nxt, struct tcp_sock); | ||
| 7445 | break; | ||
| 7446 | |||
| 7447 | case offsetof(struct bpf_sock_ops, snd_nxt): | ||
| 7448 | SOCK_OPS_GET_FIELD(snd_nxt, snd_nxt, struct tcp_sock); | ||
| 7449 | break; | ||
| 7450 | |||
| 7451 | case offsetof(struct bpf_sock_ops, snd_una): | ||
| 7452 | SOCK_OPS_GET_FIELD(snd_una, snd_una, struct tcp_sock); | ||
| 7453 | break; | ||
| 7454 | |||
| 7455 | case offsetof(struct bpf_sock_ops, mss_cache): | ||
| 7456 | SOCK_OPS_GET_FIELD(mss_cache, mss_cache, struct tcp_sock); | ||
| 7457 | break; | ||
| 7458 | |||
| 7459 | case offsetof(struct bpf_sock_ops, ecn_flags): | ||
| 7460 | SOCK_OPS_GET_FIELD(ecn_flags, ecn_flags, struct tcp_sock); | ||
| 7461 | break; | ||
| 7462 | |||
| 7463 | case offsetof(struct bpf_sock_ops, rate_delivered): | ||
| 7464 | SOCK_OPS_GET_FIELD(rate_delivered, rate_delivered, | ||
| 7465 | struct tcp_sock); | ||
| 7466 | break; | ||
| 7467 | |||
| 7468 | case offsetof(struct bpf_sock_ops, rate_interval_us): | ||
| 7469 | SOCK_OPS_GET_FIELD(rate_interval_us, rate_interval_us, | ||
| 7470 | struct tcp_sock); | ||
| 7471 | break; | ||
| 7472 | |||
| 7473 | case offsetof(struct bpf_sock_ops, packets_out): | ||
| 7474 | SOCK_OPS_GET_FIELD(packets_out, packets_out, struct tcp_sock); | ||
| 7475 | break; | ||
| 7476 | |||
| 7477 | case offsetof(struct bpf_sock_ops, retrans_out): | ||
| 7478 | SOCK_OPS_GET_FIELD(retrans_out, retrans_out, struct tcp_sock); | ||
| 7479 | break; | ||
| 7480 | |||
| 7481 | case offsetof(struct bpf_sock_ops, total_retrans): | ||
| 7482 | SOCK_OPS_GET_FIELD(total_retrans, total_retrans, | ||
| 7483 | struct tcp_sock); | ||
| 7484 | break; | ||
| 7485 | |||
| 7486 | case offsetof(struct bpf_sock_ops, segs_in): | ||
| 7487 | SOCK_OPS_GET_FIELD(segs_in, segs_in, struct tcp_sock); | ||
| 7488 | break; | ||
| 7489 | |||
| 7490 | case offsetof(struct bpf_sock_ops, data_segs_in): | ||
| 7491 | SOCK_OPS_GET_FIELD(data_segs_in, data_segs_in, struct tcp_sock); | ||
| 7492 | break; | ||
| 7493 | |||
| 7494 | case offsetof(struct bpf_sock_ops, segs_out): | ||
| 7495 | SOCK_OPS_GET_FIELD(segs_out, segs_out, struct tcp_sock); | ||
| 7496 | break; | ||
| 7497 | |||
| 7498 | case offsetof(struct bpf_sock_ops, data_segs_out): | ||
| 7499 | SOCK_OPS_GET_FIELD(data_segs_out, data_segs_out, | ||
| 7500 | struct tcp_sock); | ||
| 7501 | break; | ||
| 7502 | |||
| 7503 | case offsetof(struct bpf_sock_ops, lost_out): | ||
| 7504 | SOCK_OPS_GET_FIELD(lost_out, lost_out, struct tcp_sock); | ||
| 7505 | break; | ||
| 7506 | |||
| 7507 | case offsetof(struct bpf_sock_ops, sacked_out): | ||
| 7508 | SOCK_OPS_GET_FIELD(sacked_out, sacked_out, struct tcp_sock); | ||
| 7509 | break; | ||
| 7510 | |||
| 7511 | case offsetof(struct bpf_sock_ops, sk_txhash): | 7488 | case offsetof(struct bpf_sock_ops, sk_txhash): |
| 7512 | SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash, | 7489 | SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash, |
| 7513 | struct sock, type); | 7490 | struct sock, type); |
| 7514 | break; | 7491 | break; |
| 7515 | |||
| 7516 | case offsetof(struct bpf_sock_ops, bytes_received): | ||
| 7517 | SOCK_OPS_GET_FIELD(bytes_received, bytes_received, | ||
| 7518 | struct tcp_sock); | ||
| 7519 | break; | ||
| 7520 | |||
| 7521 | case offsetof(struct bpf_sock_ops, bytes_acked): | ||
| 7522 | SOCK_OPS_GET_FIELD(bytes_acked, bytes_acked, struct tcp_sock); | ||
| 7523 | break; | ||
| 7524 | |||
| 7525 | } | 7492 | } |
| 7526 | return insn - insn_buf; | 7493 | return insn - insn_buf; |
| 7527 | } | 7494 | } |
