aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin KaFai Lau <kafai@fb.com>2019-02-10 02:22:23 -0500
committerAlexei Starovoitov <ast@kernel.org>2019-02-10 22:46:17 -0500
commit9b1f3d6e5af295a72deb5e3f04db07a6a58be72e (patch)
treeed930951a91c0ebc2d278c6f50e19955cee9d714
parentaa65d6960a98fc15a96ce361b26e9fd55c9bccc5 (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.c287
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) \
5034do { \
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
5034static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple, 5082static 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}