nvlist/netlink/CBOR/etc. (Was: Support for nv(9) in if_clone)
- In reply to: Kristof Provost : "Re: Support for nv(9) in if_clone"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 19 Oct 2025 20:51:48 UTC
On Sat, 18 Oct 2025 10:37:00 +0200 Kristof Provost <kp@FreeBSD.org> wrote: > On 16 Oct 2025, at 22:56, Vadim Goncharov wrote: > > On Wed, 15 Oct 2025 11:15:03 +0330 > > Seyed Pouria Mousavizadeh Tehrani <info@spmzt.net> wrote: > > > >> Currently our ifreq interface supports nv(9) lists via ifreq_nv_req. > >> This allows network interface drivers to implement their > >> configuration > >> using nvlists (for example: if_ovpn, if_pf*). > >> > >> There is a problem: an interface that is implemented entirely via > >> nv(9) > >> cannot be configured during the cloning phase (via if_clone_create). > >> if_clone_create converts the ifreq struct to ifdrv and only copies > >> ifr_data to params, so the ifru_nv field is lost during cloning. > >> > >> I am interested in implementing a solution to this issue and am > >> considering two possible approaches: > >> > >> 1. Extend the ifdrv struct to include the ifreq_nv_req struct, and > >> verify/make sure that other implemented modules are not affected. > >> 2. Introduce a new ioctl, SIOCIFCREATENV, to handle the nv part > >> separately, which would be more complicated but potentially less > >> disruptive to existing modules. > >> > >> Which one do you think would be more suitable, or do you have any > >> alternative suggestions? > > > > I'd vote for the latter, because it also will make task easier > > when/if/ever > > the nvlist plague will be replaced by something more sane. > > > Absent detail this isn’t particularly useful feedback. > > Having used nvlists in pf I’ve found them to be fairly useful in > defining extensible interfaces. > There are a few downsides though. The big one being horrendous > performance and memory use for large requests. This likely isn’t a > problem for this use case. It really only bit pf for state export, which > is potentially very large. > > The other downside, and the reason I’d be inclined to look at just > transitioning entirely to netlink is that dealing with them is annoying, > because you have to cope with three sizes: the size of the nvlist passed > from userspace, the size of the buffer userspace allocated and the size > of the kernel’s reply (if applicable). It also leaves userspace to > deal with ‘Is this buffer large enough?’, which isn’t really > something you have to think about with netlink. > > As an aside, because you mention if_ovpn: I wound up using nvlists > because netlink wasn’t available yet for FreeBSD. The Linux equivalent > uses netlink (of course), and it would have been very nice to be able to > have the same interface on Linux and FreeBSD. That's not a detail question but rather, a values/goal one: nvlists must be considered legacy. It is understandable when they appeared in ZFS on century boundary, as there market hardly had anything usable in this area then. It is understandable that they were still used before 2014, alternatives were young then. But for nowadays, it's just an old NIH syndrome reinvented bicycle wheel. First of all, it is not a standard of any kind. Thus, it is not known outside FreeBSD and systems having ZFS. Situation is somewhat similar to netlink: many tools (e.g. on GitHub) target Linux, and supporting FreeBSD requires effort, while for netlink, they can just use netlink. The same with serialization formats - any (e.g. monitoring) tool e.g. in Python could consume JSON or CBOR with a single line of code. With nvlists, they can't - and this is not easy even if they wanted to - because unpopular format of course has no bindings for popular languages. Yes, is we want to promote FreeBSD, dynamic scripting languages must be considered as primary target. Then, it is not open = not being extensible. This means you can't just add new data types or constructs to it even if you want - in contrast to CBOR or even XML ir YAML where new types could be easily defined. Last but not least, a horrible API. Very large number of functions, so unsurprisingly vulnerabilities history, with not always consistent/intuitive naming. Consider e.g. XML: you have at least two modes, an entire accessible parsed tree (DOM) or a streaming event-driven interface (callbacks on each new element). You can find both kind of APIs for JSON, or at least something simple and understandable in memory (e.g. cJSON); same true for the binary CBOR [RFC 8949], and our base system even have libcbor for years. In contrast, nvlist API looks like if it was something customary above XML or JSON. The only possible upside which I see with nvlists is ability to pass file descriptor, which made into Capsicum, so nvlists, sadly, will not disappear any soon. But for all other (new) uses, it must be considered bronze age legacy and discarded in favour of something more modern, simple, extensible. Regarding netlink, this is not strict comparison - netlink is more about sending data than format of that data, like Layer 4 OSI (TCP) vs Layer 6 (JSON), so nothing prevents you from sending over netlink e.g. also nvlists or something better, like older netgraph(4)'s ng_parse (it has advantage of automatical C structs conversion) or binary CBOR or even textual JSON... the own netlink's default offered format is same stone-aged as nvlist, it just have a bunch of ready-made macros, though you will have to extend them for your data, but netlink does not insist, so you can use anything you want. -- WBR, @nuclight