On 04/09/2018 01:26 PM, Jesper Dangaard Brouer wrote: > On Fri, 6 Apr 2018 12:36:18 +0200 > Daniel Borkmann <dan...@iogearbox.net> wrote: [...] >> [...] >> The underlying problem is effectively the decoupling of program >> verification that doesn't have/know the context of where it is being >> attached to in this case. > > Yes, exactly, that the underlying problem. (plus the first XDP prog > gets verified and driver attached, and subsequent added bpf tail calls, > cannot be "rejected" (at "driver attachment time") as its too late). > >> Thinking out loud for a sec on couple of other options aside >> from feature bits, what about i) providing the target ifindex to the >> verifier for XDP programs, such that at verification time you have the >> full context similar to nfp offload case today, > > I do like that we could provide the target ifindex earlier. But > userspace still need some way to express that it e.g. need the > XDP_REDIRECT features (as verifier cannot reliability detect the action > return codes used, as discussed before, due to bpf tail calls and maps > used as return values).
(See below on the detection of it.) >> or ii) populating some >> XDP specific auxillary data to the BPF program at verification time such >> that the driver can check at program attach time whether the requested >> features are possible and if not it will reject and respond with netlink >> extack message to the user (as we do in various XDP attach cases already >> through XDP_SETUP_PROG{,_HW}). > > I like proposal ii) better. But how do I specify/input that I need > e.g. the XDP_REDIRECT feature, such that is it avail to "the BPF > program at verification time"? > > My proposal iii), what about at XDP attachment time, create a new > netlink attribute that describe XDP action codes the program > needs/wants. If the info is provided, the ndo_bpf call check and > reject, and respond with netlink extack message. > If I want to query for avail action codes, then I can use the same > netlink attribute format, and kernel will return it "populated" with > the info. > > It is very useful that the program gets rejected at attachment time (to > avoid loading an XDP prog that silently drops packets). BUT I also > want a query option/functionality (reuse netlink attr format). > > Specifically for Suricata the same "bypass" features can be implemented > at different levels (XDP, XDP-generic or clsbpf), and the XDP program > contains multiple features. Thus, depending on what NIC driver > supports, we want to load different XDP and/or clsbpf/TC BPF-programs. > Thus, still support the same user requested feature/functionality, even > if XDP_REDIRECT is not avail, just slightly slower. Makes sense to have such fallbacks. >> This would, for example, avoid the need for feature bits, and do actual >> rejection of the program while retaining flexibility (and avoiding to >> expose bits that over time hopefully will deprecate anyway due to all >> XDP aware drivers implementing them). For both cases i) and ii), it >> would mean we make the verifier a bit smarter with regards to keeping >> track of driver related (XDP) requirements. Program return code checking >> is already present in the verifier's check_return_code() and we could >> extend it for XDP as well, for example. Seems cleaner and more extensible >> than feature bits, imho. > > I thought the verifier's check_return_code() couldn't see/verify if the > XDP return action code is provided as a map lookup result(?). How is > that handled? For the latter, I would just add a BPF_F_STRICT_CONST_VERDICT load flag which e.g. enforces a constant return code in all prog types. It also needs to check for helpers like bpf_xdp_redirect() and track R0 from there that it either contains XDP_REDIRECT or XDP_ABORTED. For the bpf_prog_aux, we need a prog dependent void *private_data area pointer in bpf_prog_aux that verifier populates; e.g. we could migrate already some of the prog type specific fields into that like kprobe_override, cb_access, dst_needed that are non-generic anyway. For XDP, verifier would in your case record all seen return codes into private_data. When the flag BPF_F_STRICT_CONST_VERDICT is not used and we noticed there were cases where the verdict was not a verifiable constant, then we e.g. mark all XDP return codes as seen. Potentially the same is needed for tail calls. We can add a ndo_bpf query to drivers that return their supported XDP return codes and compare them in e.g. dev_change_xdp_fd() out of generic code and reject with extack. For tail calls, the only way that comes to mind right now where you could lift that requirement with having to mark all return codes as seen is that you'd need to pass the ifindex as in offload case at load time, such that you the program becomes tied to the device. Then you also need to record dev pointer in the private_data such that you can add a new callback to bpf_prog_ops for prog dependent compare in bpf_prog_array_compatible() to make sure both would have the same target owner dev where the return code check was previously asserted. If you want to expose that internal ndo_bpf query which specifically returns the set of supported XDP return codes I wouldn't mind, that way it's not some sort of generic feature bit query, but a specific query for the set of return codes the driver supports, thus keeping this very limited and avoiding mixing this with other future feature bits that could turn this into a big mess; I'm not sure right now though what would be the best uapi to query that info from. Cheers, Daniel