[PATCH net-next 0/4] netlink: add 'bitmap' attribute type and API

From: Alexander Lobakin
Date: Thu Jul 21 2022 - 12:02:01 EST


Add a new type of Netlink attribute -- bitmap.

Lots of different bitfields in the kernel grow through time,
sometimes significantly. They can consume a u8 at fist, then require
16 bits, 32... To support such bitfields without rewriting code each
time, kernel have bitmaps. For now, that is purely in-kernel type
and API, and to communicate with userspace, they need to be
converted to some primitive at first (e.g. __u32 etc.), dealing with
that sometimes bitfields will run out of the size set for the
corresponding Netlink attribute. Those can be netdev features,
linkmodes and so on.
Internally, in-kernel bitmaps are represented as arrays of unsigned
longs. This provides optimal performance and memory usage; however,
bitness dependent types can't be used to communicate between kernel
and userspace -- for example, userapp can be 32-bit on a 64-bit
system. So, to provide reliable communication data type, 64-bit
arrays are now used. Netlink core takes care of converting them
from/to unsigned longs when sending or receiving Netlink messages;
although, on LE and 64-bit systems conversion is a no-op. They also
can have explicit byteorder -- core code also handles this (both
kernel and userspace must know in advance the byteorder of a
particular attribute), as well as cases when the userspace and the
kernel assume different number of bits (-> different number of u64s)
for an attribute.

Basic consumer functions/macros are:
* nla_put_bitmap and nla_get_bitmap families -- to easily put a
bitmap to an skb or get it from a received message (only pointer
to an unsigned long bitmap and the number of bits in it are
needed), with optional explicit byteorder;
* nla_total_size_bitmap() -- to provide estimate size in bytes to
Netlink needed to store a bitmap;
* {,__}NLA_POLICY_BITMAP() -- to declare a Netlink policy for a
bitmap attribute.

Netlink policy for a bitmap can have an optional bitmap mask of bits
supported by the code -- for example, to filter out obsolete bits
removed some time ago. Without it, Netlink will make sure no bits
past the passed number are set. Both variants can be requested from
the userspace and the kernel will put a mask into a new policy
attribute (%NL_POLICY_TYPE_ATTR_BITMAP_MASK).
BTW, Ethtool bitsets provide similar functionality, but it operates
with u32s (u64 is more convenient and optimal on most platforms) and
Netlink bitmaps is a generic interface providing policies and data
verification (Ethtool bitsets are declared simply as %NLA_BINARY),
generic getters/setters etc.

An example of using this API can be found in my IP tunnel tree[0]
(planned for submission later), the actual average number of locs
to start both sending and receiving bitmaps in one subsys is ~10[1].
And it looks like that some of the already existing APIs could be
later converted to Netlink bitmaps or expanded as well.

[0] https://github.com/alobakin/linux/commits/ip_tunnel
[1] https://github.com/alobakin/linux/commit/26d2f2cf13fd

Alexander Lobakin (4):
bitmap: add converting from/to 64-bit arrays of explicit byteorder
bitmap: add a couple more helpers to work with arrays of u64s
lib/test_bitmap: cover explicitly byteordered arr64s
netlink: add 'bitmap' attribute type (%NL_ATTR_TYPE_BITMAP /
%NLA_BITMAP)

include/linux/bitmap.h | 80 ++++++++++++++++--
include/net/netlink.h | 159 ++++++++++++++++++++++++++++++++++-
include/uapi/linux/netlink.h | 5 ++
lib/bitmap.c | 143 +++++++++++++++++++++++++++----
lib/nlattr.c | 43 +++++++++-
lib/test_bitmap.c | 22 +++--
net/netlink/policy.c | 44 ++++++++++
7 files changed, 461 insertions(+), 35 deletions(-)


base-commit: 3a2ba42cbd0b669ce3837ba400905f93dd06c79f
---
Targeted for net-next, but uses base-commit from the bitmap tree
(a merge will be needed) and the API is for kernel-wide/generic
usage rather than networking-specific.
--
2.36.1