On Fri, 2023-12-08 at 14:04 -0800, Andrii Nakryiko wrote: [...] > > However, if this is the only API we provide, then this makes user's life > > hard, as they will have to keep track of ids, and programs used, and > > mapping from "global" id to local ids for each program (when multiple > > programs use the same static key, which is desirable). If we keep the > > higher-level "map API", then this simplifies user's life: on a program load > > a user can send a list of (local_id -> map) mappings, and then toggle all > > the branches controlled by "a [global] static key" by either > > > > bpf(MAP_UPDATE_ELEM, map, value) > > > > or > > > > kfunc bpf_static_key_set(map, value) > > > > whatever is more useful. (I think that keeping the bpf(2) userspace API is > > worth doing it, as otherwise this, again, makes life harder: users would > > have to recompile/update iterator programs if new programs using a static > > key are added, etc.) > > > > Libbpf can simplify life even more by automatically allocating local ids > > and passing mappings to kernel for a program from the > > `bpf_static_branch_{unlikely,likely}(&map)`, so that users don't ever thing > > about this, if don't want to. Again, no relocations are required here. > > > > So, to summarize: > > > > * A new instruction BPF_JA_CFG[ID,FLAGS,OFFSET] where ID is local to the > > program, FLAGS is 0/1 for normal/inverse branches > > > > +1 for a dedicated instruction fwiw, if relocations are used instead of IDs the new instruction does not have to be a control flow. It might be a mov that sets target register to a value that verifier treats as unknown. At runtime this mov could be patched to assign different values. Granted it would be three instructions: mov rax, 0; cmp rax, 0; je ... instead of one, but I don't believe there would noticeable performance difference. On a plus side: even simpler verification, likely/unlikely for free, no need to track if branch is inverted.