From: Kuniyuki Iwashima <kuniyu@google.com>
To: ameryhung@gmail.com
Cc: alexei.starovoitov@gmail.com, andrii@kernel.org,
bpf@vger.kernel.org, cleger@meta.com, daniel@iogearbox.net,
eddyz87@gmail.com, edumazet@google.com,
john.fastabend@gmail.com, kuni1840@gmail.com, kuniyu@google.com,
martin.lau@linux.dev, memxor@gmail.com, ncardwell@google.com,
netdev@vger.kernel.org, sdf@fomichev.me, ukyab@berkeley.edu,
willemb@google.com, yonghong.song@linux.dev
Subject: Re: [PATCH v2 bpf-next 3/8] bpf: tcp: Introduce bpf_tcp_ops.{enqueue,dequeue}_rcvq().
Date: Sun, 27 Sep 2026 00:18:38 +0000 [thread overview]
Message-ID: <20260927001921.604064-1-kuniyu@google.com> (raw)
In-Reply-To: <CAMB2axN93iJnrZAk6hWraSnz32FtRDdpz_UbzsVB4YU7gRK_3Q@mail.gmail.com>
From: Amery Hung <ameryhung@gmail.com>
Date: Fri, 25 Sep 2026 10:33:50 -0700
> On Thu, Sep 24, 2026 at 6:41 PM Alexei Starovoitov
> <alexei.starovoitov@gmail.com> wrote:
> >
> > On Thu, Sep 24, 2026 at 05:39 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
> > >> can we drop the flag ?
> > >> hdr_opt_len() is called for every tx skb without per-socket opt-in.
> > >
> > > Oh, I assumed bpf_tcp_ops keeps the same behaviour.
> >
> > bpf_tcp_ops were moved out of BPF_SOCK_OPS_TEST_FLAG() guards on
> > purpose. None of the existing members has per-socket opt-in.
> > hdr_opt_len() runs for every tx skb, rtt() for every rtt sample.
> > See the log of commit 3bb54768fe3e
> > ("bpf: tcp: Support parse/len/write header option hooks in bpf_tcp_ops"):
> > "A per-member/per-cgroup gate could be added later if the extra
> > fast-path work proves measurable."
> >
> > > We have a bpf prog to turn the hook on (from cgroup_skb/ingress),
> > > only when ingress rate exceeds the allocated capacity, to signal that
> > > via a custom TCP option and turn the hook off from the hook itself.
> > > (and I planned to post another patch for that)
> >
> > That should work today without another patch and without the flag.
> > cgroup_skb/ingress prog does
> > bpf_sk_storage_get(&map, sk, 0, BPF_SK_STORAGE_GET_F_CREATE);
> > when the rate is exceeded. hdr_opt_len() and write_hdr_opt() do
> > bpf_sk_storage_get(&map, sk, 0, 0);
> > and return when it's NULL. write_hdr_opt() calls
> > bpf_sk_storage_delete() after the option went out.
> > cg_skb_func_proto() has both helpers and get_func_proto() in
> > bpf_tcp_ops.c allows them in every member.
> > egress_read_sock_fields() in test_sock_fields.c does the cgroup_skb
> > part.
> >
> > > Anyway, is it because calling bpf prog is not very expensive
> > > or per-prog switch is preferable to per-socket flag ?
> >
> > The switch is still per socket. It's sk_storage instead of a bit in
> > tcp_sock, so every prog has its own.
> >
> > While such new flag is per socket, but it's one for all progs.
> >
> > And you want to take the last bit of u8 bpf_sock_ops_cb_flags...
> >
> > As far as the cost. A socket that didn't opt in pays for an indirect
> > call into the prog and for bpf_sk_storage_get() that finds nothing,
> > but only in cgroups where bpf_tcp_ops with enqueue_rcvq is attached.
> > The members that are not set are NULL and bpf_tcp_ops_call() skips
> > them. That's what hdr_opt_len() costs on tx.
> >
> > I don't remember what Amery measured, but worth benchmarking
> > for your case.
>
> I did not benchmark the initial bpf_tcp_ops patch set, so per-socket
> gating was deferred. Before deciding whether to add such a gate for
> AutoLOWAT, could we compare:
>
> 1. No bpf_tcp_ops attached.
> 2. No-op enqueue_rcvq() and dequeue_rcvq() callbacks attached.
> 3. The same callbacks performing an sk-local-storage lookup (or maybe
> rhashtable).
I used tcp_rr (128 threads, 20000 flows) and didn't see a big
perf diff between 1. and 2., but 3. showed some costs even when
only looking up sk_storage and returning immediately:
| w/o bpf | w/ bpf | diff | diff (abs)
-------------------+---------------+---------------+---------+-------------
num_transactions | 1,209,349,692 | 1,185,180,017 | -2.00% | -24.17M tx
throughput (tx/s) | 20,318,689.83 | 19,953,668.49 | -1.80% | -365.0K tx/s
remote_throughput | 19,472,629 | 19,135,463 | -1.73% | -337.2K tx/s
latency_min | 50.83 us | 46.08 us | -9.34% | -4.75 us
latency_p25 | 911.35 us | 911.35 us | 0.00% | 0.00 us
latency_p50 | 972.79 us | 983.03 us | +1.05% | +10.24 us
latency_mean | 983.64 us | 1,001.71 us | +1.84% | +18.08 us
latency_p90 | 1,136.63 us | 1,187.83 us | +4.50% | +51.20 us
latency_p95 | 1,208.31 us | 1,259.51 us | +4.24% | +51.20 us
latency_p99 | 1,392.63 us | 1,454.07 us | +4.41% | +61.44 us
latency_stddev | 141.82 us | 158.53 us | +11.78% | +16.71 us
cpu time (u+s, 60s)| 8,165.91s | 8,312.57s | +1.80% | +146.66s
Given the other hooks in the fast path (hdr_opt_len(),
parse_hdr(), etc) should add costs at the same level,
I think we should guard them with flags.
But u8 is too small, so I think we could add a new field
(maybe u32?) and a new kfunc for bpf_tcp_ops only. Also,
I'd add CONFIG_BPF_SOCK_OPS_LEGACY to save some calls.
What do you think ?
>
> >
> > >> The prog in patch 8 already returns when the socket has no
> > >> sk_storage.
> > >
> > > Yes, but this is only for bpf verifier.
> >
> > tcp_init_autolowat_cb() can be the only place that passes
> > BPF_SK_STORAGE_GET_F_CREATE.
> > So for a socket that didn't do setsockopt(BPF_TCP_AUTOLOWAT)
> > other cbs will return NULL on lookup.
> >
> > tcp_disable_autolowat() will do:
> > bpf_sk_storage_delete(&tcp_autolowat_map, sk);
> > bpf_tcp_ops_set_rcvlowat(sk, 1);
> >
> > > Just an idea, would it make sense to add a kfunc to move bpf_tcp_ops
> > > callback to a shadow pointer by allocating sizeof(bpf_tcp_ops) * 2 ?
>
> A bpf_tcp_ops instance is shared by all sockets, so this would not
> provide per-socket gating. Making it per-socket would require copying
> the callback table for every tcp_sock, which seems more complex than
> adding a gate directly to tcp_sock.
>
> Am I understanding your idea correctly?
Yes, but this is overkill indeed. I think most deployments
use just a single SOCK_OPS/bpf_tcp_ops, and per-scoket flag
would be enough.
next prev parent reply other threads:[~2026-09-27 0:19 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 21:35 [PATCH v2 bpf-next 0/8] bpf: Add bpf_tcp_ops hooks for TCP AutoLOWAT Kuniyuki Iwashima
2026-09-23 21:35 ` [PATCH v2 bpf-next 1/8] bpf: tcp: Convert deny-list for bpf_{get,set}sockopt() to allow-list Kuniyuki Iwashima
2026-09-23 22:04 ` Emil Tsalapatis
2026-09-23 22:31 ` bot+bpf-ci
2026-09-24 15:53 ` Stanislav Fomichev
2026-09-23 21:35 ` [PATCH v2 bpf-next 2/8] selftest: bpf: Use BPF_SOCK_OPS_ALL_CB_FLAGS + 1 for bad_cb_test_rv Kuniyuki Iwashima
2026-09-23 22:11 ` Emil Tsalapatis
2026-09-23 21:35 ` [PATCH v2 bpf-next 3/8] bpf: tcp: Introduce bpf_tcp_ops.{enqueue,dequeue}_rcvq() Kuniyuki Iwashima
2026-09-23 21:50 ` sashiko-bot
2026-09-23 22:42 ` Emil Tsalapatis
2026-09-25 0:04 ` Alexei Starovoitov
2026-09-25 0:39 ` Kuniyuki Iwashima
2026-09-25 1:41 ` Alexei Starovoitov
2026-09-25 17:33 ` Amery Hung
2026-09-27 0:18 ` Kuniyuki Iwashima [this message]
2026-09-30 19:56 ` Amery Hung
2026-09-30 21:03 ` Kuniyuki Iwashima
2026-09-23 21:35 ` [PATCH v2 bpf-next 4/8] bpf: tcp: Support bpf_sock_ops_cb_flags_set() for bpf_tcp_ops Kuniyuki Iwashima
2026-09-23 22:31 ` bot+bpf-ci
2026-09-23 21:35 ` [PATCH v2 bpf-next 5/8] tcp: Split out __tcp_set_rcvlowat() Kuniyuki Iwashima
2026-09-24 3:39 ` Emil Tsalapatis
2026-09-23 21:35 ` [PATCH v2 bpf-next 6/8] bpf: mptcp: Don't support BPF_SOCK_OPS_RCVQ_CB_FLAG Kuniyuki Iwashima
2026-09-24 3:48 ` Emil Tsalapatis
2026-09-24 4:10 ` Kuniyuki Iwashima
2026-09-23 21:35 ` [PATCH v2 bpf-next 7/8] bpf: tcp: Add kfunc to adjust sk->sk_rcvlowat Kuniyuki Iwashima
2026-09-23 22:02 ` sashiko-bot
2026-09-23 22:21 ` Kuniyuki Iwashima
2026-09-24 0:30 ` Emil Tsalapatis
2026-09-23 21:35 ` [PATCH v2 bpf-next 8/8] selftest: bpf: Add test for bpf_tcp_ops.{enqueue,dequeue}_rcvq() Kuniyuki Iwashima
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260927001921.604064-1-kuniyu@google.com \
--to=kuniyu@google.com \
--cc=alexei.starovoitov@gmail.com \
--cc=ameryhung@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=cleger@meta.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=john.fastabend@gmail.com \
--cc=kuni1840@gmail.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=sdf@fomichev.me \
--cc=ukyab@berkeley.edu \
--cc=willemb@google.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox