Skip to content

Commit 10b518d

Browse files
mkubecekdavem330
authored andcommitted
ethtool: netlink bitset handling
The ethtool netlink code uses common framework for passing arbitrary length bit sets to allow future extensions. A bitset can be a list (only one bitmap) or can consist of value and mask pair (used e.g. when client want to modify only some bits). A bitset can use one of two formats: verbose (bit by bit) or compact. Verbose format consists of bitset size (number of bits), list flag and an array of bit nests, telling which bits are part of the list or which bits are in the mask and which of them are to be set. In requests, bits can be identified by index (position) or by name. In replies, kernel provides both index and name. Verbose format is suitable for "one shot" applications like standard ethtool command as it avoids the need to either keep bit names (e.g. link modes) in sync with kernel or having to add an extra roundtrip for string set request (e.g. for private flags). Compact format uses one (list) or two (value/mask) arrays of 32-bit words to store the bitmap(s). It is more suitable for long running applications (ethtool in monitor mode or network management daemons) which can retrieve the names once and then pass only compact bitmaps to save space. Userspace requests can use either format; ETHTOOL_FLAG_COMPACT_BITSETS flag in request header tells kernel which format to use in reply. Notifications always use compact format. As some code uses arrays of unsigned long for internal representation and some arrays of u32 (or even a single u32), two sets of parse/compose helpers are introduced. To avoid code duplication, helpers for unsigned long arrays are implemented as wrappers around helpers for u32 arrays. There are two reasons for this choice: (1) u32 arrays are more frequent in ethtool code and (2) unsigned long array can be always interpreted as an u32 array on little endian 64-bit and all 32-bit architectures while we would need special handling for odd number of u32 words in the opposite direction. Signed-off-by: Michal Kubecek <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 041b1c5 commit 10b518d

File tree

5 files changed

+883
-1
lines changed

5 files changed

+883
-1
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,90 @@ of the flag should be interpreted the way the client expects. A client must
7676
not set flags it does not understand.
7777

7878

79+
Bit sets
80+
========
81+
82+
For short bitmaps of (reasonably) fixed length, standard ``NLA_BITFIELD32``
83+
type is used. For arbitrary length bitmaps, ethtool netlink uses a nested
84+
attribute with contents of one of two forms: compact (two binary bitmaps
85+
representing bit values and mask of affected bits) and bit-by-bit (list of
86+
bits identified by either index or name).
87+
88+
Verbose (bit-by-bit) bitsets allow sending symbolic names for bits together
89+
with their values which saves a round trip (when the bitset is passed in a
90+
request) or at least a second request (when the bitset is in a reply). This is
91+
useful for one shot applications like traditional ethtool command. On the
92+
other hand, long running applications like ethtool monitor (displaying
93+
notifications) or network management daemons may prefer fetching the names
94+
only once and using compact form to save message size. Notifications from
95+
ethtool netlink interface always use compact form for bitsets.
96+
97+
A bitset can represent either a value/mask pair (``ETHTOOL_A_BITSET_NOMASK``
98+
not set) or a single bitmap (``ETHTOOL_A_BITSET_NOMASK`` set). In requests
99+
modifying a bitmap, the former changes the bit set in mask to values set in
100+
value and preserves the rest; the latter sets the bits set in the bitmap and
101+
clears the rest.
102+
103+
Compact form: nested (bitset) atrribute contents:
104+
105+
============================ ====== ============================
106+
``ETHTOOL_A_BITSET_NOMASK`` flag no mask, only a list
107+
``ETHTOOL_A_BITSET_SIZE`` u32 number of significant bits
108+
``ETHTOOL_A_BITSET_VALUE`` binary bitmap of bit values
109+
``ETHTOOL_A_BITSET_MASK`` binary bitmap of valid bits
110+
============================ ====== ============================
111+
112+
Value and mask must have length at least ``ETHTOOL_A_BITSET_SIZE`` bits
113+
rounded up to a multiple of 32 bits. They consist of 32-bit words in host byte
114+
order, words ordered from least significant to most significant (i.e. the same
115+
way as bitmaps are passed with ioctl interface).
116+
117+
For compact form, ``ETHTOOL_A_BITSET_SIZE`` and ``ETHTOOL_A_BITSET_VALUE`` are
118+
mandatory. ``ETHTOOL_A_BITSET_MASK`` attribute is mandatory if
119+
``ETHTOOL_A_BITSET_NOMASK`` is not set (bitset represents a value/mask pair);
120+
if ``ETHTOOL_A_BITSET_NOMASK`` is not set, ``ETHTOOL_A_BITSET_MASK`` is not
121+
allowed (bitset represents a single bitmap.
122+
123+
Kernel bit set length may differ from userspace length if older application is
124+
used on newer kernel or vice versa. If userspace bitmap is longer, an error is
125+
issued only if the request actually tries to set values of some bits not
126+
recognized by kernel.
127+
128+
Bit-by-bit form: nested (bitset) attribute contents:
129+
130+
+------------------------------------+--------+-----------------------------+
131+
| ``ETHTOOL_A_BITSET_NOMASK`` | flag | no mask, only a list |
132+
+------------------------------------+--------+-----------------------------+
133+
| ``ETHTOOL_A_BITSET_SIZE`` | u32 | number of significant bits |
134+
+------------------------------------+--------+-----------------------------+
135+
| ``ETHTOOL_A_BITSET_BITS`` | nested | array of bits |
136+
+-+----------------------------------+--------+-----------------------------+
137+
| | ``ETHTOOL_A_BITSET_BITS_BIT+`` | nested | one bit |
138+
+-+-+--------------------------------+--------+-----------------------------+
139+
| | | ``ETHTOOL_A_BITSET_BIT_INDEX`` | u32 | bit index (0 for LSB) |
140+
+-+-+--------------------------------+--------+-----------------------------+
141+
| | | ``ETHTOOL_A_BITSET_BIT_NAME`` | string | bit name |
142+
+-+-+--------------------------------+--------+-----------------------------+
143+
| | | ``ETHTOOL_A_BITSET_BIT_VALUE`` | flag | present if bit is set |
144+
+-+-+--------------------------------+--------+-----------------------------+
145+
146+
Bit size is optional for bit-by-bit form. ``ETHTOOL_A_BITSET_BITS`` nest can
147+
only contain ``ETHTOOL_A_BITSET_BITS_BIT`` attributes but there can be an
148+
arbitrary number of them. A bit may be identified by its index or by its
149+
name. When used in requests, listed bits are set to 0 or 1 according to
150+
``ETHTOOL_A_BITSET_BIT_VALUE``, the rest is preserved. A request fails if
151+
index exceeds kernel bit length or if name is not recognized.
152+
153+
When ``ETHTOOL_A_BITSET_NOMASK`` flag is present, bitset is interpreted as
154+
a simple bitmap. ``ETHTOOL_A_BITSET_BIT_VALUE`` attributes are not used in
155+
such case. Such bitset represents a bitmap with listed bits set and the rest
156+
zero.
157+
158+
In requests, application can use either form. Form used by kernel in reply is
159+
determined by ``ETHTOOL_FLAG_COMPACT_BITSETS`` flag in flags field of request
160+
header. Semantics of value and mask depends on the attribute.
161+
162+
79163
List of message types
80164
=====================
81165

include/uapi/linux/ethtool_netlink.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,41 @@ enum {
5050
ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1
5151
};
5252

53+
/* bit sets */
54+
55+
enum {
56+
ETHTOOL_A_BITSET_BIT_UNSPEC,
57+
ETHTOOL_A_BITSET_BIT_INDEX, /* u32 */
58+
ETHTOOL_A_BITSET_BIT_NAME, /* string */
59+
ETHTOOL_A_BITSET_BIT_VALUE, /* flag */
60+
61+
/* add new constants above here */
62+
__ETHTOOL_A_BITSET_BIT_CNT,
63+
ETHTOOL_A_BITSET_BIT_MAX = __ETHTOOL_A_BITSET_BIT_CNT - 1
64+
};
65+
66+
enum {
67+
ETHTOOL_A_BITSET_BITS_UNSPEC,
68+
ETHTOOL_A_BITSET_BITS_BIT, /* nest - _A_BITSET_BIT_* */
69+
70+
/* add new constants above here */
71+
__ETHTOOL_A_BITSET_BITS_CNT,
72+
ETHTOOL_A_BITSET_BITS_MAX = __ETHTOOL_A_BITSET_BITS_CNT - 1
73+
};
74+
75+
enum {
76+
ETHTOOL_A_BITSET_UNSPEC,
77+
ETHTOOL_A_BITSET_NOMASK, /* flag */
78+
ETHTOOL_A_BITSET_SIZE, /* u32 */
79+
ETHTOOL_A_BITSET_BITS, /* nest - _A_BITSET_BITS_* */
80+
ETHTOOL_A_BITSET_VALUE, /* binary */
81+
ETHTOOL_A_BITSET_MASK, /* binary */
82+
83+
/* add new constants above here */
84+
__ETHTOOL_A_BITSET_CNT,
85+
ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1
86+
};
87+
5388
/* generic netlink info */
5489
#define ETHTOOL_GENL_NAME "ethtool"
5590
#define ETHTOOL_GENL_VERSION 1

net/ethtool/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ obj-y += ioctl.o common.o
44

55
obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o
66

7-
ethtool_nl-y := netlink.o
7+
ethtool_nl-y := netlink.o bitset.o

0 commit comments

Comments
 (0)