| @@ -438,6 +438,7 @@ struct tcp_out_options { · 437 unmodified lines |
| 438 | 438 | u8 ws; /* window scale, 0 to disable */ |
| 439 | 439 | u8 num_sack_blocks; /* number of SACK blocks to include */ |
| 440 | 440 | u8 hash_size; /* bytes in hash_location */ |
| 441 | + u8 bpf_opt_len; /* length of BPF hdr option */ |
| 441 | 442 | __u8 *hash_location; /* temporary pointer, overloaded */ |
| 442 | 443 | __u32 tsval, tsecr; /* need to include OPTION_TS */ |
| 443 | 444 | struct tcp_fastopen_cookie *fastopen_cookie; /* Fast open cookie */ |
| @@ -452,6 +453,59 @@ static void mptcp_options_write(__be32 *ptr, struct tcp_out_options *opts) · 8 unmodified lines |
| 452 | 453 | #endif |
| 453 | 454 | } |
| 454 | 455 | |
| 456 | +#ifdef CONFIG_CGROUP_BPF |
| 457 | +/* req, syn_skb and synack_type are used when writing synack */ |
| 458 | +static void bpf_skops_hdr_opt_len(struct sock *sk, struct sk_buff *skb, |
| 459 | + struct request_sock *req, |
| 460 | + struct sk_buff *syn_skb, |
| 461 | + enum tcp_synack_type synack_type, |
| 462 | + struct tcp_out_options *opts, |
| 463 | + unsigned int *remaining) |
| 464 | +{ |
| 465 | + if (likely(!BPF_SOCK_OPS_TEST_FLAG(tcp_sk(sk), |
| 466 | + BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG)) || |
| 467 | + !*remaining) |
| 468 | + return; |
| 469 | + |
| 470 | + /* The bpf running context preparation and the actual bpf prog |
| 471 | + * calling will be implemented in a later PATCH together with |
| 472 | + * other bpf pieces. |
| 473 | + */ |
| 474 | +} |
| 475 | + |
| 476 | +static void bpf_skops_write_hdr_opt(struct sock *sk, struct sk_buff *skb, |
| 477 | + struct request_sock *req, |
| 478 | + struct sk_buff *syn_skb, |
| 479 | + enum tcp_synack_type synack_type, |
| 480 | + struct tcp_out_options *opts) |
| 481 | +{ |
| 482 | + if (likely(!opts->bpf_opt_len)) |
| 483 | + return; |
| 484 | + |
| 485 | + /* The bpf running context preparation and the actual bpf prog |
| 486 | + * calling will be implemented in a later PATCH together with |
| 487 | + * other bpf pieces. |
| 488 | + */ |
| 489 | +} |
| 490 | +#else |
| 491 | +static void bpf_skops_hdr_opt_len(struct sock *sk, struct sk_buff *skb, |
| 492 | + struct request_sock *req, |
| 493 | + struct sk_buff *syn_skb, |
| 494 | + enum tcp_synack_type synack_type, |
| 495 | + struct tcp_out_options *opts, |
| 496 | + unsigned int *remaining) |
| 497 | +{ |
| 498 | +} |
| 499 | + |
| 500 | +static void bpf_skops_write_hdr_opt(struct sock *sk, struct sk_buff *skb, |
| 501 | + struct request_sock *req, |
| 502 | + struct sk_buff *syn_skb, |
| 503 | + enum tcp_synack_type synack_type, |
| 504 | + struct tcp_out_options *opts) |
| 505 | +{ |
| 506 | +} |
| 507 | +#endif |
| 508 | + |
| 455 | 509 | /* Write previously computed TCP options to the packet. |
| 456 | 510 | * |
| 457 | 511 | * Beware: Something in the Internet is very sensitive to the ordering of |
| @@ -691,6 +745,8 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, · 233 unmodified lines |
| 691 | 745 | } |
| 692 | 746 | } |
| 693 | 747 | |
| 748 | + bpf_skops_hdr_opt_len(sk, skb, NULL, NULL, 0, opts, &remaining); |
| 749 | + |
| 694 | 750 | return MAX_TCP_OPTION_SPACE - remaining; |
| 695 | 751 | } |
| 696 | 752 | |
| @@ -701,7 +757,8 @@ static unsigned int tcp_synack_options(const struct sock *sk, · 4 unmodified lines |
| 701 | 757 | struct tcp_out_options *opts, |
| 702 | 758 | const struct tcp_md5sig_key *md5, |
| 703 | 759 | struct tcp_fastopen_cookie *foc, |
| 704 | | − enum tcp_synack_type synack_type) |
| 760 | + enum tcp_synack_type synack_type, |
| 761 | + struct sk_buff *syn_skb) |
| 705 | 762 | { |
| 706 | 763 | struct inet_request_sock *ireq = inet_rsk(req); |
| 707 | 764 | unsigned int remaining = MAX_TCP_OPTION_SPACE; |
| @@ -758,6 +815,9 @@ static unsigned int tcp_synack_options(const struct sock *sk, · 50 unmodified lines |
| 758 | 815 | |
| 759 | 816 | smc_set_option_cond(tcp_sk(sk), ireq, opts, &remaining); |
| 760 | 817 | |
| 818 | + bpf_skops_hdr_opt_len((struct sock *)sk, skb, req, syn_skb, |
| 819 | + synack_type, opts, &remaining); |
| 820 | + |
| 761 | 821 | return MAX_TCP_OPTION_SPACE - remaining; |
| 762 | 822 | } |
| 763 | 823 | |
| @@ -826,6 +886,15 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb · 62 unmodified lines |
| 826 | 886 | opts->num_sack_blocks * TCPOLEN_SACK_PERBLOCK; |
| 827 | 887 | } |
| 828 | 888 | |
| 889 | + if (unlikely(BPF_SOCK_OPS_TEST_FLAG(tp, |
| 890 | + BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG))) { |
| 891 | + unsigned int remaining = MAX_TCP_OPTION_SPACE - size; |
| 892 | + |
| 893 | + bpf_skops_hdr_opt_len(sk, skb, NULL, NULL, 0, opts, &remaining); |
| 894 | + |
| 895 | + size = MAX_TCP_OPTION_SPACE - remaining; |
| 896 | + } |
| 897 | + |
| 829 | 898 | return size; |
| 830 | 899 | } |
| 831 | 900 | |
| @@ -1213,6 +1282,9 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, · 381 unmodified lines |
| 1213 | 1282 | } |
| 1214 | 1283 | #endif |
| 1215 | 1284 | |
| 1285 | + /* BPF prog is the last one writing header option */ |
| 1286 | + bpf_skops_write_hdr_opt(sk, skb, NULL, NULL, 0, &opts); |
| 1287 | + |
| 1216 | 1288 | INDIRECT_CALL_INET(icsk->icsk_af_ops->send_check, |
| 1217 | 1289 | tcp_v6_send_check, tcp_v4_send_check, |
| 1218 | 1290 | sk, skb); |
| @@ -3336,20 +3408,20 @@ int tcp_send_synack(struct sock *sk) · 2117 unmodified lines |
| 3336 | 3408 | } |
| 3337 | 3409 | |
| 3338 | 3410 | /** |
| 3339 | | − * tcp_make_synack - Prepare a SYN-ACK. |
| 3340 | | − * sk: listener socket |
| 3341 | | − * dst: dst entry attached to the SYNACK |
| 3342 | | − * req: request_sock pointer |
| 3343 | | − * foc: cookie for tcp fast open |
| 3344 | | − * synack_type: Type of synback to prepare |
| 3345 | | − * |
| 3346 | | − * Allocate one skb and build a SYNACK packet. |
| 3347 | | − * @dst is consumed : Caller should not use it again. |
| 3411 | + * tcp_make_synack - Allocate one skb and build a SYNACK packet. |
| 3412 | + * @sk: listener socket |
| 3413 | + * @dst: dst entry attached to the SYNACK. It is consumed and caller |
| 3414 | + * should not use it again. |
| 3415 | + * @req: request_sock pointer |
| 3416 | + * @foc: cookie for tcp fast open |
| 3417 | + * @synack_type: Type of synack to prepare |
| 3418 | + * @syn_skb: SYN packet just received. It could be NULL for rtx case. |
| 3348 | 3419 | */ |
| 3349 | 3420 | struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, |
| 3350 | 3421 | struct request_sock *req, |
| 3351 | 3422 | struct tcp_fastopen_cookie *foc, |
| 3352 | | − enum tcp_synack_type synack_type) |
| 3423 | + enum tcp_synack_type synack_type, |
| 3424 | + struct sk_buff *syn_skb) |
| 3353 | 3425 | { |
| 3354 | 3426 | struct inet_request_sock *ireq = inet_rsk(req); |
| 3355 | 3427 | const struct tcp_sock *tp = tcp_sk(sk); |
| @@ -3408,8 +3480,11 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, · 52 unmodified lines |
| 3408 | 3480 | md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req)); |
| 3409 | 3481 | #endif |
| 3410 | 3482 | skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4); |
| 3483 | + /* bpf program will be interested in the tcp_flags */ |
| 3484 | + TCP_SKB_CB(skb)->tcp_flags = TCPHDR_SYN | TCPHDR_ACK; |
| 3411 | 3485 | tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5, |
| 3412 | | − foc, synack_type) + sizeof(*th); |
| 3486 | + foc, synack_type, |
| 3487 | + syn_skb) + sizeof(*th); |
| 3413 | 3488 | |
| 3414 | 3489 | skb_push(skb, tcp_header_size); |
| 3415 | 3490 | skb_reset_transport_header(skb); |
| @@ -3441,6 +3516,9 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst, · 25 unmodified lines |
| 3441 | 3516 | rcu_read_unlock(); |
| 3442 | 3517 | #endif |
| 3443 | 3518 | |
| 3519 | + bpf_skops_write_hdr_opt((struct sock *)sk, skb, req, syn_skb, |
| 3520 | + synack_type, &opts); |
| 3521 | + |
| 3444 | 3522 | skb->skb_mstamp_ns = now; |
| 3445 | 3523 | tcp_add_tx_delay(skb, tp); |
| 3446 | 3524 | |
| @@ -3936,7 +4014,8 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req) · 489 unmodified lines |
| 3936 | 4014 | int res; |
| 3937 | 4015 | |
| 3938 | 4016 | tcp_rsk(req)->txhash = net_tx_rndhash(); |
| 3939 | | − res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL); |
| 4017 | + res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL, |
| 4018 | + NULL); |
| 3940 | 4019 | if (!res) { |
| 3941 | 4020 | __TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); |
| 3942 | 4021 | __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); |