summaryrefslogtreecommitdiff
path: root/tools/net
diff options
context:
space:
mode:
Diffstat (limited to 'tools/net')
-rwxr-xr-xtools/net/sunrpc/extract.sh11
-rw-r--r--tools/net/sunrpc/xdrgen/.gitignore2
-rw-r--r--tools/net/sunrpc/xdrgen/README261
-rw-r--r--tools/net/sunrpc/xdrgen/__init__.py2
-rw-r--r--tools/net/sunrpc/xdrgen/generators/__init__.py118
-rw-r--r--tools/net/sunrpc/xdrgen/generators/constant.py20
-rw-r--r--tools/net/sunrpc/xdrgen/generators/enum.py64
-rw-r--r--tools/net/sunrpc/xdrgen/generators/header_bottom.py33
-rw-r--r--tools/net/sunrpc/xdrgen/generators/header_top.py45
-rw-r--r--tools/net/sunrpc/xdrgen/generators/pointer.py288
-rw-r--r--tools/net/sunrpc/xdrgen/generators/program.py168
-rw-r--r--tools/net/sunrpc/xdrgen/generators/source_top.py32
-rw-r--r--tools/net/sunrpc/xdrgen/generators/struct.py288
-rw-r--r--tools/net/sunrpc/xdrgen/generators/typedef.py271
-rw-r--r--tools/net/sunrpc/xdrgen/generators/union.py291
-rw-r--r--tools/net/sunrpc/xdrgen/grammars/xdr.lark121
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/__init__.py2
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/declarations.py76
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/definitions.py96
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/lint.py33
-rw-r--r--tools/net/sunrpc/xdrgen/subcmds/source.py117
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/constants/definition.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j219
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/enumerator.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/definition/open.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/header_bottom/declaration/header.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/header_bottom/definition/header.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/header_top/declaration/header.j214
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/header_top/definition/header.j210
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/declaration/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/basic.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/close.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_array.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j222
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/optional_data.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_array.j213
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/basic.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/close.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_array.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_opaque.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/open.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/optional_data.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_array.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_opaque.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j210
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/close.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_array.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j220
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/optional_data.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_array.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_opaque.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/declaration/argument.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/declaration/result.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/decoder/argument.j221
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j218
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/definition/close.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/definition/open.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/definition/procedure.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/encoder/argument.j216
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/program/encoder/result.j221
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/source_top/client.j213
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/source_top/server.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/declaration/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/basic.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/close.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_array.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/optional_data.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_array.j213
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/basic.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/close.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_array.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_opaque.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/open.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/optional_data.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_array.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_opaque.j25
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j210
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/close.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_array.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/optional_data.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_array.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_opaque.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/basic.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_array.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_opaque.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_array.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_opaque.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/basic.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_array.j225
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_opaque.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_array.j226
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_opaque.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/basic.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_array.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_array.j29
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/basic.j221
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_array.j225
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_opaque.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_array.j230
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_opaque.j217
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/declaration/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/basic.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/break.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/default_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/open.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/optional_data.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/switch_spec.j27
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_array.j215
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_opaque.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/decoder/void.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/definition/case_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/definition/close.j28
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/definition/default_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/definition/open.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/definition/switch_spec.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/basic.j210
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/break.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/close.j24
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/default_spec.j22
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/open.j212
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/string.j26
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/switch_spec.j27
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/encoder/void.j23
-rw-r--r--tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j23
-rw-r--r--tools/net/sunrpc/xdrgen/tests/test.x36
-rw-r--r--tools/net/sunrpc/xdrgen/xdr_ast.py753
-rw-r--r--tools/net/sunrpc/xdrgen/xdr_parse.py36
-rwxr-xr-xtools/net/sunrpc/xdrgen/xdrgen139
-rw-r--r--tools/net/ynl/Makefile67
-rw-r--r--tools/net/ynl/Makefile.deps32
-rwxr-xr-xtools/net/ynl/cli.py60
-rw-r--r--tools/net/ynl/generated/.gitignore3
-rw-r--r--tools/net/ynl/generated/Makefile59
-rw-r--r--tools/net/ynl/generated/devlink-user.c2982
-rw-r--r--tools/net/ynl/generated/devlink-user.h1992
-rw-r--r--tools/net/ynl/generated/ethtool-user.c6353
-rw-r--r--tools/net/ynl/generated/ethtool-user.h5535
-rw-r--r--tools/net/ynl/generated/fou-user.c328
-rw-r--r--tools/net/ynl/generated/fou-user.h343
-rw-r--r--tools/net/ynl/generated/handshake-user.c331
-rw-r--r--tools/net/ynl/generated/handshake-user.h145
-rw-r--r--tools/net/ynl/generated/netdev-user.c206
-rw-r--r--tools/net/ynl/generated/netdev-user.h87
-rw-r--r--tools/net/ynl/lib/.gitignore2
-rw-r--r--tools/net/ynl/lib/Makefile10
-rw-r--r--tools/net/ynl/lib/__init__.py8
-rw-r--r--tools/net/ynl/lib/ynl-priv.h478
-rw-r--r--tools/net/ynl/lib/ynl.c585
-rw-r--r--tools/net/ynl/lib/ynl.h168
-rw-r--r--tools/net/ynl/lib/ynl.py729
-rw-r--r--tools/net/ynl/pyproject.toml24
-rw-r--r--tools/net/ynl/pyynl/.gitignore2
-rw-r--r--tools/net/ynl/pyynl/__init__.py0
-rwxr-xr-xtools/net/ynl/pyynl/cli.py253
-rwxr-xr-xtools/net/ynl/pyynl/ethtool.py (renamed from tools/net/ynl/ethtool.py)53
-rw-r--r--tools/net/ynl/pyynl/lib/__init__.py11
-rw-r--r--tools/net/ynl/pyynl/lib/doc_generator.py402
-rw-r--r--tools/net/ynl/pyynl/lib/nlspec.py (renamed from tools/net/ynl/lib/nlspec.py)76
-rw-r--r--tools/net/ynl/pyynl/lib/ynl.py1168
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_c.py (renamed from tools/net/ynl/ynl-gen-c.py)1883
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_rst.py83
-rw-r--r--tools/net/ynl/samples/.gitignore7
-rw-r--r--tools/net/ynl/samples/Makefile16
-rw-r--r--tools/net/ynl/samples/devlink.c7
-rw-r--r--tools/net/ynl/samples/netdev.c24
-rw-r--r--tools/net/ynl/samples/ovs.c60
-rw-r--r--tools/net/ynl/samples/rt-addr.c80
-rw-r--r--tools/net/ynl/samples/rt-link.c184
-rw-r--r--tools/net/ynl/samples/rt-route.c80
-rw-r--r--tools/net/ynl/samples/tc-filter-add.c335
-rw-r--r--tools/net/ynl/samples/tc.c80
-rw-r--r--tools/net/ynl/tests/Makefile32
-rw-r--r--tools/net/ynl/tests/config6
-rwxr-xr-xtools/net/ynl/tests/test_ynl_cli.sh327
-rwxr-xr-xtools/net/ynl/tests/test_ynl_ethtool.sh222
-rwxr-xr-xtools/net/ynl/ynl-regen.sh6
-rw-r--r--tools/net/ynl/ynltool/.gitignore2
-rw-r--r--tools/net/ynl/ynltool/Makefile55
-rw-r--r--tools/net/ynl/ynltool/json_writer.c288
-rw-r--r--tools/net/ynl/ynltool/json_writer.h75
-rw-r--r--tools/net/ynl/ynltool/main.c242
-rw-r--r--tools/net/ynl/ynltool/main.h66
-rw-r--r--tools/net/ynl/ynltool/page-pool.c461
-rw-r--r--tools/net/ynl/ynltool/qstats.c621
224 files changed, 12272 insertions, 19882 deletions
diff --git a/tools/net/sunrpc/extract.sh b/tools/net/sunrpc/extract.sh
new file mode 100755
index 000000000000..f944066f25bc
--- /dev/null
+++ b/tools/net/sunrpc/extract.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# Extract an RPC protocol specification from an RFC document.
+# The version of this script comes from RFC 8166.
+#
+# Usage:
+# $ extract.sh < rfcNNNN.txt > protocol.x
+#
+
+grep '^ *///' | sed 's?^ */// ??' | sed 's?^ *///$??'
diff --git a/tools/net/sunrpc/xdrgen/.gitignore b/tools/net/sunrpc/xdrgen/.gitignore
new file mode 100644
index 000000000000..d7366c2f9be8
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/.gitignore
@@ -0,0 +1,2 @@
+__pycache__
+generators/__pycache__
diff --git a/tools/net/sunrpc/xdrgen/README b/tools/net/sunrpc/xdrgen/README
new file mode 100644
index 000000000000..27218a78ab40
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/README
@@ -0,0 +1,261 @@
+xdrgen - Linux Kernel XDR code generator
+
+Introduction
+------------
+
+SunRPC programs are typically specified using a language defined by
+RFC 4506. In fact, all IETF-published NFS specifications provide a
+description of the specified protocol using this language.
+
+Since the 1990's, user space consumers of SunRPC have had access to
+a tool that could read such XDR specifications and then generate C
+code that implements the RPC portions of that protocol. This tool is
+called rpcgen.
+
+This RPC-level code is code that handles input directly from the
+network, and thus a high degree of memory safety and sanity checking
+is needed to help ensure proper levels of security. Bugs in this
+code can have significant impact on security and performance.
+
+However, it is code that is repetitive and tedious to write by hand.
+
+The C code generated by rpcgen makes extensive use of the facilities
+of the user space TI-RPC library and libc. Furthermore, the dialect
+of the generated code is very traditional K&R C.
+
+The Linux kernel's implementation of SunRPC-based protocols hand-roll
+their XDR implementation. There are two main reasons for this:
+
+1. libtirpc (and its predecessors) operate only in user space. The
+ kernel's RPC implementation and its API are significantly
+ different than libtirpc.
+
+2. rpcgen-generated code is believed to be less efficient than code
+ that is hand-written.
+
+These days, gcc and its kin are capable of optimizing code better
+than human authors. There are only a few instances where writing
+XDR code by hand will make a measurable performance different.
+
+In addition, the current hand-written code in the Linux kernel is
+difficult to audit and prove that it implements exactly what is in
+the protocol specification.
+
+In order to accrue the benefits of machine-generated XDR code in the
+kernel, a tool is needed that will output C code that works against
+the kernel's SunRPC implementation rather than libtirpc.
+
+Enter xdrgen.
+
+
+Dependencies
+------------
+
+These dependencies are typically packaged by Linux distributions:
+
+- python3
+- python3-lark
+- python3-jinja2
+
+These dependencies are available via PyPi:
+
+- pip install 'lark[interegular]'
+
+
+XDR Specifications
+------------------
+
+When adding a new protocol implementation to the kernel, the XDR
+specification can be derived by feeding a .txt copy of the RFC to
+the script located in tools/net/sunrpc/extract.sh.
+
+ $ extract.sh < rfc0001.txt > new2.x
+
+
+Operation
+---------
+
+Once a .x file is available, use xdrgen to generate source and
+header files containing an implementation of XDR encoding and
+decoding functions for the specified protocol.
+
+ $ ./xdrgen definitions new2.x > include/linux/sunrpc/xdrgen/new2.h
+ $ ./xdrgen declarations new2.x > new2xdr_gen.h
+
+and
+
+ $ ./xdrgen source new2.x > new2xdr_gen.c
+
+The files are ready to use for a server-side protocol implementation,
+or may be used as a guide for implementing these routines by hand.
+
+By default, the only comments added to this code are kdoc comments
+that appear directly in front of the public per-procedure APIs. For
+deeper introspection, specifying the "--annotate" flag will insert
+additional comments in the generated code to help readers match the
+generated code to specific parts of the XDR specification.
+
+Because the generated code is targeted for the Linux kernel, it
+is tagged with a GPLv2-only license.
+
+The xdrgen tool can also provide lexical and syntax checking of
+an XDR specification:
+
+ $ ./xdrgen lint xdr/new.x
+
+
+How It Works
+------------
+
+xdrgen does not use machine learning to generate source code. The
+translation is entirely deterministic.
+
+RFC 4506 Section 6 contains a BNF grammar of the XDR specification
+language. The grammar has been adapted for use by the Python Lark
+module.
+
+The xdr.ebnf file in this directory contains the grammar used to
+parse XDR specifications. xdrgen configures Lark using the grammar
+in xdr.ebnf. Lark parses the target XDR specification using this
+grammar, creating a parse tree.
+
+xdrgen then transforms the parse tree into an abstract syntax tree.
+This tree is passed to a series of code generators.
+
+The generators are implemented as Python classes residing in the
+generators/ directory. Each generator emits code created from Jinja2
+templates stored in the templates/ directory.
+
+The source code is generated in the same order in which they appear
+in the specification to ensure the generated code compiles. This
+conforms with the behavior of rpcgen.
+
+xdrgen assumes that the generated source code is further compiled by
+a compiler that can optimize in a number of ways, including:
+
+ - Unused functions are discarded (ie, not added to the executable)
+
+ - Aggressive function inlining removes unnecessary stack frames
+
+ - Single-arm switch statements are replaced by a single conditional
+ branch
+
+And so on.
+
+
+Pragmas
+-------
+
+Pragma directives specify exceptions to the normal generation of
+encoding and decoding functions. Currently one directive is
+implemented: "public".
+
+Pragma big_endian
+------ ----------
+
+ pragma big_endian <enum> ;
+
+For variables that might contain only a small number values, it
+is more efficient to avoid the byte-swap when encoding or decoding
+on little-endian machines. Such is often the case with error status
+codes. For example:
+
+ pragma big_endian nfsstat3;
+
+In this case, when generating an XDR struct or union containing a
+field of type "nfsstat3", xdrgen will make the type of that field
+"__be32" instead of "enum nfsstat3". XDR unions then switch on the
+non-byte-swapped value of that field.
+
+Pragma exclude
+------ -------
+
+ pragma exclude <RPC procedure> ;
+
+In some cases, a procedure encoder or decoder function might need
+special processing that cannot be automatically generated. The
+automatically-generated functions might conflict or interfere with
+the hand-rolled function. To avoid editing the generated source code
+by hand, a pragma can specify that the procedure's encoder and
+decoder functions are not included in the generated header and
+source.
+
+For example:
+
+ pragma exclude NFSPROC3_READDIRPLUS;
+
+Excludes the decoder function for the READDIRPLUS argument and the
+encoder function for the READDIRPLUS result.
+
+Note that because data item encoder and decoder functions are
+defined "static __maybe_unused", subsequent compilation
+automatically excludes data item encoder and decoder functions that
+are used only by excluded procedure.
+
+Pragma header
+------ ------
+
+ pragma header <string> ;
+
+Provide a name to use for the header file. For example:
+
+ pragma header nlm4;
+
+Adds
+
+ #include "nlm4xdr_gen.h"
+
+to the generated source file.
+
+Pragma public
+------ ------
+
+ pragma public <XDR data item> ;
+
+Normally XDR encoder and decoder functions are "static". In case an
+implementer wants to call these functions from other source code,
+s/he can add a public pragma in the input .x file to indicate a set
+of functions that should get a prototype in the generated header,
+and the function definitions will not be declared static.
+
+For example:
+
+ pragma public nfsstat3;
+
+Adds these prototypes in the generated header:
+
+ bool xdrgen_decode_nfsstat3(struct xdr_stream *xdr, enum nfsstat3 *ptr);
+ bool xdrgen_encode_nfsstat3(struct xdr_stream *xdr, enum nfsstat3 value);
+
+And, in the generated source code, both of these functions appear
+without the "static __maybe_unused" modifiers.
+
+
+Future Work
+-----------
+
+Finish implementing XDR pointer and list types.
+
+Generate client-side procedure functions
+
+Expand the README into a user guide similar to rpcgen(1)
+
+Add more pragma directives:
+
+ * @pages -- use xdr_read/write_pages() for the specified opaque
+ field
+ * @skip -- do not decode, but rather skip, the specified argument
+ field
+
+Enable something like a #include to dynamically insert the content
+of other specification files
+
+Properly support line-by-line pass-through via the "%" decorator
+
+Build a unit test suite for verifying translation of XDR language
+into compilable code
+
+Add a command-line option to insert trace_printk call sites in the
+generated source code, for improved (temporary) observability
+
+Generate kernel Rust code as well as C code
diff --git a/tools/net/sunrpc/xdrgen/__init__.py b/tools/net/sunrpc/xdrgen/__init__.py
new file mode 100644
index 000000000000..c940e9275252
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+# Just to make sphinx-apidoc document this directory
diff --git a/tools/net/sunrpc/xdrgen/generators/__init__.py b/tools/net/sunrpc/xdrgen/generators/__init__.py
new file mode 100644
index 000000000000..e22632cf38fb
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/__init__.py
@@ -0,0 +1,118 @@
+# SPDX-License-Identifier: GPL-2.0
+
+"""Define a base code generator class"""
+
+from pathlib import Path
+from jinja2 import Environment, FileSystemLoader, Template
+
+from xdr_ast import _XdrAst, Specification, _RpcProgram, _XdrTypeSpecifier
+from xdr_ast import public_apis, pass_by_reference, get_header_name
+from xdr_parse import get_xdr_annotate
+
+
+def create_jinja2_environment(language: str, xdr_type: str) -> Environment:
+ """Open a set of templates based on output language"""
+ match language:
+ case "C":
+ templates_dir = (
+ Path(__file__).parent.parent / "templates" / language / xdr_type
+ )
+ environment = Environment(
+ loader=FileSystemLoader(templates_dir),
+ trim_blocks=True,
+ lstrip_blocks=True,
+ )
+ environment.globals["annotate"] = get_xdr_annotate()
+ environment.globals["public_apis"] = public_apis
+ environment.globals["pass_by_reference"] = pass_by_reference
+ return environment
+ case _:
+ raise NotImplementedError("Language not supported")
+
+
+def get_jinja2_template(
+ environment: Environment, template_type: str, template_name: str
+) -> Template:
+ """Retrieve a Jinja2 template for emitting source code"""
+ return environment.get_template(template_type + "/" + template_name + ".j2")
+
+
+def find_xdr_program_name(root: Specification) -> str:
+ """Retrieve the RPC program name from an abstract syntax tree"""
+ raw_name = get_header_name()
+ if raw_name != "none":
+ return raw_name.lower()
+ for definition in root.definitions:
+ if isinstance(definition.value, _RpcProgram):
+ raw_name = definition.value.name
+ return raw_name.lower().removesuffix("_program").removesuffix("_prog")
+ return "noprog"
+
+
+def header_guard_infix(filename: str) -> str:
+ """Extract the header guard infix from the specification filename"""
+ return Path(filename).stem.upper()
+
+
+def kernel_c_type(spec: _XdrTypeSpecifier) -> str:
+ """Return name of C type"""
+ builtin_native_c_type = {
+ "bool": "bool",
+ "int": "s32",
+ "unsigned_int": "u32",
+ "long": "s32",
+ "unsigned_long": "u32",
+ "hyper": "s64",
+ "unsigned_hyper": "u64",
+ }
+ if spec.type_name in builtin_native_c_type:
+ return builtin_native_c_type[spec.type_name]
+ return spec.type_name
+
+
+class Boilerplate:
+ """Base class to generate boilerplate for source files"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ raise NotImplementedError("No language support defined")
+
+ def emit_declaration(self, filename: str, root: Specification) -> None:
+ """Emit declaration header boilerplate"""
+ raise NotImplementedError("Header boilerplate generation not supported")
+
+ def emit_definition(self, filename: str, root: Specification) -> None:
+ """Emit definition header boilerplate"""
+ raise NotImplementedError("Header boilerplate generation not supported")
+
+ def emit_source(self, filename: str, root: Specification) -> None:
+ """Emit generic source code for this XDR type"""
+ raise NotImplementedError("Source boilerplate generation not supported")
+
+
+class SourceGenerator:
+ """Base class to generate header and source code for XDR types"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ raise NotImplementedError("No language support defined")
+
+ def emit_declaration(self, node: _XdrAst) -> None:
+ """Emit one function declaration for this XDR type"""
+ raise NotImplementedError("Declaration generation not supported")
+
+ def emit_decoder(self, node: _XdrAst) -> None:
+ """Emit one decoder function for this XDR type"""
+ raise NotImplementedError("Decoder generation not supported")
+
+ def emit_definition(self, node: _XdrAst) -> None:
+ """Emit one definition for this XDR type"""
+ raise NotImplementedError("Definition generation not supported")
+
+ def emit_encoder(self, node: _XdrAst) -> None:
+ """Emit one encoder function for this XDR type"""
+ raise NotImplementedError("Encoder generation not supported")
+
+ def emit_maxsize(self, node: _XdrAst) -> None:
+ """Emit one maxsize macro for this XDR type"""
+ raise NotImplementedError("Maxsize macro generation not supported")
diff --git a/tools/net/sunrpc/xdrgen/generators/constant.py b/tools/net/sunrpc/xdrgen/generators/constant.py
new file mode 100644
index 000000000000..f2339caf0953
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/constant.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR constants"""
+
+from generators import SourceGenerator, create_jinja2_environment
+from xdr_ast import _XdrConstant
+
+class XdrConstantGenerator(SourceGenerator):
+ """Generate source code for XDR constants"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "constants")
+ self.peer = peer
+
+ def emit_definition(self, node: _XdrConstant) -> None:
+ """Emit one definition for a constant"""
+ template = self.environment.get_template("definition.j2")
+ print(template.render(name=node.name, value=node.value))
diff --git a/tools/net/sunrpc/xdrgen/generators/enum.py b/tools/net/sunrpc/xdrgen/generators/enum.py
new file mode 100644
index 000000000000..e62f715d3996
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/enum.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR enum types"""
+
+from generators import SourceGenerator, create_jinja2_environment
+from xdr_ast import _XdrEnum, public_apis, big_endian, get_header_name
+
+
+class XdrEnumGenerator(SourceGenerator):
+ """Generate source code for XDR enum types"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "enum")
+ self.peer = peer
+
+ def emit_declaration(self, node: _XdrEnum) -> None:
+ """Emit one declaration pair for an XDR enum type"""
+ if node.name in public_apis:
+ template = self.environment.get_template("declaration/enum.j2")
+ print(template.render(name=node.name))
+
+ def emit_definition(self, node: _XdrEnum) -> None:
+ """Emit one definition for an XDR enum type"""
+ template = self.environment.get_template("definition/open.j2")
+ print(template.render(name=node.name))
+
+ template = self.environment.get_template("definition/enumerator.j2")
+ for enumerator in node.enumerators:
+ print(template.render(name=enumerator.name, value=enumerator.value))
+
+ if node.name in big_endian:
+ template = self.environment.get_template("definition/close_be.j2")
+ else:
+ template = self.environment.get_template("definition/close.j2")
+ print(template.render(name=node.name))
+
+ def emit_decoder(self, node: _XdrEnum) -> None:
+ """Emit one decoder function for an XDR enum type"""
+ if node.name in big_endian:
+ template = self.environment.get_template("decoder/enum_be.j2")
+ else:
+ template = self.environment.get_template("decoder/enum.j2")
+ print(template.render(name=node.name))
+
+ def emit_encoder(self, node: _XdrEnum) -> None:
+ """Emit one encoder function for an XDR enum type"""
+ if node.name in big_endian:
+ template = self.environment.get_template("encoder/enum_be.j2")
+ else:
+ template = self.environment.get_template("encoder/enum.j2")
+ print(template.render(name=node.name))
+
+ def emit_maxsize(self, node: _XdrEnum) -> None:
+ """Emit one maxsize macro for an XDR enum type"""
+ macro_name = get_header_name().upper() + "_" + node.name + "_sz"
+ template = self.environment.get_template("maxsize/enum.j2")
+ print(
+ template.render(
+ macro=macro_name,
+ width=" + ".join(node.symbolic_width()),
+ )
+ )
diff --git a/tools/net/sunrpc/xdrgen/generators/header_bottom.py b/tools/net/sunrpc/xdrgen/generators/header_bottom.py
new file mode 100644
index 000000000000..4b55b282dfc0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/header_bottom.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate header bottom boilerplate"""
+
+import os.path
+import time
+
+from generators import Boilerplate, header_guard_infix
+from generators import create_jinja2_environment, get_jinja2_template
+from xdr_ast import Specification
+
+
+class XdrHeaderBottomGenerator(Boilerplate):
+ """Generate header boilerplate"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "header_bottom")
+ self.peer = peer
+
+ def emit_declaration(self, filename: str, root: Specification) -> None:
+ """Emit the bottom header guard"""
+ template = get_jinja2_template(self.environment, "declaration", "header")
+ print(template.render(infix=header_guard_infix(filename)))
+
+ def emit_definition(self, filename: str, root: Specification) -> None:
+ """Emit the bottom header guard"""
+ template = get_jinja2_template(self.environment, "definition", "header")
+ print(template.render(infix=header_guard_infix(filename)))
+
+ def emit_source(self, filename: str, root: Specification) -> None:
+ pass
diff --git a/tools/net/sunrpc/xdrgen/generators/header_top.py b/tools/net/sunrpc/xdrgen/generators/header_top.py
new file mode 100644
index 000000000000..c6bc21c71f19
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/header_top.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate header top boilerplate"""
+
+import os.path
+import time
+
+from generators import Boilerplate, header_guard_infix
+from generators import create_jinja2_environment, get_jinja2_template
+from xdr_ast import Specification
+
+
+class XdrHeaderTopGenerator(Boilerplate):
+ """Generate header boilerplate"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "header_top")
+ self.peer = peer
+
+ def emit_declaration(self, filename: str, root: Specification) -> None:
+ """Emit the top header guard"""
+ template = get_jinja2_template(self.environment, "declaration", "header")
+ print(
+ template.render(
+ infix=header_guard_infix(filename),
+ filename=filename,
+ mtime=time.ctime(os.path.getmtime(filename)),
+ )
+ )
+
+ def emit_definition(self, filename: str, root: Specification) -> None:
+ """Emit the top header guard"""
+ template = get_jinja2_template(self.environment, "definition", "header")
+ print(
+ template.render(
+ infix=header_guard_infix(filename),
+ filename=filename,
+ mtime=time.ctime(os.path.getmtime(filename)),
+ )
+ )
+
+ def emit_source(self, filename: str, root: Specification) -> None:
+ pass
diff --git a/tools/net/sunrpc/xdrgen/generators/pointer.py b/tools/net/sunrpc/xdrgen/generators/pointer.py
new file mode 100644
index 000000000000..6dbda60ad2db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/pointer.py
@@ -0,0 +1,288 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR pointer types"""
+
+from jinja2 import Environment
+
+from generators import SourceGenerator, kernel_c_type
+from generators import create_jinja2_environment, get_jinja2_template
+
+from xdr_ast import _XdrBasic, _XdrString
+from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
+from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
+from xdr_ast import _XdrOptionalData, _XdrPointer, _XdrDeclaration
+from xdr_ast import public_apis, get_header_name
+
+
+def emit_pointer_declaration(environment: Environment, node: _XdrPointer) -> None:
+ """Emit a declaration pair for an XDR pointer type"""
+ if node.name in public_apis:
+ template = get_jinja2_template(environment, "declaration", "close")
+ print(template.render(name=node.name))
+
+
+def emit_pointer_member_definition(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit a definition for one field in an XDR struct"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(template.render(name=field.name))
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(template.render(name=field.name))
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_pointer_definition(environment: Environment, node: _XdrPointer) -> None:
+ """Emit a definition for an XDR pointer type"""
+ template = get_jinja2_template(environment, "definition", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields[0:-1]:
+ emit_pointer_member_definition(environment, field)
+
+ template = get_jinja2_template(environment, "definition", "close")
+ print(template.render(name=node.name))
+
+
+def emit_pointer_member_decoder(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit a decoder for one field in an XDR pointer"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ size=field.size,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ maxsize=field.maxsize,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_pointer_decoder(environment: Environment, node: _XdrPointer) -> None:
+ """Emit one decoder function for an XDR pointer type"""
+ template = get_jinja2_template(environment, "decoder", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields[0:-1]:
+ emit_pointer_member_decoder(environment, field)
+
+ template = get_jinja2_template(environment, "decoder", "close")
+ print(template.render())
+
+
+def emit_pointer_member_encoder(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit an encoder for one field in a XDR pointer"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_pointer_encoder(environment: Environment, node: _XdrPointer) -> None:
+ """Emit one encoder function for an XDR pointer type"""
+ template = get_jinja2_template(environment, "encoder", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields[0:-1]:
+ emit_pointer_member_encoder(environment, field)
+
+ template = get_jinja2_template(environment, "encoder", "close")
+ print(template.render())
+
+
+def emit_pointer_maxsize(environment: Environment, node: _XdrPointer) -> None:
+ """Emit one maxsize macro for an XDR pointer type"""
+ macro_name = get_header_name().upper() + "_" + node.name + "_sz"
+ template = get_jinja2_template(environment, "maxsize", "pointer")
+ print(
+ template.render(
+ macro=macro_name,
+ width=" + ".join(node.symbolic_width()),
+ )
+ )
+
+
+class XdrPointerGenerator(SourceGenerator):
+ """Generate source code for XDR pointer"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "pointer")
+ self.peer = peer
+
+ def emit_declaration(self, node: _XdrPointer) -> None:
+ """Emit one declaration pair for an XDR pointer type"""
+ emit_pointer_declaration(self.environment, node)
+
+ def emit_definition(self, node: _XdrPointer) -> None:
+ """Emit one declaration for an XDR pointer type"""
+ emit_pointer_definition(self.environment, node)
+
+ def emit_decoder(self, node: _XdrPointer) -> None:
+ """Emit one decoder function for an XDR pointer type"""
+ emit_pointer_decoder(self.environment, node)
+
+ def emit_encoder(self, node: _XdrPointer) -> None:
+ """Emit one encoder function for an XDR pointer type"""
+ emit_pointer_encoder(self.environment, node)
+
+ def emit_maxsize(self, node: _XdrPointer) -> None:
+ """Emit one maxsize macro for an XDR pointer type"""
+ emit_pointer_maxsize(self.environment, node)
diff --git a/tools/net/sunrpc/xdrgen/generators/program.py b/tools/net/sunrpc/xdrgen/generators/program.py
new file mode 100644
index 000000000000..ac3cf1694b68
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/program.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code for an RPC program's procedures"""
+
+from jinja2 import Environment
+
+from generators import SourceGenerator, create_jinja2_environment
+from xdr_ast import _RpcProgram, _RpcVersion, excluded_apis
+
+
+def emit_version_definitions(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit procedure numbers for each RPC version's procedures"""
+ template = environment.get_template("definition/open.j2")
+ print(template.render(program=program.upper()))
+
+ template = environment.get_template("definition/procedure.j2")
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ print(
+ template.render(
+ name=procedure.name,
+ value=procedure.number,
+ )
+ )
+
+ template = environment.get_template("definition/close.j2")
+ print(template.render())
+
+
+def emit_version_declarations(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit declarations for each RPC version's procedures"""
+ arguments = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ arguments[procedure.argument.type_name] = None
+ if len(arguments) > 0:
+ print("")
+ template = environment.get_template("declaration/argument.j2")
+ for argument in arguments:
+ print(template.render(program=program, argument=argument))
+
+ results = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ results[procedure.result.type_name] = None
+ if len(results) > 0:
+ print("")
+ template = environment.get_template("declaration/result.j2")
+ for result in results:
+ print(template.render(program=program, result=result))
+
+
+def emit_version_argument_decoders(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit server argument decoders for each RPC version's procedures"""
+ arguments = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ arguments[procedure.argument.type_name] = None
+
+ template = environment.get_template("decoder/argument.j2")
+ for argument in arguments:
+ print(template.render(program=program, argument=argument))
+
+
+def emit_version_result_decoders(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit client result decoders for each RPC version's procedures"""
+ results = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ results[procedure.result.type_name] = None
+
+ template = environment.get_template("decoder/result.j2")
+ for result in results:
+ print(template.render(program=program, result=result))
+
+
+def emit_version_argument_encoders(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit client argument encoders for each RPC version's procedures"""
+ arguments = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ arguments[procedure.argument.type_name] = None
+
+ template = environment.get_template("encoder/argument.j2")
+ for argument in arguments:
+ print(template.render(program=program, argument=argument))
+
+
+def emit_version_result_encoders(
+ environment: Environment, program: str, version: _RpcVersion
+) -> None:
+ """Emit server result encoders for each RPC version's procedures"""
+ results = dict.fromkeys([])
+ for procedure in version.procedures:
+ if procedure.name not in excluded_apis:
+ results[procedure.result.type_name] = None
+
+ template = environment.get_template("encoder/result.j2")
+ for result in results:
+ print(template.render(program=program, result=result))
+
+
+class XdrProgramGenerator(SourceGenerator):
+ """Generate source code for an RPC program's procedures"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "program")
+ self.peer = peer
+
+ def emit_definition(self, node: _RpcProgram) -> None:
+ """Emit procedure numbers for each of an RPC programs's procedures"""
+ raw_name = node.name
+ program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
+
+ for version in node.versions:
+ emit_version_definitions(self.environment, program, version)
+
+ def emit_declaration(self, node: _RpcProgram) -> None:
+ """Emit a declaration pair for each of an RPC programs's procedures"""
+ raw_name = node.name
+ program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
+
+ for version in node.versions:
+ emit_version_declarations(self.environment, program, version)
+
+ def emit_decoder(self, node: _RpcProgram) -> None:
+ """Emit all decoder functions for an RPC program's procedures"""
+ raw_name = node.name
+ program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
+ match self.peer:
+ case "server":
+ for version in node.versions:
+ emit_version_argument_decoders(
+ self.environment, program, version,
+ )
+ case "client":
+ for version in node.versions:
+ emit_version_result_decoders(
+ self.environment, program, version,
+ )
+
+ def emit_encoder(self, node: _RpcProgram) -> None:
+ """Emit all encoder functions for an RPC program's procedures"""
+ raw_name = node.name
+ program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
+ match self.peer:
+ case "server":
+ for version in node.versions:
+ emit_version_result_encoders(
+ self.environment, program, version,
+ )
+ case "client":
+ for version in node.versions:
+ emit_version_argument_encoders(
+ self.environment, program, version,
+ )
diff --git a/tools/net/sunrpc/xdrgen/generators/source_top.py b/tools/net/sunrpc/xdrgen/generators/source_top.py
new file mode 100644
index 000000000000..bcf47d93d6f1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/source_top.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate source code boilerplate"""
+
+import os.path
+import time
+
+from generators import Boilerplate
+from generators import find_xdr_program_name, create_jinja2_environment
+from xdr_ast import _RpcProgram, Specification, get_header_name
+
+
+class XdrSourceTopGenerator(Boilerplate):
+ """Generate source code boilerplate"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "source_top")
+ self.peer = peer
+
+ def emit_source(self, filename: str, root: Specification) -> None:
+ """Emit the top source boilerplate"""
+ name = find_xdr_program_name(root)
+ template = self.environment.get_template(self.peer + ".j2")
+ print(
+ template.render(
+ program=name,
+ filename=filename,
+ mtime=time.ctime(os.path.getmtime(filename)),
+ )
+ )
diff --git a/tools/net/sunrpc/xdrgen/generators/struct.py b/tools/net/sunrpc/xdrgen/generators/struct.py
new file mode 100644
index 000000000000..64911de46f62
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/struct.py
@@ -0,0 +1,288 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR struct types"""
+
+from jinja2 import Environment
+
+from generators import SourceGenerator, kernel_c_type
+from generators import create_jinja2_environment, get_jinja2_template
+
+from xdr_ast import _XdrBasic, _XdrString
+from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
+from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
+from xdr_ast import _XdrOptionalData, _XdrStruct, _XdrDeclaration
+from xdr_ast import public_apis, get_header_name
+
+
+def emit_struct_declaration(environment: Environment, node: _XdrStruct) -> None:
+ """Emit one declaration pair for an XDR struct type"""
+ if node.name in public_apis:
+ template = get_jinja2_template(environment, "declaration", "close")
+ print(template.render(name=node.name))
+
+
+def emit_struct_member_definition(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit a definition for one field in an XDR struct"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(template.render(name=field.name))
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(template.render(name=field.name))
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "definition", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=kernel_c_type(field.spec),
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_struct_definition(environment: Environment, node: _XdrStruct) -> None:
+ """Emit one definition for an XDR struct type"""
+ template = get_jinja2_template(environment, "definition", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields:
+ emit_struct_member_definition(environment, field)
+
+ template = get_jinja2_template(environment, "definition", "close")
+ print(template.render(name=node.name))
+
+
+def emit_struct_member_decoder(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit a decoder for one field in an XDR struct"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ size=field.size,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ maxsize=field.maxsize,
+ classifier=field.spec.c_classifier,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "decoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_struct_decoder(environment: Environment, node: _XdrStruct) -> None:
+ """Emit one decoder function for an XDR struct type"""
+ template = get_jinja2_template(environment, "decoder", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields:
+ emit_struct_member_decoder(environment, field)
+
+ template = get_jinja2_template(environment, "decoder", "close")
+ print(template.render())
+
+
+def emit_struct_member_encoder(
+ environment: Environment, field: _XdrDeclaration
+) -> None:
+ """Emit an encoder for one field in an XDR struct"""
+ if isinstance(field, _XdrBasic):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrString):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ size=field.size,
+ )
+ )
+ elif isinstance(field, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ maxsize=field.maxsize,
+ )
+ )
+ elif isinstance(field, _XdrOptionalData):
+ template = get_jinja2_template(environment, "encoder", field.template)
+ print(
+ template.render(
+ name=field.name,
+ type=field.spec.type_name,
+ classifier=field.spec.c_classifier,
+ )
+ )
+
+
+def emit_struct_encoder(environment: Environment, node: _XdrStruct) -> None:
+ """Emit one encoder function for an XDR struct type"""
+ template = get_jinja2_template(environment, "encoder", "open")
+ print(template.render(name=node.name))
+
+ for field in node.fields:
+ emit_struct_member_encoder(environment, field)
+
+ template = get_jinja2_template(environment, "encoder", "close")
+ print(template.render())
+
+
+def emit_struct_maxsize(environment: Environment, node: _XdrStruct) -> None:
+ """Emit one maxsize macro for an XDR struct type"""
+ macro_name = get_header_name().upper() + "_" + node.name + "_sz"
+ template = get_jinja2_template(environment, "maxsize", "struct")
+ print(
+ template.render(
+ macro=macro_name,
+ width=" + ".join(node.symbolic_width()),
+ )
+ )
+
+
+class XdrStructGenerator(SourceGenerator):
+ """Generate source code for XDR structs"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "struct")
+ self.peer = peer
+
+ def emit_declaration(self, node: _XdrStruct) -> None:
+ """Emit one declaration pair for an XDR struct type"""
+ emit_struct_declaration(self.environment, node)
+
+ def emit_definition(self, node: _XdrStruct) -> None:
+ """Emit one definition for an XDR struct type"""
+ emit_struct_definition(self.environment, node)
+
+ def emit_decoder(self, node: _XdrStruct) -> None:
+ """Emit one decoder function for an XDR struct type"""
+ emit_struct_decoder(self.environment, node)
+
+ def emit_encoder(self, node: _XdrStruct) -> None:
+ """Emit one encoder function for an XDR struct type"""
+ emit_struct_encoder(self.environment, node)
+
+ def emit_maxsize(self, node: _XdrStruct) -> None:
+ """Emit one maxsize macro for an XDR struct type"""
+ emit_struct_maxsize(self.environment, node)
diff --git a/tools/net/sunrpc/xdrgen/generators/typedef.py b/tools/net/sunrpc/xdrgen/generators/typedef.py
new file mode 100644
index 000000000000..fab72e9d6915
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/typedef.py
@@ -0,0 +1,271 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR typedefs"""
+
+from jinja2 import Environment
+
+from generators import SourceGenerator, kernel_c_type
+from generators import create_jinja2_environment, get_jinja2_template
+
+from xdr_ast import _XdrBasic, _XdrTypedef, _XdrString
+from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
+from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
+from xdr_ast import _XdrOptionalData, _XdrVoid, _XdrDeclaration
+from xdr_ast import public_apis, get_header_name
+
+
+def emit_typedef_declaration(environment: Environment, node: _XdrDeclaration) -> None:
+ """Emit a declaration pair for one XDR typedef"""
+ if node.name not in public_apis:
+ return
+ if isinstance(node, _XdrBasic):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=kernel_c_type(node.spec),
+ classifier=node.spec.c_classifier,
+ )
+ )
+ elif isinstance(node, _XdrString):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(template.render(name=node.name))
+ elif isinstance(node, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(template.render(name=node.name, size=node.size))
+ elif isinstance(node, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(template.render(name=node.name))
+ elif isinstance(node, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ size=node.size,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "declaration", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ classifier=node.spec.c_classifier,
+ )
+ )
+ elif isinstance(node, _XdrOptionalData):
+ raise NotImplementedError("<optional_data> typedef not yet implemented")
+ elif isinstance(node, _XdrVoid):
+ raise NotImplementedError("<void> typedef not yet implemented")
+ else:
+ raise NotImplementedError("typedef: type not recognized")
+
+
+def emit_type_definition(environment: Environment, node: _XdrDeclaration) -> None:
+ """Emit a definition for one XDR typedef"""
+ if isinstance(node, _XdrBasic):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=kernel_c_type(node.spec),
+ classifier=node.spec.c_classifier,
+ )
+ )
+ elif isinstance(node, _XdrString):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(template.render(name=node.name))
+ elif isinstance(node, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(template.render(name=node.name, size=node.size))
+ elif isinstance(node, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(template.render(name=node.name))
+ elif isinstance(node, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ size=node.size,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "definition", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ classifier=node.spec.c_classifier,
+ )
+ )
+ elif isinstance(node, _XdrOptionalData):
+ raise NotImplementedError("<optional_data> typedef not yet implemented")
+ elif isinstance(node, _XdrVoid):
+ raise NotImplementedError("<void> typedef not yet implemented")
+ else:
+ raise NotImplementedError("typedef: type not recognized")
+
+
+def emit_typedef_decoder(environment: Environment, node: _XdrDeclaration) -> None:
+ """Emit a decoder function for one XDR typedef"""
+ if isinstance(node, _XdrBasic):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ )
+ )
+ elif isinstance(node, _XdrString):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ size=node.size,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ size=node.size,
+ classifier=node.spec.c_classifier,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "decoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrOptionalData):
+ raise NotImplementedError("<optional_data> typedef not yet implemented")
+ elif isinstance(node, _XdrVoid):
+ raise NotImplementedError("<void> typedef not yet implemented")
+ else:
+ raise NotImplementedError("typedef: type not recognized")
+
+
+def emit_typedef_encoder(environment: Environment, node: _XdrDeclaration) -> None:
+ """Emit an encoder function for one XDR typedef"""
+ if isinstance(node, _XdrBasic):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ )
+ )
+ elif isinstance(node, _XdrString):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrFixedLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ size=node.size,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthOpaque):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrFixedLengthArray):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ size=node.size,
+ )
+ )
+ elif isinstance(node, _XdrVariableLengthArray):
+ template = get_jinja2_template(environment, "encoder", node.template)
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ maxsize=node.maxsize,
+ )
+ )
+ elif isinstance(node, _XdrOptionalData):
+ raise NotImplementedError("<optional_data> typedef not yet implemented")
+ elif isinstance(node, _XdrVoid):
+ raise NotImplementedError("<void> typedef not yet implemented")
+ else:
+ raise NotImplementedError("typedef: type not recognized")
+
+
+def emit_typedef_maxsize(environment: Environment, node: _XdrDeclaration) -> None:
+ """Emit a maxsize macro for an XDR typedef"""
+ macro_name = get_header_name().upper() + "_" + node.name + "_sz"
+ template = get_jinja2_template(environment, "maxsize", node.template)
+ print(
+ template.render(
+ macro=macro_name,
+ width=" + ".join(node.symbolic_width()),
+ )
+ )
+
+
+class XdrTypedefGenerator(SourceGenerator):
+ """Generate source code for XDR typedefs"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "typedef")
+ self.peer = peer
+
+ def emit_declaration(self, node: _XdrTypedef) -> None:
+ """Emit one declaration pair for an XDR enum type"""
+ emit_typedef_declaration(self.environment, node.declaration)
+
+ def emit_definition(self, node: _XdrTypedef) -> None:
+ """Emit one definition for an XDR typedef"""
+ emit_type_definition(self.environment, node.declaration)
+
+ def emit_decoder(self, node: _XdrTypedef) -> None:
+ """Emit one decoder function for an XDR typedef"""
+ emit_typedef_decoder(self.environment, node.declaration)
+
+ def emit_encoder(self, node: _XdrTypedef) -> None:
+ """Emit one encoder function for an XDR typedef"""
+ emit_typedef_encoder(self.environment, node.declaration)
+
+ def emit_maxsize(self, node: _XdrTypedef) -> None:
+ """Emit one maxsize macro for an XDR typedef"""
+ emit_typedef_maxsize(self.environment, node.declaration)
diff --git a/tools/net/sunrpc/xdrgen/generators/union.py b/tools/net/sunrpc/xdrgen/generators/union.py
new file mode 100644
index 000000000000..ad1f214ef22a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/generators/union.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Generate code to handle XDR unions"""
+
+from jinja2 import Environment
+
+from generators import SourceGenerator
+from generators import create_jinja2_environment, get_jinja2_template
+
+from xdr_ast import _XdrBasic, _XdrUnion, _XdrVoid, _XdrString, get_header_name
+from xdr_ast import _XdrDeclaration, _XdrCaseSpec, public_apis, big_endian
+
+
+def emit_union_declaration(environment: Environment, node: _XdrUnion) -> None:
+ """Emit one declaration pair for an XDR union type"""
+ if node.name in public_apis:
+ template = get_jinja2_template(environment, "declaration", "close")
+ print(template.render(name=node.name))
+
+
+def emit_union_switch_spec_definition(
+ environment: Environment, node: _XdrDeclaration
+) -> None:
+ """Emit a definition for an XDR union's discriminant"""
+ assert isinstance(node, _XdrBasic)
+ template = get_jinja2_template(environment, "definition", "switch_spec")
+ print(
+ template.render(
+ name=node.name,
+ type=node.spec.type_name,
+ classifier=node.spec.c_classifier,
+ )
+ )
+
+
+def emit_union_case_spec_definition(
+ environment: Environment, node: _XdrDeclaration
+) -> None:
+ """Emit a definition for an XDR union's case arm"""
+ if isinstance(node.arm, _XdrVoid):
+ return
+ if isinstance(node.arm, _XdrString):
+ type_name = "char *"
+ classifier = ""
+ else:
+ type_name = node.arm.spec.type_name
+ classifier = node.arm.spec.c_classifier
+
+ assert isinstance(node.arm, (_XdrBasic, _XdrString))
+ template = get_jinja2_template(environment, "definition", "case_spec")
+ print(
+ template.render(
+ name=node.arm.name,
+ type=type_name,
+ classifier=classifier,
+ )
+ )
+
+
+def emit_union_definition(environment: Environment, node: _XdrUnion) -> None:
+ """Emit one XDR union definition"""
+ template = get_jinja2_template(environment, "definition", "open")
+ print(template.render(name=node.name))
+
+ emit_union_switch_spec_definition(environment, node.discriminant)
+
+ for case in node.cases:
+ emit_union_case_spec_definition(environment, case)
+
+ if node.default is not None:
+ emit_union_case_spec_definition(environment, node.default)
+
+ template = get_jinja2_template(environment, "definition", "close")
+ print(template.render(name=node.name))
+
+
+def emit_union_switch_spec_decoder(
+ environment: Environment, node: _XdrDeclaration
+) -> None:
+ """Emit a decoder for an XDR union's discriminant"""
+ assert isinstance(node, _XdrBasic)
+ template = get_jinja2_template(environment, "decoder", "switch_spec")
+ print(template.render(name=node.name, type=node.spec.type_name))
+
+
+def emit_union_case_spec_decoder(
+ environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
+) -> None:
+ """Emit decoder functions for an XDR union's case arm"""
+
+ if isinstance(node.arm, _XdrVoid):
+ return
+ if isinstance(node.arm, _XdrString):
+ type_name = "char *"
+ classifier = ""
+ else:
+ type_name = node.arm.spec.type_name
+ classifier = node.arm.spec.c_classifier
+
+ if big_endian_discriminant:
+ template = get_jinja2_template(environment, "decoder", "case_spec_be")
+ else:
+ template = get_jinja2_template(environment, "decoder", "case_spec")
+ for case in node.values:
+ print(template.render(case=case))
+
+ assert isinstance(node.arm, (_XdrBasic, _XdrString))
+ template = get_jinja2_template(environment, "decoder", node.arm.template)
+ print(
+ template.render(
+ name=node.arm.name,
+ type=type_name,
+ classifier=classifier,
+ )
+ )
+
+ template = get_jinja2_template(environment, "decoder", "break")
+ print(template.render())
+
+
+def emit_union_default_spec_decoder(environment: Environment, node: _XdrUnion) -> None:
+ """Emit a decoder function for an XDR union's default arm"""
+ default_case = node.default
+
+ # Avoid a gcc warning about a default case with boolean discriminant
+ if default_case is None and node.discriminant.spec.type_name == "bool":
+ return
+
+ template = get_jinja2_template(environment, "decoder", "default_spec")
+ print(template.render())
+
+ if default_case is None or isinstance(default_case.arm, _XdrVoid):
+ template = get_jinja2_template(environment, "decoder", "break")
+ print(template.render())
+ return
+
+ assert isinstance(default_case.arm, _XdrBasic)
+ template = get_jinja2_template(environment, "decoder", default_case.arm.template)
+ print(
+ template.render(
+ name=default_case.arm.name,
+ type=default_case.arm.spec.type_name,
+ classifier=default_case.arm.spec.c_classifier,
+ )
+ )
+
+
+def emit_union_decoder(environment: Environment, node: _XdrUnion) -> None:
+ """Emit one XDR union decoder"""
+ template = get_jinja2_template(environment, "decoder", "open")
+ print(template.render(name=node.name))
+
+ emit_union_switch_spec_decoder(environment, node.discriminant)
+
+ for case in node.cases:
+ emit_union_case_spec_decoder(
+ environment,
+ case,
+ node.discriminant.spec.type_name in big_endian,
+ )
+
+ emit_union_default_spec_decoder(environment, node)
+
+ template = get_jinja2_template(environment, "decoder", "close")
+ print(template.render())
+
+
+def emit_union_switch_spec_encoder(
+ environment: Environment, node: _XdrDeclaration
+) -> None:
+ """Emit an encoder for an XDR union's discriminant"""
+ assert isinstance(node, _XdrBasic)
+ template = get_jinja2_template(environment, "encoder", "switch_spec")
+ print(template.render(name=node.name, type=node.spec.type_name))
+
+
+def emit_union_case_spec_encoder(
+ environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
+) -> None:
+ """Emit encoder functions for an XDR union's case arm"""
+
+ if isinstance(node.arm, _XdrVoid):
+ return
+ if isinstance(node.arm, _XdrString):
+ type_name = "char *"
+ else:
+ type_name = node.arm.spec.type_name
+ if big_endian_discriminant:
+ template = get_jinja2_template(environment, "encoder", "case_spec_be")
+ else:
+ template = get_jinja2_template(environment, "encoder", "case_spec")
+ for case in node.values:
+ print(template.render(case=case))
+
+ template = get_jinja2_template(environment, "encoder", node.arm.template)
+ print(
+ template.render(
+ name=node.arm.name,
+ type=type_name,
+ )
+ )
+
+ template = get_jinja2_template(environment, "encoder", "break")
+ print(template.render())
+
+
+def emit_union_default_spec_encoder(environment: Environment, node: _XdrUnion) -> None:
+ """Emit an encoder function for an XDR union's default arm"""
+ default_case = node.default
+
+ # Avoid a gcc warning about a default case with boolean discriminant
+ if default_case is None and node.discriminant.spec.type_name == "bool":
+ return
+
+ template = get_jinja2_template(environment, "encoder", "default_spec")
+ print(template.render())
+
+ if default_case is None or isinstance(default_case.arm, _XdrVoid):
+ template = get_jinja2_template(environment, "encoder", "break")
+ print(template.render())
+ return
+
+ template = get_jinja2_template(environment, "encoder", default_case.arm.template)
+ print(
+ template.render(
+ name=default_case.arm.name,
+ type=default_case.arm.spec.type_name,
+ )
+ )
+
+
+def emit_union_encoder(environment, node: _XdrUnion) -> None:
+ """Emit one XDR union encoder"""
+ template = get_jinja2_template(environment, "encoder", "open")
+ print(template.render(name=node.name))
+
+ emit_union_switch_spec_encoder(environment, node.discriminant)
+
+ for case in node.cases:
+ emit_union_case_spec_encoder(
+ environment,
+ case,
+ node.discriminant.spec.type_name in big_endian,
+ )
+
+ emit_union_default_spec_encoder(environment, node)
+
+ template = get_jinja2_template(environment, "encoder", "close")
+ print(template.render())
+
+
+def emit_union_maxsize(environment: Environment, node: _XdrUnion) -> None:
+ """Emit one maxsize macro for an XDR union type"""
+ macro_name = get_header_name().upper() + "_" + node.name + "_sz"
+ template = get_jinja2_template(environment, "maxsize", "union")
+ print(
+ template.render(
+ macro=macro_name,
+ width=" + ".join(node.symbolic_width()),
+ )
+ )
+
+
+class XdrUnionGenerator(SourceGenerator):
+ """Generate source code for XDR unions"""
+
+ def __init__(self, language: str, peer: str):
+ """Initialize an instance of this class"""
+ self.environment = create_jinja2_environment(language, "union")
+ self.peer = peer
+
+ def emit_declaration(self, node: _XdrUnion) -> None:
+ """Emit one declaration pair for an XDR union"""
+ emit_union_declaration(self.environment, node)
+
+ def emit_definition(self, node: _XdrUnion) -> None:
+ """Emit one definition for an XDR union"""
+ emit_union_definition(self.environment, node)
+
+ def emit_decoder(self, node: _XdrUnion) -> None:
+ """Emit one decoder function for an XDR union"""
+ emit_union_decoder(self.environment, node)
+
+ def emit_encoder(self, node: _XdrUnion) -> None:
+ """Emit one encoder function for an XDR union"""
+ emit_union_encoder(self.environment, node)
+
+ def emit_maxsize(self, node: _XdrUnion) -> None:
+ """Emit one maxsize macro for an XDR union"""
+ emit_union_maxsize(self.environment, node)
diff --git a/tools/net/sunrpc/xdrgen/grammars/xdr.lark b/tools/net/sunrpc/xdrgen/grammars/xdr.lark
new file mode 100644
index 000000000000..7c2c1b8c86d1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/grammars/xdr.lark
@@ -0,0 +1,121 @@
+// A Lark grammar for the XDR specification language based on
+// https://tools.ietf.org/html/rfc4506 Section 6.3
+
+declaration : "opaque" identifier "[" value "]" -> fixed_length_opaque
+ | "opaque" identifier "<" [ value ] ">" -> variable_length_opaque
+ | "string" identifier "<" [ value ] ">" -> string
+ | type_specifier identifier "[" value "]" -> fixed_length_array
+ | type_specifier identifier "<" [ value ] ">" -> variable_length_array
+ | type_specifier "*" identifier -> optional_data
+ | type_specifier identifier -> basic
+ | "void" -> void
+
+value : decimal_constant
+ | hexadecimal_constant
+ | octal_constant
+ | identifier
+
+constant : decimal_constant | hexadecimal_constant | octal_constant
+
+type_specifier : unsigned_hyper
+ | unsigned_long
+ | unsigned_int
+ | hyper
+ | long
+ | int
+ | float
+ | double
+ | quadruple
+ | bool
+ | enum_type_spec
+ | struct_type_spec
+ | union_type_spec
+ | identifier
+
+unsigned_hyper : "unsigned" "hyper"
+unsigned_long : "unsigned" "long"
+unsigned_int : "unsigned" "int"
+hyper : "hyper"
+long : "long"
+int : "int"
+float : "float"
+double : "double"
+quadruple : "quadruple"
+bool : "bool"
+
+enum_type_spec : "enum" enum_body
+
+enum_body : "{" ( identifier "=" value ) ( "," identifier "=" value )* "}"
+
+struct_type_spec : "struct" struct_body
+
+struct_body : "{" ( declaration ";" )+ "}"
+
+union_type_spec : "union" union_body
+
+union_body : switch_spec "{" case_spec+ [ default_spec ] "}"
+
+switch_spec : "switch" "(" declaration ")"
+
+case_spec : ( "case" value ":" )+ declaration ";"
+
+default_spec : "default" ":" declaration ";"
+
+constant_def : "const" identifier "=" value ";"
+
+type_def : "typedef" declaration ";" -> typedef
+ | "enum" identifier enum_body ";" -> enum
+ | "struct" identifier struct_body ";" -> struct
+ | "union" identifier union_body ";" -> union
+
+specification : definition*
+
+definition : constant_def
+ | type_def
+ | program_def
+ | pragma_def
+
+//
+// RPC program definitions not specified in RFC 4506
+//
+
+program_def : "program" identifier "{" version_def+ "}" "=" constant ";"
+
+version_def : "version" identifier "{" procedure_def+ "}" "=" constant ";"
+
+procedure_def : type_specifier identifier "(" type_specifier ")" "=" constant ";"
+
+pragma_def : "pragma" directive identifier [ identifier ] ";"
+
+directive : big_endian_directive
+ | exclude_directive
+ | header_directive
+ | pages_directive
+ | public_directive
+ | skip_directive
+
+big_endian_directive : "big_endian"
+exclude_directive : "exclude"
+header_directive : "header"
+pages_directive : "pages"
+public_directive : "public"
+skip_directive : "skip"
+
+//
+// XDR language primitives
+//
+
+identifier : /([a-z]|[A-Z])(_|[a-z]|[A-Z]|[0-9])*/
+
+decimal_constant : /[\+-]?(0|[1-9][0-9]*)/
+hexadecimal_constant : /0x([a-f]|[A-F]|[0-9])+/
+octal_constant : /0[0-7]+/
+
+PASSTHRU : "%" | "%" /.+/
+%ignore PASSTHRU
+
+%import common.C_COMMENT
+%ignore C_COMMENT
+
+%import common.WS
+%ignore WS
diff --git a/tools/net/sunrpc/xdrgen/subcmds/__init__.py b/tools/net/sunrpc/xdrgen/subcmds/__init__.py
new file mode 100644
index 000000000000..c940e9275252
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/subcmds/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+# Just to make sphinx-apidoc document this directory
diff --git a/tools/net/sunrpc/xdrgen/subcmds/declarations.py b/tools/net/sunrpc/xdrgen/subcmds/declarations.py
new file mode 100644
index 000000000000..c5e8d79986ef
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/subcmds/declarations.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Translate an XDR specification into executable code that
+can be compiled for the Linux kernel."""
+
+import logging
+
+from argparse import Namespace
+from lark import logger
+from lark.exceptions import UnexpectedInput
+
+from generators.constant import XdrConstantGenerator
+from generators.enum import XdrEnumGenerator
+from generators.header_bottom import XdrHeaderBottomGenerator
+from generators.header_top import XdrHeaderTopGenerator
+from generators.pointer import XdrPointerGenerator
+from generators.program import XdrProgramGenerator
+from generators.typedef import XdrTypedefGenerator
+from generators.struct import XdrStructGenerator
+from generators.union import XdrUnionGenerator
+
+from xdr_ast import transform_parse_tree, _RpcProgram, Specification
+from xdr_ast import _XdrConstant, _XdrEnum, _XdrPointer
+from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion
+from xdr_parse import xdr_parser, set_xdr_annotate
+
+logger.setLevel(logging.INFO)
+
+
+def emit_header_declarations(
+ root: Specification, language: str, peer: str
+) -> None:
+ """Emit header declarations"""
+ for definition in root.definitions:
+ if isinstance(definition.value, _XdrEnum):
+ gen = XdrEnumGenerator(language, peer)
+ elif isinstance(definition.value, _XdrPointer):
+ gen = XdrPointerGenerator(language, peer)
+ elif isinstance(definition.value, _XdrTypedef):
+ gen = XdrTypedefGenerator(language, peer)
+ elif isinstance(definition.value, _XdrStruct):
+ gen = XdrStructGenerator(language, peer)
+ elif isinstance(definition.value, _XdrUnion):
+ gen = XdrUnionGenerator(language, peer)
+ elif isinstance(definition.value, _RpcProgram):
+ gen = XdrProgramGenerator(language, peer)
+ else:
+ continue
+ gen.emit_declaration(definition.value)
+
+
+def handle_parse_error(e: UnexpectedInput) -> bool:
+ """Simple parse error reporting, no recovery attempted"""
+ print(e)
+ return True
+
+
+def subcmd(args: Namespace) -> int:
+ """Generate definitions and declarations"""
+
+ set_xdr_annotate(args.annotate)
+ parser = xdr_parser()
+ with open(args.filename, encoding="utf-8") as f:
+ parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
+ ast = transform_parse_tree(parse_tree)
+
+ gen = XdrHeaderTopGenerator(args.language, args.peer)
+ gen.emit_declaration(args.filename, ast)
+
+ emit_header_declarations(ast, args.language, args.peer)
+
+ gen = XdrHeaderBottomGenerator(args.language, args.peer)
+ gen.emit_declaration(args.filename, ast)
+
+ return 0
diff --git a/tools/net/sunrpc/xdrgen/subcmds/definitions.py b/tools/net/sunrpc/xdrgen/subcmds/definitions.py
new file mode 100644
index 000000000000..c956e27f37c0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/subcmds/definitions.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Translate an XDR specification into executable code that
+can be compiled for the Linux kernel."""
+
+import logging
+
+from argparse import Namespace
+from lark import logger
+from lark.exceptions import UnexpectedInput
+
+from generators.constant import XdrConstantGenerator
+from generators.enum import XdrEnumGenerator
+from generators.header_bottom import XdrHeaderBottomGenerator
+from generators.header_top import XdrHeaderTopGenerator
+from generators.pointer import XdrPointerGenerator
+from generators.program import XdrProgramGenerator
+from generators.typedef import XdrTypedefGenerator
+from generators.struct import XdrStructGenerator
+from generators.union import XdrUnionGenerator
+
+from xdr_ast import transform_parse_tree, Specification
+from xdr_ast import _RpcProgram, _XdrConstant, _XdrEnum, _XdrPointer
+from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion
+from xdr_parse import xdr_parser, set_xdr_annotate
+
+logger.setLevel(logging.INFO)
+
+
+def emit_header_definitions(root: Specification, language: str, peer: str) -> None:
+ """Emit header definitions"""
+ for definition in root.definitions:
+ if isinstance(definition.value, _XdrConstant):
+ gen = XdrConstantGenerator(language, peer)
+ elif isinstance(definition.value, _XdrEnum):
+ gen = XdrEnumGenerator(language, peer)
+ elif isinstance(definition.value, _XdrPointer):
+ gen = XdrPointerGenerator(language, peer)
+ elif isinstance(definition.value, _RpcProgram):
+ gen = XdrProgramGenerator(language, peer)
+ elif isinstance(definition.value, _XdrTypedef):
+ gen = XdrTypedefGenerator(language, peer)
+ elif isinstance(definition.value, _XdrStruct):
+ gen = XdrStructGenerator(language, peer)
+ elif isinstance(definition.value, _XdrUnion):
+ gen = XdrUnionGenerator(language, peer)
+ else:
+ continue
+ gen.emit_definition(definition.value)
+
+
+def emit_header_maxsize(root: Specification, language: str, peer: str) -> None:
+ """Emit header maxsize macros"""
+ print("")
+ for definition in root.definitions:
+ if isinstance(definition.value, _XdrEnum):
+ gen = XdrEnumGenerator(language, peer)
+ elif isinstance(definition.value, _XdrPointer):
+ gen = XdrPointerGenerator(language, peer)
+ elif isinstance(definition.value, _XdrTypedef):
+ gen = XdrTypedefGenerator(language, peer)
+ elif isinstance(definition.value, _XdrStruct):
+ gen = XdrStructGenerator(language, peer)
+ elif isinstance(definition.value, _XdrUnion):
+ gen = XdrUnionGenerator(language, peer)
+ else:
+ continue
+ gen.emit_maxsize(definition.value)
+
+
+def handle_parse_error(e: UnexpectedInput) -> bool:
+ """Simple parse error reporting, no recovery attempted"""
+ print(e)
+ return True
+
+
+def subcmd(args: Namespace) -> int:
+ """Generate definitions"""
+
+ set_xdr_annotate(args.annotate)
+ parser = xdr_parser()
+ with open(args.filename, encoding="utf-8") as f:
+ parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
+ ast = transform_parse_tree(parse_tree)
+
+ gen = XdrHeaderTopGenerator(args.language, args.peer)
+ gen.emit_definition(args.filename, ast)
+
+ emit_header_definitions(ast, args.language, args.peer)
+ emit_header_maxsize(ast, args.language, args.peer)
+
+ gen = XdrHeaderBottomGenerator(args.language, args.peer)
+ gen.emit_definition(args.filename, ast)
+
+ return 0
diff --git a/tools/net/sunrpc/xdrgen/subcmds/lint.py b/tools/net/sunrpc/xdrgen/subcmds/lint.py
new file mode 100644
index 000000000000..36cc43717d30
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/subcmds/lint.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Translate an XDR specification into executable code that
+can be compiled for the Linux kernel."""
+
+import logging
+
+from argparse import Namespace
+from lark import logger
+from lark.exceptions import UnexpectedInput
+
+from xdr_parse import xdr_parser
+from xdr_ast import transform_parse_tree
+
+logger.setLevel(logging.DEBUG)
+
+
+def handle_parse_error(e: UnexpectedInput) -> bool:
+ """Simple parse error reporting, no recovery attempted"""
+ print(e)
+ return True
+
+
+def subcmd(args: Namespace) -> int:
+ """Lexical and syntax check of an XDR specification"""
+
+ parser = xdr_parser()
+ with open(args.filename, encoding="utf-8") as f:
+ parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
+ transform_parse_tree(parse_tree)
+
+ return 0
diff --git a/tools/net/sunrpc/xdrgen/subcmds/source.py b/tools/net/sunrpc/xdrgen/subcmds/source.py
new file mode 100644
index 000000000000..2024954748f0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/subcmds/source.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Translate an XDR specification into executable code that
+can be compiled for the Linux kernel."""
+
+import logging
+
+from argparse import Namespace
+from lark import logger
+from lark.exceptions import UnexpectedInput
+
+from generators.source_top import XdrSourceTopGenerator
+from generators.enum import XdrEnumGenerator
+from generators.pointer import XdrPointerGenerator
+from generators.program import XdrProgramGenerator
+from generators.typedef import XdrTypedefGenerator
+from generators.struct import XdrStructGenerator
+from generators.union import XdrUnionGenerator
+
+from xdr_ast import transform_parse_tree, _RpcProgram, Specification
+from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer
+from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion
+
+from xdr_parse import xdr_parser, set_xdr_annotate
+
+logger.setLevel(logging.INFO)
+
+
+def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:
+ """Emit one XDR decoder function for a source file"""
+ if isinstance(node, _XdrEnum):
+ gen = XdrEnumGenerator(language, peer)
+ elif isinstance(node, _XdrPointer):
+ gen = XdrPointerGenerator(language, peer)
+ elif isinstance(node, _XdrTypedef):
+ gen = XdrTypedefGenerator(language, peer)
+ elif isinstance(node, _XdrStruct):
+ gen = XdrStructGenerator(language, peer)
+ elif isinstance(node, _XdrUnion):
+ gen = XdrUnionGenerator(language, peer)
+ elif isinstance(node, _RpcProgram):
+ gen = XdrProgramGenerator(language, peer)
+ else:
+ return
+ gen.emit_decoder(node)
+
+
+def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:
+ """Emit one XDR encoder function for a source file"""
+ if isinstance(node, _XdrEnum):
+ gen = XdrEnumGenerator(language, peer)
+ elif isinstance(node, _XdrPointer):
+ gen = XdrPointerGenerator(language, peer)
+ elif isinstance(node, _XdrTypedef):
+ gen = XdrTypedefGenerator(language, peer)
+ elif isinstance(node, _XdrStruct):
+ gen = XdrStructGenerator(language, peer)
+ elif isinstance(node, _XdrUnion):
+ gen = XdrUnionGenerator(language, peer)
+ elif isinstance(node, _RpcProgram):
+ gen = XdrProgramGenerator(language, peer)
+ else:
+ return
+ gen.emit_encoder(node)
+
+
+def generate_server_source(filename: str, root: Specification, language: str) -> None:
+ """Generate server-side source code"""
+
+ gen = XdrSourceTopGenerator(language, "server")
+ gen.emit_source(filename, root)
+
+ for definition in root.definitions:
+ emit_source_decoder(definition.value, language, "server")
+ for definition in root.definitions:
+ emit_source_encoder(definition.value, language, "server")
+
+
+def generate_client_source(filename: str, root: Specification, language: str) -> None:
+ """Generate server-side source code"""
+
+ gen = XdrSourceTopGenerator(language, "client")
+ gen.emit_source(filename, root)
+
+ print("")
+ for definition in root.definitions:
+ emit_source_encoder(definition.value, language, "client")
+ for definition in root.definitions:
+ emit_source_decoder(definition.value, language, "client")
+
+ # cel: todo: client needs PROC macros
+
+
+def handle_parse_error(e: UnexpectedInput) -> bool:
+ """Simple parse error reporting, no recovery attempted"""
+ print(e)
+ return True
+
+
+def subcmd(args: Namespace) -> int:
+ """Generate encoder and decoder functions"""
+
+ set_xdr_annotate(args.annotate)
+ parser = xdr_parser()
+ with open(args.filename, encoding="utf-8") as f:
+ parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
+ ast = transform_parse_tree(parse_tree)
+ match args.peer:
+ case "server":
+ generate_server_source(args.filename, ast, args.language)
+ case "client":
+ generate_client_source(args.filename, ast, args.language)
+ case _:
+ print("Code generation for", args.peer, "is not yet supported")
+
+ return 0
diff --git a/tools/net/sunrpc/xdrgen/templates/C/constants/definition.j2 b/tools/net/sunrpc/xdrgen/templates/C/constants/definition.j2
new file mode 100644
index 000000000000..d648ca4193f8
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/constants/definition.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+enum { {{ name }} = {{ value }} };
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2
new file mode 100644
index 000000000000..d1405c7c5354
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, {{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2
new file mode 100644
index 000000000000..6482984f1cb7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2
@@ -0,0 +1,19 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* enum {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr)
+{
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ *ptr = val;
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2
new file mode 100644
index 000000000000..44c391c10b42
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2
@@ -0,0 +1,14 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* enum {{ name }} (big-endian) */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr)
+{
+ return xdr_stream_decode_be32(xdr, ptr) == 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j2
new file mode 100644
index 000000000000..a07586cbee17
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+};
+typedef enum {{ name }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j2
new file mode 100644
index 000000000000..2c18948bddf7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+};
+typedef __be32 {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/definition/enumerator.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/enumerator.j2
new file mode 100644
index 000000000000..ff0b893b8b14
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/enumerator.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ {{ name }} = {{ value }},
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/definition/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/open.j2
new file mode 100644
index 000000000000..b25335221d48
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/definition/open.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+enum {{ name }} {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2
new file mode 100644
index 000000000000..67245b9a914d
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2
@@ -0,0 +1,14 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* enum {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, {{ name }} value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2
new file mode 100644
index 000000000000..fbbcc45948d6
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2
@@ -0,0 +1,14 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* enum {{ name }} (big-endian) */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, {{ name }} value)
+{
+ return xdr_stream_encode_be32(xdr, value) == XDR_UNIT;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j2 b/tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j2
new file mode 100644
index 000000000000..45c1d4c21b22
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/header_bottom/declaration/header.j2 b/tools/net/sunrpc/xdrgen/templates/C/header_bottom/declaration/header.j2
new file mode 100644
index 000000000000..0bb8c6fc0c20
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/header_bottom/declaration/header.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+#endif /* _LINUX_XDRGEN_{{ infix }}_DECL_H */
diff --git a/tools/net/sunrpc/xdrgen/templates/C/header_bottom/definition/header.j2 b/tools/net/sunrpc/xdrgen/templates/C/header_bottom/definition/header.j2
new file mode 100644
index 000000000000..69069d08dc91
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/header_bottom/definition/header.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+#endif /* _LINUX_XDRGEN_{{ infix }}_DEF_H */
diff --git a/tools/net/sunrpc/xdrgen/templates/C/header_top/declaration/header.j2 b/tools/net/sunrpc/xdrgen/templates/C/header_top/declaration/header.j2
new file mode 100644
index 000000000000..ebb4e1d32f85
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/header_top/declaration/header.j2
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Generated by xdrgen. Manual edits will be lost. */
+/* XDR specification file: {{ filename }} */
+/* XDR specification modification time: {{ mtime }} */
+
+#ifndef _LINUX_XDRGEN_{{ infix }}_DECL_H
+#define _LINUX_XDRGEN_{{ infix }}_DECL_H
+
+#include <linux/types.h>
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
+#include <linux/sunrpc/xdrgen/_builtins.h>
+#include <linux/sunrpc/xdrgen/{{ infix.lower() }}.h>
diff --git a/tools/net/sunrpc/xdrgen/templates/C/header_top/definition/header.j2 b/tools/net/sunrpc/xdrgen/templates/C/header_top/definition/header.j2
new file mode 100644
index 000000000000..92f1fd4ba024
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/header_top/definition/header.j2
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Generated by xdrgen. Manual edits will be lost. */
+/* XDR specification file: {{ filename }} */
+/* XDR specification modification time: {{ mtime }} */
+
+#ifndef _LINUX_XDRGEN_{{ infix }}_DEF_H
+#define _LINUX_XDRGEN_{{ infix }}_DEF_H
+
+#include <linux/types.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/declaration/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/declaration/close.j2
new file mode 100644
index 000000000000..816291184e8c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/declaration/close.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/basic.j2
new file mode 100644
index 000000000000..cde4ab53f4be
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/basic.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/close.j2
new file mode 100644
index 000000000000..3dbd724d7f17
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/close.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_array.j2
new file mode 100644
index 000000000000..cfd64217ad82
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_array.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+ if (xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.items[i]) < 0)
+ return false;
+ }
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..b4695ece1884
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/fixed_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length opaque) */
+{% endif %}
+ if (xdr_stream_decode_opaque_fixed(xdr, ptr->{{ name }}, {{ size }}) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j2
new file mode 100644
index 000000000000..c093d9e3c9ad
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j2
@@ -0,0 +1,22 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* pointer {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr)
+{
+ bool opted;
+
+{% if annotate %}
+ /* opted */
+{% endif %}
+ if (!xdrgen_decode_bool(xdr, &opted))
+ return false;
+ if (!opted)
+ return true;
+
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/optional_data.j2
new file mode 100644
index 000000000000..b6834299a04b
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/optional_data.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (optional data) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, ptr->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2
new file mode 100644
index 000000000000..12d20b143b43
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (!xdrgen_decode_string(xdr, (string *)ptr, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_array.j2
new file mode 100644
index 000000000000..2f943909cdf7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_array.j2
@@ -0,0 +1,13 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length array) */
+{% endif %}
+ if (xdr_stream_decode_u32(xdr, &ptr->{{ name }}.count) < 0)
+ return false;
+{% if maxsize != "0" %}
+ if (ptr->{{ name }}.count > {{ maxsize }})
+ return false;
+{% endif %}
+ for (u32 i = 0; i < ptr->{{ name }}.count; i++)
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.element[i]))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..9a814de54ae8
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length opaque) */
+{% endif %}
+ if (!xdrgen_decode_opaque(xdr, (opaque *)ptr, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/basic.j2
new file mode 100644
index 000000000000..b3430895f311
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/basic.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (basic) */
+{% endif %}
+ {{ classifier }}{{ type }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/close.j2
new file mode 100644
index 000000000000..9e62344a976a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/close.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_array.j2
new file mode 100644
index 000000000000..66be836826a0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_array.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (fixed-length array) */
+{% endif %}
+ {{ type }} {{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_opaque.j2
new file mode 100644
index 000000000000..0daba19aa0f0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/fixed_length_opaque.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (fixed-length opaque) */
+{% endif %}
+ u8 {{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/open.j2
new file mode 100644
index 000000000000..bc886b818d85
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/open.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* pointer {{ name }} */
+{% endif %}
+struct {{ name }} {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/optional_data.j2
new file mode 100644
index 000000000000..a33341f45e8f
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/optional_data.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (optional data) */
+{% endif %}
+ {{ classifier }}{{ type }} *{{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2
new file mode 100644
index 000000000000..2de2feec77db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length string) */
+{% endif %}
+ string {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_array.j2
new file mode 100644
index 000000000000..5d767f9b3674
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_array.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length array) */
+{% endif %}
+ struct {
+ u32 count;
+ {{ classifier }}{{ type }} *element;
+ } {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_opaque.j2
new file mode 100644
index 000000000000..4d0cd84be3db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_opaque.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length opaque) */
+{% endif %}
+ opaque {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j2
new file mode 100644
index 000000000000..a7d3695c5a6a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j2
@@ -0,0 +1,10 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
+{% endif %}
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/close.j2
new file mode 100644
index 000000000000..3dbd724d7f17
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/close.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_array.j2
new file mode 100644
index 000000000000..b01833a2c7a1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_array.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+{% if type in pass_by_reference %}
+ if (xdrgen_encode_{{ type }}(xdr, &value->items[i]) < 0)
+{% else %}
+ if (xdrgen_encode_{{ type }}(xdr, value->items[i]) < 0)
+{% endif %}
+ return false;
+ }
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..07bc91919898
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/fixed_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length opaque) */
+{% endif %}
+ if (xdr_stream_encode_opaque_fixed(xdr, value->{{ name }}, {{ size }}) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j2
new file mode 100644
index 000000000000..d67fae200261
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j2
@@ -0,0 +1,20 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* pointer {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value)
+{
+{% if annotate %}
+ /* opted */
+{% endif %}
+ if (!xdrgen_encode_bool(xdr, value != NULL))
+ return false;
+ if (!value)
+ return true;
+
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/optional_data.j2
new file mode 100644
index 000000000000..16fb3e09bba1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/optional_data.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (optional data) */
+{% endif %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2
new file mode 100644
index 000000000000..cf65b71eaef3
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (value->{{ name }}.len > {{ maxsize }})
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_array.j2
new file mode 100644
index 000000000000..b21476629679
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_array.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length array) */
+{% endif %}
+{% if maxsize != "0" %}
+ if (value->{{ name }}.count > {{ maxsize }})
+ return false;
+{% endif %}
+ if (xdr_stream_encode_u32(xdr, value->{{ name }}.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->{{ name }}.count; i++)
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}.element[i]))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}.element[i]))
+{% endif %}
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..1d477c2d197a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_opaque.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length opaque) */
+{% endif %}
+ if (value->{{ name }}.len > {{ maxsize }})
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j2 b/tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j2
new file mode 100644
index 000000000000..9f3bfb47d2f4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} \
+ ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/declaration/argument.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/declaration/argument.j2
new file mode 100644
index 000000000000..4364fed19162
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/declaration/argument.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_stream *xdr);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/declaration/result.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/declaration/result.j2
new file mode 100644
index 000000000000..e0ea1e849910
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/declaration/result.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_stream *xdr);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/decoder/argument.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/decoder/argument.j2
new file mode 100644
index 000000000000..0b1709cca0d4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/decoder/argument.j2
@@ -0,0 +1,21 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+/**
+ * {{ program }}_svc_decode_{{ argument }} - Decode a {{ argument }} argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+{% if argument == 'void' %}
+ return xdrgen_decode_void(xdr);
+{% else %}
+ struct {{ argument }} *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_{{ argument }}(xdr, argp);
+{% endif %}
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j2
new file mode 100644
index 000000000000..aa9940e322db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j2
@@ -0,0 +1,18 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* Decode {{ result }} results */
+{% endif %}
+static int {{ program }}_xdr_dec_{{ result }}(struct rpc_rqst *req,
+ struct xdr_stream *xdr, void *data)
+{
+{% if result == 'void' %}
+ xdrgen_decode_void(xdr);
+{% else %}
+ struct {{ result }} *result = data;
+
+ if (!xdrgen_decode_{{ result }}(xdr, result))
+ return -EIO;
+{% endif %}
+ return 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/definition/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/definition/close.j2
new file mode 100644
index 000000000000..9e62344a976a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/definition/close.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/definition/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/definition/open.j2
new file mode 100644
index 000000000000..f9a6d439f156
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/definition/open.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* procedure numbers for {{ program }} */
+{% endif %}
+enum {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/definition/procedure.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/definition/procedure.j2
new file mode 100644
index 000000000000..ff0b893b8b14
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/definition/procedure.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ {{ name }} = {{ value }},
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/encoder/argument.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/encoder/argument.j2
new file mode 100644
index 000000000000..2fbb5bd13aec
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/encoder/argument.j2
@@ -0,0 +1,16 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{%if annotate %}
+/* Encode {{ argument }} arguments */
+{% endif %}
+static void {{ program }}_xdr_enc_{{ argument }}(struct rpc_rqst *req,
+ struct xdr_stream *xdr, const void *data)
+{
+{% if argument == 'void' %}
+ xdrgen_encode_void(xdr);
+{% else %}
+ const struct {{ argument }} *args = data;
+
+ xdrgen_encode_{{ argument }}(xdr, args);
+{% endif %}
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/program/encoder/result.j2 b/tools/net/sunrpc/xdrgen/templates/C/program/encoder/result.j2
new file mode 100644
index 000000000000..6fc61a5d47b7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/program/encoder/result.j2
@@ -0,0 +1,21 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+/**
+ * {{ program }}_svc_encode_{{ result }} - Encode a {{ result }} result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ * %true: procedure results encoded successfully
+ * %false: encode failed
+ */
+bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+{% if result == 'void' %}
+ return xdrgen_encode_void(xdr);
+{% else %}
+ struct {{ result }} *resp = rqstp->rq_resp;
+
+ return xdrgen_encode_{{ result }}(xdr, resp);
+{% endif %}
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2 b/tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2
new file mode 100644
index 000000000000..c5518c519854
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+// Generated by xdrgen. Manual edits will be lost.
+// XDR specification file: {{ filename }}
+// XDR specification modification time: {{ mtime }}
+
+#include <linux/types.h>
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
+#include <linux/sunrpc/xdrgen/_builtins.h>
+#include <linux/sunrpc/xdrgen/nlm4.h>
+
+#include <linux/sunrpc/clnt.h>
diff --git a/tools/net/sunrpc/xdrgen/templates/C/source_top/server.j2 b/tools/net/sunrpc/xdrgen/templates/C/source_top/server.j2
new file mode 100644
index 000000000000..974e1d971e5d
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/source_top/server.j2
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+// Generated by xdrgen. Manual edits will be lost.
+// XDR specification file: {{ filename }}
+// XDR specification modification time: {{ mtime }}
+
+#include <linux/sunrpc/svc.h>
+
+#include "{{ program }}xdr_gen.h"
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/declaration/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/declaration/close.j2
new file mode 100644
index 000000000000..816291184e8c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/declaration/close.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/basic.j2
new file mode 100644
index 000000000000..cde4ab53f4be
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/basic.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/close.j2
new file mode 100644
index 000000000000..3dbd724d7f17
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/close.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_array.j2
new file mode 100644
index 000000000000..cfd64217ad82
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_array.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+ if (xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.items[i]) < 0)
+ return false;
+ }
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..b4695ece1884
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/fixed_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length opaque) */
+{% endif %}
+ if (xdr_stream_decode_opaque_fixed(xdr, ptr->{{ name }}, {{ size }}) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j2
new file mode 100644
index 000000000000..289e67259f55
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* struct {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr)
+{
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/optional_data.j2
new file mode 100644
index 000000000000..b6834299a04b
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/optional_data.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (optional data) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, ptr->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2
new file mode 100644
index 000000000000..12d20b143b43
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (!xdrgen_decode_string(xdr, (string *)ptr, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_array.j2
new file mode 100644
index 000000000000..2f943909cdf7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_array.j2
@@ -0,0 +1,13 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length array) */
+{% endif %}
+ if (xdr_stream_decode_u32(xdr, &ptr->{{ name }}.count) < 0)
+ return false;
+{% if maxsize != "0" %}
+ if (ptr->{{ name }}.count > {{ maxsize }})
+ return false;
+{% endif %}
+ for (u32 i = 0; i < ptr->{{ name }}.count; i++)
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.element[i]))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..65698e20d8cd
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length opaque) */
+{% endif %}
+ if (!xdrgen_decode_opaque(xdr, &ptr->{{ name }}, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/basic.j2
new file mode 100644
index 000000000000..b3430895f311
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/basic.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (basic) */
+{% endif %}
+ {{ classifier }}{{ type }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/close.j2
new file mode 100644
index 000000000000..9e62344a976a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/close.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_array.j2
new file mode 100644
index 000000000000..66be836826a0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_array.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (fixed-length array) */
+{% endif %}
+ {{ type }} {{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_opaque.j2
new file mode 100644
index 000000000000..0daba19aa0f0
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/fixed_length_opaque.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (fixed-length opaque) */
+{% endif %}
+ u8 {{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/open.j2
new file mode 100644
index 000000000000..07cbf5424546
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/open.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* struct {{ name }} */
+{% endif %}
+struct {{ name }} {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/optional_data.j2
new file mode 100644
index 000000000000..a33341f45e8f
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/optional_data.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (optional data) */
+{% endif %}
+ {{ classifier }}{{ type }} *{{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2
new file mode 100644
index 000000000000..2de2feec77db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length string) */
+{% endif %}
+ string {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_array.j2
new file mode 100644
index 000000000000..5d767f9b3674
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_array.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length array) */
+{% endif %}
+ struct {
+ u32 count;
+ {{ classifier }}{{ type }} *element;
+ } {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_opaque.j2
new file mode 100644
index 000000000000..4d0cd84be3db
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_opaque.j2
@@ -0,0 +1,5 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* (variable-length opaque) */
+{% endif %}
+ opaque {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j2
new file mode 100644
index 000000000000..a7d3695c5a6a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j2
@@ -0,0 +1,10 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
+{% endif %}
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/close.j2
new file mode 100644
index 000000000000..3dbd724d7f17
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/close.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_array.j2
new file mode 100644
index 000000000000..b01833a2c7a1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_array.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+{% if type in pass_by_reference %}
+ if (xdrgen_encode_{{ type }}(xdr, &value->items[i]) < 0)
+{% else %}
+ if (xdrgen_encode_{{ type }}(xdr, value->items[i]) < 0)
+{% endif %}
+ return false;
+ }
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..07bc91919898
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/fixed_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (fixed-length opaque) */
+{% endif %}
+ if (xdr_stream_encode_opaque_fixed(xdr, value->{{ name }}, {{ size }}) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j2
new file mode 100644
index 000000000000..2286a3adf82a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* struct {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value)
+{
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/optional_data.j2
new file mode 100644
index 000000000000..16fb3e09bba1
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/optional_data.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (optional data) */
+{% endif %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2
new file mode 100644
index 000000000000..cf65b71eaef3
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (value->{{ name }}.len > {{ maxsize }})
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_array.j2
new file mode 100644
index 000000000000..b21476629679
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_array.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length array) */
+{% endif %}
+{% if maxsize != "0" %}
+ if (value->{{ name }}.count > {{ maxsize }})
+ return false;
+{% endif %}
+ if (xdr_stream_encode_u32(xdr, value->{{ name }}.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value->{{ name }}.count; i++)
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}.element[i]))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}.element[i]))
+{% endif %}
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..1d477c2d197a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_opaque.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length opaque) */
+{% endif %}
+ if (value->{{ name }}.len > {{ maxsize }})
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j2 b/tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j2
new file mode 100644
index 000000000000..9f3bfb47d2f4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} \
+ ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/basic.j2
new file mode 100644
index 000000000000..455b10bd90ec
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/basic.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr);
+{% if name in pass_by_reference %}
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ name }} *value);
+{%- else -%}
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ name }} value);
+{% endif %}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_array.j2
new file mode 100644
index 000000000000..3fe3ddd9f359
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_array.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_opaque.j2
new file mode 100644
index 000000000000..3fe3ddd9f359
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/fixed_length_opaque.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2
new file mode 100644
index 000000000000..3fe3ddd9f359
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_array.j2
new file mode 100644
index 000000000000..3fe3ddd9f359
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_array.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_opaque.j2
new file mode 100644
index 000000000000..3fe3ddd9f359
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_opaque.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/basic.j2
new file mode 100644
index 000000000000..b215e157dfa7
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/basic.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr)
+{
+{% if annotate %}
+ /* (basic) */
+{% endif %}
+ return xdrgen_decode_{{ type }}(xdr, ptr);
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_array.j2
new file mode 100644
index 000000000000..c8953719e626
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_array.j2
@@ -0,0 +1,25 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr)
+{
+{% if annotate %}
+ /* (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+{%- if classifier == '' %}
+ if (xdrgen_decode_{{ type }}(xdr, ptr->items[i]) < 0)
+{% else %}
+ if (xdrgen_decode_{{ type }}(xdr, &ptr->items[i]) < 0)
+{% endif %}
+ return false;
+ }
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..c854fc8c74e3
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/fixed_length_opaque.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr)
+{
+{% if annotate %}
+ /* (fixed-length opaque) */
+{% endif %}
+ return xdr_stream_decode_opaque_fixed(xdr, ptr, {{ size }}) == 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2
new file mode 100644
index 000000000000..bcbc1758aae9
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr)
+{
+{% if annotate %}
+ /* (variable-length string) */
+{% endif %}
+ return xdrgen_decode_string(xdr, ptr, {{ maxsize }});
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_array.j2
new file mode 100644
index 000000000000..a59cc1f38eed
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_array.j2
@@ -0,0 +1,26 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr)
+{
+{% if annotate %}
+ /* (variable-length array) */
+{% endif %}
+ if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
+ return false;
+{% if maxsize != "0" %}
+ if (ptr->count > {{ maxsize }})
+ return false;
+{% endif %}
+ for (u32 i = 0; i < ptr->count; i++)
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->element[i]))
+ return false;
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..eb05f53e1041
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_opaque.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ classifier }}{{ name }} *ptr)
+{
+{% if annotate %}
+ /* (variable-length opaque) */
+{% endif %}
+ return xdrgen_decode_opaque(xdr, ptr, {{ maxsize }});
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/basic.j2
new file mode 100644
index 000000000000..1c5f28135eec
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/basic.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (basic) */
+{% endif %}
+typedef {{ classifier }}{{ type }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_array.j2
new file mode 100644
index 000000000000..c3a67c952e77
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_array.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (fixed-length array) */
+{% endif %}
+typedef {{ type }}{{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_opaque.j2
new file mode 100644
index 000000000000..8788b02fe4f5
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/fixed_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (fixed-length opaque) */
+{% endif %}
+typedef u8 {{ name }}[{{ size }}];
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2
new file mode 100644
index 000000000000..c03c2df8e625
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (variable-length string) */
+{% endif %}
+typedef string {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_array.j2
new file mode 100644
index 000000000000..f03393760545
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_array.j2
@@ -0,0 +1,9 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (variable-length array) */
+{% endif %}
+typedef struct {
+ u32 count;
+ {{ classifier }}{{ type }} *element;
+} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_opaque.j2
new file mode 100644
index 000000000000..162f2610af34
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} (variable-length opaque) */
+{% endif %}
+typedef opaque {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/basic.j2
new file mode 100644
index 000000000000..0d21dd0b723a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/basic.j2
@@ -0,0 +1,21 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+{% if name in pass_by_reference %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} *value)
+{% else %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{% endif %}
+{
+{% if annotate %}
+ /* (basic) */
+{% endif %}
+ return xdrgen_encode_{{ type }}(xdr, value);
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_array.j2
new file mode 100644
index 000000000000..ec8cd6509514
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_array.j2
@@ -0,0 +1,25 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{
+{% if annotate %}
+ /* (fixed-length array) */
+{% endif %}
+ for (u32 i = 0; i < {{ size }}; i++) {
+{% if type in pass_by_reference %}
+ if (xdrgen_encode_{{ type }}(xdr, &value->items[i]) < 0)
+{% else %}
+ if (xdrgen_encode_{{ type }}(xdr, value->items[i]) < 0)
+{% endif %}
+ return false;
+ }
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_opaque.j2
new file mode 100644
index 000000000000..b53fa87e1858
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/fixed_length_opaque.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{
+{% if annotate %}
+ /* (fixed-length opaque) */
+{% endif %}
+ return xdr_stream_encode_opaque_fixed(xdr, value, {{ size }}) >= 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2
new file mode 100644
index 000000000000..28b81f1d0bd6
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{
+{% if annotate %}
+ /* (variable-length string) */
+{% endif %}
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_array.j2
new file mode 100644
index 000000000000..ff093c281d51
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_array.j2
@@ -0,0 +1,30 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{
+{% if annotate %}
+ /* (variable-length array) */
+{% endif %}
+{% if maxsize != "0" %}
+ if (unlikely(value.count > {{ maxsize }}))
+ return false;
+{% endif %}
+ if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
+ return false;
+ for (u32 i = 0; i < value.count; i++)
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &value.element[i]))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, value.element[i]))
+{% endif %}
+ return false;
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..2e89592fa702
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_opaque.j2
@@ -0,0 +1,17 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* typedef {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const {{ classifier }}{{ name }} value)
+{
+{% if annotate %}
+ /* (variable-length opaque) */
+{% endif %}
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j2
new file mode 100644
index 000000000000..9f3bfb47d2f4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} \
+ ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j2
new file mode 100644
index 000000000000..45c1d4c21b22
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j2
new file mode 100644
index 000000000000..45c1d4c21b22
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j2
new file mode 100644
index 000000000000..45c1d4c21b22
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j2
new file mode 100644
index 000000000000..45c1d4c21b22
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/declaration/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/declaration/close.j2
new file mode 100644
index 000000000000..816291184e8c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/declaration/close.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value);
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/basic.j2
new file mode 100644
index 000000000000..4d97cc5395eb
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/basic.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->u.{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/break.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/break.j2
new file mode 100644
index 000000000000..b286d1407029
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/break.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ break;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec.j2
new file mode 100644
index 000000000000..5fa2163f0a74
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ case {{ case }}:
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j2
new file mode 100644
index 000000000000..917f3a1c4588
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ case __constant_cpu_to_be32({{ case }}):
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/close.j2
new file mode 100644
index 000000000000..39d8d6c5094d
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/close.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ }
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/default_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/default_spec.j2
new file mode 100644
index 000000000000..044a002d0589
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/default_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ default:
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/open.j2
new file mode 100644
index 000000000000..eb9941376e49
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/open.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* union {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr)
+{
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/optional_data.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/optional_data.j2
new file mode 100644
index 000000000000..e4476f5fd8d3
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/optional_data.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (optional data) */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->u.{{ name }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2
new file mode 100644
index 000000000000..83b6e5a14e7f
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (!xdrgen_decode_string(xdr, (struct string *)ptr->u.{{ name }}, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/switch_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/switch_spec.j2
new file mode 100644
index 000000000000..99b3067ef617
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/switch_spec.j2
@@ -0,0 +1,7 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* discriminant {{ name }} */
+{% endif %}
+ if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}))
+ return false;
+ switch (ptr->{{ name }}) {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_array.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_array.j2
new file mode 100644
index 000000000000..53dfaf9cec68
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_array.j2
@@ -0,0 +1,15 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length array) */
+{% endif %}
+ if (xdr_stream_decode_u32(xdr, &count) < 0)
+ return false;
+{% if maxsize != "0" %}
+ if (count > {{ maxsize }})
+ return false;
+{% endif %}
+ for (u32 i = 0; i < count; i++) {
+ if (xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.items[i]) < 0)
+ return false;
+ }
+ ptr->{{ name }}.len = count;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_opaque.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_opaque.j2
new file mode 100644
index 000000000000..c9d88ed29c78
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_opaque.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length opaque) */
+{% endif %}
+ if (!xdrgen_decode_opaque(xdr, (struct opaque *)ptr->u.{{ name }}, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/decoder/void.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/void.j2
new file mode 100644
index 000000000000..65205ce37b36
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/decoder/void.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ if (!xdrgen_decode_void(xdr))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/definition/case_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/definition/case_spec.j2
new file mode 100644
index 000000000000..52f8d131b805
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/definition/case_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ {{ classifier }}{{ type }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/definition/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/definition/close.j2
new file mode 100644
index 000000000000..01d716d0099e
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/definition/close.j2
@@ -0,0 +1,8 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ } u;
+};
+{%- if name in public_apis %}
+
+bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
+bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *ptr);
+{%- endif -%}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/definition/default_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/definition/default_spec.j2
new file mode 100644
index 000000000000..52f8d131b805
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/definition/default_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ {{ classifier }}{{ type }} {{ name }};
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/definition/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/definition/open.j2
new file mode 100644
index 000000000000..20fcfd1fc4e5
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/definition/open.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* union {{ name }} */
+{% endif %}
+struct {{ name }} {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/definition/switch_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/definition/switch_spec.j2
new file mode 100644
index 000000000000..3e552732502c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/definition/switch_spec.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ {{ classifier }}{{ type }} {{ name }};
+ union {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/basic.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/basic.j2
new file mode 100644
index 000000000000..6452d75c6f9a
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/basic.j2
@@ -0,0 +1,10 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (basic) */
+{% endif %}
+{% if type in pass_by_reference %}
+ if (!xdrgen_encode_{{ type }}(xdr, &ptr->u.{{ name }}))
+{% else %}
+ if (!xdrgen_encode_{{ type }}(xdr, ptr->u.{{ name }}))
+{% endif %}
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/break.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/break.j2
new file mode 100644
index 000000000000..b286d1407029
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/break.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ break;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec.j2
new file mode 100644
index 000000000000..5fa2163f0a74
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ case {{ case }}:
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j2
new file mode 100644
index 000000000000..917f3a1c4588
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ case __constant_cpu_to_be32({{ case }}):
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/close.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/close.j2
new file mode 100644
index 000000000000..39d8d6c5094d
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/close.j2
@@ -0,0 +1,4 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ }
+ return true;
+}
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/default_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/default_spec.j2
new file mode 100644
index 000000000000..044a002d0589
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/default_spec.j2
@@ -0,0 +1,2 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ default:
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/open.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/open.j2
new file mode 100644
index 000000000000..e5a206df10c6
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/open.j2
@@ -0,0 +1,12 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+
+{% if annotate %}
+/* union {{ name }} */
+{% endif %}
+{% if name in public_apis %}
+bool
+{% else %}
+static bool __maybe_unused
+{% endif %}
+xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *ptr)
+{
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/string.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/string.j2
new file mode 100644
index 000000000000..2f035a64f1f4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/string.j2
@@ -0,0 +1,6 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* member {{ name }} (variable-length string) */
+{% endif %}
+ if (!xdrgen_encode_string(xdr, ptr->u.{{ name }}, {{ maxsize }}))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/switch_spec.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/switch_spec.j2
new file mode 100644
index 000000000000..c8c3ecbe038b
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/switch_spec.j2
@@ -0,0 +1,7 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+{% if annotate %}
+ /* discriminant {{ name }} */
+{% endif %}
+ if (!xdrgen_encode_{{ type }}(xdr, ptr->{{ name }}))
+ return false;
+ switch (ptr->{{ name }}) {
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/encoder/void.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/void.j2
new file mode 100644
index 000000000000..84e7c2127d75
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/encoder/void.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+ if (!xdrgen_encode_void(xdr))
+ return false;
diff --git a/tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j2 b/tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j2
new file mode 100644
index 000000000000..9f3bfb47d2f4
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j2
@@ -0,0 +1,3 @@
+{# SPDX-License-Identifier: GPL-2.0 #}
+#define {{ '{:<31}'.format(macro) }} \
+ ({{ width }})
diff --git a/tools/net/sunrpc/xdrgen/tests/test.x b/tools/net/sunrpc/xdrgen/tests/test.x
new file mode 100644
index 000000000000..90c8587f6fe5
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/tests/test.x
@@ -0,0 +1,36 @@
+/* Sample XDR specification from RFC 1832 Section 5.5 */
+
+const MAXUSERNAME = 32; /* max length of a user name */
+const MAXFILELEN = 65535; /* max length of a file */
+const MAXNAMELEN = 255; /* max length of a file name */
+
+/*
+ * Types of files:
+ */
+enum filekind {
+ TEXT = 0, /* ascii data */
+ DATA = 1, /* raw data */
+ EXEC = 2 /* executable */
+};
+
+/*
+ * File information, per kind of file:
+ */
+union filetype switch (filekind kind) {
+case TEXT:
+ void; /* no extra information */
+case DATA:
+ string creator<MAXNAMELEN>; /* data creator */
+case EXEC:
+ string interpretor<MAXNAMELEN>; /* program interpretor */
+};
+
+/*
+ * A complete file:
+ */
+struct file {
+ string filename<MAXNAMELEN>; /* name of file */
+ filetype type; /* info about file */
+ string owner<MAXUSERNAME>; /* owner of file */
+ opaque data<MAXFILELEN>; /* file data */
+};
diff --git a/tools/net/sunrpc/xdrgen/xdr_ast.py b/tools/net/sunrpc/xdrgen/xdr_ast.py
new file mode 100644
index 000000000000..5233e73c7046
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/xdr_ast.py
@@ -0,0 +1,753 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Define and implement the Abstract Syntax Tree for the XDR language."""
+
+import sys
+from typing import List
+from dataclasses import dataclass
+
+from lark import ast_utils, Transformer
+from lark.tree import Meta
+
+this_module = sys.modules[__name__]
+
+big_endian = []
+excluded_apis = []
+header_name = "none"
+public_apis = []
+structs = set()
+pass_by_reference = set()
+
+constants = {}
+
+
+def xdr_quadlen(val: str) -> int:
+ """Return integer XDR width of an XDR type"""
+ if val in constants:
+ octets = constants[val]
+ else:
+ octets = int(val)
+ return int((octets + 3) / 4)
+
+
+symbolic_widths = {
+ "void": ["XDR_void"],
+ "bool": ["XDR_bool"],
+ "int": ["XDR_int"],
+ "unsigned_int": ["XDR_unsigned_int"],
+ "long": ["XDR_long"],
+ "unsigned_long": ["XDR_unsigned_long"],
+ "hyper": ["XDR_hyper"],
+ "unsigned_hyper": ["XDR_unsigned_hyper"],
+}
+
+# Numeric XDR widths are tracked in a dictionary that is keyed
+# by type_name because sometimes a caller has nothing more than
+# the type_name to use to figure out the numeric width.
+max_widths = {
+ "void": 0,
+ "bool": 1,
+ "int": 1,
+ "unsigned_int": 1,
+ "long": 1,
+ "unsigned_long": 1,
+ "hyper": 2,
+ "unsigned_hyper": 2,
+}
+
+
+@dataclass
+class _XdrAst(ast_utils.Ast):
+ """Base class for the XDR abstract syntax tree"""
+
+
+@dataclass
+class _XdrIdentifier(_XdrAst):
+ """Corresponds to 'identifier' in the XDR language grammar"""
+
+ symbol: str
+
+
+@dataclass
+class _XdrValue(_XdrAst):
+ """Corresponds to 'value' in the XDR language grammar"""
+
+ value: str
+
+
+@dataclass
+class _XdrConstantValue(_XdrAst):
+ """Corresponds to 'constant' in the XDR language grammar"""
+
+ value: int
+
+
+@dataclass
+class _XdrTypeSpecifier(_XdrAst):
+ """Corresponds to 'type_specifier' in the XDR language grammar"""
+
+ type_name: str
+ c_classifier: str = ""
+
+
+@dataclass
+class _XdrDefinedType(_XdrTypeSpecifier):
+ """Corresponds to a type defined by the input specification"""
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return [get_header_name().upper() + "_" + self.type_name + "_sz"]
+
+ def __post_init__(self):
+ if self.type_name in structs:
+ self.c_classifier = "struct "
+ symbolic_widths[self.type_name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrBuiltInType(_XdrTypeSpecifier):
+ """Corresponds to a built-in XDR type"""
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return symbolic_widths[self.type_name]
+
+
+@dataclass
+class _XdrDeclaration(_XdrAst):
+ """Base class of XDR type declarations"""
+
+
+@dataclass
+class _XdrFixedLengthOpaque(_XdrDeclaration):
+ """A fixed-length opaque declaration"""
+
+ name: str
+ size: str
+ template: str = "fixed_length_opaque"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return xdr_quadlen(self.size)
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return ["XDR_QUADLEN(" + self.size + ")"]
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrVariableLengthOpaque(_XdrDeclaration):
+ """A variable-length opaque declaration"""
+
+ name: str
+ maxsize: str
+ template: str = "variable_length_opaque"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 1 + xdr_quadlen(self.maxsize)
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ widths = ["XDR_unsigned_int"]
+ if self.maxsize != "0":
+ widths.append("XDR_QUADLEN(" + self.maxsize + ")")
+ return widths
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrString(_XdrDeclaration):
+ """A (NUL-terminated) variable-length string declaration"""
+
+ name: str
+ maxsize: str
+ template: str = "string"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 1 + xdr_quadlen(self.maxsize)
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ widths = ["XDR_unsigned_int"]
+ if self.maxsize != "0":
+ widths.append("XDR_QUADLEN(" + self.maxsize + ")")
+ return widths
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrFixedLengthArray(_XdrDeclaration):
+ """A fixed-length array declaration"""
+
+ name: str
+ spec: _XdrTypeSpecifier
+ size: str
+ template: str = "fixed_length_array"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return xdr_quadlen(self.size) * max_widths[self.spec.type_name]
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ item_width = " + ".join(symbolic_widths[self.spec.type_name])
+ return ["(" + self.size + " * (" + item_width + "))"]
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrVariableLengthArray(_XdrDeclaration):
+ """A variable-length array declaration"""
+
+ name: str
+ spec: _XdrTypeSpecifier
+ maxsize: str
+ template: str = "variable_length_array"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 1 + (xdr_quadlen(self.maxsize) * max_widths[self.spec.type_name])
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ widths = ["XDR_unsigned_int"]
+ if self.maxsize != "0":
+ item_width = " + ".join(symbolic_widths[self.spec.type_name])
+ widths.append("(" + self.maxsize + " * (" + item_width + "))")
+ return widths
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrOptionalData(_XdrDeclaration):
+ """An 'optional_data' declaration"""
+
+ name: str
+ spec: _XdrTypeSpecifier
+ template: str = "optional_data"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 1
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return ["XDR_bool"]
+
+ def __post_init__(self):
+ structs.add(self.name)
+ pass_by_reference.add(self.name)
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrBasic(_XdrDeclaration):
+ """A 'basic' declaration"""
+
+ name: str
+ spec: _XdrTypeSpecifier
+ template: str = "basic"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return max_widths[self.spec.type_name]
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return symbolic_widths[self.spec.type_name]
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrVoid(_XdrDeclaration):
+ """A void declaration"""
+
+ name: str = "void"
+ template: str = "void"
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 0
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return []
+
+
+@dataclass
+class _XdrConstant(_XdrAst):
+ """Corresponds to 'constant_def' in the grammar"""
+
+ name: str
+ value: str
+
+ def __post_init__(self):
+ if self.value not in constants:
+ constants[self.name] = int(self.value, 0)
+
+
+@dataclass
+class _XdrEnumerator(_XdrAst):
+ """An 'identifier = value' enumerator"""
+
+ name: str
+ value: str
+
+ def __post_init__(self):
+ if self.value not in constants:
+ constants[self.name] = int(self.value, 0)
+
+
+@dataclass
+class _XdrEnum(_XdrAst):
+ """An XDR enum definition"""
+
+ name: str
+ minimum: int
+ maximum: int
+ enumerators: List[_XdrEnumerator]
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return 1
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return ["XDR_int"]
+
+ def __post_init__(self):
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrStruct(_XdrAst):
+ """An XDR struct definition"""
+
+ name: str
+ fields: List[_XdrDeclaration]
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ width = 0
+ for field in self.fields:
+ width += field.max_width()
+ return width
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ widths = []
+ for field in self.fields:
+ widths += field.symbolic_width()
+ return widths
+
+ def __post_init__(self):
+ structs.add(self.name)
+ pass_by_reference.add(self.name)
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrPointer(_XdrAst):
+ """An XDR pointer definition"""
+
+ name: str
+ fields: List[_XdrDeclaration]
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ width = 1
+ for field in self.fields[0:-1]:
+ width += field.max_width()
+ return width
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ widths = []
+ widths += ["XDR_bool"]
+ for field in self.fields[0:-1]:
+ widths += field.symbolic_width()
+ return widths
+
+ def __post_init__(self):
+ structs.add(self.name)
+ pass_by_reference.add(self.name)
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrTypedef(_XdrAst):
+ """An XDR typedef"""
+
+ declaration: _XdrDeclaration
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ return self.declaration.max_width()
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ return self.declaration.symbolic_width()
+
+ def __post_init__(self):
+ if isinstance(self.declaration, _XdrBasic):
+ new_type = self.declaration
+ if isinstance(new_type.spec, _XdrDefinedType):
+ if new_type.spec.type_name in pass_by_reference:
+ pass_by_reference.add(new_type.name)
+ max_widths[new_type.name] = self.max_width()
+ symbolic_widths[new_type.name] = self.symbolic_width()
+
+
+@dataclass
+class _XdrCaseSpec(_XdrAst):
+ """One case in an XDR union"""
+
+ values: List[str]
+ arm: _XdrDeclaration
+ template: str = "case_spec"
+
+
+@dataclass
+class _XdrDefaultSpec(_XdrAst):
+ """Default case in an XDR union"""
+
+ arm: _XdrDeclaration
+ template: str = "default_spec"
+
+
+@dataclass
+class _XdrUnion(_XdrAst):
+ """An XDR union"""
+
+ name: str
+ discriminant: _XdrDeclaration
+ cases: List[_XdrCaseSpec]
+ default: _XdrDeclaration
+
+ def max_width(self) -> int:
+ """Return width of type in XDR_UNITS"""
+ max_width = 0
+ for case in self.cases:
+ if case.arm.max_width() > max_width:
+ max_width = case.arm.max_width()
+ if self.default:
+ if self.default.arm.max_width() > max_width:
+ max_width = self.default.arm.max_width()
+ return 1 + max_width
+
+ def symbolic_width(self) -> List:
+ """Return list containing XDR width of type's components"""
+ max_width = 0
+ for case in self.cases:
+ if case.arm.max_width() > max_width:
+ max_width = case.arm.max_width()
+ width = case.arm.symbolic_width()
+ if self.default:
+ if self.default.arm.max_width() > max_width:
+ max_width = self.default.arm.max_width()
+ width = self.default.arm.symbolic_width()
+ return symbolic_widths[self.discriminant.name] + width
+
+ def __post_init__(self):
+ structs.add(self.name)
+ pass_by_reference.add(self.name)
+ max_widths[self.name] = self.max_width()
+ symbolic_widths[self.name] = self.symbolic_width()
+
+
+@dataclass
+class _RpcProcedure(_XdrAst):
+ """RPC procedure definition"""
+
+ name: str
+ number: str
+ argument: _XdrTypeSpecifier
+ result: _XdrTypeSpecifier
+
+
+@dataclass
+class _RpcVersion(_XdrAst):
+ """RPC version definition"""
+
+ name: str
+ number: str
+ procedures: List[_RpcProcedure]
+
+
+@dataclass
+class _RpcProgram(_XdrAst):
+ """RPC program definition"""
+
+ name: str
+ number: str
+ versions: List[_RpcVersion]
+
+
+@dataclass
+class _Pragma(_XdrAst):
+ """Empty class for pragma directives"""
+
+
+@dataclass
+class Definition(_XdrAst, ast_utils.WithMeta):
+ """Corresponds to 'definition' in the grammar"""
+
+ meta: Meta
+ value: _XdrAst
+
+
+@dataclass
+class Specification(_XdrAst, ast_utils.AsList):
+ """Corresponds to 'specification' in the grammar"""
+
+ definitions: List[Definition]
+
+
+class ParseToAst(Transformer):
+ """Functions that transform productions into AST nodes"""
+
+ def identifier(self, children):
+ """Instantiate one _XdrIdentifier object"""
+ return _XdrIdentifier(children[0].value)
+
+ def value(self, children):
+ """Instantiate one _XdrValue object"""
+ if isinstance(children[0], _XdrIdentifier):
+ return _XdrValue(children[0].symbol)
+ return _XdrValue(children[0].children[0].value)
+
+ def constant(self, children):
+ """Instantiate one _XdrConstantValue object"""
+ match children[0].data:
+ case "decimal_constant":
+ value = int(children[0].children[0].value, base=10)
+ case "hexadecimal_constant":
+ value = int(children[0].children[0].value, base=16)
+ case "octal_constant":
+ value = int(children[0].children[0].value, base=8)
+ return _XdrConstantValue(value)
+
+ def type_specifier(self, children):
+ """Instantiate one _XdrTypeSpecifier object"""
+ if isinstance(children[0], _XdrIdentifier):
+ name = children[0].symbol
+ return _XdrDefinedType(type_name=name)
+
+ name = children[0].data.value
+ return _XdrBuiltInType(type_name=name)
+
+ def constant_def(self, children):
+ """Instantiate one _XdrConstant object"""
+ name = children[0].symbol
+ value = children[1].value
+ return _XdrConstant(name, value)
+
+ # cel: Python can compute a min() and max() for the enumerator values
+ # so that the generated code can perform proper range checking.
+ def enum(self, children):
+ """Instantiate one _XdrEnum object"""
+ enum_name = children[0].symbol
+
+ i = 0
+ enumerators = []
+ body = children[1]
+ while i < len(body.children):
+ name = body.children[i].symbol
+ value = body.children[i + 1].value
+ enumerators.append(_XdrEnumerator(name, value))
+ i = i + 2
+
+ return _XdrEnum(enum_name, 0, 0, enumerators)
+
+ def fixed_length_opaque(self, children):
+ """Instantiate one _XdrFixedLengthOpaque declaration object"""
+ name = children[0].symbol
+ size = children[1].value
+
+ return _XdrFixedLengthOpaque(name, size)
+
+ def variable_length_opaque(self, children):
+ """Instantiate one _XdrVariableLengthOpaque declaration object"""
+ name = children[0].symbol
+ if children[1] is not None:
+ maxsize = children[1].value
+ else:
+ maxsize = "0"
+
+ return _XdrVariableLengthOpaque(name, maxsize)
+
+ def string(self, children):
+ """Instantiate one _XdrString declaration object"""
+ name = children[0].symbol
+ if children[1] is not None:
+ maxsize = children[1].value
+ else:
+ maxsize = "0"
+
+ return _XdrString(name, maxsize)
+
+ def fixed_length_array(self, children):
+ """Instantiate one _XdrFixedLengthArray declaration object"""
+ spec = children[0]
+ name = children[1].symbol
+ size = children[2].value
+
+ return _XdrFixedLengthArray(name, spec, size)
+
+ def variable_length_array(self, children):
+ """Instantiate one _XdrVariableLengthArray declaration object"""
+ spec = children[0]
+ name = children[1].symbol
+ if children[2] is not None:
+ maxsize = children[2].value
+ else:
+ maxsize = "0"
+
+ return _XdrVariableLengthArray(name, spec, maxsize)
+
+ def optional_data(self, children):
+ """Instantiate one _XdrOptionalData declaration object"""
+ spec = children[0]
+ name = children[1].symbol
+
+ return _XdrOptionalData(name, spec)
+
+ def basic(self, children):
+ """Instantiate one _XdrBasic object"""
+ spec = children[0]
+ name = children[1].symbol
+
+ return _XdrBasic(name, spec)
+
+ def void(self, children):
+ """Instantiate one _XdrVoid declaration object"""
+
+ return _XdrVoid()
+
+ def struct(self, children):
+ """Instantiate one _XdrStruct object"""
+ name = children[0].symbol
+ fields = children[1].children
+
+ last_field = fields[-1]
+ if (
+ isinstance(last_field, _XdrOptionalData)
+ and name == last_field.spec.type_name
+ ):
+ return _XdrPointer(name, fields)
+
+ return _XdrStruct(name, fields)
+
+ def typedef(self, children):
+ """Instantiate one _XdrTypedef object"""
+ new_type = children[0]
+
+ return _XdrTypedef(new_type)
+
+ def case_spec(self, children):
+ """Instantiate one _XdrCaseSpec object"""
+ values = []
+ for item in children[0:-1]:
+ values.append(item.value)
+ arm = children[-1]
+
+ return _XdrCaseSpec(values, arm)
+
+ def default_spec(self, children):
+ """Instantiate one _XdrDefaultSpec object"""
+ arm = children[0]
+
+ return _XdrDefaultSpec(arm)
+
+ def union(self, children):
+ """Instantiate one _XdrUnion object"""
+ name = children[0].symbol
+
+ body = children[1]
+ discriminant = body.children[0].children[0]
+ cases = body.children[1:-1]
+ default = body.children[-1]
+
+ return _XdrUnion(name, discriminant, cases, default)
+
+ def procedure_def(self, children):
+ """Instantiate one _RpcProcedure object"""
+ result = children[0]
+ name = children[1].symbol
+ argument = children[2]
+ number = children[3].value
+
+ return _RpcProcedure(name, number, argument, result)
+
+ def version_def(self, children):
+ """Instantiate one _RpcVersion object"""
+ name = children[0].symbol
+ number = children[-1].value
+ procedures = children[1:-1]
+
+ return _RpcVersion(name, number, procedures)
+
+ def program_def(self, children):
+ """Instantiate one _RpcProgram object"""
+ name = children[0].symbol
+ number = children[-1].value
+ versions = children[1:-1]
+
+ return _RpcProgram(name, number, versions)
+
+ def pragma_def(self, children):
+ """Instantiate one _Pragma object"""
+ directive = children[0].children[0].data
+ match directive:
+ case "big_endian_directive":
+ big_endian.append(children[1].symbol)
+ case "exclude_directive":
+ excluded_apis.append(children[1].symbol)
+ case "header_directive":
+ global header_name
+ header_name = children[1].symbol
+ case "public_directive":
+ public_apis.append(children[1].symbol)
+ case _:
+ raise NotImplementedError("Directive not supported")
+ return _Pragma()
+
+
+transformer = ast_utils.create_transformer(this_module, ParseToAst())
+
+
+def transform_parse_tree(parse_tree):
+ """Transform productions into an abstract syntax tree"""
+
+ return transformer.transform(parse_tree)
+
+
+def get_header_name() -> str:
+ """Return header name set by pragma header directive"""
+ return header_name
diff --git a/tools/net/sunrpc/xdrgen/xdr_parse.py b/tools/net/sunrpc/xdrgen/xdr_parse.py
new file mode 100644
index 000000000000..964b44e675df
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/xdr_parse.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Common parsing code for xdrgen"""
+
+from lark import Lark
+
+
+# Set to True to emit annotation comments in generated source
+annotate = False
+
+
+def set_xdr_annotate(set_it: bool) -> None:
+ """Set 'annotate' if --annotate was specified on the command line"""
+ global annotate
+ annotate = set_it
+
+
+def get_xdr_annotate() -> bool:
+ """Return True if --annotate was specified on the command line"""
+ return annotate
+
+
+def xdr_parser() -> Lark:
+ """Return a Lark parser instance configured with the XDR language grammar"""
+
+ return Lark.open(
+ "grammars/xdr.lark",
+ rel_to=__file__,
+ start="specification",
+ debug=True,
+ strict=True,
+ propagate_positions=True,
+ parser="lalr",
+ lexer="contextual",
+ )
diff --git a/tools/net/sunrpc/xdrgen/xdrgen b/tools/net/sunrpc/xdrgen/xdrgen
new file mode 100755
index 000000000000..3afd0547d67c
--- /dev/null
+++ b/tools/net/sunrpc/xdrgen/xdrgen
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+# ex: set filetype=python:
+
+"""Translate an XDR specification into executable code that
+can be compiled for the Linux kernel."""
+
+__author__ = "Chuck Lever"
+__copyright__ = "Copyright (c) 2024 Oracle and/or its affiliates."
+__license__ = "GPL-2.0 only"
+__version__ = "0.2"
+
+import sys
+from pathlib import Path
+import argparse
+
+_XDRGEN_DIR = Path(__file__).resolve().parent
+if str(_XDRGEN_DIR) not in sys.path:
+ sys.path.insert(0, str(_XDRGEN_DIR))
+
+from subcmds import definitions
+from subcmds import declarations
+from subcmds import lint
+from subcmds import source
+
+
+sys.path.insert(1, "@pythondir@")
+
+
+def main() -> int:
+ """Parse command-line options"""
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="Convert an XDR specification to Linux kernel source code",
+ epilog="""\
+Copyright (c) 2024 Oracle and/or its affiliates.
+
+License GPLv2: <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>
+This is free software. You are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.""",
+ )
+ parser.add_argument(
+ "--version",
+ help="Display the version of this tool",
+ action="version",
+ version=__version__,
+ )
+
+ subcommands = parser.add_subparsers(title="Subcommands", required=True)
+
+ definitions_parser = subcommands.add_parser(
+ "definitions", help="Generate XDR definitions"
+ )
+ definitions_parser.add_argument(
+ "--annotate",
+ action="store_true",
+ default=False,
+ help="Add annotation comments",
+ )
+ definitions_parser.add_argument(
+ "--language",
+ action="store_true",
+ default="C",
+ help="Output language",
+ )
+ definitions_parser.add_argument(
+ "--peer",
+ choices=["server", "client",],
+ default="server",
+ help="Generate header code for client or server side",
+ type=str,
+ )
+ definitions_parser.add_argument("filename", help="File containing an XDR specification")
+ definitions_parser.set_defaults(func=definitions.subcmd)
+
+ declarations_parser = subcommands.add_parser(
+ "declarations", help="Generate function declarations"
+ )
+ declarations_parser.add_argument(
+ "--annotate",
+ action="store_true",
+ default=False,
+ help="Add annotation comments",
+ )
+ declarations_parser.add_argument(
+ "--language",
+ action="store_true",
+ default="C",
+ help="Output language",
+ )
+ declarations_parser.add_argument(
+ "--peer",
+ choices=["server", "client",],
+ default="server",
+ help="Generate code for client or server side",
+ type=str,
+ )
+ declarations_parser.add_argument("filename", help="File containing an XDR specification")
+ declarations_parser.set_defaults(func=declarations.subcmd)
+
+ linter_parser = subcommands.add_parser("lint", help="Check an XDR specification")
+ linter_parser.add_argument("filename", help="File containing an XDR specification")
+ linter_parser.set_defaults(func=lint.subcmd)
+
+ source_parser = subcommands.add_parser(
+ "source", help="Generate XDR encoder and decoder source code"
+ )
+ source_parser.add_argument(
+ "--annotate",
+ action="store_true",
+ default=False,
+ help="Add annotation comments",
+ )
+ source_parser.add_argument(
+ "--language",
+ action="store_true",
+ default="C",
+ help="Output language",
+ )
+ source_parser.add_argument(
+ "--peer",
+ choices=["server", "client",],
+ default="server",
+ help="Generate code for client or server side",
+ type=str,
+ )
+ source_parser.add_argument("filename", help="File containing an XDR specification")
+ source_parser.set_defaults(func=source.subcmd)
+
+ args = parser.parse_args()
+ return args.func(args)
+
+
+try:
+ if __name__ == "__main__":
+ sys.exit(main())
+except SystemExit:
+ sys.exit(0)
+except (KeyboardInterrupt, BrokenPipeError):
+ sys.exit(1)
diff --git a/tools/net/ynl/Makefile b/tools/net/ynl/Makefile
index 8156f03e23ac..7736b492f559 100644
--- a/tools/net/ynl/Makefile
+++ b/tools/net/ynl/Makefile
@@ -1,20 +1,77 @@
# SPDX-License-Identifier: GPL-2.0
-SUBDIRS = lib generated samples
+include ../../scripts/Makefile.arch
-all: $(SUBDIRS)
- ./ynl-regen.sh -f -p $(PWD)/../../../
+INSTALL ?= install
+prefix ?= /usr
+ifeq ($(LP64), 1)
+ libdir_relative = lib64
+else
+ libdir_relative = lib
+endif
+libdir ?= $(prefix)/$(libdir_relative)
+includedir ?= $(prefix)/include
+
+SPECDIR=../../../Documentation/netlink/specs
+
+SUBDIRS = lib generated samples ynltool tests
+
+all: $(SUBDIRS) libynl.a
+
+ynltool: | lib generated libynl.a
+samples: | lib generated
+libynl.a: | lib generated
+ @echo -e "\tAR $@"
+ @ar rcs $@ lib/ynl.o generated/*-user.o
$(SUBDIRS):
@if [ -f "$@/Makefile" ] ; then \
$(MAKE) -C $@ ; \
fi
-clean hardclean:
+clean distclean:
@for dir in $(SUBDIRS) ; do \
if [ -f "$$dir/Makefile" ] ; then \
$(MAKE) -C $$dir $@; \
fi \
done
+ rm -f libynl.a
+ rm -rf pyynl/__pycache__
+ rm -rf pyynl/lib/__pycache__
+ rm -rf pyynl.egg-info
+ rm -rf build
+
+install: libynl.a lib/*.h
+ @echo -e "\tINSTALL libynl.a"
+ @$(INSTALL) -d $(DESTDIR)$(libdir)
+ @$(INSTALL) -m 0644 libynl.a $(DESTDIR)$(libdir)/libynl.a
+ @echo -e "\tINSTALL libynl headers"
+ @$(INSTALL) -d $(DESTDIR)$(includedir)/ynl
+ @$(INSTALL) -m 0644 lib/*.h $(DESTDIR)$(includedir)/ynl/
+ @echo -e "\tINSTALL pyynl"
+ @pip install --prefix=$(DESTDIR)$(prefix) .
+ @make -C generated install
+ @make -C tests install
+
+run_tests:
+ @$(MAKE) -C tests run_tests
+
+lint:
+ yamllint $(SPECDIR)
+
+schema_check:
+ @N=1; \
+ for spec in $(SPECDIR)/*.yaml ; do \
+ NAME=$$(basename $$spec) ; \
+ OUTPUT=$$(./pyynl/cli.py --spec $$spec --validate) ; \
+ if [ $$? -eq 0 ] ; then \
+ echo "ok $$N $$NAME schema validation" ; \
+ else \
+ echo "not ok $$N $$NAME schema validation" ; \
+ echo "$$OUTPUT" ; \
+ echo ; \
+ fi ; \
+ N=$$((N+1)) ; \
+ done
-.PHONY: clean all $(SUBDIRS)
+.PHONY: all clean distclean install run_tests lint schema_check $(SUBDIRS)
diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps
index f842bc66b967..865fd2e8519e 100644
--- a/tools/net/ynl/Makefile.deps
+++ b/tools/net/ynl/Makefile.deps
@@ -15,6 +15,36 @@ UAPI_PATH:=../../../../include/uapi/
get_hdr_inc=-D$(1) -include $(UAPI_PATH)/linux/$(2)
CFLAGS_devlink:=$(call get_hdr_inc,_LINUX_DEVLINK_H_,devlink.h)
-CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h)
+CFLAGS_dpll:=$(call get_hdr_inc,_LINUX_DPLL_H,dpll.h)
+CFLAGS_ethtool:=$(call get_hdr_inc,_LINUX_ETHTOOL_H,ethtool.h) \
+ $(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_H_,ethtool_netlink.h) \
+ $(call get_hdr_inc,_LINUX_ETHTOOL_NETLINK_GENERATED_H,ethtool_netlink_generated.h)
CFLAGS_handshake:=$(call get_hdr_inc,_LINUX_HANDSHAKE_H,handshake.h)
+CFLAGS_lockd_netlink:=$(call get_hdr_inc,_LINUX_LOCKD_NETLINK_H,lockd_netlink.h)
+CFLAGS_mptcp_pm:=$(call get_hdr_inc,_LINUX_MPTCP_PM_H,mptcp_pm.h)
+CFLAGS_net_shaper:=$(call get_hdr_inc,_LINUX_NET_SHAPER_H,net_shaper.h)
CFLAGS_netdev:=$(call get_hdr_inc,_LINUX_NETDEV_H,netdev.h)
+CFLAGS_nl80211:=$(call get_hdr_inc,__LINUX_NL802121_H,nl80211.h)
+CFLAGS_nlctrl:=$(call get_hdr_inc,__LINUX_GENERIC_NETLINK_H,genetlink.h)
+CFLAGS_nfsd:=$(call get_hdr_inc,_LINUX_NFSD_NETLINK_H,nfsd_netlink.h)
+CFLAGS_ovpn:=$(call get_hdr_inc,_LINUX_OVPN_H,ovpn.h)
+CFLAGS_ovs_datapath:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h)
+CFLAGS_ovs_flow:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h)
+CFLAGS_ovs_vport:=$(call get_hdr_inc,__LINUX_OPENVSWITCH_H,openvswitch.h)
+CFLAGS_psp:=$(call get_hdr_inc,_LINUX_PSP_H,psp.h)
+CFLAGS_rt-addr:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
+ $(call get_hdr_inc,__LINUX_IF_ADDR_H,if_addr.h)
+CFLAGS_rt-link:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
+ $(call get_hdr_inc,_LINUX_IF_LINK_H,if_link.h)
+CFLAGS_rt-neigh:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
+ $(call get_hdr_inc,__LINUX_NEIGHBOUR_H,neighbour.h)
+CFLAGS_rt-route:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h)
+CFLAGS_rt-rule:=$(call get_hdr_inc,__LINUX_FIB_RULES_H,fib_rules.h)
+CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \
+ $(call get_hdr_inc,__LINUX_PKT_SCHED_H,pkt_sched.h) \
+ $(call get_hdr_inc,__LINUX_PKT_CLS_H,pkt_cls.h) \
+ $(call get_hdr_inc,_TC_CT_H,tc_act/tc_ct.h) \
+ $(call get_hdr_inc,_TC_MIRRED_H,tc_act/tc_mirred.h) \
+ $(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \
+ $(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h)
+CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h)
diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/cli.py
deleted file mode 100755
index 564ecf07cd2c..000000000000
--- a/tools/net/ynl/cli.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-
-import argparse
-import json
-import pprint
-import time
-
-from lib import YnlFamily, Netlink
-
-
-def main():
- parser = argparse.ArgumentParser(description='YNL CLI sample')
- parser.add_argument('--spec', dest='spec', type=str, required=True)
- parser.add_argument('--schema', dest='schema', type=str)
- parser.add_argument('--no-schema', action='store_true')
- parser.add_argument('--json', dest='json_text', type=str)
- parser.add_argument('--do', dest='do', type=str)
- parser.add_argument('--dump', dest='dump', type=str)
- parser.add_argument('--sleep', dest='sleep', type=int)
- parser.add_argument('--subscribe', dest='ntf', type=str)
- parser.add_argument('--replace', dest='flags', action='append_const',
- const=Netlink.NLM_F_REPLACE)
- parser.add_argument('--excl', dest='flags', action='append_const',
- const=Netlink.NLM_F_EXCL)
- parser.add_argument('--create', dest='flags', action='append_const',
- const=Netlink.NLM_F_CREATE)
- parser.add_argument('--append', dest='flags', action='append_const',
- const=Netlink.NLM_F_APPEND)
- args = parser.parse_args()
-
- if args.no_schema:
- args.schema = ''
-
- attrs = {}
- if args.json_text:
- attrs = json.loads(args.json_text)
-
- ynl = YnlFamily(args.spec, args.schema)
-
- if args.ntf:
- ynl.ntf_subscribe(args.ntf)
-
- if args.sleep:
- time.sleep(args.sleep)
-
- if args.do:
- reply = ynl.do(args.do, attrs, args.flags)
- pprint.PrettyPrinter().pprint(reply)
- if args.dump:
- reply = ynl.dump(args.dump, attrs)
- pprint.PrettyPrinter().pprint(reply)
-
- if args.ntf:
- ynl.check_ntf()
- pprint.PrettyPrinter().pprint(ynl.async_msg_queue)
-
-
-if __name__ == "__main__":
- main()
diff --git a/tools/net/ynl/generated/.gitignore b/tools/net/ynl/generated/.gitignore
new file mode 100644
index 000000000000..859a6fb446e1
--- /dev/null
+++ b/tools/net/ynl/generated/.gitignore
@@ -0,0 +1,3 @@
+*-user.c
+*-user.h
+*.rst
diff --git a/tools/net/ynl/generated/Makefile b/tools/net/ynl/generated/Makefile
index f8817d2e56e4..86e1e4a959a7 100644
--- a/tools/net/ynl/generated/Makefile
+++ b/tools/net/ynl/generated/Makefile
@@ -1,50 +1,87 @@
# SPDX-License-Identifier: GPL-2.0
CC=gcc
-CFLAGS=-std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow \
+CFLAGS += -std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow \
-I../lib/ -idirafter $(UAPI_PATH)
ifeq ("$(DEBUG)","1")
CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
endif
+INSTALL ?= install
+prefix ?= /usr
+datarootdir ?= $(prefix)/share
+docdir ?= $(datarootdir)/doc
+includedir ?= $(prefix)/include
+
include ../Makefile.deps
YNL_GEN_ARG_ethtool:=--user-header linux/ethtool_netlink.h \
--exclude-op stats-get
-TOOL:=../ynl-gen-c.py
+TOOL:=../pyynl/ynl_gen_c.py
+TOOL_RST:=../pyynl/ynl_gen_rst.py
-GENS:=ethtool devlink handshake fou netdev
+SPECS_DIR:=../../../../Documentation/netlink/specs
+SPECS_PATHS=$(wildcard $(SPECS_DIR)/*.yaml)
+GENS_UNSUP=conntrack nftables
+GENS=$(filter-out ${GENS_UNSUP},$(patsubst $(SPECS_DIR)/%.yaml,%,${SPECS_PATHS}))
SRCS=$(patsubst %,%-user.c,${GENS})
HDRS=$(patsubst %,%-user.h,${GENS})
OBJS=$(patsubst %,%-user.o,${GENS})
-all: protos.a $(HDRS) $(SRCS) $(KHDRS) $(KSRCS) $(UAPI) regen
+SPECS_PATHS=$(wildcard $(SPECS_DIR)/*.yaml)
+SPECS=$(patsubst $(SPECS_DIR)/%.yaml,%,${SPECS_PATHS})
+RSTS=$(patsubst %,%.rst,${SPECS})
+
+all: protos.a $(HDRS) $(SRCS) $(KHDRS) $(KSRCS) $(UAPI) $(RSTS)
protos.a: $(OBJS)
@echo -e "\tAR $@"
@ar rcs $@ $(OBJS)
-%-user.h: ../../../../Documentation/netlink/specs/%.yaml $(TOOL)
+%-user.h: $(SPECS_DIR)/%.yaml $(TOOL)
@echo -e "\tGEN $@"
- @$(TOOL) --mode user --header --spec $< $(YNL_GEN_ARG_$*) > $@
+ @$(TOOL) --mode user --header --spec $< -o $@ $(YNL_GEN_ARG_$*)
-%-user.c: ../../../../Documentation/netlink/specs/%.yaml $(TOOL)
+%-user.c: $(SPECS_DIR)/%.yaml $(TOOL)
@echo -e "\tGEN $@"
- @$(TOOL) --mode user --source --spec $< $(YNL_GEN_ARG_$*) > $@
+ @$(TOOL) --mode user --source --spec $< -o $@ $(YNL_GEN_ARG_$*)
%-user.o: %-user.c %-user.h
@echo -e "\tCC $@"
@$(COMPILE.c) $(CFLAGS_$*) -o $@ $<
+%.rst: $(SPECS_DIR)/%.yaml $(TOOL_RST)
+ @echo -e "\tGEN_RST $@"
+ @$(TOOL_RST) -o $@ -i $<
+
clean:
rm -f *.o
-hardclean: clean
- rm -f *.c *.h *.a
+distclean: clean
+ rm -f *.c *.h *.a *.rst
regen:
@../ynl-regen.sh
-.PHONY: all clean hardclean regen
+install-headers: $(HDRS)
+ @echo -e "\tINSTALL generated headers"
+ @$(INSTALL) -d $(DESTDIR)$(includedir)/ynl
+ @$(INSTALL) -m 0644 *.h $(DESTDIR)$(includedir)/ynl/
+
+install-rsts: $(RSTS)
+ @echo -e "\tINSTALL generated docs"
+ @$(INSTALL) -d $(DESTDIR)$(docdir)/ynl
+ @$(INSTALL) -m 0644 $(RSTS) $(DESTDIR)$(docdir)/ynl/
+
+install-specs:
+ @echo -e "\tINSTALL specs"
+ @$(INSTALL) -d $(DESTDIR)$(datarootdir)/ynl
+ @$(INSTALL) -m 0644 ../../../../Documentation/netlink/*.yaml $(DESTDIR)$(datarootdir)/ynl/
+ @$(INSTALL) -d $(DESTDIR)$(datarootdir)/ynl/specs
+ @$(INSTALL) -m 0644 $(SPECS_DIR)/*.yaml $(DESTDIR)$(datarootdir)/ynl/specs/
+
+install: install-headers install-rsts install-specs
+
+.PHONY: all clean distclean regen install install-headers install-rsts install-specs
.DEFAULT_GOAL: all
diff --git a/tools/net/ynl/generated/devlink-user.c b/tools/net/ynl/generated/devlink-user.c
deleted file mode 100644
index 3a8d8499fab6..000000000000
--- a/tools/net/ynl/generated/devlink-user.c
+++ /dev/null
@@ -1,2982 +0,0 @@
-// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/devlink.yaml */
-/* YNL-GEN user source */
-
-#include <stdlib.h>
-#include <string.h>
-#include "devlink-user.h"
-#include "ynl.h"
-#include <linux/devlink.h>
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-
-/* Enums */
-static const char * const devlink_op_strmap[] = {
- [3] = "get",
- [7] = "port-get",
- [DEVLINK_CMD_SB_GET] = "sb-get",
- [DEVLINK_CMD_SB_POOL_GET] = "sb-pool-get",
- [DEVLINK_CMD_SB_PORT_POOL_GET] = "sb-port-pool-get",
- [DEVLINK_CMD_SB_TC_POOL_BIND_GET] = "sb-tc-pool-bind-get",
- [DEVLINK_CMD_PARAM_GET] = "param-get",
- [DEVLINK_CMD_REGION_GET] = "region-get",
- [DEVLINK_CMD_INFO_GET] = "info-get",
- [DEVLINK_CMD_HEALTH_REPORTER_GET] = "health-reporter-get",
- [DEVLINK_CMD_TRAP_GET] = "trap-get",
- [DEVLINK_CMD_TRAP_GROUP_GET] = "trap-group-get",
- [DEVLINK_CMD_TRAP_POLICER_GET] = "trap-policer-get",
- [DEVLINK_CMD_RATE_GET] = "rate-get",
- [DEVLINK_CMD_LINECARD_GET] = "linecard-get",
- [DEVLINK_CMD_SELFTESTS_GET] = "selftests-get",
-};
-
-const char *devlink_op_str(int op)
-{
- if (op < 0 || op >= (int)MNL_ARRAY_SIZE(devlink_op_strmap))
- return NULL;
- return devlink_op_strmap[op];
-}
-
-static const char * const devlink_sb_pool_type_strmap[] = {
- [0] = "ingress",
- [1] = "egress",
-};
-
-const char *devlink_sb_pool_type_str(enum devlink_sb_pool_type value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(devlink_sb_pool_type_strmap))
- return NULL;
- return devlink_sb_pool_type_strmap[value];
-}
-
-/* Policies */
-struct ynl_policy_attr devlink_dl_info_version_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
-};
-
-struct ynl_policy_nest devlink_dl_info_version_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_info_version_policy,
-};
-
-struct ynl_policy_attr devlink_dl_reload_stats_entry_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest devlink_dl_reload_stats_entry_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_reload_stats_entry_policy,
-};
-
-struct ynl_policy_attr devlink_dl_reload_act_stats_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
-};
-
-struct ynl_policy_nest devlink_dl_reload_act_stats_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_reload_act_stats_policy,
-};
-
-struct ynl_policy_attr devlink_dl_reload_act_info_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
-};
-
-struct ynl_policy_nest devlink_dl_reload_act_info_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_reload_act_info_policy,
-};
-
-struct ynl_policy_attr devlink_dl_reload_stats_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
-};
-
-struct ynl_policy_nest devlink_dl_reload_stats_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_reload_stats_policy,
-};
-
-struct ynl_policy_attr devlink_dl_dev_stats_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
- [DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
-};
-
-struct ynl_policy_nest devlink_dl_dev_stats_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_dl_dev_stats_policy,
-};
-
-struct ynl_policy_attr devlink_policy[DEVLINK_ATTR_MAX + 1] = {
- [DEVLINK_ATTR_BUS_NAME] = { .name = "bus-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_PORT_INDEX] = { .name = "port-index", .type = YNL_PT_U32, },
- [DEVLINK_ATTR_SB_INDEX] = { .name = "sb-index", .type = YNL_PT_U32, },
- [DEVLINK_ATTR_SB_POOL_INDEX] = { .name = "sb-pool-index", .type = YNL_PT_U16, },
- [DEVLINK_ATTR_SB_POOL_TYPE] = { .name = "sb-pool-type", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_SB_TC_INDEX] = { .name = "sb-tc-index", .type = YNL_PT_U16, },
- [DEVLINK_ATTR_PARAM_NAME] = { .name = "param-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_REGION_NAME] = { .name = "region-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_INFO_DRIVER_NAME] = { .name = "info-driver-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_INFO_SERIAL_NUMBER] = { .name = "info-serial-number", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_INFO_VERSION_FIXED] = { .name = "info-version-fixed", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
- [DEVLINK_ATTR_INFO_VERSION_RUNNING] = { .name = "info-version-running", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
- [DEVLINK_ATTR_INFO_VERSION_STORED] = { .name = "info-version-stored", .type = YNL_PT_NEST, .nest = &devlink_dl_info_version_nest, },
- [DEVLINK_ATTR_INFO_VERSION_NAME] = { .name = "info-version-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_INFO_VERSION_VALUE] = { .name = "info-version-value", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .name = "health-reporter-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_TRAP_NAME] = { .name = "trap-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .name = "trap-group-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_RELOAD_FAILED] = { .name = "reload-failed", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_TRAP_POLICER_ID] = { .name = "trap-policer-id", .type = YNL_PT_U32, },
- [DEVLINK_ATTR_RELOAD_ACTION] = { .name = "reload-action", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_DEV_STATS] = { .name = "dev-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_dev_stats_nest, },
- [DEVLINK_ATTR_RELOAD_STATS] = { .name = "reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
- [DEVLINK_ATTR_RELOAD_STATS_ENTRY] = { .name = "reload-stats-entry", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_entry_nest, },
- [DEVLINK_ATTR_RELOAD_STATS_LIMIT] = { .name = "reload-stats-limit", .type = YNL_PT_U8, },
- [DEVLINK_ATTR_RELOAD_STATS_VALUE] = { .name = "reload-stats-value", .type = YNL_PT_U32, },
- [DEVLINK_ATTR_REMOTE_RELOAD_STATS] = { .name = "remote-reload-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_stats_nest, },
- [DEVLINK_ATTR_RELOAD_ACTION_INFO] = { .name = "reload-action-info", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_info_nest, },
- [DEVLINK_ATTR_RELOAD_ACTION_STATS] = { .name = "reload-action-stats", .type = YNL_PT_NEST, .nest = &devlink_dl_reload_act_stats_nest, },
- [DEVLINK_ATTR_RATE_NODE_NAME] = { .name = "rate-node-name", .type = YNL_PT_NUL_STR, },
- [DEVLINK_ATTR_LINECARD_INDEX] = { .name = "linecard-index", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest devlink_nest = {
- .max_attr = DEVLINK_ATTR_MAX,
- .table = devlink_policy,
-};
-
-/* Common nested types */
-void devlink_dl_info_version_free(struct devlink_dl_info_version *obj)
-{
- free(obj->info_version_name);
- free(obj->info_version_value);
-}
-
-int devlink_dl_info_version_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_info_version *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_INFO_VERSION_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.info_version_name_len = len;
- dst->info_version_name = malloc(len + 1);
- memcpy(dst->info_version_name, mnl_attr_get_str(attr), len);
- dst->info_version_name[len] = 0;
- } else if (type == DEVLINK_ATTR_INFO_VERSION_VALUE) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.info_version_value_len = len;
- dst->info_version_value = malloc(len + 1);
- memcpy(dst->info_version_value, mnl_attr_get_str(attr), len);
- dst->info_version_value[len] = 0;
- }
- }
-
- return 0;
-}
-
-void
-devlink_dl_reload_stats_entry_free(struct devlink_dl_reload_stats_entry *obj)
-{
-}
-
-int devlink_dl_reload_stats_entry_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_reload_stats_entry *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_RELOAD_STATS_LIMIT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_stats_limit = 1;
- dst->reload_stats_limit = mnl_attr_get_u8(attr);
- } else if (type == DEVLINK_ATTR_RELOAD_STATS_VALUE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_stats_value = 1;
- dst->reload_stats_value = mnl_attr_get_u32(attr);
- }
- }
-
- return 0;
-}
-
-void devlink_dl_reload_act_stats_free(struct devlink_dl_reload_act_stats *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_reload_stats_entry; i++)
- devlink_dl_reload_stats_entry_free(&obj->reload_stats_entry[i]);
- free(obj->reload_stats_entry);
-}
-
-int devlink_dl_reload_act_stats_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_reload_act_stats *dst = yarg->data;
- unsigned int n_reload_stats_entry = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->reload_stats_entry)
- return ynl_error_parse(yarg, "attribute already present (dl-reload-act-stats.reload-stats-entry)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
- n_reload_stats_entry++;
- }
- }
-
- if (n_reload_stats_entry) {
- dst->reload_stats_entry = calloc(n_reload_stats_entry, sizeof(*dst->reload_stats_entry));
- dst->n_reload_stats_entry = n_reload_stats_entry;
- i = 0;
- parg.rsp_policy = &devlink_dl_reload_stats_entry_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_STATS_ENTRY) {
- parg.data = &dst->reload_stats_entry[i];
- if (devlink_dl_reload_stats_entry_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void devlink_dl_reload_act_info_free(struct devlink_dl_reload_act_info *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_reload_action_stats; i++)
- devlink_dl_reload_act_stats_free(&obj->reload_action_stats[i]);
- free(obj->reload_action_stats);
-}
-
-int devlink_dl_reload_act_info_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_reload_act_info *dst = yarg->data;
- unsigned int n_reload_action_stats = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->reload_action_stats)
- return ynl_error_parse(yarg, "attribute already present (dl-reload-act-info.reload-action-stats)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_RELOAD_ACTION) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_action = 1;
- dst->reload_action = mnl_attr_get_u8(attr);
- } else if (type == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
- n_reload_action_stats++;
- }
- }
-
- if (n_reload_action_stats) {
- dst->reload_action_stats = calloc(n_reload_action_stats, sizeof(*dst->reload_action_stats));
- dst->n_reload_action_stats = n_reload_action_stats;
- i = 0;
- parg.rsp_policy = &devlink_dl_reload_act_stats_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_STATS) {
- parg.data = &dst->reload_action_stats[i];
- if (devlink_dl_reload_act_stats_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void devlink_dl_reload_stats_free(struct devlink_dl_reload_stats *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_reload_action_info; i++)
- devlink_dl_reload_act_info_free(&obj->reload_action_info[i]);
- free(obj->reload_action_info);
-}
-
-int devlink_dl_reload_stats_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_reload_stats *dst = yarg->data;
- unsigned int n_reload_action_info = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->reload_action_info)
- return ynl_error_parse(yarg, "attribute already present (dl-reload-stats.reload-action-info)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
- n_reload_action_info++;
- }
- }
-
- if (n_reload_action_info) {
- dst->reload_action_info = calloc(n_reload_action_info, sizeof(*dst->reload_action_info));
- dst->n_reload_action_info = n_reload_action_info;
- i = 0;
- parg.rsp_policy = &devlink_dl_reload_act_info_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_RELOAD_ACTION_INFO) {
- parg.data = &dst->reload_action_info[i];
- if (devlink_dl_reload_act_info_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void devlink_dl_dev_stats_free(struct devlink_dl_dev_stats *obj)
-{
- devlink_dl_reload_stats_free(&obj->reload_stats);
- devlink_dl_reload_stats_free(&obj->remote_reload_stats);
-}
-
-int devlink_dl_dev_stats_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct devlink_dl_dev_stats *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- parg.ys = yarg->ys;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_RELOAD_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_stats = 1;
-
- parg.rsp_policy = &devlink_dl_reload_stats_nest;
- parg.data = &dst->reload_stats;
- if (devlink_dl_reload_stats_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == DEVLINK_ATTR_REMOTE_RELOAD_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.remote_reload_stats = 1;
-
- parg.rsp_policy = &devlink_dl_reload_stats_nest;
- parg.data = &dst->remote_reload_stats;
- if (devlink_dl_reload_stats_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return 0;
-}
-
-/* ============== DEVLINK_CMD_GET ============== */
-/* DEVLINK_CMD_GET - do */
-void devlink_get_req_free(struct devlink_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_get_rsp_free(struct devlink_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- devlink_dl_dev_stats_free(&rsp->dev_stats);
- free(rsp);
-}
-
-int devlink_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct devlink_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_RELOAD_FAILED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_failed = 1;
- dst->reload_failed = mnl_attr_get_u8(attr);
- } else if (type == DEVLINK_ATTR_RELOAD_ACTION) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reload_action = 1;
- dst->reload_action = mnl_attr_get_u8(attr);
- } else if (type == DEVLINK_ATTR_DEV_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.dev_stats = 1;
-
- parg.rsp_policy = &devlink_dl_dev_stats_nest;
- parg.data = &dst->dev_stats;
- if (devlink_dl_dev_stats_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_get_rsp *
-devlink_get(struct ynl_sock *ys, struct devlink_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_get_rsp_parse;
- yrs.rsp_cmd = 3;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_GET - dump */
-void devlink_get_list_free(struct devlink_get_list *rsp)
-{
- struct devlink_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- devlink_dl_dev_stats_free(&rsp->obj.dev_stats);
- free(rsp);
- }
-}
-
-struct devlink_get_list *devlink_get_dump(struct ynl_sock *ys)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_get_list);
- yds.cb = devlink_get_rsp_parse;
- yds.rsp_cmd = 3;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_GET, 1);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_PORT_GET ============== */
-/* DEVLINK_CMD_PORT_GET - do */
-void devlink_port_get_req_free(struct devlink_port_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_port_get_rsp_free(struct devlink_port_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_port_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct devlink_port_get_rsp *dst;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_port_get_rsp *
-devlink_port_get(struct ynl_sock *ys, struct devlink_port_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_port_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_PORT_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_port_get_rsp_parse;
- yrs.rsp_cmd = 7;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_port_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_PORT_GET - dump */
-int devlink_port_get_rsp_dump_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_port_get_rsp_dump *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-void devlink_port_get_rsp_list_free(struct devlink_port_get_rsp_list *rsp)
-{
- struct devlink_port_get_rsp_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_port_get_rsp_list *
-devlink_port_get_dump(struct ynl_sock *ys,
- struct devlink_port_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_port_get_rsp_list);
- yds.cb = devlink_port_get_rsp_dump_parse;
- yds.rsp_cmd = 7;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_PORT_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_port_get_rsp_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_SB_GET ============== */
-/* DEVLINK_CMD_SB_GET - do */
-void devlink_sb_get_req_free(struct devlink_sb_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_sb_get_rsp_free(struct devlink_sb_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_sb_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct devlink_sb_get_rsp *dst;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_SB_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_index = 1;
- dst->sb_index = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_sb_get_rsp *
-devlink_sb_get(struct ynl_sock *ys, struct devlink_sb_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_sb_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_SB_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.sb_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_sb_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_SB_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_sb_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_SB_GET - dump */
-void devlink_sb_get_list_free(struct devlink_sb_get_list *rsp)
-{
- struct devlink_sb_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_sb_get_list *
-devlink_sb_get_dump(struct ynl_sock *ys, struct devlink_sb_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_sb_get_list);
- yds.cb = devlink_sb_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_SB_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_SB_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_sb_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_SB_POOL_GET ============== */
-/* DEVLINK_CMD_SB_POOL_GET - do */
-void devlink_sb_pool_get_req_free(struct devlink_sb_pool_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_sb_pool_get_rsp_free(struct devlink_sb_pool_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_sb_pool_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_sb_pool_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_SB_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_index = 1;
- dst->sb_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_SB_POOL_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_pool_index = 1;
- dst->sb_pool_index = mnl_attr_get_u16(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_sb_pool_get_rsp *
-devlink_sb_pool_get(struct ynl_sock *ys, struct devlink_sb_pool_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_sb_pool_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_SB_POOL_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.sb_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index);
- if (req->_present.sb_pool_index)
- mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_POOL_INDEX, req->sb_pool_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_sb_pool_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_SB_POOL_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_sb_pool_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_SB_POOL_GET - dump */
-void devlink_sb_pool_get_list_free(struct devlink_sb_pool_get_list *rsp)
-{
- struct devlink_sb_pool_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_sb_pool_get_list *
-devlink_sb_pool_get_dump(struct ynl_sock *ys,
- struct devlink_sb_pool_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_sb_pool_get_list);
- yds.cb = devlink_sb_pool_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_SB_POOL_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_SB_POOL_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_sb_pool_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_SB_PORT_POOL_GET ============== */
-/* DEVLINK_CMD_SB_PORT_POOL_GET - do */
-void
-devlink_sb_port_pool_get_req_free(struct devlink_sb_port_pool_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void
-devlink_sb_port_pool_get_rsp_free(struct devlink_sb_port_pool_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_sb_port_pool_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_sb_port_pool_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_SB_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_index = 1;
- dst->sb_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_SB_POOL_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_pool_index = 1;
- dst->sb_pool_index = mnl_attr_get_u16(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_sb_port_pool_get_rsp *
-devlink_sb_port_pool_get(struct ynl_sock *ys,
- struct devlink_sb_port_pool_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_sb_port_pool_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_SB_PORT_POOL_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
- if (req->_present.sb_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index);
- if (req->_present.sb_pool_index)
- mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_POOL_INDEX, req->sb_pool_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_sb_port_pool_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_SB_PORT_POOL_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_sb_port_pool_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_SB_PORT_POOL_GET - dump */
-void
-devlink_sb_port_pool_get_list_free(struct devlink_sb_port_pool_get_list *rsp)
-{
- struct devlink_sb_port_pool_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_sb_port_pool_get_list *
-devlink_sb_port_pool_get_dump(struct ynl_sock *ys,
- struct devlink_sb_port_pool_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_sb_port_pool_get_list);
- yds.cb = devlink_sb_port_pool_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_SB_PORT_POOL_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_SB_PORT_POOL_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_sb_port_pool_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_SB_TC_POOL_BIND_GET ============== */
-/* DEVLINK_CMD_SB_TC_POOL_BIND_GET - do */
-void
-devlink_sb_tc_pool_bind_get_req_free(struct devlink_sb_tc_pool_bind_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void
-devlink_sb_tc_pool_bind_get_rsp_free(struct devlink_sb_tc_pool_bind_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_sb_tc_pool_bind_get_rsp_parse(const struct nlmsghdr *nlh,
- void *data)
-{
- struct devlink_sb_tc_pool_bind_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_SB_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_index = 1;
- dst->sb_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_SB_POOL_TYPE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_pool_type = 1;
- dst->sb_pool_type = mnl_attr_get_u8(attr);
- } else if (type == DEVLINK_ATTR_SB_TC_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sb_tc_index = 1;
- dst->sb_tc_index = mnl_attr_get_u16(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_sb_tc_pool_bind_get_rsp *
-devlink_sb_tc_pool_bind_get(struct ynl_sock *ys,
- struct devlink_sb_tc_pool_bind_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_sb_tc_pool_bind_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_SB_TC_POOL_BIND_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
- if (req->_present.sb_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index);
- if (req->_present.sb_pool_type)
- mnl_attr_put_u8(nlh, DEVLINK_ATTR_SB_POOL_TYPE, req->sb_pool_type);
- if (req->_present.sb_tc_index)
- mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_TC_INDEX, req->sb_tc_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_sb_tc_pool_bind_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_sb_tc_pool_bind_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_SB_TC_POOL_BIND_GET - dump */
-void
-devlink_sb_tc_pool_bind_get_list_free(struct devlink_sb_tc_pool_bind_get_list *rsp)
-{
- struct devlink_sb_tc_pool_bind_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_sb_tc_pool_bind_get_list *
-devlink_sb_tc_pool_bind_get_dump(struct ynl_sock *ys,
- struct devlink_sb_tc_pool_bind_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_sb_tc_pool_bind_get_list);
- yds.cb = devlink_sb_tc_pool_bind_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_SB_TC_POOL_BIND_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_sb_tc_pool_bind_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_PARAM_GET ============== */
-/* DEVLINK_CMD_PARAM_GET - do */
-void devlink_param_get_req_free(struct devlink_param_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->param_name);
- free(req);
-}
-
-void devlink_param_get_rsp_free(struct devlink_param_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->param_name);
- free(rsp);
-}
-
-int devlink_param_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_param_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PARAM_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.param_name_len = len;
- dst->param_name = malloc(len + 1);
- memcpy(dst->param_name, mnl_attr_get_str(attr), len);
- dst->param_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_param_get_rsp *
-devlink_param_get(struct ynl_sock *ys, struct devlink_param_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_param_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_PARAM_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.param_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_PARAM_NAME, req->param_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_param_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_PARAM_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_param_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_PARAM_GET - dump */
-void devlink_param_get_list_free(struct devlink_param_get_list *rsp)
-{
- struct devlink_param_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.param_name);
- free(rsp);
- }
-}
-
-struct devlink_param_get_list *
-devlink_param_get_dump(struct ynl_sock *ys,
- struct devlink_param_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_param_get_list);
- yds.cb = devlink_param_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_PARAM_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_PARAM_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_param_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_REGION_GET ============== */
-/* DEVLINK_CMD_REGION_GET - do */
-void devlink_region_get_req_free(struct devlink_region_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->region_name);
- free(req);
-}
-
-void devlink_region_get_rsp_free(struct devlink_region_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->region_name);
- free(rsp);
-}
-
-int devlink_region_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_region_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_REGION_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.region_name_len = len;
- dst->region_name = malloc(len + 1);
- memcpy(dst->region_name, mnl_attr_get_str(attr), len);
- dst->region_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_region_get_rsp *
-devlink_region_get(struct ynl_sock *ys, struct devlink_region_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_region_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_REGION_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
- if (req->_present.region_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_REGION_NAME, req->region_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_region_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_REGION_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_region_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_REGION_GET - dump */
-void devlink_region_get_list_free(struct devlink_region_get_list *rsp)
-{
- struct devlink_region_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.region_name);
- free(rsp);
- }
-}
-
-struct devlink_region_get_list *
-devlink_region_get_dump(struct ynl_sock *ys,
- struct devlink_region_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_region_get_list);
- yds.cb = devlink_region_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_REGION_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_REGION_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_region_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_INFO_GET ============== */
-/* DEVLINK_CMD_INFO_GET - do */
-void devlink_info_get_req_free(struct devlink_info_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_info_get_rsp_free(struct devlink_info_get_rsp *rsp)
-{
- unsigned int i;
-
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->info_driver_name);
- free(rsp->info_serial_number);
- for (i = 0; i < rsp->n_info_version_fixed; i++)
- devlink_dl_info_version_free(&rsp->info_version_fixed[i]);
- free(rsp->info_version_fixed);
- for (i = 0; i < rsp->n_info_version_running; i++)
- devlink_dl_info_version_free(&rsp->info_version_running[i]);
- free(rsp->info_version_running);
- for (i = 0; i < rsp->n_info_version_stored; i++)
- devlink_dl_info_version_free(&rsp->info_version_stored[i]);
- free(rsp->info_version_stored);
- free(rsp);
-}
-
-int devlink_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- unsigned int n_info_version_running = 0;
- unsigned int n_info_version_stored = 0;
- unsigned int n_info_version_fixed = 0;
- struct ynl_parse_arg *yarg = data;
- struct devlink_info_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- if (dst->info_version_fixed)
- return ynl_error_parse(yarg, "attribute already present (devlink.info-version-fixed)");
- if (dst->info_version_running)
- return ynl_error_parse(yarg, "attribute already present (devlink.info-version-running)");
- if (dst->info_version_stored)
- return ynl_error_parse(yarg, "attribute already present (devlink.info-version-stored)");
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_INFO_DRIVER_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.info_driver_name_len = len;
- dst->info_driver_name = malloc(len + 1);
- memcpy(dst->info_driver_name, mnl_attr_get_str(attr), len);
- dst->info_driver_name[len] = 0;
- } else if (type == DEVLINK_ATTR_INFO_SERIAL_NUMBER) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.info_serial_number_len = len;
- dst->info_serial_number = malloc(len + 1);
- memcpy(dst->info_serial_number, mnl_attr_get_str(attr), len);
- dst->info_serial_number[len] = 0;
- } else if (type == DEVLINK_ATTR_INFO_VERSION_FIXED) {
- n_info_version_fixed++;
- } else if (type == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
- n_info_version_running++;
- } else if (type == DEVLINK_ATTR_INFO_VERSION_STORED) {
- n_info_version_stored++;
- }
- }
-
- if (n_info_version_fixed) {
- dst->info_version_fixed = calloc(n_info_version_fixed, sizeof(*dst->info_version_fixed));
- dst->n_info_version_fixed = n_info_version_fixed;
- i = 0;
- parg.rsp_policy = &devlink_dl_info_version_nest;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_FIXED) {
- parg.data = &dst->info_version_fixed[i];
- if (devlink_dl_info_version_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
- if (n_info_version_running) {
- dst->info_version_running = calloc(n_info_version_running, sizeof(*dst->info_version_running));
- dst->n_info_version_running = n_info_version_running;
- i = 0;
- parg.rsp_policy = &devlink_dl_info_version_nest;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_RUNNING) {
- parg.data = &dst->info_version_running[i];
- if (devlink_dl_info_version_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
- if (n_info_version_stored) {
- dst->info_version_stored = calloc(n_info_version_stored, sizeof(*dst->info_version_stored));
- dst->n_info_version_stored = n_info_version_stored;
- i = 0;
- parg.rsp_policy = &devlink_dl_info_version_nest;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == DEVLINK_ATTR_INFO_VERSION_STORED) {
- parg.data = &dst->info_version_stored[i];
- if (devlink_dl_info_version_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_info_get_rsp *
-devlink_info_get(struct ynl_sock *ys, struct devlink_info_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_info_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_info_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_INFO_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_info_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_INFO_GET - dump */
-void devlink_info_get_list_free(struct devlink_info_get_list *rsp)
-{
- struct devlink_info_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- unsigned int i;
-
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.info_driver_name);
- free(rsp->obj.info_serial_number);
- for (i = 0; i < rsp->obj.n_info_version_fixed; i++)
- devlink_dl_info_version_free(&rsp->obj.info_version_fixed[i]);
- free(rsp->obj.info_version_fixed);
- for (i = 0; i < rsp->obj.n_info_version_running; i++)
- devlink_dl_info_version_free(&rsp->obj.info_version_running[i]);
- free(rsp->obj.info_version_running);
- for (i = 0; i < rsp->obj.n_info_version_stored; i++)
- devlink_dl_info_version_free(&rsp->obj.info_version_stored[i]);
- free(rsp->obj.info_version_stored);
- free(rsp);
- }
-}
-
-struct devlink_info_get_list *devlink_info_get_dump(struct ynl_sock *ys)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_info_get_list);
- yds.cb = devlink_info_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_INFO_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_INFO_GET, 1);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_info_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_HEALTH_REPORTER_GET ============== */
-/* DEVLINK_CMD_HEALTH_REPORTER_GET - do */
-void
-devlink_health_reporter_get_req_free(struct devlink_health_reporter_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->health_reporter_name);
- free(req);
-}
-
-void
-devlink_health_reporter_get_rsp_free(struct devlink_health_reporter_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->health_reporter_name);
- free(rsp);
-}
-
-int devlink_health_reporter_get_rsp_parse(const struct nlmsghdr *nlh,
- void *data)
-{
- struct devlink_health_reporter_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_HEALTH_REPORTER_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.health_reporter_name_len = len;
- dst->health_reporter_name = malloc(len + 1);
- memcpy(dst->health_reporter_name, mnl_attr_get_str(attr), len);
- dst->health_reporter_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_health_reporter_get_rsp *
-devlink_health_reporter_get(struct ynl_sock *ys,
- struct devlink_health_reporter_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_health_reporter_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_HEALTH_REPORTER_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
- if (req->_present.health_reporter_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_health_reporter_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_HEALTH_REPORTER_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_health_reporter_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_HEALTH_REPORTER_GET - dump */
-void
-devlink_health_reporter_get_list_free(struct devlink_health_reporter_get_list *rsp)
-{
- struct devlink_health_reporter_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.health_reporter_name);
- free(rsp);
- }
-}
-
-struct devlink_health_reporter_get_list *
-devlink_health_reporter_get_dump(struct ynl_sock *ys,
- struct devlink_health_reporter_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_health_reporter_get_list);
- yds.cb = devlink_health_reporter_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_HEALTH_REPORTER_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_HEALTH_REPORTER_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_health_reporter_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_TRAP_GET ============== */
-/* DEVLINK_CMD_TRAP_GET - do */
-void devlink_trap_get_req_free(struct devlink_trap_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->trap_name);
- free(req);
-}
-
-void devlink_trap_get_rsp_free(struct devlink_trap_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->trap_name);
- free(rsp);
-}
-
-int devlink_trap_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct devlink_trap_get_rsp *dst;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_TRAP_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.trap_name_len = len;
- dst->trap_name = malloc(len + 1);
- memcpy(dst->trap_name, mnl_attr_get_str(attr), len);
- dst->trap_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_trap_get_rsp *
-devlink_trap_get(struct ynl_sock *ys, struct devlink_trap_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_trap_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_TRAP_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.trap_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_TRAP_NAME, req->trap_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_trap_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_TRAP_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_trap_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_TRAP_GET - dump */
-void devlink_trap_get_list_free(struct devlink_trap_get_list *rsp)
-{
- struct devlink_trap_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.trap_name);
- free(rsp);
- }
-}
-
-struct devlink_trap_get_list *
-devlink_trap_get_dump(struct ynl_sock *ys,
- struct devlink_trap_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_trap_get_list);
- yds.cb = devlink_trap_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_TRAP_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_TRAP_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_trap_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_TRAP_GROUP_GET ============== */
-/* DEVLINK_CMD_TRAP_GROUP_GET - do */
-void devlink_trap_group_get_req_free(struct devlink_trap_group_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->trap_group_name);
- free(req);
-}
-
-void devlink_trap_group_get_rsp_free(struct devlink_trap_group_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->trap_group_name);
- free(rsp);
-}
-
-int devlink_trap_group_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_trap_group_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_TRAP_GROUP_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.trap_group_name_len = len;
- dst->trap_group_name = malloc(len + 1);
- memcpy(dst->trap_group_name, mnl_attr_get_str(attr), len);
- dst->trap_group_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_trap_group_get_rsp *
-devlink_trap_group_get(struct ynl_sock *ys,
- struct devlink_trap_group_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_trap_group_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_TRAP_GROUP_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.trap_group_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_TRAP_GROUP_NAME, req->trap_group_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_trap_group_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_TRAP_GROUP_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_trap_group_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_TRAP_GROUP_GET - dump */
-void devlink_trap_group_get_list_free(struct devlink_trap_group_get_list *rsp)
-{
- struct devlink_trap_group_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.trap_group_name);
- free(rsp);
- }
-}
-
-struct devlink_trap_group_get_list *
-devlink_trap_group_get_dump(struct ynl_sock *ys,
- struct devlink_trap_group_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_trap_group_get_list);
- yds.cb = devlink_trap_group_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_TRAP_GROUP_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_TRAP_GROUP_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_trap_group_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_TRAP_POLICER_GET ============== */
-/* DEVLINK_CMD_TRAP_POLICER_GET - do */
-void
-devlink_trap_policer_get_req_free(struct devlink_trap_policer_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void
-devlink_trap_policer_get_rsp_free(struct devlink_trap_policer_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_trap_policer_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_trap_policer_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_TRAP_POLICER_ID) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.trap_policer_id = 1;
- dst->trap_policer_id = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_trap_policer_get_rsp *
-devlink_trap_policer_get(struct ynl_sock *ys,
- struct devlink_trap_policer_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_trap_policer_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_TRAP_POLICER_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.trap_policer_id)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_TRAP_POLICER_ID, req->trap_policer_id);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_trap_policer_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_TRAP_POLICER_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_trap_policer_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_TRAP_POLICER_GET - dump */
-void
-devlink_trap_policer_get_list_free(struct devlink_trap_policer_get_list *rsp)
-{
- struct devlink_trap_policer_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_trap_policer_get_list *
-devlink_trap_policer_get_dump(struct ynl_sock *ys,
- struct devlink_trap_policer_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_trap_policer_get_list);
- yds.cb = devlink_trap_policer_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_TRAP_POLICER_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_TRAP_POLICER_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_trap_policer_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_RATE_GET ============== */
-/* DEVLINK_CMD_RATE_GET - do */
-void devlink_rate_get_req_free(struct devlink_rate_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req->rate_node_name);
- free(req);
-}
-
-void devlink_rate_get_rsp_free(struct devlink_rate_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp->rate_node_name);
- free(rsp);
-}
-
-int devlink_rate_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct devlink_rate_get_rsp *dst;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_PORT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port_index = 1;
- dst->port_index = mnl_attr_get_u32(attr);
- } else if (type == DEVLINK_ATTR_RATE_NODE_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.rate_node_name_len = len;
- dst->rate_node_name = malloc(len + 1);
- memcpy(dst->rate_node_name, mnl_attr_get_str(attr), len);
- dst->rate_node_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_rate_get_rsp *
-devlink_rate_get(struct ynl_sock *ys, struct devlink_rate_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_rate_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_RATE_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.port_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index);
- if (req->_present.rate_node_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_NODE_NAME, req->rate_node_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_rate_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_RATE_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_rate_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_RATE_GET - dump */
-void devlink_rate_get_list_free(struct devlink_rate_get_list *rsp)
-{
- struct devlink_rate_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp->obj.rate_node_name);
- free(rsp);
- }
-}
-
-struct devlink_rate_get_list *
-devlink_rate_get_dump(struct ynl_sock *ys,
- struct devlink_rate_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_rate_get_list);
- yds.cb = devlink_rate_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_RATE_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_RATE_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_rate_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_LINECARD_GET ============== */
-/* DEVLINK_CMD_LINECARD_GET - do */
-void devlink_linecard_get_req_free(struct devlink_linecard_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_linecard_get_rsp_free(struct devlink_linecard_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_linecard_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_linecard_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == DEVLINK_ATTR_LINECARD_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.linecard_index = 1;
- dst->linecard_index = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_linecard_get_rsp *
-devlink_linecard_get(struct ynl_sock *ys, struct devlink_linecard_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_linecard_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_LINECARD_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
- if (req->_present.linecard_index)
- mnl_attr_put_u32(nlh, DEVLINK_ATTR_LINECARD_INDEX, req->linecard_index);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_linecard_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_LINECARD_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_linecard_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_LINECARD_GET - dump */
-void devlink_linecard_get_list_free(struct devlink_linecard_get_list *rsp)
-{
- struct devlink_linecard_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_linecard_get_list *
-devlink_linecard_get_dump(struct ynl_sock *ys,
- struct devlink_linecard_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_linecard_get_list);
- yds.cb = devlink_linecard_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_LINECARD_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_LINECARD_GET, 1);
- ys->req_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_linecard_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== DEVLINK_CMD_SELFTESTS_GET ============== */
-/* DEVLINK_CMD_SELFTESTS_GET - do */
-void devlink_selftests_get_req_free(struct devlink_selftests_get_req *req)
-{
- free(req->bus_name);
- free(req->dev_name);
- free(req);
-}
-
-void devlink_selftests_get_rsp_free(struct devlink_selftests_get_rsp *rsp)
-{
- free(rsp->bus_name);
- free(rsp->dev_name);
- free(rsp);
-}
-
-int devlink_selftests_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct devlink_selftests_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == DEVLINK_ATTR_BUS_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.bus_name_len = len;
- dst->bus_name = malloc(len + 1);
- memcpy(dst->bus_name, mnl_attr_get_str(attr), len);
- dst->bus_name[len] = 0;
- } else if (type == DEVLINK_ATTR_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct devlink_selftests_get_rsp *
-devlink_selftests_get(struct ynl_sock *ys,
- struct devlink_selftests_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct devlink_selftests_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, DEVLINK_CMD_SELFTESTS_GET, 1);
- ys->req_policy = &devlink_nest;
- yrs.yarg.rsp_policy = &devlink_nest;
-
- if (req->_present.bus_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_BUS_NAME, req->bus_name);
- if (req->_present.dev_name_len)
- mnl_attr_put_strz(nlh, DEVLINK_ATTR_DEV_NAME, req->dev_name);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = devlink_selftests_get_rsp_parse;
- yrs.rsp_cmd = DEVLINK_CMD_SELFTESTS_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- devlink_selftests_get_rsp_free(rsp);
- return NULL;
-}
-
-/* DEVLINK_CMD_SELFTESTS_GET - dump */
-void devlink_selftests_get_list_free(struct devlink_selftests_get_list *rsp)
-{
- struct devlink_selftests_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.bus_name);
- free(rsp->obj.dev_name);
- free(rsp);
- }
-}
-
-struct devlink_selftests_get_list *
-devlink_selftests_get_dump(struct ynl_sock *ys)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct devlink_selftests_get_list);
- yds.cb = devlink_selftests_get_rsp_parse;
- yds.rsp_cmd = DEVLINK_CMD_SELFTESTS_GET;
- yds.rsp_policy = &devlink_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, DEVLINK_CMD_SELFTESTS_GET, 1);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- devlink_selftests_get_list_free(yds.first);
- return NULL;
-}
-
-const struct ynl_family ynl_devlink_family = {
- .name = "devlink",
-};
diff --git a/tools/net/ynl/generated/devlink-user.h b/tools/net/ynl/generated/devlink-user.h
deleted file mode 100644
index 4b686d147613..000000000000
--- a/tools/net/ynl/generated/devlink-user.h
+++ /dev/null
@@ -1,1992 +0,0 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/devlink.yaml */
-/* YNL-GEN user header */
-
-#ifndef _LINUX_DEVLINK_GEN_H
-#define _LINUX_DEVLINK_GEN_H
-
-#include <stdlib.h>
-#include <string.h>
-#include <linux/types.h>
-#include <linux/devlink.h>
-
-struct ynl_sock;
-
-extern const struct ynl_family ynl_devlink_family;
-
-/* Enums */
-const char *devlink_op_str(int op);
-const char *devlink_sb_pool_type_str(enum devlink_sb_pool_type value);
-
-/* Common nested types */
-struct devlink_dl_info_version {
- struct {
- __u32 info_version_name_len;
- __u32 info_version_value_len;
- } _present;
-
- char *info_version_name;
- char *info_version_value;
-};
-
-struct devlink_dl_reload_stats_entry {
- struct {
- __u32 reload_stats_limit:1;
- __u32 reload_stats_value:1;
- } _present;
-
- __u8 reload_stats_limit;
- __u32 reload_stats_value;
-};
-
-struct devlink_dl_reload_act_stats {
- unsigned int n_reload_stats_entry;
- struct devlink_dl_reload_stats_entry *reload_stats_entry;
-};
-
-struct devlink_dl_reload_act_info {
- struct {
- __u32 reload_action:1;
- } _present;
-
- __u8 reload_action;
- unsigned int n_reload_action_stats;
- struct devlink_dl_reload_act_stats *reload_action_stats;
-};
-
-struct devlink_dl_reload_stats {
- unsigned int n_reload_action_info;
- struct devlink_dl_reload_act_info *reload_action_info;
-};
-
-struct devlink_dl_dev_stats {
- struct {
- __u32 reload_stats:1;
- __u32 remote_reload_stats:1;
- } _present;
-
- struct devlink_dl_reload_stats reload_stats;
- struct devlink_dl_reload_stats remote_reload_stats;
-};
-
-/* ============== DEVLINK_CMD_GET ============== */
-/* DEVLINK_CMD_GET - do */
-struct devlink_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_get_req *devlink_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_get_req));
-}
-void devlink_get_req_free(struct devlink_get_req *req);
-
-static inline void
-devlink_get_req_set_bus_name(struct devlink_get_req *req, const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_get_req_set_dev_name(struct devlink_get_req *req, const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 reload_failed:1;
- __u32 reload_action:1;
- __u32 dev_stats:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u8 reload_failed;
- __u8 reload_action;
- struct devlink_dl_dev_stats dev_stats;
-};
-
-void devlink_get_rsp_free(struct devlink_get_rsp *rsp);
-
-/*
- * Get devlink instances.
- */
-struct devlink_get_rsp *
-devlink_get(struct ynl_sock *ys, struct devlink_get_req *req);
-
-/* DEVLINK_CMD_GET - dump */
-struct devlink_get_list {
- struct devlink_get_list *next;
- struct devlink_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_get_list_free(struct devlink_get_list *rsp);
-
-struct devlink_get_list *devlink_get_dump(struct ynl_sock *ys);
-
-/* ============== DEVLINK_CMD_PORT_GET ============== */
-/* DEVLINK_CMD_PORT_GET - do */
-struct devlink_port_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
-};
-
-static inline struct devlink_port_get_req *devlink_port_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_port_get_req));
-}
-void devlink_port_get_req_free(struct devlink_port_get_req *req);
-
-static inline void
-devlink_port_get_req_set_bus_name(struct devlink_port_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_port_get_req_set_dev_name(struct devlink_port_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_port_get_req_set_port_index(struct devlink_port_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-
-struct devlink_port_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
-};
-
-void devlink_port_get_rsp_free(struct devlink_port_get_rsp *rsp);
-
-/*
- * Get devlink port instances.
- */
-struct devlink_port_get_rsp *
-devlink_port_get(struct ynl_sock *ys, struct devlink_port_get_req *req);
-
-/* DEVLINK_CMD_PORT_GET - dump */
-struct devlink_port_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_port_get_req_dump *
-devlink_port_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_port_get_req_dump));
-}
-void devlink_port_get_req_dump_free(struct devlink_port_get_req_dump *req);
-
-static inline void
-devlink_port_get_req_dump_set_bus_name(struct devlink_port_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_port_get_req_dump_set_dev_name(struct devlink_port_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_port_get_rsp_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
-};
-
-struct devlink_port_get_rsp_list {
- struct devlink_port_get_rsp_list *next;
- struct devlink_port_get_rsp_dump obj __attribute__ ((aligned (8)));
-};
-
-void devlink_port_get_rsp_list_free(struct devlink_port_get_rsp_list *rsp);
-
-struct devlink_port_get_rsp_list *
-devlink_port_get_dump(struct ynl_sock *ys,
- struct devlink_port_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_SB_GET ============== */
-/* DEVLINK_CMD_SB_GET - do */
-struct devlink_sb_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 sb_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 sb_index;
-};
-
-static inline struct devlink_sb_get_req *devlink_sb_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_get_req));
-}
-void devlink_sb_get_req_free(struct devlink_sb_get_req *req);
-
-static inline void
-devlink_sb_get_req_set_bus_name(struct devlink_sb_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_get_req_set_dev_name(struct devlink_sb_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_sb_get_req_set_sb_index(struct devlink_sb_get_req *req, __u32 sb_index)
-{
- req->_present.sb_index = 1;
- req->sb_index = sb_index;
-}
-
-struct devlink_sb_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 sb_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 sb_index;
-};
-
-void devlink_sb_get_rsp_free(struct devlink_sb_get_rsp *rsp);
-
-/*
- * Get shared buffer instances.
- */
-struct devlink_sb_get_rsp *
-devlink_sb_get(struct ynl_sock *ys, struct devlink_sb_get_req *req);
-
-/* DEVLINK_CMD_SB_GET - dump */
-struct devlink_sb_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_sb_get_req_dump *
-devlink_sb_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_get_req_dump));
-}
-void devlink_sb_get_req_dump_free(struct devlink_sb_get_req_dump *req);
-
-static inline void
-devlink_sb_get_req_dump_set_bus_name(struct devlink_sb_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_get_req_dump_set_dev_name(struct devlink_sb_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_sb_get_list {
- struct devlink_sb_get_list *next;
- struct devlink_sb_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_sb_get_list_free(struct devlink_sb_get_list *rsp);
-
-struct devlink_sb_get_list *
-devlink_sb_get_dump(struct ynl_sock *ys, struct devlink_sb_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_SB_POOL_GET ============== */
-/* DEVLINK_CMD_SB_POOL_GET - do */
-struct devlink_sb_pool_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 sb_index:1;
- __u32 sb_pool_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 sb_index;
- __u16 sb_pool_index;
-};
-
-static inline struct devlink_sb_pool_get_req *
-devlink_sb_pool_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_pool_get_req));
-}
-void devlink_sb_pool_get_req_free(struct devlink_sb_pool_get_req *req);
-
-static inline void
-devlink_sb_pool_get_req_set_bus_name(struct devlink_sb_pool_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_pool_get_req_set_dev_name(struct devlink_sb_pool_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_sb_pool_get_req_set_sb_index(struct devlink_sb_pool_get_req *req,
- __u32 sb_index)
-{
- req->_present.sb_index = 1;
- req->sb_index = sb_index;
-}
-static inline void
-devlink_sb_pool_get_req_set_sb_pool_index(struct devlink_sb_pool_get_req *req,
- __u16 sb_pool_index)
-{
- req->_present.sb_pool_index = 1;
- req->sb_pool_index = sb_pool_index;
-}
-
-struct devlink_sb_pool_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 sb_index:1;
- __u32 sb_pool_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 sb_index;
- __u16 sb_pool_index;
-};
-
-void devlink_sb_pool_get_rsp_free(struct devlink_sb_pool_get_rsp *rsp);
-
-/*
- * Get shared buffer pool instances.
- */
-struct devlink_sb_pool_get_rsp *
-devlink_sb_pool_get(struct ynl_sock *ys, struct devlink_sb_pool_get_req *req);
-
-/* DEVLINK_CMD_SB_POOL_GET - dump */
-struct devlink_sb_pool_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_sb_pool_get_req_dump *
-devlink_sb_pool_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_pool_get_req_dump));
-}
-void
-devlink_sb_pool_get_req_dump_free(struct devlink_sb_pool_get_req_dump *req);
-
-static inline void
-devlink_sb_pool_get_req_dump_set_bus_name(struct devlink_sb_pool_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_pool_get_req_dump_set_dev_name(struct devlink_sb_pool_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_sb_pool_get_list {
- struct devlink_sb_pool_get_list *next;
- struct devlink_sb_pool_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_sb_pool_get_list_free(struct devlink_sb_pool_get_list *rsp);
-
-struct devlink_sb_pool_get_list *
-devlink_sb_pool_get_dump(struct ynl_sock *ys,
- struct devlink_sb_pool_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_SB_PORT_POOL_GET ============== */
-/* DEVLINK_CMD_SB_PORT_POOL_GET - do */
-struct devlink_sb_port_pool_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 sb_index:1;
- __u32 sb_pool_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- __u32 sb_index;
- __u16 sb_pool_index;
-};
-
-static inline struct devlink_sb_port_pool_get_req *
-devlink_sb_port_pool_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_port_pool_get_req));
-}
-void
-devlink_sb_port_pool_get_req_free(struct devlink_sb_port_pool_get_req *req);
-
-static inline void
-devlink_sb_port_pool_get_req_set_bus_name(struct devlink_sb_port_pool_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_port_pool_get_req_set_dev_name(struct devlink_sb_port_pool_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_sb_port_pool_get_req_set_port_index(struct devlink_sb_port_pool_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-static inline void
-devlink_sb_port_pool_get_req_set_sb_index(struct devlink_sb_port_pool_get_req *req,
- __u32 sb_index)
-{
- req->_present.sb_index = 1;
- req->sb_index = sb_index;
-}
-static inline void
-devlink_sb_port_pool_get_req_set_sb_pool_index(struct devlink_sb_port_pool_get_req *req,
- __u16 sb_pool_index)
-{
- req->_present.sb_pool_index = 1;
- req->sb_pool_index = sb_pool_index;
-}
-
-struct devlink_sb_port_pool_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 sb_index:1;
- __u32 sb_pool_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- __u32 sb_index;
- __u16 sb_pool_index;
-};
-
-void
-devlink_sb_port_pool_get_rsp_free(struct devlink_sb_port_pool_get_rsp *rsp);
-
-/*
- * Get shared buffer port-pool combinations and threshold.
- */
-struct devlink_sb_port_pool_get_rsp *
-devlink_sb_port_pool_get(struct ynl_sock *ys,
- struct devlink_sb_port_pool_get_req *req);
-
-/* DEVLINK_CMD_SB_PORT_POOL_GET - dump */
-struct devlink_sb_port_pool_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_sb_port_pool_get_req_dump *
-devlink_sb_port_pool_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_port_pool_get_req_dump));
-}
-void
-devlink_sb_port_pool_get_req_dump_free(struct devlink_sb_port_pool_get_req_dump *req);
-
-static inline void
-devlink_sb_port_pool_get_req_dump_set_bus_name(struct devlink_sb_port_pool_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_port_pool_get_req_dump_set_dev_name(struct devlink_sb_port_pool_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_sb_port_pool_get_list {
- struct devlink_sb_port_pool_get_list *next;
- struct devlink_sb_port_pool_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-devlink_sb_port_pool_get_list_free(struct devlink_sb_port_pool_get_list *rsp);
-
-struct devlink_sb_port_pool_get_list *
-devlink_sb_port_pool_get_dump(struct ynl_sock *ys,
- struct devlink_sb_port_pool_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_SB_TC_POOL_BIND_GET ============== */
-/* DEVLINK_CMD_SB_TC_POOL_BIND_GET - do */
-struct devlink_sb_tc_pool_bind_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 sb_index:1;
- __u32 sb_pool_type:1;
- __u32 sb_tc_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- __u32 sb_index;
- enum devlink_sb_pool_type sb_pool_type;
- __u16 sb_tc_index;
-};
-
-static inline struct devlink_sb_tc_pool_bind_get_req *
-devlink_sb_tc_pool_bind_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_tc_pool_bind_get_req));
-}
-void
-devlink_sb_tc_pool_bind_get_req_free(struct devlink_sb_tc_pool_bind_get_req *req);
-
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_bus_name(struct devlink_sb_tc_pool_bind_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_dev_name(struct devlink_sb_tc_pool_bind_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_port_index(struct devlink_sb_tc_pool_bind_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_sb_index(struct devlink_sb_tc_pool_bind_get_req *req,
- __u32 sb_index)
-{
- req->_present.sb_index = 1;
- req->sb_index = sb_index;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_sb_pool_type(struct devlink_sb_tc_pool_bind_get_req *req,
- enum devlink_sb_pool_type sb_pool_type)
-{
- req->_present.sb_pool_type = 1;
- req->sb_pool_type = sb_pool_type;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_set_sb_tc_index(struct devlink_sb_tc_pool_bind_get_req *req,
- __u16 sb_tc_index)
-{
- req->_present.sb_tc_index = 1;
- req->sb_tc_index = sb_tc_index;
-}
-
-struct devlink_sb_tc_pool_bind_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 sb_index:1;
- __u32 sb_pool_type:1;
- __u32 sb_tc_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- __u32 sb_index;
- enum devlink_sb_pool_type sb_pool_type;
- __u16 sb_tc_index;
-};
-
-void
-devlink_sb_tc_pool_bind_get_rsp_free(struct devlink_sb_tc_pool_bind_get_rsp *rsp);
-
-/*
- * Get shared buffer port-TC to pool bindings and threshold.
- */
-struct devlink_sb_tc_pool_bind_get_rsp *
-devlink_sb_tc_pool_bind_get(struct ynl_sock *ys,
- struct devlink_sb_tc_pool_bind_get_req *req);
-
-/* DEVLINK_CMD_SB_TC_POOL_BIND_GET - dump */
-struct devlink_sb_tc_pool_bind_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_sb_tc_pool_bind_get_req_dump *
-devlink_sb_tc_pool_bind_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_sb_tc_pool_bind_get_req_dump));
-}
-void
-devlink_sb_tc_pool_bind_get_req_dump_free(struct devlink_sb_tc_pool_bind_get_req_dump *req);
-
-static inline void
-devlink_sb_tc_pool_bind_get_req_dump_set_bus_name(struct devlink_sb_tc_pool_bind_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_sb_tc_pool_bind_get_req_dump_set_dev_name(struct devlink_sb_tc_pool_bind_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_sb_tc_pool_bind_get_list {
- struct devlink_sb_tc_pool_bind_get_list *next;
- struct devlink_sb_tc_pool_bind_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-devlink_sb_tc_pool_bind_get_list_free(struct devlink_sb_tc_pool_bind_get_list *rsp);
-
-struct devlink_sb_tc_pool_bind_get_list *
-devlink_sb_tc_pool_bind_get_dump(struct ynl_sock *ys,
- struct devlink_sb_tc_pool_bind_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_PARAM_GET ============== */
-/* DEVLINK_CMD_PARAM_GET - do */
-struct devlink_param_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 param_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *param_name;
-};
-
-static inline struct devlink_param_get_req *devlink_param_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_param_get_req));
-}
-void devlink_param_get_req_free(struct devlink_param_get_req *req);
-
-static inline void
-devlink_param_get_req_set_bus_name(struct devlink_param_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_param_get_req_set_dev_name(struct devlink_param_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_param_get_req_set_param_name(struct devlink_param_get_req *req,
- const char *param_name)
-{
- free(req->param_name);
- req->_present.param_name_len = strlen(param_name);
- req->param_name = malloc(req->_present.param_name_len + 1);
- memcpy(req->param_name, param_name, req->_present.param_name_len);
- req->param_name[req->_present.param_name_len] = 0;
-}
-
-struct devlink_param_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 param_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *param_name;
-};
-
-void devlink_param_get_rsp_free(struct devlink_param_get_rsp *rsp);
-
-/*
- * Get param instances.
- */
-struct devlink_param_get_rsp *
-devlink_param_get(struct ynl_sock *ys, struct devlink_param_get_req *req);
-
-/* DEVLINK_CMD_PARAM_GET - dump */
-struct devlink_param_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_param_get_req_dump *
-devlink_param_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_param_get_req_dump));
-}
-void devlink_param_get_req_dump_free(struct devlink_param_get_req_dump *req);
-
-static inline void
-devlink_param_get_req_dump_set_bus_name(struct devlink_param_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_param_get_req_dump_set_dev_name(struct devlink_param_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_param_get_list {
- struct devlink_param_get_list *next;
- struct devlink_param_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_param_get_list_free(struct devlink_param_get_list *rsp);
-
-struct devlink_param_get_list *
-devlink_param_get_dump(struct ynl_sock *ys,
- struct devlink_param_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_REGION_GET ============== */
-/* DEVLINK_CMD_REGION_GET - do */
-struct devlink_region_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 region_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *region_name;
-};
-
-static inline struct devlink_region_get_req *devlink_region_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_region_get_req));
-}
-void devlink_region_get_req_free(struct devlink_region_get_req *req);
-
-static inline void
-devlink_region_get_req_set_bus_name(struct devlink_region_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_region_get_req_set_dev_name(struct devlink_region_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_region_get_req_set_port_index(struct devlink_region_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-static inline void
-devlink_region_get_req_set_region_name(struct devlink_region_get_req *req,
- const char *region_name)
-{
- free(req->region_name);
- req->_present.region_name_len = strlen(region_name);
- req->region_name = malloc(req->_present.region_name_len + 1);
- memcpy(req->region_name, region_name, req->_present.region_name_len);
- req->region_name[req->_present.region_name_len] = 0;
-}
-
-struct devlink_region_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 region_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *region_name;
-};
-
-void devlink_region_get_rsp_free(struct devlink_region_get_rsp *rsp);
-
-/*
- * Get region instances.
- */
-struct devlink_region_get_rsp *
-devlink_region_get(struct ynl_sock *ys, struct devlink_region_get_req *req);
-
-/* DEVLINK_CMD_REGION_GET - dump */
-struct devlink_region_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_region_get_req_dump *
-devlink_region_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_region_get_req_dump));
-}
-void devlink_region_get_req_dump_free(struct devlink_region_get_req_dump *req);
-
-static inline void
-devlink_region_get_req_dump_set_bus_name(struct devlink_region_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_region_get_req_dump_set_dev_name(struct devlink_region_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_region_get_list {
- struct devlink_region_get_list *next;
- struct devlink_region_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_region_get_list_free(struct devlink_region_get_list *rsp);
-
-struct devlink_region_get_list *
-devlink_region_get_dump(struct ynl_sock *ys,
- struct devlink_region_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_INFO_GET ============== */
-/* DEVLINK_CMD_INFO_GET - do */
-struct devlink_info_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_info_get_req *devlink_info_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_info_get_req));
-}
-void devlink_info_get_req_free(struct devlink_info_get_req *req);
-
-static inline void
-devlink_info_get_req_set_bus_name(struct devlink_info_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_info_get_req_set_dev_name(struct devlink_info_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_info_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 info_driver_name_len;
- __u32 info_serial_number_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *info_driver_name;
- char *info_serial_number;
- unsigned int n_info_version_fixed;
- struct devlink_dl_info_version *info_version_fixed;
- unsigned int n_info_version_running;
- struct devlink_dl_info_version *info_version_running;
- unsigned int n_info_version_stored;
- struct devlink_dl_info_version *info_version_stored;
-};
-
-void devlink_info_get_rsp_free(struct devlink_info_get_rsp *rsp);
-
-/*
- * Get device information, like driver name, hardware and firmware versions etc.
- */
-struct devlink_info_get_rsp *
-devlink_info_get(struct ynl_sock *ys, struct devlink_info_get_req *req);
-
-/* DEVLINK_CMD_INFO_GET - dump */
-struct devlink_info_get_list {
- struct devlink_info_get_list *next;
- struct devlink_info_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_info_get_list_free(struct devlink_info_get_list *rsp);
-
-struct devlink_info_get_list *devlink_info_get_dump(struct ynl_sock *ys);
-
-/* ============== DEVLINK_CMD_HEALTH_REPORTER_GET ============== */
-/* DEVLINK_CMD_HEALTH_REPORTER_GET - do */
-struct devlink_health_reporter_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 health_reporter_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *health_reporter_name;
-};
-
-static inline struct devlink_health_reporter_get_req *
-devlink_health_reporter_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_health_reporter_get_req));
-}
-void
-devlink_health_reporter_get_req_free(struct devlink_health_reporter_get_req *req);
-
-static inline void
-devlink_health_reporter_get_req_set_bus_name(struct devlink_health_reporter_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_health_reporter_get_req_set_dev_name(struct devlink_health_reporter_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_health_reporter_get_req_set_port_index(struct devlink_health_reporter_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-static inline void
-devlink_health_reporter_get_req_set_health_reporter_name(struct devlink_health_reporter_get_req *req,
- const char *health_reporter_name)
-{
- free(req->health_reporter_name);
- req->_present.health_reporter_name_len = strlen(health_reporter_name);
- req->health_reporter_name = malloc(req->_present.health_reporter_name_len + 1);
- memcpy(req->health_reporter_name, health_reporter_name, req->_present.health_reporter_name_len);
- req->health_reporter_name[req->_present.health_reporter_name_len] = 0;
-}
-
-struct devlink_health_reporter_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 health_reporter_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *health_reporter_name;
-};
-
-void
-devlink_health_reporter_get_rsp_free(struct devlink_health_reporter_get_rsp *rsp);
-
-/*
- * Get health reporter instances.
- */
-struct devlink_health_reporter_get_rsp *
-devlink_health_reporter_get(struct ynl_sock *ys,
- struct devlink_health_reporter_get_req *req);
-
-/* DEVLINK_CMD_HEALTH_REPORTER_GET - dump */
-struct devlink_health_reporter_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
-};
-
-static inline struct devlink_health_reporter_get_req_dump *
-devlink_health_reporter_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_health_reporter_get_req_dump));
-}
-void
-devlink_health_reporter_get_req_dump_free(struct devlink_health_reporter_get_req_dump *req);
-
-static inline void
-devlink_health_reporter_get_req_dump_set_bus_name(struct devlink_health_reporter_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_health_reporter_get_req_dump_set_dev_name(struct devlink_health_reporter_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_health_reporter_get_req_dump_set_port_index(struct devlink_health_reporter_get_req_dump *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-
-struct devlink_health_reporter_get_list {
- struct devlink_health_reporter_get_list *next;
- struct devlink_health_reporter_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-devlink_health_reporter_get_list_free(struct devlink_health_reporter_get_list *rsp);
-
-struct devlink_health_reporter_get_list *
-devlink_health_reporter_get_dump(struct ynl_sock *ys,
- struct devlink_health_reporter_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_TRAP_GET ============== */
-/* DEVLINK_CMD_TRAP_GET - do */
-struct devlink_trap_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *trap_name;
-};
-
-static inline struct devlink_trap_get_req *devlink_trap_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_get_req));
-}
-void devlink_trap_get_req_free(struct devlink_trap_get_req *req);
-
-static inline void
-devlink_trap_get_req_set_bus_name(struct devlink_trap_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_get_req_set_dev_name(struct devlink_trap_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_trap_get_req_set_trap_name(struct devlink_trap_get_req *req,
- const char *trap_name)
-{
- free(req->trap_name);
- req->_present.trap_name_len = strlen(trap_name);
- req->trap_name = malloc(req->_present.trap_name_len + 1);
- memcpy(req->trap_name, trap_name, req->_present.trap_name_len);
- req->trap_name[req->_present.trap_name_len] = 0;
-}
-
-struct devlink_trap_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *trap_name;
-};
-
-void devlink_trap_get_rsp_free(struct devlink_trap_get_rsp *rsp);
-
-/*
- * Get trap instances.
- */
-struct devlink_trap_get_rsp *
-devlink_trap_get(struct ynl_sock *ys, struct devlink_trap_get_req *req);
-
-/* DEVLINK_CMD_TRAP_GET - dump */
-struct devlink_trap_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_trap_get_req_dump *
-devlink_trap_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_get_req_dump));
-}
-void devlink_trap_get_req_dump_free(struct devlink_trap_get_req_dump *req);
-
-static inline void
-devlink_trap_get_req_dump_set_bus_name(struct devlink_trap_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_get_req_dump_set_dev_name(struct devlink_trap_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_trap_get_list {
- struct devlink_trap_get_list *next;
- struct devlink_trap_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_trap_get_list_free(struct devlink_trap_get_list *rsp);
-
-struct devlink_trap_get_list *
-devlink_trap_get_dump(struct ynl_sock *ys,
- struct devlink_trap_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_TRAP_GROUP_GET ============== */
-/* DEVLINK_CMD_TRAP_GROUP_GET - do */
-struct devlink_trap_group_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_group_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *trap_group_name;
-};
-
-static inline struct devlink_trap_group_get_req *
-devlink_trap_group_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_group_get_req));
-}
-void devlink_trap_group_get_req_free(struct devlink_trap_group_get_req *req);
-
-static inline void
-devlink_trap_group_get_req_set_bus_name(struct devlink_trap_group_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_group_get_req_set_dev_name(struct devlink_trap_group_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_trap_group_get_req_set_trap_group_name(struct devlink_trap_group_get_req *req,
- const char *trap_group_name)
-{
- free(req->trap_group_name);
- req->_present.trap_group_name_len = strlen(trap_group_name);
- req->trap_group_name = malloc(req->_present.trap_group_name_len + 1);
- memcpy(req->trap_group_name, trap_group_name, req->_present.trap_group_name_len);
- req->trap_group_name[req->_present.trap_group_name_len] = 0;
-}
-
-struct devlink_trap_group_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_group_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- char *trap_group_name;
-};
-
-void devlink_trap_group_get_rsp_free(struct devlink_trap_group_get_rsp *rsp);
-
-/*
- * Get trap group instances.
- */
-struct devlink_trap_group_get_rsp *
-devlink_trap_group_get(struct ynl_sock *ys,
- struct devlink_trap_group_get_req *req);
-
-/* DEVLINK_CMD_TRAP_GROUP_GET - dump */
-struct devlink_trap_group_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_trap_group_get_req_dump *
-devlink_trap_group_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_group_get_req_dump));
-}
-void
-devlink_trap_group_get_req_dump_free(struct devlink_trap_group_get_req_dump *req);
-
-static inline void
-devlink_trap_group_get_req_dump_set_bus_name(struct devlink_trap_group_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_group_get_req_dump_set_dev_name(struct devlink_trap_group_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_trap_group_get_list {
- struct devlink_trap_group_get_list *next;
- struct devlink_trap_group_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_trap_group_get_list_free(struct devlink_trap_group_get_list *rsp);
-
-struct devlink_trap_group_get_list *
-devlink_trap_group_get_dump(struct ynl_sock *ys,
- struct devlink_trap_group_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_TRAP_POLICER_GET ============== */
-/* DEVLINK_CMD_TRAP_POLICER_GET - do */
-struct devlink_trap_policer_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_policer_id:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 trap_policer_id;
-};
-
-static inline struct devlink_trap_policer_get_req *
-devlink_trap_policer_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_policer_get_req));
-}
-void
-devlink_trap_policer_get_req_free(struct devlink_trap_policer_get_req *req);
-
-static inline void
-devlink_trap_policer_get_req_set_bus_name(struct devlink_trap_policer_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_policer_get_req_set_dev_name(struct devlink_trap_policer_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_trap_policer_get_req_set_trap_policer_id(struct devlink_trap_policer_get_req *req,
- __u32 trap_policer_id)
-{
- req->_present.trap_policer_id = 1;
- req->trap_policer_id = trap_policer_id;
-}
-
-struct devlink_trap_policer_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 trap_policer_id:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 trap_policer_id;
-};
-
-void
-devlink_trap_policer_get_rsp_free(struct devlink_trap_policer_get_rsp *rsp);
-
-/*
- * Get trap policer instances.
- */
-struct devlink_trap_policer_get_rsp *
-devlink_trap_policer_get(struct ynl_sock *ys,
- struct devlink_trap_policer_get_req *req);
-
-/* DEVLINK_CMD_TRAP_POLICER_GET - dump */
-struct devlink_trap_policer_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_trap_policer_get_req_dump *
-devlink_trap_policer_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_trap_policer_get_req_dump));
-}
-void
-devlink_trap_policer_get_req_dump_free(struct devlink_trap_policer_get_req_dump *req);
-
-static inline void
-devlink_trap_policer_get_req_dump_set_bus_name(struct devlink_trap_policer_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_trap_policer_get_req_dump_set_dev_name(struct devlink_trap_policer_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_trap_policer_get_list {
- struct devlink_trap_policer_get_list *next;
- struct devlink_trap_policer_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-devlink_trap_policer_get_list_free(struct devlink_trap_policer_get_list *rsp);
-
-struct devlink_trap_policer_get_list *
-devlink_trap_policer_get_dump(struct ynl_sock *ys,
- struct devlink_trap_policer_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_RATE_GET ============== */
-/* DEVLINK_CMD_RATE_GET - do */
-struct devlink_rate_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 rate_node_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *rate_node_name;
-};
-
-static inline struct devlink_rate_get_req *devlink_rate_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_rate_get_req));
-}
-void devlink_rate_get_req_free(struct devlink_rate_get_req *req);
-
-static inline void
-devlink_rate_get_req_set_bus_name(struct devlink_rate_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_rate_get_req_set_dev_name(struct devlink_rate_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_rate_get_req_set_port_index(struct devlink_rate_get_req *req,
- __u32 port_index)
-{
- req->_present.port_index = 1;
- req->port_index = port_index;
-}
-static inline void
-devlink_rate_get_req_set_rate_node_name(struct devlink_rate_get_req *req,
- const char *rate_node_name)
-{
- free(req->rate_node_name);
- req->_present.rate_node_name_len = strlen(rate_node_name);
- req->rate_node_name = malloc(req->_present.rate_node_name_len + 1);
- memcpy(req->rate_node_name, rate_node_name, req->_present.rate_node_name_len);
- req->rate_node_name[req->_present.rate_node_name_len] = 0;
-}
-
-struct devlink_rate_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 port_index:1;
- __u32 rate_node_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 port_index;
- char *rate_node_name;
-};
-
-void devlink_rate_get_rsp_free(struct devlink_rate_get_rsp *rsp);
-
-/*
- * Get rate instances.
- */
-struct devlink_rate_get_rsp *
-devlink_rate_get(struct ynl_sock *ys, struct devlink_rate_get_req *req);
-
-/* DEVLINK_CMD_RATE_GET - dump */
-struct devlink_rate_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_rate_get_req_dump *
-devlink_rate_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_rate_get_req_dump));
-}
-void devlink_rate_get_req_dump_free(struct devlink_rate_get_req_dump *req);
-
-static inline void
-devlink_rate_get_req_dump_set_bus_name(struct devlink_rate_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_rate_get_req_dump_set_dev_name(struct devlink_rate_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_rate_get_list {
- struct devlink_rate_get_list *next;
- struct devlink_rate_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_rate_get_list_free(struct devlink_rate_get_list *rsp);
-
-struct devlink_rate_get_list *
-devlink_rate_get_dump(struct ynl_sock *ys,
- struct devlink_rate_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_LINECARD_GET ============== */
-/* DEVLINK_CMD_LINECARD_GET - do */
-struct devlink_linecard_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 linecard_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 linecard_index;
-};
-
-static inline struct devlink_linecard_get_req *
-devlink_linecard_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_linecard_get_req));
-}
-void devlink_linecard_get_req_free(struct devlink_linecard_get_req *req);
-
-static inline void
-devlink_linecard_get_req_set_bus_name(struct devlink_linecard_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_linecard_get_req_set_dev_name(struct devlink_linecard_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-static inline void
-devlink_linecard_get_req_set_linecard_index(struct devlink_linecard_get_req *req,
- __u32 linecard_index)
-{
- req->_present.linecard_index = 1;
- req->linecard_index = linecard_index;
-}
-
-struct devlink_linecard_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- __u32 linecard_index:1;
- } _present;
-
- char *bus_name;
- char *dev_name;
- __u32 linecard_index;
-};
-
-void devlink_linecard_get_rsp_free(struct devlink_linecard_get_rsp *rsp);
-
-/*
- * Get line card instances.
- */
-struct devlink_linecard_get_rsp *
-devlink_linecard_get(struct ynl_sock *ys, struct devlink_linecard_get_req *req);
-
-/* DEVLINK_CMD_LINECARD_GET - dump */
-struct devlink_linecard_get_req_dump {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_linecard_get_req_dump *
-devlink_linecard_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_linecard_get_req_dump));
-}
-void
-devlink_linecard_get_req_dump_free(struct devlink_linecard_get_req_dump *req);
-
-static inline void
-devlink_linecard_get_req_dump_set_bus_name(struct devlink_linecard_get_req_dump *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_linecard_get_req_dump_set_dev_name(struct devlink_linecard_get_req_dump *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_linecard_get_list {
- struct devlink_linecard_get_list *next;
- struct devlink_linecard_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_linecard_get_list_free(struct devlink_linecard_get_list *rsp);
-
-struct devlink_linecard_get_list *
-devlink_linecard_get_dump(struct ynl_sock *ys,
- struct devlink_linecard_get_req_dump *req);
-
-/* ============== DEVLINK_CMD_SELFTESTS_GET ============== */
-/* DEVLINK_CMD_SELFTESTS_GET - do */
-struct devlink_selftests_get_req {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-static inline struct devlink_selftests_get_req *
-devlink_selftests_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct devlink_selftests_get_req));
-}
-void devlink_selftests_get_req_free(struct devlink_selftests_get_req *req);
-
-static inline void
-devlink_selftests_get_req_set_bus_name(struct devlink_selftests_get_req *req,
- const char *bus_name)
-{
- free(req->bus_name);
- req->_present.bus_name_len = strlen(bus_name);
- req->bus_name = malloc(req->_present.bus_name_len + 1);
- memcpy(req->bus_name, bus_name, req->_present.bus_name_len);
- req->bus_name[req->_present.bus_name_len] = 0;
-}
-static inline void
-devlink_selftests_get_req_set_dev_name(struct devlink_selftests_get_req *req,
- const char *dev_name)
-{
- free(req->dev_name);
- req->_present.dev_name_len = strlen(dev_name);
- req->dev_name = malloc(req->_present.dev_name_len + 1);
- memcpy(req->dev_name, dev_name, req->_present.dev_name_len);
- req->dev_name[req->_present.dev_name_len] = 0;
-}
-
-struct devlink_selftests_get_rsp {
- struct {
- __u32 bus_name_len;
- __u32 dev_name_len;
- } _present;
-
- char *bus_name;
- char *dev_name;
-};
-
-void devlink_selftests_get_rsp_free(struct devlink_selftests_get_rsp *rsp);
-
-/*
- * Get device selftest instances.
- */
-struct devlink_selftests_get_rsp *
-devlink_selftests_get(struct ynl_sock *ys,
- struct devlink_selftests_get_req *req);
-
-/* DEVLINK_CMD_SELFTESTS_GET - dump */
-struct devlink_selftests_get_list {
- struct devlink_selftests_get_list *next;
- struct devlink_selftests_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void devlink_selftests_get_list_free(struct devlink_selftests_get_list *rsp);
-
-struct devlink_selftests_get_list *
-devlink_selftests_get_dump(struct ynl_sock *ys);
-
-#endif /* _LINUX_DEVLINK_GEN_H */
diff --git a/tools/net/ynl/generated/ethtool-user.c b/tools/net/ynl/generated/ethtool-user.c
deleted file mode 100644
index 74b883a14958..000000000000
--- a/tools/net/ynl/generated/ethtool-user.c
+++ /dev/null
@@ -1,6353 +0,0 @@
-// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/ethtool.yaml */
-/* YNL-GEN user source */
-/* YNL-ARG --user-header linux/ethtool_netlink.h --exclude-op stats-get */
-
-#include <stdlib.h>
-#include <string.h>
-#include "ethtool-user.h"
-#include "ynl.h"
-#include <linux/ethtool.h>
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-
-#include "linux/ethtool_netlink.h"
-
-/* Enums */
-static const char * const ethtool_op_strmap[] = {
- [ETHTOOL_MSG_STRSET_GET] = "strset-get",
- [ETHTOOL_MSG_LINKINFO_GET] = "linkinfo-get",
- [3] = "linkinfo-ntf",
- [ETHTOOL_MSG_LINKMODES_GET] = "linkmodes-get",
- [5] = "linkmodes-ntf",
- [ETHTOOL_MSG_LINKSTATE_GET] = "linkstate-get",
- [ETHTOOL_MSG_DEBUG_GET] = "debug-get",
- [8] = "debug-ntf",
- [ETHTOOL_MSG_WOL_GET] = "wol-get",
- [10] = "wol-ntf",
- [ETHTOOL_MSG_FEATURES_GET] = "features-get",
- [ETHTOOL_MSG_FEATURES_SET] = "features-set",
- [13] = "features-ntf",
- [14] = "privflags-get",
- [15] = "privflags-ntf",
- [16] = "rings-get",
- [17] = "rings-ntf",
- [18] = "channels-get",
- [19] = "channels-ntf",
- [20] = "coalesce-get",
- [21] = "coalesce-ntf",
- [22] = "pause-get",
- [23] = "pause-ntf",
- [24] = "eee-get",
- [25] = "eee-ntf",
- [26] = "tsinfo-get",
- [27] = "cable-test-ntf",
- [28] = "cable-test-tdr-ntf",
- [29] = "tunnel-info-get",
- [30] = "fec-get",
- [31] = "fec-ntf",
- [32] = "module-eeprom-get",
- [34] = "phc-vclocks-get",
- [35] = "module-get",
- [36] = "module-ntf",
- [37] = "pse-get",
- [ETHTOOL_MSG_RSS_GET] = "rss-get",
- [ETHTOOL_MSG_PLCA_GET_CFG] = "plca-get-cfg",
- [40] = "plca-get-status",
- [41] = "plca-ntf",
- [ETHTOOL_MSG_MM_GET] = "mm-get",
- [43] = "mm-ntf",
-};
-
-const char *ethtool_op_str(int op)
-{
- if (op < 0 || op >= (int)MNL_ARRAY_SIZE(ethtool_op_strmap))
- return NULL;
- return ethtool_op_strmap[op];
-}
-
-static const char * const ethtool_udp_tunnel_type_strmap[] = {
- [0] = "vxlan",
- [1] = "geneve",
- [2] = "vxlan-gpe",
-};
-
-const char *ethtool_udp_tunnel_type_str(int value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_udp_tunnel_type_strmap))
- return NULL;
- return ethtool_udp_tunnel_type_strmap[value];
-}
-
-static const char * const ethtool_stringset_strmap[] = {
-};
-
-const char *ethtool_stringset_str(enum ethtool_stringset value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_stringset_strmap))
- return NULL;
- return ethtool_stringset_strmap[value];
-}
-
-/* Policies */
-struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = {
- [ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, },
- [ETHTOOL_A_HEADER_DEV_NAME] = { .name = "dev-name", .type = YNL_PT_NUL_STR, },
- [ETHTOOL_A_HEADER_FLAGS] = { .name = "flags", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_header_nest = {
- .max_attr = ETHTOOL_A_HEADER_MAX,
- .table = ethtool_header_policy,
-};
-
-struct ynl_policy_attr ethtool_pause_stat_policy[ETHTOOL_A_PAUSE_STAT_MAX + 1] = {
- [ETHTOOL_A_PAUSE_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
- [ETHTOOL_A_PAUSE_STAT_TX_FRAMES] = { .name = "tx-frames", .type = YNL_PT_U64, },
- [ETHTOOL_A_PAUSE_STAT_RX_FRAMES] = { .name = "rx-frames", .type = YNL_PT_U64, },
-};
-
-struct ynl_policy_nest ethtool_pause_stat_nest = {
- .max_attr = ETHTOOL_A_PAUSE_STAT_MAX,
- .table = ethtool_pause_stat_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_test_tdr_cfg_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX + 1] = {
- [ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST] = { .name = "first", .type = YNL_PT_U32, },
- [ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST] = { .name = "last", .type = YNL_PT_U32, },
- [ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP] = { .name = "step", .type = YNL_PT_U32, },
- [ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
-};
-
-struct ynl_policy_nest ethtool_cable_test_tdr_cfg_nest = {
- .max_attr = ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX,
- .table = ethtool_cable_test_tdr_cfg_policy,
-};
-
-struct ynl_policy_attr ethtool_fec_stat_policy[ETHTOOL_A_FEC_STAT_MAX + 1] = {
- [ETHTOOL_A_FEC_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
- [ETHTOOL_A_FEC_STAT_CORRECTED] = { .name = "corrected", .type = YNL_PT_BINARY,},
- [ETHTOOL_A_FEC_STAT_UNCORR] = { .name = "uncorr", .type = YNL_PT_BINARY,},
- [ETHTOOL_A_FEC_STAT_CORR_BITS] = { .name = "corr-bits", .type = YNL_PT_BINARY,},
-};
-
-struct ynl_policy_nest ethtool_fec_stat_nest = {
- .max_attr = ETHTOOL_A_FEC_STAT_MAX,
- .table = ethtool_fec_stat_policy,
-};
-
-struct ynl_policy_attr ethtool_mm_stat_policy[ETHTOOL_A_MM_STAT_MAX + 1] = {
- [ETHTOOL_A_MM_STAT_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
- [ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS] = { .name = "reassembly-errors", .type = YNL_PT_U64, },
- [ETHTOOL_A_MM_STAT_SMD_ERRORS] = { .name = "smd-errors", .type = YNL_PT_U64, },
- [ETHTOOL_A_MM_STAT_REASSEMBLY_OK] = { .name = "reassembly-ok", .type = YNL_PT_U64, },
- [ETHTOOL_A_MM_STAT_RX_FRAG_COUNT] = { .name = "rx-frag-count", .type = YNL_PT_U64, },
- [ETHTOOL_A_MM_STAT_TX_FRAG_COUNT] = { .name = "tx-frag-count", .type = YNL_PT_U64, },
- [ETHTOOL_A_MM_STAT_HOLD_COUNT] = { .name = "hold-count", .type = YNL_PT_U64, },
-};
-
-struct ynl_policy_nest ethtool_mm_stat_nest = {
- .max_attr = ETHTOOL_A_MM_STAT_MAX,
- .table = ethtool_mm_stat_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_result_policy[ETHTOOL_A_CABLE_RESULT_MAX + 1] = {
- [ETHTOOL_A_CABLE_RESULT_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
- [ETHTOOL_A_CABLE_RESULT_CODE] = { .name = "code", .type = YNL_PT_U8, },
-};
-
-struct ynl_policy_nest ethtool_cable_result_nest = {
- .max_attr = ETHTOOL_A_CABLE_RESULT_MAX,
- .table = ethtool_cable_result_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_fault_length_policy[ETHTOOL_A_CABLE_FAULT_LENGTH_MAX + 1] = {
- [ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR] = { .name = "pair", .type = YNL_PT_U8, },
- [ETHTOOL_A_CABLE_FAULT_LENGTH_CM] = { .name = "cm", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_cable_fault_length_nest = {
- .max_attr = ETHTOOL_A_CABLE_FAULT_LENGTH_MAX,
- .table = ethtool_cable_fault_length_policy,
-};
-
-struct ynl_policy_attr ethtool_bitset_bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = {
- [ETHTOOL_A_BITSET_BIT_INDEX] = { .name = "index", .type = YNL_PT_U32, },
- [ETHTOOL_A_BITSET_BIT_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, },
- [ETHTOOL_A_BITSET_BIT_VALUE] = { .name = "value", .type = YNL_PT_FLAG, },
-};
-
-struct ynl_policy_nest ethtool_bitset_bit_nest = {
- .max_attr = ETHTOOL_A_BITSET_BIT_MAX,
- .table = ethtool_bitset_bit_policy,
-};
-
-struct ynl_policy_attr ethtool_tunnel_udp_entry_policy[ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX + 1] = {
- [ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT] = { .name = "port", .type = YNL_PT_U16, },
- [ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE] = { .name = "type", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_tunnel_udp_entry_nest = {
- .max_attr = ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX,
- .table = ethtool_tunnel_udp_entry_policy,
-};
-
-struct ynl_policy_attr ethtool_string_policy[ETHTOOL_A_STRING_MAX + 1] = {
- [ETHTOOL_A_STRING_INDEX] = { .name = "index", .type = YNL_PT_U32, },
- [ETHTOOL_A_STRING_VALUE] = { .name = "value", .type = YNL_PT_NUL_STR, },
-};
-
-struct ynl_policy_nest ethtool_string_nest = {
- .max_attr = ETHTOOL_A_STRING_MAX,
- .table = ethtool_string_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_nest_policy[ETHTOOL_A_CABLE_NEST_MAX + 1] = {
- [ETHTOOL_A_CABLE_NEST_RESULT] = { .name = "result", .type = YNL_PT_NEST, .nest = &ethtool_cable_result_nest, },
- [ETHTOOL_A_CABLE_NEST_FAULT_LENGTH] = { .name = "fault-length", .type = YNL_PT_NEST, .nest = &ethtool_cable_fault_length_nest, },
-};
-
-struct ynl_policy_nest ethtool_cable_nest_nest = {
- .max_attr = ETHTOOL_A_CABLE_NEST_MAX,
- .table = ethtool_cable_nest_policy,
-};
-
-struct ynl_policy_attr ethtool_bitset_bits_policy[ETHTOOL_A_BITSET_BITS_MAX + 1] = {
- [ETHTOOL_A_BITSET_BITS_BIT] = { .name = "bit", .type = YNL_PT_NEST, .nest = &ethtool_bitset_bit_nest, },
-};
-
-struct ynl_policy_nest ethtool_bitset_bits_nest = {
- .max_attr = ETHTOOL_A_BITSET_BITS_MAX,
- .table = ethtool_bitset_bits_policy,
-};
-
-struct ynl_policy_attr ethtool_strings_policy[ETHTOOL_A_STRINGS_MAX + 1] = {
- [ETHTOOL_A_STRINGS_STRING] = { .name = "string", .type = YNL_PT_NEST, .nest = &ethtool_string_nest, },
-};
-
-struct ynl_policy_nest ethtool_strings_nest = {
- .max_attr = ETHTOOL_A_STRINGS_MAX,
- .table = ethtool_strings_policy,
-};
-
-struct ynl_policy_attr ethtool_bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = {
- [ETHTOOL_A_BITSET_NOMASK] = { .name = "nomask", .type = YNL_PT_FLAG, },
- [ETHTOOL_A_BITSET_SIZE] = { .name = "size", .type = YNL_PT_U32, },
- [ETHTOOL_A_BITSET_BITS] = { .name = "bits", .type = YNL_PT_NEST, .nest = &ethtool_bitset_bits_nest, },
-};
-
-struct ynl_policy_nest ethtool_bitset_nest = {
- .max_attr = ETHTOOL_A_BITSET_MAX,
- .table = ethtool_bitset_policy,
-};
-
-struct ynl_policy_attr ethtool_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = {
- [ETHTOOL_A_STRINGSET_ID] = { .name = "id", .type = YNL_PT_U32, },
- [ETHTOOL_A_STRINGSET_COUNT] = { .name = "count", .type = YNL_PT_U32, },
- [ETHTOOL_A_STRINGSET_STRINGS] = { .name = "strings", .type = YNL_PT_NEST, .nest = &ethtool_strings_nest, },
-};
-
-struct ynl_policy_nest ethtool_stringset_nest = {
- .max_attr = ETHTOOL_A_STRINGSET_MAX,
- .table = ethtool_stringset_policy,
-};
-
-struct ynl_policy_attr ethtool_tunnel_udp_table_policy[ETHTOOL_A_TUNNEL_UDP_TABLE_MAX + 1] = {
- [ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE] = { .name = "size", .type = YNL_PT_U32, },
- [ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES] = { .name = "types", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY] = { .name = "entry", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_entry_nest, },
-};
-
-struct ynl_policy_nest ethtool_tunnel_udp_table_nest = {
- .max_attr = ETHTOOL_A_TUNNEL_UDP_TABLE_MAX,
- .table = ethtool_tunnel_udp_table_policy,
-};
-
-struct ynl_policy_attr ethtool_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = {
- [ETHTOOL_A_STRINGSETS_STRINGSET] = { .name = "stringset", .type = YNL_PT_NEST, .nest = &ethtool_stringset_nest, },
-};
-
-struct ynl_policy_nest ethtool_stringsets_nest = {
- .max_attr = ETHTOOL_A_STRINGSETS_MAX,
- .table = ethtool_stringsets_policy,
-};
-
-struct ynl_policy_attr ethtool_tunnel_udp_policy[ETHTOOL_A_TUNNEL_UDP_MAX + 1] = {
- [ETHTOOL_A_TUNNEL_UDP_TABLE] = { .name = "table", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_table_nest, },
-};
-
-struct ynl_policy_nest ethtool_tunnel_udp_nest = {
- .max_attr = ETHTOOL_A_TUNNEL_UDP_MAX,
- .table = ethtool_tunnel_udp_policy,
-};
-
-struct ynl_policy_attr ethtool_strset_policy[ETHTOOL_A_STRSET_MAX + 1] = {
- [ETHTOOL_A_STRSET_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_STRSET_STRINGSETS] = { .name = "stringsets", .type = YNL_PT_NEST, .nest = &ethtool_stringsets_nest, },
- [ETHTOOL_A_STRSET_COUNTS_ONLY] = { .name = "counts-only", .type = YNL_PT_FLAG, },
-};
-
-struct ynl_policy_nest ethtool_strset_nest = {
- .max_attr = ETHTOOL_A_STRSET_MAX,
- .table = ethtool_strset_policy,
-};
-
-struct ynl_policy_attr ethtool_linkinfo_policy[ETHTOOL_A_LINKINFO_MAX + 1] = {
- [ETHTOOL_A_LINKINFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_LINKINFO_PORT] = { .name = "port", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKINFO_PHYADDR] = { .name = "phyaddr", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKINFO_TP_MDIX] = { .name = "tp-mdix", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .name = "tp-mdix-ctrl", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .name = "transceiver", .type = YNL_PT_U8, },
-};
-
-struct ynl_policy_nest ethtool_linkinfo_nest = {
- .max_attr = ETHTOOL_A_LINKINFO_MAX,
- .table = ethtool_linkinfo_policy,
-};
-
-struct ynl_policy_attr ethtool_linkmodes_policy[ETHTOOL_A_LINKMODES_MAX + 1] = {
- [ETHTOOL_A_LINKMODES_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_LINKMODES_AUTONEG] = { .name = "autoneg", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKMODES_OURS] = { .name = "ours", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_LINKMODES_PEER] = { .name = "peer", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_LINKMODES_SPEED] = { .name = "speed", .type = YNL_PT_U32, },
- [ETHTOOL_A_LINKMODES_DUPLEX] = { .name = "duplex", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG] = { .name = "master-slave-cfg", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE] = { .name = "master-slave-state", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKMODES_LANES] = { .name = "lanes", .type = YNL_PT_U32, },
- [ETHTOOL_A_LINKMODES_RATE_MATCHING] = { .name = "rate-matching", .type = YNL_PT_U8, },
-};
-
-struct ynl_policy_nest ethtool_linkmodes_nest = {
- .max_attr = ETHTOOL_A_LINKMODES_MAX,
- .table = ethtool_linkmodes_policy,
-};
-
-struct ynl_policy_attr ethtool_linkstate_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = {
- [ETHTOOL_A_LINKSTATE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_LINKSTATE_LINK] = { .name = "link", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKSTATE_SQI] = { .name = "sqi", .type = YNL_PT_U32, },
- [ETHTOOL_A_LINKSTATE_SQI_MAX] = { .name = "sqi-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_LINKSTATE_EXT_STATE] = { .name = "ext-state", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKSTATE_EXT_SUBSTATE] = { .name = "ext-substate", .type = YNL_PT_U8, },
- [ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT] = { .name = "ext-down-cnt", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_linkstate_nest = {
- .max_attr = ETHTOOL_A_LINKSTATE_MAX,
- .table = ethtool_linkstate_policy,
-};
-
-struct ynl_policy_attr ethtool_debug_policy[ETHTOOL_A_DEBUG_MAX + 1] = {
- [ETHTOOL_A_DEBUG_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_DEBUG_MSGMASK] = { .name = "msgmask", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
-};
-
-struct ynl_policy_nest ethtool_debug_nest = {
- .max_attr = ETHTOOL_A_DEBUG_MAX,
- .table = ethtool_debug_policy,
-};
-
-struct ynl_policy_attr ethtool_wol_policy[ETHTOOL_A_WOL_MAX + 1] = {
- [ETHTOOL_A_WOL_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_WOL_MODES] = { .name = "modes", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_WOL_SOPASS] = { .name = "sopass", .type = YNL_PT_BINARY,},
-};
-
-struct ynl_policy_nest ethtool_wol_nest = {
- .max_attr = ETHTOOL_A_WOL_MAX,
- .table = ethtool_wol_policy,
-};
-
-struct ynl_policy_attr ethtool_features_policy[ETHTOOL_A_FEATURES_MAX + 1] = {
- [ETHTOOL_A_FEATURES_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_FEATURES_HW] = { .name = "hw", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_FEATURES_WANTED] = { .name = "wanted", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_FEATURES_ACTIVE] = { .name = "active", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_FEATURES_NOCHANGE] = { .name = "nochange", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
-};
-
-struct ynl_policy_nest ethtool_features_nest = {
- .max_attr = ETHTOOL_A_FEATURES_MAX,
- .table = ethtool_features_policy,
-};
-
-struct ynl_policy_attr ethtool_privflags_policy[ETHTOOL_A_PRIVFLAGS_MAX + 1] = {
- [ETHTOOL_A_PRIVFLAGS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_PRIVFLAGS_FLAGS] = { .name = "flags", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
-};
-
-struct ynl_policy_nest ethtool_privflags_nest = {
- .max_attr = ETHTOOL_A_PRIVFLAGS_MAX,
- .table = ethtool_privflags_policy,
-};
-
-struct ynl_policy_attr ethtool_rings_policy[ETHTOOL_A_RINGS_MAX + 1] = {
- [ETHTOOL_A_RINGS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_RINGS_RX_MAX] = { .name = "rx-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX_MINI_MAX] = { .name = "rx-mini-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX_JUMBO_MAX] = { .name = "rx-jumbo-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_TX_MAX] = { .name = "tx-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX] = { .name = "rx", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX_MINI] = { .name = "rx-mini", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX_JUMBO] = { .name = "rx-jumbo", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_TX] = { .name = "tx", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_RX_BUF_LEN] = { .name = "rx-buf-len", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_TCP_DATA_SPLIT] = { .name = "tcp-data-split", .type = YNL_PT_U8, },
- [ETHTOOL_A_RINGS_CQE_SIZE] = { .name = "cqe-size", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_TX_PUSH] = { .name = "tx-push", .type = YNL_PT_U8, },
- [ETHTOOL_A_RINGS_RX_PUSH] = { .name = "rx-push", .type = YNL_PT_U8, },
- [ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN] = { .name = "tx-push-buf-len", .type = YNL_PT_U32, },
- [ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX] = { .name = "tx-push-buf-len-max", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_rings_nest = {
- .max_attr = ETHTOOL_A_RINGS_MAX,
- .table = ethtool_rings_policy,
-};
-
-struct ynl_policy_attr ethtool_channels_policy[ETHTOOL_A_CHANNELS_MAX + 1] = {
- [ETHTOOL_A_CHANNELS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_CHANNELS_RX_MAX] = { .name = "rx-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_TX_MAX] = { .name = "tx-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .name = "other-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .name = "combined-max", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_RX_COUNT] = { .name = "rx-count", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_TX_COUNT] = { .name = "tx-count", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .name = "other-count", .type = YNL_PT_U32, },
- [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .name = "combined-count", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_channels_nest = {
- .max_attr = ETHTOOL_A_CHANNELS_MAX,
- .table = ethtool_channels_policy,
-};
-
-struct ynl_policy_attr ethtool_coalesce_policy[ETHTOOL_A_COALESCE_MAX + 1] = {
- [ETHTOOL_A_COALESCE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_COALESCE_RX_USECS] = { .name = "rx-usecs", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_MAX_FRAMES] = { .name = "rx-max-frames", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_USECS_IRQ] = { .name = "rx-usecs-irq", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ] = { .name = "rx-max-frames-irq", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_USECS] = { .name = "tx-usecs", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_MAX_FRAMES] = { .name = "tx-max-frames", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_USECS_IRQ] = { .name = "tx-usecs-irq", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ] = { .name = "tx-max-frames-irq", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_STATS_BLOCK_USECS] = { .name = "stats-block-usecs", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX] = { .name = "use-adaptive-rx", .type = YNL_PT_U8, },
- [ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX] = { .name = "use-adaptive-tx", .type = YNL_PT_U8, },
- [ETHTOOL_A_COALESCE_PKT_RATE_LOW] = { .name = "pkt-rate-low", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_USECS_LOW] = { .name = "rx-usecs-low", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW] = { .name = "rx-max-frames-low", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_USECS_LOW] = { .name = "tx-usecs-low", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW] = { .name = "tx-max-frames-low", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_PKT_RATE_HIGH] = { .name = "pkt-rate-high", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_USECS_HIGH] = { .name = "rx-usecs-high", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH] = { .name = "rx-max-frames-high", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_USECS_HIGH] = { .name = "tx-usecs-high", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH] = { .name = "tx-max-frames-high", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL] = { .name = "rate-sample-interval", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_USE_CQE_MODE_TX] = { .name = "use-cqe-mode-tx", .type = YNL_PT_U8, },
- [ETHTOOL_A_COALESCE_USE_CQE_MODE_RX] = { .name = "use-cqe-mode-rx", .type = YNL_PT_U8, },
- [ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES] = { .name = "tx-aggr-max-bytes", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES] = { .name = "tx-aggr-max-frames", .type = YNL_PT_U32, },
- [ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS] = { .name = "tx-aggr-time-usecs", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_coalesce_nest = {
- .max_attr = ETHTOOL_A_COALESCE_MAX,
- .table = ethtool_coalesce_policy,
-};
-
-struct ynl_policy_attr ethtool_pause_policy[ETHTOOL_A_PAUSE_MAX + 1] = {
- [ETHTOOL_A_PAUSE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_PAUSE_AUTONEG] = { .name = "autoneg", .type = YNL_PT_U8, },
- [ETHTOOL_A_PAUSE_RX] = { .name = "rx", .type = YNL_PT_U8, },
- [ETHTOOL_A_PAUSE_TX] = { .name = "tx", .type = YNL_PT_U8, },
- [ETHTOOL_A_PAUSE_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_pause_stat_nest, },
- [ETHTOOL_A_PAUSE_STATS_SRC] = { .name = "stats-src", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_pause_nest = {
- .max_attr = ETHTOOL_A_PAUSE_MAX,
- .table = ethtool_pause_policy,
-};
-
-struct ynl_policy_attr ethtool_eee_policy[ETHTOOL_A_EEE_MAX + 1] = {
- [ETHTOOL_A_EEE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_EEE_MODES_OURS] = { .name = "modes-ours", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_EEE_MODES_PEER] = { .name = "modes-peer", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_EEE_ACTIVE] = { .name = "active", .type = YNL_PT_U8, },
- [ETHTOOL_A_EEE_ENABLED] = { .name = "enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .name = "tx-lpi-enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .name = "tx-lpi-timer", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_eee_nest = {
- .max_attr = ETHTOOL_A_EEE_MAX,
- .table = ethtool_eee_policy,
-};
-
-struct ynl_policy_attr ethtool_tsinfo_policy[ETHTOOL_A_TSINFO_MAX + 1] = {
- [ETHTOOL_A_TSINFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_TSINFO_TIMESTAMPING] = { .name = "timestamping", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_TSINFO_TX_TYPES] = { .name = "tx-types", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_TSINFO_RX_FILTERS] = { .name = "rx-filters", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_TSINFO_PHC_INDEX] = { .name = "phc-index", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_tsinfo_nest = {
- .max_attr = ETHTOOL_A_TSINFO_MAX,
- .table = ethtool_tsinfo_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_test_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = {
- [ETHTOOL_A_CABLE_TEST_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
-};
-
-struct ynl_policy_nest ethtool_cable_test_nest = {
- .max_attr = ETHTOOL_A_CABLE_TEST_MAX,
- .table = ethtool_cable_test_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_test_ntf_policy[ETHTOOL_A_CABLE_TEST_NTF_MAX + 1] = {
- [ETHTOOL_A_CABLE_TEST_NTF_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_CABLE_TEST_NTF_STATUS] = { .name = "status", .type = YNL_PT_U8, },
- [ETHTOOL_A_CABLE_TEST_NTF_NEST] = { .name = "nest", .type = YNL_PT_NEST, .nest = &ethtool_cable_nest_nest, },
-};
-
-struct ynl_policy_nest ethtool_cable_test_ntf_nest = {
- .max_attr = ETHTOOL_A_CABLE_TEST_NTF_MAX,
- .table = ethtool_cable_test_ntf_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_test_tdr_policy[ETHTOOL_A_CABLE_TEST_TDR_MAX + 1] = {
- [ETHTOOL_A_CABLE_TEST_TDR_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_CABLE_TEST_TDR_CFG] = { .name = "cfg", .type = YNL_PT_NEST, .nest = &ethtool_cable_test_tdr_cfg_nest, },
-};
-
-struct ynl_policy_nest ethtool_cable_test_tdr_nest = {
- .max_attr = ETHTOOL_A_CABLE_TEST_TDR_MAX,
- .table = ethtool_cable_test_tdr_policy,
-};
-
-struct ynl_policy_attr ethtool_cable_test_tdr_ntf_policy[ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX + 1] = {
- [ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS] = { .name = "status", .type = YNL_PT_U8, },
- [ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST] = { .name = "nest", .type = YNL_PT_NEST, .nest = &ethtool_cable_nest_nest, },
-};
-
-struct ynl_policy_nest ethtool_cable_test_tdr_ntf_nest = {
- .max_attr = ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX,
- .table = ethtool_cable_test_tdr_ntf_policy,
-};
-
-struct ynl_policy_attr ethtool_tunnel_info_policy[ETHTOOL_A_TUNNEL_INFO_MAX + 1] = {
- [ETHTOOL_A_TUNNEL_INFO_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_TUNNEL_INFO_UDP_PORTS] = { .name = "udp-ports", .type = YNL_PT_NEST, .nest = &ethtool_tunnel_udp_nest, },
-};
-
-struct ynl_policy_nest ethtool_tunnel_info_nest = {
- .max_attr = ETHTOOL_A_TUNNEL_INFO_MAX,
- .table = ethtool_tunnel_info_policy,
-};
-
-struct ynl_policy_attr ethtool_fec_policy[ETHTOOL_A_FEC_MAX + 1] = {
- [ETHTOOL_A_FEC_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_FEC_MODES] = { .name = "modes", .type = YNL_PT_NEST, .nest = &ethtool_bitset_nest, },
- [ETHTOOL_A_FEC_AUTO] = { .name = "auto", .type = YNL_PT_U8, },
- [ETHTOOL_A_FEC_ACTIVE] = { .name = "active", .type = YNL_PT_U32, },
- [ETHTOOL_A_FEC_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_fec_stat_nest, },
-};
-
-struct ynl_policy_nest ethtool_fec_nest = {
- .max_attr = ETHTOOL_A_FEC_MAX,
- .table = ethtool_fec_policy,
-};
-
-struct ynl_policy_attr ethtool_module_eeprom_policy[ETHTOOL_A_MODULE_EEPROM_MAX + 1] = {
- [ETHTOOL_A_MODULE_EEPROM_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_MODULE_EEPROM_OFFSET] = { .name = "offset", .type = YNL_PT_U32, },
- [ETHTOOL_A_MODULE_EEPROM_LENGTH] = { .name = "length", .type = YNL_PT_U32, },
- [ETHTOOL_A_MODULE_EEPROM_PAGE] = { .name = "page", .type = YNL_PT_U8, },
- [ETHTOOL_A_MODULE_EEPROM_BANK] = { .name = "bank", .type = YNL_PT_U8, },
- [ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS] = { .name = "i2c-address", .type = YNL_PT_U8, },
- [ETHTOOL_A_MODULE_EEPROM_DATA] = { .name = "data", .type = YNL_PT_BINARY,},
-};
-
-struct ynl_policy_nest ethtool_module_eeprom_nest = {
- .max_attr = ETHTOOL_A_MODULE_EEPROM_MAX,
- .table = ethtool_module_eeprom_policy,
-};
-
-struct ynl_policy_attr ethtool_phc_vclocks_policy[ETHTOOL_A_PHC_VCLOCKS_MAX + 1] = {
- [ETHTOOL_A_PHC_VCLOCKS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_PHC_VCLOCKS_NUM] = { .name = "num", .type = YNL_PT_U32, },
- [ETHTOOL_A_PHC_VCLOCKS_INDEX] = { .name = "index", .type = YNL_PT_BINARY,},
-};
-
-struct ynl_policy_nest ethtool_phc_vclocks_nest = {
- .max_attr = ETHTOOL_A_PHC_VCLOCKS_MAX,
- .table = ethtool_phc_vclocks_policy,
-};
-
-struct ynl_policy_attr ethtool_module_policy[ETHTOOL_A_MODULE_MAX + 1] = {
- [ETHTOOL_A_MODULE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_MODULE_POWER_MODE_POLICY] = { .name = "power-mode-policy", .type = YNL_PT_U8, },
- [ETHTOOL_A_MODULE_POWER_MODE] = { .name = "power-mode", .type = YNL_PT_U8, },
-};
-
-struct ynl_policy_nest ethtool_module_nest = {
- .max_attr = ETHTOOL_A_MODULE_MAX,
- .table = ethtool_module_policy,
-};
-
-struct ynl_policy_attr ethtool_pse_policy[ETHTOOL_A_PSE_MAX + 1] = {
- [ETHTOOL_A_PSE_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_PODL_PSE_ADMIN_STATE] = { .name = "admin-state", .type = YNL_PT_U32, },
- [ETHTOOL_A_PODL_PSE_ADMIN_CONTROL] = { .name = "admin-control", .type = YNL_PT_U32, },
- [ETHTOOL_A_PODL_PSE_PW_D_STATUS] = { .name = "pw-d-status", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_pse_nest = {
- .max_attr = ETHTOOL_A_PSE_MAX,
- .table = ethtool_pse_policy,
-};
-
-struct ynl_policy_attr ethtool_rss_policy[ETHTOOL_A_RSS_MAX + 1] = {
- [ETHTOOL_A_RSS_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_RSS_CONTEXT] = { .name = "context", .type = YNL_PT_U32, },
- [ETHTOOL_A_RSS_HFUNC] = { .name = "hfunc", .type = YNL_PT_U32, },
- [ETHTOOL_A_RSS_INDIR] = { .name = "indir", .type = YNL_PT_BINARY,},
- [ETHTOOL_A_RSS_HKEY] = { .name = "hkey", .type = YNL_PT_BINARY,},
-};
-
-struct ynl_policy_nest ethtool_rss_nest = {
- .max_attr = ETHTOOL_A_RSS_MAX,
- .table = ethtool_rss_policy,
-};
-
-struct ynl_policy_attr ethtool_plca_policy[ETHTOOL_A_PLCA_MAX + 1] = {
- [ETHTOOL_A_PLCA_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_PLCA_VERSION] = { .name = "version", .type = YNL_PT_U16, },
- [ETHTOOL_A_PLCA_ENABLED] = { .name = "enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_PLCA_STATUS] = { .name = "status", .type = YNL_PT_U8, },
- [ETHTOOL_A_PLCA_NODE_CNT] = { .name = "node-cnt", .type = YNL_PT_U32, },
- [ETHTOOL_A_PLCA_NODE_ID] = { .name = "node-id", .type = YNL_PT_U32, },
- [ETHTOOL_A_PLCA_TO_TMR] = { .name = "to-tmr", .type = YNL_PT_U32, },
- [ETHTOOL_A_PLCA_BURST_CNT] = { .name = "burst-cnt", .type = YNL_PT_U32, },
- [ETHTOOL_A_PLCA_BURST_TMR] = { .name = "burst-tmr", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest ethtool_plca_nest = {
- .max_attr = ETHTOOL_A_PLCA_MAX,
- .table = ethtool_plca_policy,
-};
-
-struct ynl_policy_attr ethtool_mm_policy[ETHTOOL_A_MM_MAX + 1] = {
- [ETHTOOL_A_MM_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = &ethtool_header_nest, },
- [ETHTOOL_A_MM_PMAC_ENABLED] = { .name = "pmac-enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_MM_TX_ENABLED] = { .name = "tx-enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_MM_TX_ACTIVE] = { .name = "tx-active", .type = YNL_PT_U8, },
- [ETHTOOL_A_MM_TX_MIN_FRAG_SIZE] = { .name = "tx-min-frag-size", .type = YNL_PT_U32, },
- [ETHTOOL_A_MM_RX_MIN_FRAG_SIZE] = { .name = "rx-min-frag-size", .type = YNL_PT_U32, },
- [ETHTOOL_A_MM_VERIFY_ENABLED] = { .name = "verify-enabled", .type = YNL_PT_U8, },
- [ETHTOOL_A_MM_VERIFY_STATUS] = { .name = "verify-status", .type = YNL_PT_U8, },
- [ETHTOOL_A_MM_VERIFY_TIME] = { .name = "verify-time", .type = YNL_PT_U32, },
- [ETHTOOL_A_MM_MAX_VERIFY_TIME] = { .name = "max-verify-time", .type = YNL_PT_U32, },
- [ETHTOOL_A_MM_STATS] = { .name = "stats", .type = YNL_PT_NEST, .nest = &ethtool_mm_stat_nest, },
-};
-
-struct ynl_policy_nest ethtool_mm_nest = {
- .max_attr = ETHTOOL_A_MM_MAX,
- .table = ethtool_mm_policy,
-};
-
-/* Common nested types */
-void ethtool_header_free(struct ethtool_header *obj)
-{
- free(obj->dev_name);
-}
-
-int ethtool_header_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_header *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.dev_index)
- mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_DEV_INDEX, obj->dev_index);
- if (obj->_present.dev_name_len)
- mnl_attr_put_strz(nlh, ETHTOOL_A_HEADER_DEV_NAME, obj->dev_name);
- if (obj->_present.flags)
- mnl_attr_put_u32(nlh, ETHTOOL_A_HEADER_FLAGS, obj->flags);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_header_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_header *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_HEADER_DEV_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.dev_index = 1;
- dst->dev_index = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_HEADER_DEV_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.dev_name_len = len;
- dst->dev_name = malloc(len + 1);
- memcpy(dst->dev_name, mnl_attr_get_str(attr), len);
- dst->dev_name[len] = 0;
- } else if (type == ETHTOOL_A_HEADER_FLAGS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.flags = 1;
- dst->flags = mnl_attr_get_u32(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_pause_stat_free(struct ethtool_pause_stat *obj)
-{
-}
-
-int ethtool_pause_stat_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_pause_stat *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.tx_frames)
- mnl_attr_put_u64(nlh, ETHTOOL_A_PAUSE_STAT_TX_FRAMES, obj->tx_frames);
- if (obj->_present.rx_frames)
- mnl_attr_put_u64(nlh, ETHTOOL_A_PAUSE_STAT_RX_FRAMES, obj->rx_frames);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_pause_stat_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_pause_stat *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PAUSE_STAT_TX_FRAMES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_frames = 1;
- dst->tx_frames = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_PAUSE_STAT_RX_FRAMES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_frames = 1;
- dst->rx_frames = mnl_attr_get_u64(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_cable_test_tdr_cfg_free(struct ethtool_cable_test_tdr_cfg *obj)
-{
-}
-
-void ethtool_fec_stat_free(struct ethtool_fec_stat *obj)
-{
- free(obj->corrected);
- free(obj->uncorr);
- free(obj->corr_bits);
-}
-
-int ethtool_fec_stat_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_fec_stat *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.corrected_len)
- mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_CORRECTED, obj->_present.corrected_len, obj->corrected);
- if (obj->_present.uncorr_len)
- mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_UNCORR, obj->_present.uncorr_len, obj->uncorr);
- if (obj->_present.corr_bits_len)
- mnl_attr_put(nlh, ETHTOOL_A_FEC_STAT_CORR_BITS, obj->_present.corr_bits_len, obj->corr_bits);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_fec_stat_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_fec_stat *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_FEC_STAT_CORRECTED) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.corrected_len = len;
- dst->corrected = malloc(len);
- memcpy(dst->corrected, mnl_attr_get_payload(attr), len);
- } else if (type == ETHTOOL_A_FEC_STAT_UNCORR) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.uncorr_len = len;
- dst->uncorr = malloc(len);
- memcpy(dst->uncorr, mnl_attr_get_payload(attr), len);
- } else if (type == ETHTOOL_A_FEC_STAT_CORR_BITS) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.corr_bits_len = len;
- dst->corr_bits = malloc(len);
- memcpy(dst->corr_bits, mnl_attr_get_payload(attr), len);
- }
- }
-
- return 0;
-}
-
-void ethtool_mm_stat_free(struct ethtool_mm_stat *obj)
-{
-}
-
-int ethtool_mm_stat_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_mm_stat *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reassembly_errors = 1;
- dst->reassembly_errors = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_MM_STAT_SMD_ERRORS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.smd_errors = 1;
- dst->smd_errors = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_MM_STAT_REASSEMBLY_OK) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.reassembly_ok = 1;
- dst->reassembly_ok = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_MM_STAT_RX_FRAG_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_frag_count = 1;
- dst->rx_frag_count = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_MM_STAT_TX_FRAG_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_frag_count = 1;
- dst->tx_frag_count = mnl_attr_get_u64(attr);
- } else if (type == ETHTOOL_A_MM_STAT_HOLD_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.hold_count = 1;
- dst->hold_count = mnl_attr_get_u64(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_cable_result_free(struct ethtool_cable_result *obj)
-{
-}
-
-int ethtool_cable_result_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_cable_result *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CABLE_RESULT_PAIR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pair = 1;
- dst->pair = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_CABLE_RESULT_CODE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.code = 1;
- dst->code = mnl_attr_get_u8(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_cable_fault_length_free(struct ethtool_cable_fault_length *obj)
-{
-}
-
-int ethtool_cable_fault_length_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_cable_fault_length *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pair = 1;
- dst->pair = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_CABLE_FAULT_LENGTH_CM) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.cm = 1;
- dst->cm = mnl_attr_get_u32(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_bitset_bit_free(struct ethtool_bitset_bit *obj)
-{
- free(obj->name);
-}
-
-int ethtool_bitset_bit_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_bitset_bit *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.index)
- mnl_attr_put_u32(nlh, ETHTOOL_A_BITSET_BIT_INDEX, obj->index);
- if (obj->_present.name_len)
- mnl_attr_put_strz(nlh, ETHTOOL_A_BITSET_BIT_NAME, obj->name);
- if (obj->_present.value)
- mnl_attr_put(nlh, ETHTOOL_A_BITSET_BIT_VALUE, 0, NULL);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_bitset_bit_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_bitset_bit *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_BITSET_BIT_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.index = 1;
- dst->index = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_BITSET_BIT_NAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.name_len = len;
- dst->name = malloc(len + 1);
- memcpy(dst->name, mnl_attr_get_str(attr), len);
- dst->name[len] = 0;
- } else if (type == ETHTOOL_A_BITSET_BIT_VALUE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.value = 1;
- }
- }
-
- return 0;
-}
-
-void ethtool_tunnel_udp_entry_free(struct ethtool_tunnel_udp_entry *obj)
-{
-}
-
-int ethtool_tunnel_udp_entry_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_tunnel_udp_entry *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port = 1;
- dst->port = mnl_attr_get_u16(attr);
- } else if (type == ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.type = 1;
- dst->type = mnl_attr_get_u32(attr);
- }
- }
-
- return 0;
-}
-
-void ethtool_string_free(struct ethtool_string *obj)
-{
- free(obj->value);
-}
-
-int ethtool_string_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_string *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.index)
- mnl_attr_put_u32(nlh, ETHTOOL_A_STRING_INDEX, obj->index);
- if (obj->_present.value_len)
- mnl_attr_put_strz(nlh, ETHTOOL_A_STRING_VALUE, obj->value);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_string_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_string *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_STRING_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.index = 1;
- dst->index = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_STRING_VALUE) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.value_len = len;
- dst->value = malloc(len + 1);
- memcpy(dst->value, mnl_attr_get_str(attr), len);
- dst->value[len] = 0;
- }
- }
-
- return 0;
-}
-
-void ethtool_cable_nest_free(struct ethtool_cable_nest *obj)
-{
- ethtool_cable_result_free(&obj->result);
- ethtool_cable_fault_length_free(&obj->fault_length);
-}
-
-int ethtool_cable_nest_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_cable_nest *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- parg.ys = yarg->ys;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CABLE_NEST_RESULT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.result = 1;
-
- parg.rsp_policy = &ethtool_cable_result_nest;
- parg.data = &dst->result;
- if (ethtool_cable_result_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_CABLE_NEST_FAULT_LENGTH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.fault_length = 1;
-
- parg.rsp_policy = &ethtool_cable_fault_length_nest;
- parg.data = &dst->fault_length;
- if (ethtool_cable_fault_length_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return 0;
-}
-
-void ethtool_bitset_bits_free(struct ethtool_bitset_bits *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_bit; i++)
- ethtool_bitset_bit_free(&obj->bit[i]);
- free(obj->bit);
-}
-
-int ethtool_bitset_bits_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_bitset_bits *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- for (unsigned int i = 0; i < obj->n_bit; i++)
- ethtool_bitset_bit_put(nlh, ETHTOOL_A_BITSET_BITS_BIT, &obj->bit[i]);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_bitset_bits_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_bitset_bits *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- unsigned int n_bit = 0;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->bit)
- return ynl_error_parse(yarg, "attribute already present (bitset-bits.bit)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_BITSET_BITS_BIT) {
- n_bit++;
- }
- }
-
- if (n_bit) {
- dst->bit = calloc(n_bit, sizeof(*dst->bit));
- dst->n_bit = n_bit;
- i = 0;
- parg.rsp_policy = &ethtool_bitset_bit_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == ETHTOOL_A_BITSET_BITS_BIT) {
- parg.data = &dst->bit[i];
- if (ethtool_bitset_bit_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void ethtool_strings_free(struct ethtool_strings *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_string; i++)
- ethtool_string_free(&obj->string[i]);
- free(obj->string);
-}
-
-int ethtool_strings_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_strings *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- for (unsigned int i = 0; i < obj->n_string; i++)
- ethtool_string_put(nlh, ETHTOOL_A_STRINGS_STRING, &obj->string[i]);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_strings_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_strings *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- unsigned int n_string = 0;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->string)
- return ynl_error_parse(yarg, "attribute already present (strings.string)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_STRINGS_STRING) {
- n_string++;
- }
- }
-
- if (n_string) {
- dst->string = calloc(n_string, sizeof(*dst->string));
- dst->n_string = n_string;
- i = 0;
- parg.rsp_policy = &ethtool_string_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGS_STRING) {
- parg.data = &dst->string[i];
- if (ethtool_string_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void ethtool_bitset_free(struct ethtool_bitset *obj)
-{
- ethtool_bitset_bits_free(&obj->bits);
-}
-
-int ethtool_bitset_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_bitset *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.nomask)
- mnl_attr_put(nlh, ETHTOOL_A_BITSET_NOMASK, 0, NULL);
- if (obj->_present.size)
- mnl_attr_put_u32(nlh, ETHTOOL_A_BITSET_SIZE, obj->size);
- if (obj->_present.bits)
- ethtool_bitset_bits_put(nlh, ETHTOOL_A_BITSET_BITS, &obj->bits);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_bitset_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_bitset *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- parg.ys = yarg->ys;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_BITSET_NOMASK) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.nomask = 1;
- } else if (type == ETHTOOL_A_BITSET_SIZE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.size = 1;
- dst->size = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_BITSET_BITS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.bits = 1;
-
- parg.rsp_policy = &ethtool_bitset_bits_nest;
- parg.data = &dst->bits;
- if (ethtool_bitset_bits_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return 0;
-}
-
-void ethtool_stringset_free(struct ethtool_stringset_ *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_strings; i++)
- ethtool_strings_free(&obj->strings[i]);
- free(obj->strings);
-}
-
-int ethtool_stringset_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_stringset_ *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- if (obj->_present.id)
- mnl_attr_put_u32(nlh, ETHTOOL_A_STRINGSET_ID, obj->id);
- if (obj->_present.count)
- mnl_attr_put_u32(nlh, ETHTOOL_A_STRINGSET_COUNT, obj->count);
- for (unsigned int i = 0; i < obj->n_strings; i++)
- ethtool_strings_put(nlh, ETHTOOL_A_STRINGSET_STRINGS, &obj->strings[i]);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_stringset_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_stringset_ *dst = yarg->data;
- unsigned int n_strings = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->strings)
- return ynl_error_parse(yarg, "attribute already present (stringset.strings)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_STRINGSET_ID) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.id = 1;
- dst->id = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_STRINGSET_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.count = 1;
- dst->count = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_STRINGSET_STRINGS) {
- n_strings++;
- }
- }
-
- if (n_strings) {
- dst->strings = calloc(n_strings, sizeof(*dst->strings));
- dst->n_strings = n_strings;
- i = 0;
- parg.rsp_policy = &ethtool_strings_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGSET_STRINGS) {
- parg.data = &dst->strings[i];
- if (ethtool_strings_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void ethtool_tunnel_udp_table_free(struct ethtool_tunnel_udp_table *obj)
-{
- unsigned int i;
-
- ethtool_bitset_free(&obj->types);
- for (i = 0; i < obj->n_entry; i++)
- ethtool_tunnel_udp_entry_free(&obj->entry[i]);
- free(obj->entry);
-}
-
-int ethtool_tunnel_udp_table_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_tunnel_udp_table *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- unsigned int n_entry = 0;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->entry)
- return ynl_error_parse(yarg, "attribute already present (tunnel-udp-table.entry)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.size = 1;
- dst->size = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.types = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->types;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY) {
- n_entry++;
- }
- }
-
- if (n_entry) {
- dst->entry = calloc(n_entry, sizeof(*dst->entry));
- dst->n_entry = n_entry;
- i = 0;
- parg.rsp_policy = &ethtool_tunnel_udp_entry_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY) {
- parg.data = &dst->entry[i];
- if (ethtool_tunnel_udp_entry_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void ethtool_stringsets_free(struct ethtool_stringsets *obj)
-{
- unsigned int i;
-
- for (i = 0; i < obj->n_stringset; i++)
- ethtool_stringset_free(&obj->stringset[i]);
- free(obj->stringset);
-}
-
-int ethtool_stringsets_put(struct nlmsghdr *nlh, unsigned int attr_type,
- struct ethtool_stringsets *obj)
-{
- struct nlattr *nest;
-
- nest = mnl_attr_nest_start(nlh, attr_type);
- for (unsigned int i = 0; i < obj->n_stringset; i++)
- ethtool_stringset_put(nlh, ETHTOOL_A_STRINGSETS_STRINGSET, &obj->stringset[i]);
- mnl_attr_nest_end(nlh, nest);
-
- return 0;
-}
-
-int ethtool_stringsets_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_stringsets *dst = yarg->data;
- unsigned int n_stringset = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- parg.ys = yarg->ys;
-
- if (dst->stringset)
- return ynl_error_parse(yarg, "attribute already present (stringsets.stringset)");
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_STRINGSETS_STRINGSET) {
- n_stringset++;
- }
- }
-
- if (n_stringset) {
- dst->stringset = calloc(n_stringset, sizeof(*dst->stringset));
- dst->n_stringset = n_stringset;
- i = 0;
- parg.rsp_policy = &ethtool_stringset_nest;
- mnl_attr_for_each_nested(attr, nested) {
- if (mnl_attr_get_type(attr) == ETHTOOL_A_STRINGSETS_STRINGSET) {
- parg.data = &dst->stringset[i];
- if (ethtool_stringset_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
-
- return 0;
-}
-
-void ethtool_tunnel_udp_free(struct ethtool_tunnel_udp *obj)
-{
- ethtool_tunnel_udp_table_free(&obj->table);
-}
-
-int ethtool_tunnel_udp_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct ethtool_tunnel_udp *dst = yarg->data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- parg.ys = yarg->ys;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_TUNNEL_UDP_TABLE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.table = 1;
-
- parg.rsp_policy = &ethtool_tunnel_udp_table_nest;
- parg.data = &dst->table;
- if (ethtool_tunnel_udp_table_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_STRSET_GET ============== */
-/* ETHTOOL_MSG_STRSET_GET - do */
-void ethtool_strset_get_req_free(struct ethtool_strset_get_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_stringsets_free(&req->stringsets);
- free(req);
-}
-
-void ethtool_strset_get_rsp_free(struct ethtool_strset_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_stringsets_free(&rsp->stringsets);
- free(rsp);
-}
-
-int ethtool_strset_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_strset_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_STRSET_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_STRSET_STRINGSETS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stringsets = 1;
-
- parg.rsp_policy = &ethtool_stringsets_nest;
- parg.data = &dst->stringsets;
- if (ethtool_stringsets_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_strset_get_rsp *
-ethtool_strset_get(struct ynl_sock *ys, struct ethtool_strset_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_strset_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_STRSET_GET, 1);
- ys->req_policy = &ethtool_strset_nest;
- yrs.yarg.rsp_policy = &ethtool_strset_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_STRSET_HEADER, &req->header);
- if (req->_present.stringsets)
- ethtool_stringsets_put(nlh, ETHTOOL_A_STRSET_STRINGSETS, &req->stringsets);
- if (req->_present.counts_only)
- mnl_attr_put(nlh, ETHTOOL_A_STRSET_COUNTS_ONLY, 0, NULL);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_strset_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_STRSET_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_strset_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_STRSET_GET - dump */
-void ethtool_strset_get_list_free(struct ethtool_strset_get_list *rsp)
-{
- struct ethtool_strset_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_stringsets_free(&rsp->obj.stringsets);
- free(rsp);
- }
-}
-
-struct ethtool_strset_get_list *
-ethtool_strset_get_dump(struct ynl_sock *ys,
- struct ethtool_strset_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_strset_get_list);
- yds.cb = ethtool_strset_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_STRSET_GET;
- yds.rsp_policy = &ethtool_strset_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_STRSET_GET, 1);
- ys->req_policy = &ethtool_strset_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_STRSET_HEADER, &req->header);
- if (req->_present.stringsets)
- ethtool_stringsets_put(nlh, ETHTOOL_A_STRSET_STRINGSETS, &req->stringsets);
- if (req->_present.counts_only)
- mnl_attr_put(nlh, ETHTOOL_A_STRSET_COUNTS_ONLY, 0, NULL);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_strset_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_LINKINFO_GET ============== */
-/* ETHTOOL_MSG_LINKINFO_GET - do */
-void ethtool_linkinfo_get_req_free(struct ethtool_linkinfo_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_linkinfo_get_rsp_free(struct ethtool_linkinfo_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_linkinfo_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_linkinfo_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_LINKINFO_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_LINKINFO_PORT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port = 1;
- dst->port = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKINFO_PHYADDR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.phyaddr = 1;
- dst->phyaddr = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKINFO_TP_MDIX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tp_mdix = 1;
- dst->tp_mdix = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKINFO_TP_MDIX_CTRL) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tp_mdix_ctrl = 1;
- dst->tp_mdix_ctrl = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKINFO_TRANSCEIVER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.transceiver = 1;
- dst->transceiver = mnl_attr_get_u8(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_linkinfo_get_rsp *
-ethtool_linkinfo_get(struct ynl_sock *ys, struct ethtool_linkinfo_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_linkinfo_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_GET, 1);
- ys->req_policy = &ethtool_linkinfo_nest;
- yrs.yarg.rsp_policy = &ethtool_linkinfo_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_linkinfo_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_LINKINFO_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_linkinfo_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_LINKINFO_GET - dump */
-void ethtool_linkinfo_get_list_free(struct ethtool_linkinfo_get_list *rsp)
-{
- struct ethtool_linkinfo_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_linkinfo_get_list *
-ethtool_linkinfo_get_dump(struct ynl_sock *ys,
- struct ethtool_linkinfo_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_linkinfo_get_list);
- yds.cb = ethtool_linkinfo_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_LINKINFO_GET;
- yds.rsp_policy = &ethtool_linkinfo_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_GET, 1);
- ys->req_policy = &ethtool_linkinfo_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_linkinfo_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_LINKINFO_GET - notify */
-void ethtool_linkinfo_get_ntf_free(struct ethtool_linkinfo_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_LINKINFO_SET ============== */
-/* ETHTOOL_MSG_LINKINFO_SET - do */
-void ethtool_linkinfo_set_req_free(struct ethtool_linkinfo_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_linkinfo_set(struct ynl_sock *ys,
- struct ethtool_linkinfo_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKINFO_SET, 1);
- ys->req_policy = &ethtool_linkinfo_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKINFO_HEADER, &req->header);
- if (req->_present.port)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_PORT, req->port);
- if (req->_present.phyaddr)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_PHYADDR, req->phyaddr);
- if (req->_present.tp_mdix)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TP_MDIX, req->tp_mdix);
- if (req->_present.tp_mdix_ctrl)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, req->tp_mdix_ctrl);
- if (req->_present.transceiver)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TRANSCEIVER, req->transceiver);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_LINKMODES_GET ============== */
-/* ETHTOOL_MSG_LINKMODES_GET - do */
-void ethtool_linkmodes_get_req_free(struct ethtool_linkmodes_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_linkmodes_get_rsp_free(struct ethtool_linkmodes_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->ours);
- ethtool_bitset_free(&rsp->peer);
- free(rsp);
-}
-
-int ethtool_linkmodes_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_linkmodes_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_LINKMODES_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_LINKMODES_AUTONEG) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.autoneg = 1;
- dst->autoneg = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKMODES_OURS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ours = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->ours;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_LINKMODES_PEER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.peer = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->peer;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_LINKMODES_SPEED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.speed = 1;
- dst->speed = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_LINKMODES_DUPLEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.duplex = 1;
- dst->duplex = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.master_slave_cfg = 1;
- dst->master_slave_cfg = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.master_slave_state = 1;
- dst->master_slave_state = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKMODES_LANES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.lanes = 1;
- dst->lanes = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_LINKMODES_RATE_MATCHING) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rate_matching = 1;
- dst->rate_matching = mnl_attr_get_u8(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_linkmodes_get_rsp *
-ethtool_linkmodes_get(struct ynl_sock *ys,
- struct ethtool_linkmodes_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_linkmodes_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_GET, 1);
- ys->req_policy = &ethtool_linkmodes_nest;
- yrs.yarg.rsp_policy = &ethtool_linkmodes_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_linkmodes_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_LINKMODES_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_linkmodes_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_LINKMODES_GET - dump */
-void ethtool_linkmodes_get_list_free(struct ethtool_linkmodes_get_list *rsp)
-{
- struct ethtool_linkmodes_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.ours);
- ethtool_bitset_free(&rsp->obj.peer);
- free(rsp);
- }
-}
-
-struct ethtool_linkmodes_get_list *
-ethtool_linkmodes_get_dump(struct ynl_sock *ys,
- struct ethtool_linkmodes_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_linkmodes_get_list);
- yds.cb = ethtool_linkmodes_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_LINKMODES_GET;
- yds.rsp_policy = &ethtool_linkmodes_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_GET, 1);
- ys->req_policy = &ethtool_linkmodes_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_linkmodes_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_LINKMODES_GET - notify */
-void ethtool_linkmodes_get_ntf_free(struct ethtool_linkmodes_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.ours);
- ethtool_bitset_free(&rsp->obj.peer);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_LINKMODES_SET ============== */
-/* ETHTOOL_MSG_LINKMODES_SET - do */
-void ethtool_linkmodes_set_req_free(struct ethtool_linkmodes_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->ours);
- ethtool_bitset_free(&req->peer);
- free(req);
-}
-
-int ethtool_linkmodes_set(struct ynl_sock *ys,
- struct ethtool_linkmodes_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKMODES_SET, 1);
- ys->req_policy = &ethtool_linkmodes_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKMODES_HEADER, &req->header);
- if (req->_present.autoneg)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_AUTONEG, req->autoneg);
- if (req->_present.ours)
- ethtool_bitset_put(nlh, ETHTOOL_A_LINKMODES_OURS, &req->ours);
- if (req->_present.peer)
- ethtool_bitset_put(nlh, ETHTOOL_A_LINKMODES_PEER, &req->peer);
- if (req->_present.speed)
- mnl_attr_put_u32(nlh, ETHTOOL_A_LINKMODES_SPEED, req->speed);
- if (req->_present.duplex)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_DUPLEX, req->duplex);
- if (req->_present.master_slave_cfg)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, req->master_slave_cfg);
- if (req->_present.master_slave_state)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, req->master_slave_state);
- if (req->_present.lanes)
- mnl_attr_put_u32(nlh, ETHTOOL_A_LINKMODES_LANES, req->lanes);
- if (req->_present.rate_matching)
- mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_RATE_MATCHING, req->rate_matching);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_LINKSTATE_GET ============== */
-/* ETHTOOL_MSG_LINKSTATE_GET - do */
-void ethtool_linkstate_get_req_free(struct ethtool_linkstate_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_linkstate_get_rsp_free(struct ethtool_linkstate_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_linkstate_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_linkstate_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_LINKSTATE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_LINKSTATE_LINK) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.link = 1;
- dst->link = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKSTATE_SQI) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sqi = 1;
- dst->sqi = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_LINKSTATE_SQI_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sqi_max = 1;
- dst->sqi_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_LINKSTATE_EXT_STATE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ext_state = 1;
- dst->ext_state = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKSTATE_EXT_SUBSTATE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ext_substate = 1;
- dst->ext_substate = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ext_down_cnt = 1;
- dst->ext_down_cnt = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_linkstate_get_rsp *
-ethtool_linkstate_get(struct ynl_sock *ys,
- struct ethtool_linkstate_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_linkstate_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_LINKSTATE_GET, 1);
- ys->req_policy = &ethtool_linkstate_nest;
- yrs.yarg.rsp_policy = &ethtool_linkstate_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKSTATE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_linkstate_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_LINKSTATE_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_linkstate_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_LINKSTATE_GET - dump */
-void ethtool_linkstate_get_list_free(struct ethtool_linkstate_get_list *rsp)
-{
- struct ethtool_linkstate_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_linkstate_get_list *
-ethtool_linkstate_get_dump(struct ynl_sock *ys,
- struct ethtool_linkstate_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_linkstate_get_list);
- yds.cb = ethtool_linkstate_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_LINKSTATE_GET;
- yds.rsp_policy = &ethtool_linkstate_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_LINKSTATE_GET, 1);
- ys->req_policy = &ethtool_linkstate_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_LINKSTATE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_linkstate_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_DEBUG_GET ============== */
-/* ETHTOOL_MSG_DEBUG_GET - do */
-void ethtool_debug_get_req_free(struct ethtool_debug_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_debug_get_rsp_free(struct ethtool_debug_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->msgmask);
- free(rsp);
-}
-
-int ethtool_debug_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_debug_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_DEBUG_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_DEBUG_MSGMASK) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.msgmask = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->msgmask;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_debug_get_rsp *
-ethtool_debug_get(struct ynl_sock *ys, struct ethtool_debug_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_debug_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_DEBUG_GET, 1);
- ys->req_policy = &ethtool_debug_nest;
- yrs.yarg.rsp_policy = &ethtool_debug_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_debug_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_DEBUG_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_debug_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_DEBUG_GET - dump */
-void ethtool_debug_get_list_free(struct ethtool_debug_get_list *rsp)
-{
- struct ethtool_debug_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.msgmask);
- free(rsp);
- }
-}
-
-struct ethtool_debug_get_list *
-ethtool_debug_get_dump(struct ynl_sock *ys,
- struct ethtool_debug_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_debug_get_list);
- yds.cb = ethtool_debug_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_DEBUG_GET;
- yds.rsp_policy = &ethtool_debug_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_DEBUG_GET, 1);
- ys->req_policy = &ethtool_debug_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_debug_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_DEBUG_GET - notify */
-void ethtool_debug_get_ntf_free(struct ethtool_debug_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.msgmask);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_DEBUG_SET ============== */
-/* ETHTOOL_MSG_DEBUG_SET - do */
-void ethtool_debug_set_req_free(struct ethtool_debug_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->msgmask);
- free(req);
-}
-
-int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_DEBUG_SET, 1);
- ys->req_policy = &ethtool_debug_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_DEBUG_HEADER, &req->header);
- if (req->_present.msgmask)
- ethtool_bitset_put(nlh, ETHTOOL_A_DEBUG_MSGMASK, &req->msgmask);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_WOL_GET ============== */
-/* ETHTOOL_MSG_WOL_GET - do */
-void ethtool_wol_get_req_free(struct ethtool_wol_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_wol_get_rsp_free(struct ethtool_wol_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->modes);
- free(rsp->sopass);
- free(rsp);
-}
-
-int ethtool_wol_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_wol_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_WOL_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_WOL_MODES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.modes = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->modes;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_WOL_SOPASS) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.sopass_len = len;
- dst->sopass = malloc(len);
- memcpy(dst->sopass, mnl_attr_get_payload(attr), len);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_wol_get_rsp *
-ethtool_wol_get(struct ynl_sock *ys, struct ethtool_wol_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_wol_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_WOL_GET, 1);
- ys->req_policy = &ethtool_wol_nest;
- yrs.yarg.rsp_policy = &ethtool_wol_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_wol_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_WOL_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_wol_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_WOL_GET - dump */
-void ethtool_wol_get_list_free(struct ethtool_wol_get_list *rsp)
-{
- struct ethtool_wol_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes);
- free(rsp->obj.sopass);
- free(rsp);
- }
-}
-
-struct ethtool_wol_get_list *
-ethtool_wol_get_dump(struct ynl_sock *ys, struct ethtool_wol_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_wol_get_list);
- yds.cb = ethtool_wol_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_WOL_GET;
- yds.rsp_policy = &ethtool_wol_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_WOL_GET, 1);
- ys->req_policy = &ethtool_wol_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_wol_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_WOL_GET - notify */
-void ethtool_wol_get_ntf_free(struct ethtool_wol_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes);
- free(rsp->obj.sopass);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_WOL_SET ============== */
-/* ETHTOOL_MSG_WOL_SET - do */
-void ethtool_wol_set_req_free(struct ethtool_wol_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->modes);
- free(req->sopass);
- free(req);
-}
-
-int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_WOL_SET, 1);
- ys->req_policy = &ethtool_wol_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_WOL_HEADER, &req->header);
- if (req->_present.modes)
- ethtool_bitset_put(nlh, ETHTOOL_A_WOL_MODES, &req->modes);
- if (req->_present.sopass_len)
- mnl_attr_put(nlh, ETHTOOL_A_WOL_SOPASS, req->_present.sopass_len, req->sopass);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_FEATURES_GET ============== */
-/* ETHTOOL_MSG_FEATURES_GET - do */
-void ethtool_features_get_req_free(struct ethtool_features_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_features_get_rsp_free(struct ethtool_features_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->hw);
- ethtool_bitset_free(&rsp->wanted);
- ethtool_bitset_free(&rsp->active);
- ethtool_bitset_free(&rsp->nochange);
- free(rsp);
-}
-
-int ethtool_features_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_features_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_FEATURES_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_HW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.hw = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->hw;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_WANTED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.wanted = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->wanted;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_ACTIVE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.active = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->active;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_NOCHANGE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.nochange = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->nochange;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_features_get_rsp *
-ethtool_features_get(struct ynl_sock *ys, struct ethtool_features_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_features_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEATURES_GET, 1);
- ys->req_policy = &ethtool_features_nest;
- yrs.yarg.rsp_policy = &ethtool_features_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_features_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_FEATURES_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_features_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_FEATURES_GET - dump */
-void ethtool_features_get_list_free(struct ethtool_features_get_list *rsp)
-{
- struct ethtool_features_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.hw);
- ethtool_bitset_free(&rsp->obj.wanted);
- ethtool_bitset_free(&rsp->obj.active);
- ethtool_bitset_free(&rsp->obj.nochange);
- free(rsp);
- }
-}
-
-struct ethtool_features_get_list *
-ethtool_features_get_dump(struct ynl_sock *ys,
- struct ethtool_features_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_features_get_list);
- yds.cb = ethtool_features_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_FEATURES_GET;
- yds.rsp_policy = &ethtool_features_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_FEATURES_GET, 1);
- ys->req_policy = &ethtool_features_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_features_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_FEATURES_GET - notify */
-void ethtool_features_get_ntf_free(struct ethtool_features_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.hw);
- ethtool_bitset_free(&rsp->obj.wanted);
- ethtool_bitset_free(&rsp->obj.active);
- ethtool_bitset_free(&rsp->obj.nochange);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_FEATURES_SET ============== */
-/* ETHTOOL_MSG_FEATURES_SET - do */
-void ethtool_features_set_req_free(struct ethtool_features_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->hw);
- ethtool_bitset_free(&req->wanted);
- ethtool_bitset_free(&req->active);
- ethtool_bitset_free(&req->nochange);
- free(req);
-}
-
-void ethtool_features_set_rsp_free(struct ethtool_features_set_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->hw);
- ethtool_bitset_free(&rsp->wanted);
- ethtool_bitset_free(&rsp->active);
- ethtool_bitset_free(&rsp->nochange);
- free(rsp);
-}
-
-int ethtool_features_set_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_features_set_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_FEATURES_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_HW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.hw = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->hw;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_WANTED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.wanted = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->wanted;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_ACTIVE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.active = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->active;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEATURES_NOCHANGE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.nochange = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->nochange;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_features_set_rsp *
-ethtool_features_set(struct ynl_sock *ys, struct ethtool_features_set_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_features_set_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEATURES_SET, 1);
- ys->req_policy = &ethtool_features_nest;
- yrs.yarg.rsp_policy = &ethtool_features_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEATURES_HEADER, &req->header);
- if (req->_present.hw)
- ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_HW, &req->hw);
- if (req->_present.wanted)
- ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_WANTED, &req->wanted);
- if (req->_present.active)
- ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_ACTIVE, &req->active);
- if (req->_present.nochange)
- ethtool_bitset_put(nlh, ETHTOOL_A_FEATURES_NOCHANGE, &req->nochange);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_features_set_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_FEATURES_SET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_features_set_rsp_free(rsp);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_PRIVFLAGS_GET ============== */
-/* ETHTOOL_MSG_PRIVFLAGS_GET - do */
-void ethtool_privflags_get_req_free(struct ethtool_privflags_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_privflags_get_rsp_free(struct ethtool_privflags_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->flags);
- free(rsp);
-}
-
-int ethtool_privflags_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_privflags_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PRIVFLAGS_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PRIVFLAGS_FLAGS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.flags = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->flags;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_privflags_get_rsp *
-ethtool_privflags_get(struct ynl_sock *ys,
- struct ethtool_privflags_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_privflags_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_GET, 1);
- ys->req_policy = &ethtool_privflags_nest;
- yrs.yarg.rsp_policy = &ethtool_privflags_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_privflags_get_rsp_parse;
- yrs.rsp_cmd = 14;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_privflags_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PRIVFLAGS_GET - dump */
-void ethtool_privflags_get_list_free(struct ethtool_privflags_get_list *rsp)
-{
- struct ethtool_privflags_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.flags);
- free(rsp);
- }
-}
-
-struct ethtool_privflags_get_list *
-ethtool_privflags_get_dump(struct ynl_sock *ys,
- struct ethtool_privflags_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_privflags_get_list);
- yds.cb = ethtool_privflags_get_rsp_parse;
- yds.rsp_cmd = 14;
- yds.rsp_policy = &ethtool_privflags_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_GET, 1);
- ys->req_policy = &ethtool_privflags_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_privflags_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PRIVFLAGS_GET - notify */
-void ethtool_privflags_get_ntf_free(struct ethtool_privflags_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.flags);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_PRIVFLAGS_SET ============== */
-/* ETHTOOL_MSG_PRIVFLAGS_SET - do */
-void ethtool_privflags_set_req_free(struct ethtool_privflags_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->flags);
- free(req);
-}
-
-int ethtool_privflags_set(struct ynl_sock *ys,
- struct ethtool_privflags_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PRIVFLAGS_SET, 1);
- ys->req_policy = &ethtool_privflags_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PRIVFLAGS_HEADER, &req->header);
- if (req->_present.flags)
- ethtool_bitset_put(nlh, ETHTOOL_A_PRIVFLAGS_FLAGS, &req->flags);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_RINGS_GET ============== */
-/* ETHTOOL_MSG_RINGS_GET - do */
-void ethtool_rings_get_req_free(struct ethtool_rings_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_rings_get_rsp_free(struct ethtool_rings_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_rings_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_rings_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_RINGS_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_RINGS_RX_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max = 1;
- dst->rx_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_MINI_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_mini_max = 1;
- dst->rx_mini_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_JUMBO_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_jumbo_max = 1;
- dst->rx_jumbo_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_TX_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max = 1;
- dst->tx_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx = 1;
- dst->rx = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_MINI) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_mini = 1;
- dst->rx_mini = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_JUMBO) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_jumbo = 1;
- dst->rx_jumbo = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_TX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx = 1;
- dst->tx = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_BUF_LEN) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_buf_len = 1;
- dst->rx_buf_len = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_TCP_DATA_SPLIT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tcp_data_split = 1;
- dst->tcp_data_split = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_RINGS_CQE_SIZE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.cqe_size = 1;
- dst->cqe_size = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_TX_PUSH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_push = 1;
- dst->tx_push = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_RINGS_RX_PUSH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_push = 1;
- dst->rx_push = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_push_buf_len = 1;
- dst->tx_push_buf_len = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_push_buf_len_max = 1;
- dst->tx_push_buf_len_max = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_rings_get_rsp *
-ethtool_rings_get(struct ynl_sock *ys, struct ethtool_rings_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_rings_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RINGS_GET, 1);
- ys->req_policy = &ethtool_rings_nest;
- yrs.yarg.rsp_policy = &ethtool_rings_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_rings_get_rsp_parse;
- yrs.rsp_cmd = 16;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_rings_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_RINGS_GET - dump */
-void ethtool_rings_get_list_free(struct ethtool_rings_get_list *rsp)
-{
- struct ethtool_rings_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_rings_get_list *
-ethtool_rings_get_dump(struct ynl_sock *ys,
- struct ethtool_rings_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_rings_get_list);
- yds.cb = ethtool_rings_get_rsp_parse;
- yds.rsp_cmd = 16;
- yds.rsp_policy = &ethtool_rings_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_RINGS_GET, 1);
- ys->req_policy = &ethtool_rings_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_rings_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_RINGS_GET - notify */
-void ethtool_rings_get_ntf_free(struct ethtool_rings_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_RINGS_SET ============== */
-/* ETHTOOL_MSG_RINGS_SET - do */
-void ethtool_rings_set_req_free(struct ethtool_rings_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RINGS_SET, 1);
- ys->req_policy = &ethtool_rings_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_RINGS_HEADER, &req->header);
- if (req->_present.rx_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MAX, req->rx_max);
- if (req->_present.rx_mini_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MINI_MAX, req->rx_mini_max);
- if (req->_present.rx_jumbo_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_JUMBO_MAX, req->rx_jumbo_max);
- if (req->_present.tx_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_MAX, req->tx_max);
- if (req->_present.rx)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX, req->rx);
- if (req->_present.rx_mini)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_MINI, req->rx_mini);
- if (req->_present.rx_jumbo)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_JUMBO, req->rx_jumbo);
- if (req->_present.tx)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX, req->tx);
- if (req->_present.rx_buf_len)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_RX_BUF_LEN, req->rx_buf_len);
- if (req->_present.tcp_data_split)
- mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_TCP_DATA_SPLIT, req->tcp_data_split);
- if (req->_present.cqe_size)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_CQE_SIZE, req->cqe_size);
- if (req->_present.tx_push)
- mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_TX_PUSH, req->tx_push);
- if (req->_present.rx_push)
- mnl_attr_put_u8(nlh, ETHTOOL_A_RINGS_RX_PUSH, req->rx_push);
- if (req->_present.tx_push_buf_len)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN, req->tx_push_buf_len);
- if (req->_present.tx_push_buf_len_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX, req->tx_push_buf_len_max);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_CHANNELS_GET ============== */
-/* ETHTOOL_MSG_CHANNELS_GET - do */
-void ethtool_channels_get_req_free(struct ethtool_channels_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_channels_get_rsp_free(struct ethtool_channels_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_channels_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_channels_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CHANNELS_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_CHANNELS_RX_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max = 1;
- dst->rx_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_TX_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max = 1;
- dst->tx_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_OTHER_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.other_max = 1;
- dst->other_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_COMBINED_MAX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.combined_max = 1;
- dst->combined_max = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_RX_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_count = 1;
- dst->rx_count = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_TX_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_count = 1;
- dst->tx_count = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_OTHER_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.other_count = 1;
- dst->other_count = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_CHANNELS_COMBINED_COUNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.combined_count = 1;
- dst->combined_count = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_channels_get_rsp *
-ethtool_channels_get(struct ynl_sock *ys, struct ethtool_channels_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_channels_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_GET, 1);
- ys->req_policy = &ethtool_channels_nest;
- yrs.yarg.rsp_policy = &ethtool_channels_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_channels_get_rsp_parse;
- yrs.rsp_cmd = 18;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_channels_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_CHANNELS_GET - dump */
-void ethtool_channels_get_list_free(struct ethtool_channels_get_list *rsp)
-{
- struct ethtool_channels_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_channels_get_list *
-ethtool_channels_get_dump(struct ynl_sock *ys,
- struct ethtool_channels_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_channels_get_list);
- yds.cb = ethtool_channels_get_rsp_parse;
- yds.rsp_cmd = 18;
- yds.rsp_policy = &ethtool_channels_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_GET, 1);
- ys->req_policy = &ethtool_channels_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_channels_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_CHANNELS_GET - notify */
-void ethtool_channels_get_ntf_free(struct ethtool_channels_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_CHANNELS_SET ============== */
-/* ETHTOOL_MSG_CHANNELS_SET - do */
-void ethtool_channels_set_req_free(struct ethtool_channels_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_channels_set(struct ynl_sock *ys,
- struct ethtool_channels_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CHANNELS_SET, 1);
- ys->req_policy = &ethtool_channels_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_CHANNELS_HEADER, &req->header);
- if (req->_present.rx_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_RX_MAX, req->rx_max);
- if (req->_present.tx_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_TX_MAX, req->tx_max);
- if (req->_present.other_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_OTHER_MAX, req->other_max);
- if (req->_present.combined_max)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_MAX, req->combined_max);
- if (req->_present.rx_count)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_RX_COUNT, req->rx_count);
- if (req->_present.tx_count)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_TX_COUNT, req->tx_count);
- if (req->_present.other_count)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_OTHER_COUNT, req->other_count);
- if (req->_present.combined_count)
- mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_COUNT, req->combined_count);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_COALESCE_GET ============== */
-/* ETHTOOL_MSG_COALESCE_GET - do */
-void ethtool_coalesce_get_req_free(struct ethtool_coalesce_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_coalesce_get_rsp_free(struct ethtool_coalesce_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_coalesce_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_coalesce_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_COALESCE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_COALESCE_RX_USECS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_usecs = 1;
- dst->rx_usecs = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max_frames = 1;
- dst->rx_max_frames = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_USECS_IRQ) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_usecs_irq = 1;
- dst->rx_usecs_irq = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max_frames_irq = 1;
- dst->rx_max_frames_irq = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_USECS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_usecs = 1;
- dst->tx_usecs = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max_frames = 1;
- dst->tx_max_frames = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_USECS_IRQ) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_usecs_irq = 1;
- dst->tx_usecs_irq = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max_frames_irq = 1;
- dst->tx_max_frames_irq = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_STATS_BLOCK_USECS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stats_block_usecs = 1;
- dst->stats_block_usecs = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.use_adaptive_rx = 1;
- dst->use_adaptive_rx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.use_adaptive_tx = 1;
- dst->use_adaptive_tx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_COALESCE_PKT_RATE_LOW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pkt_rate_low = 1;
- dst->pkt_rate_low = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_USECS_LOW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_usecs_low = 1;
- dst->rx_usecs_low = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max_frames_low = 1;
- dst->rx_max_frames_low = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_USECS_LOW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_usecs_low = 1;
- dst->tx_usecs_low = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max_frames_low = 1;
- dst->tx_max_frames_low = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_PKT_RATE_HIGH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pkt_rate_high = 1;
- dst->pkt_rate_high = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_USECS_HIGH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_usecs_high = 1;
- dst->rx_usecs_high = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_max_frames_high = 1;
- dst->rx_max_frames_high = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_USECS_HIGH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_usecs_high = 1;
- dst->tx_usecs_high = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_max_frames_high = 1;
- dst->tx_max_frames_high = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rate_sample_interval = 1;
- dst->rate_sample_interval = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_USE_CQE_MODE_TX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.use_cqe_mode_tx = 1;
- dst->use_cqe_mode_tx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_COALESCE_USE_CQE_MODE_RX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.use_cqe_mode_rx = 1;
- dst->use_cqe_mode_rx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_aggr_max_bytes = 1;
- dst->tx_aggr_max_bytes = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_aggr_max_frames = 1;
- dst->tx_aggr_max_frames = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_aggr_time_usecs = 1;
- dst->tx_aggr_time_usecs = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_coalesce_get_rsp *
-ethtool_coalesce_get(struct ynl_sock *ys, struct ethtool_coalesce_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_coalesce_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_COALESCE_GET, 1);
- ys->req_policy = &ethtool_coalesce_nest;
- yrs.yarg.rsp_policy = &ethtool_coalesce_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_coalesce_get_rsp_parse;
- yrs.rsp_cmd = 20;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_coalesce_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_COALESCE_GET - dump */
-void ethtool_coalesce_get_list_free(struct ethtool_coalesce_get_list *rsp)
-{
- struct ethtool_coalesce_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_coalesce_get_list *
-ethtool_coalesce_get_dump(struct ynl_sock *ys,
- struct ethtool_coalesce_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_coalesce_get_list);
- yds.cb = ethtool_coalesce_get_rsp_parse;
- yds.rsp_cmd = 20;
- yds.rsp_policy = &ethtool_coalesce_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_COALESCE_GET, 1);
- ys->req_policy = &ethtool_coalesce_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_coalesce_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_COALESCE_GET - notify */
-void ethtool_coalesce_get_ntf_free(struct ethtool_coalesce_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_COALESCE_SET ============== */
-/* ETHTOOL_MSG_COALESCE_SET - do */
-void ethtool_coalesce_set_req_free(struct ethtool_coalesce_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_coalesce_set(struct ynl_sock *ys,
- struct ethtool_coalesce_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_COALESCE_SET, 1);
- ys->req_policy = &ethtool_coalesce_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_COALESCE_HEADER, &req->header);
- if (req->_present.rx_usecs)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS, req->rx_usecs);
- if (req->_present.rx_max_frames)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES, req->rx_max_frames);
- if (req->_present.rx_usecs_irq)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_IRQ, req->rx_usecs_irq);
- if (req->_present.rx_max_frames_irq)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ, req->rx_max_frames_irq);
- if (req->_present.tx_usecs)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS, req->tx_usecs);
- if (req->_present.tx_max_frames)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES, req->tx_max_frames);
- if (req->_present.tx_usecs_irq)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_IRQ, req->tx_usecs_irq);
- if (req->_present.tx_max_frames_irq)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ, req->tx_max_frames_irq);
- if (req->_present.stats_block_usecs)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_STATS_BLOCK_USECS, req->stats_block_usecs);
- if (req->_present.use_adaptive_rx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX, req->use_adaptive_rx);
- if (req->_present.use_adaptive_tx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX, req->use_adaptive_tx);
- if (req->_present.pkt_rate_low)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_PKT_RATE_LOW, req->pkt_rate_low);
- if (req->_present.rx_usecs_low)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_LOW, req->rx_usecs_low);
- if (req->_present.rx_max_frames_low)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW, req->rx_max_frames_low);
- if (req->_present.tx_usecs_low)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_LOW, req->tx_usecs_low);
- if (req->_present.tx_max_frames_low)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW, req->tx_max_frames_low);
- if (req->_present.pkt_rate_high)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_PKT_RATE_HIGH, req->pkt_rate_high);
- if (req->_present.rx_usecs_high)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_USECS_HIGH, req->rx_usecs_high);
- if (req->_present.rx_max_frames_high)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH, req->rx_max_frames_high);
- if (req->_present.tx_usecs_high)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_USECS_HIGH, req->tx_usecs_high);
- if (req->_present.tx_max_frames_high)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH, req->tx_max_frames_high);
- if (req->_present.rate_sample_interval)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, req->rate_sample_interval);
- if (req->_present.use_cqe_mode_tx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_CQE_MODE_TX, req->use_cqe_mode_tx);
- if (req->_present.use_cqe_mode_rx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_COALESCE_USE_CQE_MODE_RX, req->use_cqe_mode_rx);
- if (req->_present.tx_aggr_max_bytes)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES, req->tx_aggr_max_bytes);
- if (req->_present.tx_aggr_max_frames)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES, req->tx_aggr_max_frames);
- if (req->_present.tx_aggr_time_usecs)
- mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, req->tx_aggr_time_usecs);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_PAUSE_GET ============== */
-/* ETHTOOL_MSG_PAUSE_GET - do */
-void ethtool_pause_get_req_free(struct ethtool_pause_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_pause_get_rsp_free(struct ethtool_pause_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_pause_stat_free(&rsp->stats);
- free(rsp);
-}
-
-int ethtool_pause_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_pause_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PAUSE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PAUSE_AUTONEG) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.autoneg = 1;
- dst->autoneg = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PAUSE_RX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx = 1;
- dst->rx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PAUSE_TX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx = 1;
- dst->tx = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PAUSE_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stats = 1;
-
- parg.rsp_policy = &ethtool_pause_stat_nest;
- parg.data = &dst->stats;
- if (ethtool_pause_stat_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PAUSE_STATS_SRC) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stats_src = 1;
- dst->stats_src = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_pause_get_rsp *
-ethtool_pause_get(struct ynl_sock *ys, struct ethtool_pause_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_pause_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PAUSE_GET, 1);
- ys->req_policy = &ethtool_pause_nest;
- yrs.yarg.rsp_policy = &ethtool_pause_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_pause_get_rsp_parse;
- yrs.rsp_cmd = 22;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_pause_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PAUSE_GET - dump */
-void ethtool_pause_get_list_free(struct ethtool_pause_get_list *rsp)
-{
- struct ethtool_pause_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_pause_stat_free(&rsp->obj.stats);
- free(rsp);
- }
-}
-
-struct ethtool_pause_get_list *
-ethtool_pause_get_dump(struct ynl_sock *ys,
- struct ethtool_pause_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_pause_get_list);
- yds.cb = ethtool_pause_get_rsp_parse;
- yds.rsp_cmd = 22;
- yds.rsp_policy = &ethtool_pause_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PAUSE_GET, 1);
- ys->req_policy = &ethtool_pause_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_pause_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PAUSE_GET - notify */
-void ethtool_pause_get_ntf_free(struct ethtool_pause_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_pause_stat_free(&rsp->obj.stats);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_PAUSE_SET ============== */
-/* ETHTOOL_MSG_PAUSE_SET - do */
-void ethtool_pause_set_req_free(struct ethtool_pause_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_pause_stat_free(&req->stats);
- free(req);
-}
-
-int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PAUSE_SET, 1);
- ys->req_policy = &ethtool_pause_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PAUSE_HEADER, &req->header);
- if (req->_present.autoneg)
- mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_AUTONEG, req->autoneg);
- if (req->_present.rx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_RX, req->rx);
- if (req->_present.tx)
- mnl_attr_put_u8(nlh, ETHTOOL_A_PAUSE_TX, req->tx);
- if (req->_present.stats)
- ethtool_pause_stat_put(nlh, ETHTOOL_A_PAUSE_STATS, &req->stats);
- if (req->_present.stats_src)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PAUSE_STATS_SRC, req->stats_src);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_EEE_GET ============== */
-/* ETHTOOL_MSG_EEE_GET - do */
-void ethtool_eee_get_req_free(struct ethtool_eee_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_eee_get_rsp_free(struct ethtool_eee_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->modes_ours);
- ethtool_bitset_free(&rsp->modes_peer);
- free(rsp);
-}
-
-int ethtool_eee_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_eee_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_EEE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_EEE_MODES_OURS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.modes_ours = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->modes_ours;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_EEE_MODES_PEER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.modes_peer = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->modes_peer;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_EEE_ACTIVE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.active = 1;
- dst->active = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_EEE_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.enabled = 1;
- dst->enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_EEE_TX_LPI_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_lpi_enabled = 1;
- dst->tx_lpi_enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_EEE_TX_LPI_TIMER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_lpi_timer = 1;
- dst->tx_lpi_timer = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_eee_get_rsp *
-ethtool_eee_get(struct ynl_sock *ys, struct ethtool_eee_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_eee_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_EEE_GET, 1);
- ys->req_policy = &ethtool_eee_nest;
- yrs.yarg.rsp_policy = &ethtool_eee_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_eee_get_rsp_parse;
- yrs.rsp_cmd = 24;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_eee_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_EEE_GET - dump */
-void ethtool_eee_get_list_free(struct ethtool_eee_get_list *rsp)
-{
- struct ethtool_eee_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes_ours);
- ethtool_bitset_free(&rsp->obj.modes_peer);
- free(rsp);
- }
-}
-
-struct ethtool_eee_get_list *
-ethtool_eee_get_dump(struct ynl_sock *ys, struct ethtool_eee_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_eee_get_list);
- yds.cb = ethtool_eee_get_rsp_parse;
- yds.rsp_cmd = 24;
- yds.rsp_policy = &ethtool_eee_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_EEE_GET, 1);
- ys->req_policy = &ethtool_eee_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_eee_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_EEE_GET - notify */
-void ethtool_eee_get_ntf_free(struct ethtool_eee_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes_ours);
- ethtool_bitset_free(&rsp->obj.modes_peer);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_EEE_SET ============== */
-/* ETHTOOL_MSG_EEE_SET - do */
-void ethtool_eee_set_req_free(struct ethtool_eee_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->modes_ours);
- ethtool_bitset_free(&req->modes_peer);
- free(req);
-}
-
-int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_EEE_SET, 1);
- ys->req_policy = &ethtool_eee_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_EEE_HEADER, &req->header);
- if (req->_present.modes_ours)
- ethtool_bitset_put(nlh, ETHTOOL_A_EEE_MODES_OURS, &req->modes_ours);
- if (req->_present.modes_peer)
- ethtool_bitset_put(nlh, ETHTOOL_A_EEE_MODES_PEER, &req->modes_peer);
- if (req->_present.active)
- mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_ACTIVE, req->active);
- if (req->_present.enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_ENABLED, req->enabled);
- if (req->_present.tx_lpi_enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_EEE_TX_LPI_ENABLED, req->tx_lpi_enabled);
- if (req->_present.tx_lpi_timer)
- mnl_attr_put_u32(nlh, ETHTOOL_A_EEE_TX_LPI_TIMER, req->tx_lpi_timer);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_TSINFO_GET ============== */
-/* ETHTOOL_MSG_TSINFO_GET - do */
-void ethtool_tsinfo_get_req_free(struct ethtool_tsinfo_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_tsinfo_get_rsp_free(struct ethtool_tsinfo_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->timestamping);
- ethtool_bitset_free(&rsp->tx_types);
- ethtool_bitset_free(&rsp->rx_filters);
- free(rsp);
-}
-
-int ethtool_tsinfo_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_tsinfo_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_TSINFO_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TSINFO_TIMESTAMPING) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.timestamping = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->timestamping;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TSINFO_TX_TYPES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_types = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->tx_types;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TSINFO_RX_FILTERS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_filters = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->rx_filters;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TSINFO_PHC_INDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.phc_index = 1;
- dst->phc_index = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_tsinfo_get_rsp *
-ethtool_tsinfo_get(struct ynl_sock *ys, struct ethtool_tsinfo_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_tsinfo_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_TSINFO_GET, 1);
- ys->req_policy = &ethtool_tsinfo_nest;
- yrs.yarg.rsp_policy = &ethtool_tsinfo_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_TSINFO_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_tsinfo_get_rsp_parse;
- yrs.rsp_cmd = 26;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_tsinfo_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_TSINFO_GET - dump */
-void ethtool_tsinfo_get_list_free(struct ethtool_tsinfo_get_list *rsp)
-{
- struct ethtool_tsinfo_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.timestamping);
- ethtool_bitset_free(&rsp->obj.tx_types);
- ethtool_bitset_free(&rsp->obj.rx_filters);
- free(rsp);
- }
-}
-
-struct ethtool_tsinfo_get_list *
-ethtool_tsinfo_get_dump(struct ynl_sock *ys,
- struct ethtool_tsinfo_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_tsinfo_get_list);
- yds.cb = ethtool_tsinfo_get_rsp_parse;
- yds.rsp_cmd = 26;
- yds.rsp_policy = &ethtool_tsinfo_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_TSINFO_GET, 1);
- ys->req_policy = &ethtool_tsinfo_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_TSINFO_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_tsinfo_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_CABLE_TEST_ACT ============== */
-/* ETHTOOL_MSG_CABLE_TEST_ACT - do */
-void ethtool_cable_test_act_req_free(struct ethtool_cable_test_act_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_cable_test_act(struct ynl_sock *ys,
- struct ethtool_cable_test_act_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CABLE_TEST_ACT, 1);
- ys->req_policy = &ethtool_cable_test_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_HEADER, &req->header);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_CABLE_TEST_TDR_ACT ============== */
-/* ETHTOOL_MSG_CABLE_TEST_TDR_ACT - do */
-void
-ethtool_cable_test_tdr_act_req_free(struct ethtool_cable_test_tdr_act_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_cable_test_tdr_act(struct ynl_sock *ys,
- struct ethtool_cable_test_tdr_act_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_CABLE_TEST_TDR_ACT, 1);
- ys->req_policy = &ethtool_cable_test_tdr_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_TDR_HEADER, &req->header);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_TUNNEL_INFO_GET ============== */
-/* ETHTOOL_MSG_TUNNEL_INFO_GET - do */
-void ethtool_tunnel_info_get_req_free(struct ethtool_tunnel_info_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_tunnel_info_get_rsp_free(struct ethtool_tunnel_info_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_tunnel_udp_free(&rsp->udp_ports);
- free(rsp);
-}
-
-int ethtool_tunnel_info_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_tunnel_info_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_TUNNEL_INFO_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_TUNNEL_INFO_UDP_PORTS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.udp_ports = 1;
-
- parg.rsp_policy = &ethtool_tunnel_udp_nest;
- parg.data = &dst->udp_ports;
- if (ethtool_tunnel_udp_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_tunnel_info_get_rsp *
-ethtool_tunnel_info_get(struct ynl_sock *ys,
- struct ethtool_tunnel_info_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_tunnel_info_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_TUNNEL_INFO_GET, 1);
- ys->req_policy = &ethtool_tunnel_info_nest;
- yrs.yarg.rsp_policy = &ethtool_tunnel_info_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_TUNNEL_INFO_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_tunnel_info_get_rsp_parse;
- yrs.rsp_cmd = 29;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_tunnel_info_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_TUNNEL_INFO_GET - dump */
-void
-ethtool_tunnel_info_get_list_free(struct ethtool_tunnel_info_get_list *rsp)
-{
- struct ethtool_tunnel_info_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_tunnel_udp_free(&rsp->obj.udp_ports);
- free(rsp);
- }
-}
-
-struct ethtool_tunnel_info_get_list *
-ethtool_tunnel_info_get_dump(struct ynl_sock *ys,
- struct ethtool_tunnel_info_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_tunnel_info_get_list);
- yds.cb = ethtool_tunnel_info_get_rsp_parse;
- yds.rsp_cmd = 29;
- yds.rsp_policy = &ethtool_tunnel_info_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_TUNNEL_INFO_GET, 1);
- ys->req_policy = &ethtool_tunnel_info_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_TUNNEL_INFO_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_tunnel_info_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_FEC_GET ============== */
-/* ETHTOOL_MSG_FEC_GET - do */
-void ethtool_fec_get_req_free(struct ethtool_fec_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_fec_get_rsp_free(struct ethtool_fec_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_bitset_free(&rsp->modes);
- ethtool_fec_stat_free(&rsp->stats);
- free(rsp);
-}
-
-int ethtool_fec_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_fec_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_FEC_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEC_MODES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.modes = 1;
-
- parg.rsp_policy = &ethtool_bitset_nest;
- parg.data = &dst->modes;
- if (ethtool_bitset_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_FEC_AUTO) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.auto_ = 1;
- dst->auto_ = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_FEC_ACTIVE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.active = 1;
- dst->active = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_FEC_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stats = 1;
-
- parg.rsp_policy = &ethtool_fec_stat_nest;
- parg.data = &dst->stats;
- if (ethtool_fec_stat_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_fec_get_rsp *
-ethtool_fec_get(struct ynl_sock *ys, struct ethtool_fec_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_fec_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEC_GET, 1);
- ys->req_policy = &ethtool_fec_nest;
- yrs.yarg.rsp_policy = &ethtool_fec_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_fec_get_rsp_parse;
- yrs.rsp_cmd = 30;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_fec_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_FEC_GET - dump */
-void ethtool_fec_get_list_free(struct ethtool_fec_get_list *rsp)
-{
- struct ethtool_fec_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes);
- ethtool_fec_stat_free(&rsp->obj.stats);
- free(rsp);
- }
-}
-
-struct ethtool_fec_get_list *
-ethtool_fec_get_dump(struct ynl_sock *ys, struct ethtool_fec_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_fec_get_list);
- yds.cb = ethtool_fec_get_rsp_parse;
- yds.rsp_cmd = 30;
- yds.rsp_policy = &ethtool_fec_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_FEC_GET, 1);
- ys->req_policy = &ethtool_fec_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_fec_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_FEC_GET - notify */
-void ethtool_fec_get_ntf_free(struct ethtool_fec_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_bitset_free(&rsp->obj.modes);
- ethtool_fec_stat_free(&rsp->obj.stats);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_FEC_SET ============== */
-/* ETHTOOL_MSG_FEC_SET - do */
-void ethtool_fec_set_req_free(struct ethtool_fec_set_req *req)
-{
- ethtool_header_free(&req->header);
- ethtool_bitset_free(&req->modes);
- ethtool_fec_stat_free(&req->stats);
- free(req);
-}
-
-int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_FEC_SET, 1);
- ys->req_policy = &ethtool_fec_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_FEC_HEADER, &req->header);
- if (req->_present.modes)
- ethtool_bitset_put(nlh, ETHTOOL_A_FEC_MODES, &req->modes);
- if (req->_present.auto_)
- mnl_attr_put_u8(nlh, ETHTOOL_A_FEC_AUTO, req->auto_);
- if (req->_present.active)
- mnl_attr_put_u32(nlh, ETHTOOL_A_FEC_ACTIVE, req->active);
- if (req->_present.stats)
- ethtool_fec_stat_put(nlh, ETHTOOL_A_FEC_STATS, &req->stats);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_MODULE_EEPROM_GET ============== */
-/* ETHTOOL_MSG_MODULE_EEPROM_GET - do */
-void
-ethtool_module_eeprom_get_req_free(struct ethtool_module_eeprom_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void
-ethtool_module_eeprom_get_rsp_free(struct ethtool_module_eeprom_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp->data);
- free(rsp);
-}
-
-int ethtool_module_eeprom_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_module_eeprom_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_MODULE_EEPROM_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_MODULE_EEPROM_OFFSET) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.offset = 1;
- dst->offset = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MODULE_EEPROM_LENGTH) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.length = 1;
- dst->length = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MODULE_EEPROM_PAGE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.page = 1;
- dst->page = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MODULE_EEPROM_BANK) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.bank = 1;
- dst->bank = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.i2c_address = 1;
- dst->i2c_address = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MODULE_EEPROM_DATA) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.data_len = len;
- dst->data = malloc(len);
- memcpy(dst->data, mnl_attr_get_payload(attr), len);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_module_eeprom_get_rsp *
-ethtool_module_eeprom_get(struct ynl_sock *ys,
- struct ethtool_module_eeprom_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_module_eeprom_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_EEPROM_GET, 1);
- ys->req_policy = &ethtool_module_eeprom_nest;
- yrs.yarg.rsp_policy = &ethtool_module_eeprom_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MODULE_EEPROM_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_module_eeprom_get_rsp_parse;
- yrs.rsp_cmd = 32;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_module_eeprom_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_MODULE_EEPROM_GET - dump */
-void
-ethtool_module_eeprom_get_list_free(struct ethtool_module_eeprom_get_list *rsp)
-{
- struct ethtool_module_eeprom_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp->obj.data);
- free(rsp);
- }
-}
-
-struct ethtool_module_eeprom_get_list *
-ethtool_module_eeprom_get_dump(struct ynl_sock *ys,
- struct ethtool_module_eeprom_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_module_eeprom_get_list);
- yds.cb = ethtool_module_eeprom_get_rsp_parse;
- yds.rsp_cmd = 32;
- yds.rsp_policy = &ethtool_module_eeprom_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MODULE_EEPROM_GET, 1);
- ys->req_policy = &ethtool_module_eeprom_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MODULE_EEPROM_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_module_eeprom_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_PHC_VCLOCKS_GET ============== */
-/* ETHTOOL_MSG_PHC_VCLOCKS_GET - do */
-void ethtool_phc_vclocks_get_req_free(struct ethtool_phc_vclocks_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_phc_vclocks_get_rsp_free(struct ethtool_phc_vclocks_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_phc_vclocks_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_phc_vclocks_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PHC_VCLOCKS_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PHC_VCLOCKS_NUM) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.num = 1;
- dst->num = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_phc_vclocks_get_rsp *
-ethtool_phc_vclocks_get(struct ynl_sock *ys,
- struct ethtool_phc_vclocks_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_phc_vclocks_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PHC_VCLOCKS_GET, 1);
- ys->req_policy = &ethtool_phc_vclocks_nest;
- yrs.yarg.rsp_policy = &ethtool_phc_vclocks_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PHC_VCLOCKS_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_phc_vclocks_get_rsp_parse;
- yrs.rsp_cmd = 34;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_phc_vclocks_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PHC_VCLOCKS_GET - dump */
-void
-ethtool_phc_vclocks_get_list_free(struct ethtool_phc_vclocks_get_list *rsp)
-{
- struct ethtool_phc_vclocks_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_phc_vclocks_get_list *
-ethtool_phc_vclocks_get_dump(struct ynl_sock *ys,
- struct ethtool_phc_vclocks_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_phc_vclocks_get_list);
- yds.cb = ethtool_phc_vclocks_get_rsp_parse;
- yds.rsp_cmd = 34;
- yds.rsp_policy = &ethtool_phc_vclocks_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PHC_VCLOCKS_GET, 1);
- ys->req_policy = &ethtool_phc_vclocks_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PHC_VCLOCKS_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_phc_vclocks_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_MODULE_GET ============== */
-/* ETHTOOL_MSG_MODULE_GET - do */
-void ethtool_module_get_req_free(struct ethtool_module_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_module_get_rsp_free(struct ethtool_module_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_module_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_module_get_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_MODULE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_MODULE_POWER_MODE_POLICY) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.power_mode_policy = 1;
- dst->power_mode_policy = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MODULE_POWER_MODE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.power_mode = 1;
- dst->power_mode = mnl_attr_get_u8(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_module_get_rsp *
-ethtool_module_get(struct ynl_sock *ys, struct ethtool_module_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_module_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_GET, 1);
- ys->req_policy = &ethtool_module_nest;
- yrs.yarg.rsp_policy = &ethtool_module_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_module_get_rsp_parse;
- yrs.rsp_cmd = 35;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_module_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_MODULE_GET - dump */
-void ethtool_module_get_list_free(struct ethtool_module_get_list *rsp)
-{
- struct ethtool_module_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_module_get_list *
-ethtool_module_get_dump(struct ynl_sock *ys,
- struct ethtool_module_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_module_get_list);
- yds.cb = ethtool_module_get_rsp_parse;
- yds.rsp_cmd = 35;
- yds.rsp_policy = &ethtool_module_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MODULE_GET, 1);
- ys->req_policy = &ethtool_module_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_module_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_MODULE_GET - notify */
-void ethtool_module_get_ntf_free(struct ethtool_module_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_MODULE_SET ============== */
-/* ETHTOOL_MSG_MODULE_SET - do */
-void ethtool_module_set_req_free(struct ethtool_module_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MODULE_SET, 1);
- ys->req_policy = &ethtool_module_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MODULE_HEADER, &req->header);
- if (req->_present.power_mode_policy)
- mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE_POLICY, req->power_mode_policy);
- if (req->_present.power_mode)
- mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE, req->power_mode);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_PSE_GET ============== */
-/* ETHTOOL_MSG_PSE_GET - do */
-void ethtool_pse_get_req_free(struct ethtool_pse_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_pse_get_rsp_free(struct ethtool_pse_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_pse_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_pse_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PSE_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PODL_PSE_ADMIN_STATE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.admin_state = 1;
- dst->admin_state = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PODL_PSE_ADMIN_CONTROL) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.admin_control = 1;
- dst->admin_control = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PODL_PSE_PW_D_STATUS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pw_d_status = 1;
- dst->pw_d_status = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_pse_get_rsp *
-ethtool_pse_get(struct ynl_sock *ys, struct ethtool_pse_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_pse_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PSE_GET, 1);
- ys->req_policy = &ethtool_pse_nest;
- yrs.yarg.rsp_policy = &ethtool_pse_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_pse_get_rsp_parse;
- yrs.rsp_cmd = 37;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_pse_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PSE_GET - dump */
-void ethtool_pse_get_list_free(struct ethtool_pse_get_list *rsp)
-{
- struct ethtool_pse_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_pse_get_list *
-ethtool_pse_get_dump(struct ynl_sock *ys, struct ethtool_pse_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_pse_get_list);
- yds.cb = ethtool_pse_get_rsp_parse;
- yds.rsp_cmd = 37;
- yds.rsp_policy = &ethtool_pse_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PSE_GET, 1);
- ys->req_policy = &ethtool_pse_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_pse_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_PSE_SET ============== */
-/* ETHTOOL_MSG_PSE_SET - do */
-void ethtool_pse_set_req_free(struct ethtool_pse_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PSE_SET, 1);
- ys->req_policy = &ethtool_pse_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PSE_HEADER, &req->header);
- if (req->_present.admin_state)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_ADMIN_STATE, req->admin_state);
- if (req->_present.admin_control)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_ADMIN_CONTROL, req->admin_control);
- if (req->_present.pw_d_status)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_PW_D_STATUS, req->pw_d_status);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_RSS_GET ============== */
-/* ETHTOOL_MSG_RSS_GET - do */
-void ethtool_rss_get_req_free(struct ethtool_rss_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_rss_get_rsp_free(struct ethtool_rss_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp->indir);
- free(rsp->hkey);
- free(rsp);
-}
-
-int ethtool_rss_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_rss_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_RSS_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_RSS_CONTEXT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.context = 1;
- dst->context = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RSS_HFUNC) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.hfunc = 1;
- dst->hfunc = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_RSS_INDIR) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.indir_len = len;
- dst->indir = malloc(len);
- memcpy(dst->indir, mnl_attr_get_payload(attr), len);
- } else if (type == ETHTOOL_A_RSS_HKEY) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.hkey_len = len;
- dst->hkey = malloc(len);
- memcpy(dst->hkey, mnl_attr_get_payload(attr), len);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_rss_get_rsp *
-ethtool_rss_get(struct ynl_sock *ys, struct ethtool_rss_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_rss_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_RSS_GET, 1);
- ys->req_policy = &ethtool_rss_nest;
- yrs.yarg.rsp_policy = &ethtool_rss_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_RSS_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_rss_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_RSS_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_rss_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_RSS_GET - dump */
-void ethtool_rss_get_list_free(struct ethtool_rss_get_list *rsp)
-{
- struct ethtool_rss_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp->obj.indir);
- free(rsp->obj.hkey);
- free(rsp);
- }
-}
-
-struct ethtool_rss_get_list *
-ethtool_rss_get_dump(struct ynl_sock *ys, struct ethtool_rss_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_rss_get_list);
- yds.cb = ethtool_rss_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_RSS_GET;
- yds.rsp_policy = &ethtool_rss_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_RSS_GET, 1);
- ys->req_policy = &ethtool_rss_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_RSS_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_rss_get_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_PLCA_GET_CFG ============== */
-/* ETHTOOL_MSG_PLCA_GET_CFG - do */
-void ethtool_plca_get_cfg_req_free(struct ethtool_plca_get_cfg_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_plca_get_cfg_rsp_free(struct ethtool_plca_get_cfg_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_plca_get_cfg_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_plca_get_cfg_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PLCA_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PLCA_VERSION) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.version = 1;
- dst->version = mnl_attr_get_u16(attr);
- } else if (type == ETHTOOL_A_PLCA_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.enabled = 1;
- dst->enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PLCA_STATUS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.status = 1;
- dst->status = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PLCA_NODE_CNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.node_cnt = 1;
- dst->node_cnt = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_NODE_ID) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.node_id = 1;
- dst->node_id = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_TO_TMR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.to_tmr = 1;
- dst->to_tmr = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_BURST_CNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.burst_cnt = 1;
- dst->burst_cnt = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_BURST_TMR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.burst_tmr = 1;
- dst->burst_tmr = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_plca_get_cfg_rsp *
-ethtool_plca_get_cfg(struct ynl_sock *ys, struct ethtool_plca_get_cfg_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_plca_get_cfg_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_CFG, 1);
- ys->req_policy = &ethtool_plca_nest;
- yrs.yarg.rsp_policy = &ethtool_plca_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_plca_get_cfg_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_PLCA_GET_CFG;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_plca_get_cfg_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PLCA_GET_CFG - dump */
-void ethtool_plca_get_cfg_list_free(struct ethtool_plca_get_cfg_list *rsp)
-{
- struct ethtool_plca_get_cfg_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_plca_get_cfg_list *
-ethtool_plca_get_cfg_dump(struct ynl_sock *ys,
- struct ethtool_plca_get_cfg_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_plca_get_cfg_list);
- yds.cb = ethtool_plca_get_cfg_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_PLCA_GET_CFG;
- yds.rsp_policy = &ethtool_plca_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_CFG, 1);
- ys->req_policy = &ethtool_plca_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_plca_get_cfg_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PLCA_GET_CFG - notify */
-void ethtool_plca_get_cfg_ntf_free(struct ethtool_plca_get_cfg_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_PLCA_SET_CFG ============== */
-/* ETHTOOL_MSG_PLCA_SET_CFG - do */
-void ethtool_plca_set_cfg_req_free(struct ethtool_plca_set_cfg_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_plca_set_cfg(struct ynl_sock *ys,
- struct ethtool_plca_set_cfg_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_SET_CFG, 1);
- ys->req_policy = &ethtool_plca_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
- if (req->_present.version)
- mnl_attr_put_u16(nlh, ETHTOOL_A_PLCA_VERSION, req->version);
- if (req->_present.enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_PLCA_ENABLED, req->enabled);
- if (req->_present.status)
- mnl_attr_put_u8(nlh, ETHTOOL_A_PLCA_STATUS, req->status);
- if (req->_present.node_cnt)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_NODE_CNT, req->node_cnt);
- if (req->_present.node_id)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_NODE_ID, req->node_id);
- if (req->_present.to_tmr)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_TO_TMR, req->to_tmr);
- if (req->_present.burst_cnt)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_CNT, req->burst_cnt);
- if (req->_present.burst_tmr)
- mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_TMR, req->burst_tmr);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== ETHTOOL_MSG_PLCA_GET_STATUS ============== */
-/* ETHTOOL_MSG_PLCA_GET_STATUS - do */
-void ethtool_plca_get_status_req_free(struct ethtool_plca_get_status_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_plca_get_status_rsp_free(struct ethtool_plca_get_status_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- free(rsp);
-}
-
-int ethtool_plca_get_status_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_plca_get_status_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_PLCA_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_PLCA_VERSION) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.version = 1;
- dst->version = mnl_attr_get_u16(attr);
- } else if (type == ETHTOOL_A_PLCA_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.enabled = 1;
- dst->enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PLCA_STATUS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.status = 1;
- dst->status = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_PLCA_NODE_CNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.node_cnt = 1;
- dst->node_cnt = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_NODE_ID) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.node_id = 1;
- dst->node_id = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_TO_TMR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.to_tmr = 1;
- dst->to_tmr = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_BURST_CNT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.burst_cnt = 1;
- dst->burst_cnt = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_PLCA_BURST_TMR) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.burst_tmr = 1;
- dst->burst_tmr = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_plca_get_status_rsp *
-ethtool_plca_get_status(struct ynl_sock *ys,
- struct ethtool_plca_get_status_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_plca_get_status_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_STATUS, 1);
- ys->req_policy = &ethtool_plca_nest;
- yrs.yarg.rsp_policy = &ethtool_plca_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_plca_get_status_rsp_parse;
- yrs.rsp_cmd = 40;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_plca_get_status_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_PLCA_GET_STATUS - dump */
-void
-ethtool_plca_get_status_list_free(struct ethtool_plca_get_status_list *rsp)
-{
- struct ethtool_plca_get_status_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
- }
-}
-
-struct ethtool_plca_get_status_list *
-ethtool_plca_get_status_dump(struct ynl_sock *ys,
- struct ethtool_plca_get_status_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_plca_get_status_list);
- yds.cb = ethtool_plca_get_status_rsp_parse;
- yds.rsp_cmd = 40;
- yds.rsp_policy = &ethtool_plca_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PLCA_GET_STATUS, 1);
- ys->req_policy = &ethtool_plca_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_PLCA_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_plca_get_status_list_free(yds.first);
- return NULL;
-}
-
-/* ============== ETHTOOL_MSG_MM_GET ============== */
-/* ETHTOOL_MSG_MM_GET - do */
-void ethtool_mm_get_req_free(struct ethtool_mm_get_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-void ethtool_mm_get_rsp_free(struct ethtool_mm_get_rsp *rsp)
-{
- ethtool_header_free(&rsp->header);
- ethtool_mm_stat_free(&rsp->stats);
- free(rsp);
-}
-
-int ethtool_mm_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct ethtool_mm_get_rsp *dst;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_MM_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_MM_PMAC_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.pmac_enabled = 1;
- dst->pmac_enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MM_TX_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_enabled = 1;
- dst->tx_enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MM_TX_ACTIVE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_active = 1;
- dst->tx_active = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MM_TX_MIN_FRAG_SIZE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.tx_min_frag_size = 1;
- dst->tx_min_frag_size = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MM_RX_MIN_FRAG_SIZE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.rx_min_frag_size = 1;
- dst->rx_min_frag_size = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MM_VERIFY_ENABLED) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.verify_enabled = 1;
- dst->verify_enabled = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_MM_VERIFY_TIME) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.verify_time = 1;
- dst->verify_time = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MM_MAX_VERIFY_TIME) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.max_verify_time = 1;
- dst->max_verify_time = mnl_attr_get_u32(attr);
- } else if (type == ETHTOOL_A_MM_STATS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.stats = 1;
-
- parg.rsp_policy = &ethtool_mm_stat_nest;
- parg.data = &dst->stats;
- if (ethtool_mm_stat_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct ethtool_mm_get_rsp *
-ethtool_mm_get(struct ynl_sock *ys, struct ethtool_mm_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct ethtool_mm_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MM_GET, 1);
- ys->req_policy = &ethtool_mm_nest;
- yrs.yarg.rsp_policy = &ethtool_mm_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = ethtool_mm_get_rsp_parse;
- yrs.rsp_cmd = ETHTOOL_MSG_MM_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- ethtool_mm_get_rsp_free(rsp);
- return NULL;
-}
-
-/* ETHTOOL_MSG_MM_GET - dump */
-void ethtool_mm_get_list_free(struct ethtool_mm_get_list *rsp)
-{
- struct ethtool_mm_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- ethtool_header_free(&rsp->obj.header);
- ethtool_mm_stat_free(&rsp->obj.stats);
- free(rsp);
- }
-}
-
-struct ethtool_mm_get_list *
-ethtool_mm_get_dump(struct ynl_sock *ys, struct ethtool_mm_get_req_dump *req)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct ethtool_mm_get_list);
- yds.cb = ethtool_mm_get_rsp_parse;
- yds.rsp_cmd = ETHTOOL_MSG_MM_GET;
- yds.rsp_policy = &ethtool_mm_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_MM_GET, 1);
- ys->req_policy = &ethtool_mm_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- ethtool_mm_get_list_free(yds.first);
- return NULL;
-}
-
-/* ETHTOOL_MSG_MM_GET - notify */
-void ethtool_mm_get_ntf_free(struct ethtool_mm_get_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_mm_stat_free(&rsp->obj.stats);
- free(rsp);
-}
-
-/* ============== ETHTOOL_MSG_MM_SET ============== */
-/* ETHTOOL_MSG_MM_SET - do */
-void ethtool_mm_set_req_free(struct ethtool_mm_set_req *req)
-{
- ethtool_header_free(&req->header);
- free(req);
-}
-
-int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_MM_SET, 1);
- ys->req_policy = &ethtool_mm_nest;
-
- if (req->_present.header)
- ethtool_header_put(nlh, ETHTOOL_A_MM_HEADER, &req->header);
- if (req->_present.verify_enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_MM_VERIFY_ENABLED, req->verify_enabled);
- if (req->_present.verify_time)
- mnl_attr_put_u32(nlh, ETHTOOL_A_MM_VERIFY_TIME, req->verify_time);
- if (req->_present.tx_enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_MM_TX_ENABLED, req->tx_enabled);
- if (req->_present.pmac_enabled)
- mnl_attr_put_u8(nlh, ETHTOOL_A_MM_PMAC_ENABLED, req->pmac_enabled);
- if (req->_present.tx_min_frag_size)
- mnl_attr_put_u32(nlh, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, req->tx_min_frag_size);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ETHTOOL_MSG_CABLE_TEST_NTF - event */
-int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ethtool_cable_test_ntf_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CABLE_TEST_NTF_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_CABLE_TEST_NTF_STATUS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.status = 1;
- dst->status = mnl_attr_get_u8(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-void ethtool_cable_test_ntf_free(struct ethtool_cable_test_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- free(rsp);
-}
-
-/* ETHTOOL_MSG_CABLE_TEST_TDR_NTF - event */
-int ethtool_cable_test_tdr_ntf_rsp_parse(const struct nlmsghdr *nlh,
- void *data)
-{
- struct ethtool_cable_test_tdr_ntf_rsp *dst;
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.header = 1;
-
- parg.rsp_policy = &ethtool_header_nest;
- parg.data = &dst->header;
- if (ethtool_header_parse(&parg, attr))
- return MNL_CB_ERROR;
- } else if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.status = 1;
- dst->status = mnl_attr_get_u8(attr);
- } else if (type == ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.nest = 1;
-
- parg.rsp_policy = &ethtool_cable_nest_nest;
- parg.data = &dst->nest;
- if (ethtool_cable_nest_parse(&parg, attr))
- return MNL_CB_ERROR;
- }
- }
-
- return MNL_CB_OK;
-}
-
-void ethtool_cable_test_tdr_ntf_free(struct ethtool_cable_test_tdr_ntf *rsp)
-{
- ethtool_header_free(&rsp->obj.header);
- ethtool_cable_nest_free(&rsp->obj.nest);
- free(rsp);
-}
-
-static const struct ynl_ntf_info ethtool_ntf_info[] = {
- [ETHTOOL_MSG_LINKINFO_NTF] = {
- .alloc_sz = sizeof(struct ethtool_linkinfo_get_ntf),
- .cb = ethtool_linkinfo_get_rsp_parse,
- .policy = &ethtool_linkinfo_nest,
- .free = (void *)ethtool_linkinfo_get_ntf_free,
- },
- [ETHTOOL_MSG_LINKMODES_NTF] = {
- .alloc_sz = sizeof(struct ethtool_linkmodes_get_ntf),
- .cb = ethtool_linkmodes_get_rsp_parse,
- .policy = &ethtool_linkmodes_nest,
- .free = (void *)ethtool_linkmodes_get_ntf_free,
- },
- [ETHTOOL_MSG_DEBUG_NTF] = {
- .alloc_sz = sizeof(struct ethtool_debug_get_ntf),
- .cb = ethtool_debug_get_rsp_parse,
- .policy = &ethtool_debug_nest,
- .free = (void *)ethtool_debug_get_ntf_free,
- },
- [ETHTOOL_MSG_WOL_NTF] = {
- .alloc_sz = sizeof(struct ethtool_wol_get_ntf),
- .cb = ethtool_wol_get_rsp_parse,
- .policy = &ethtool_wol_nest,
- .free = (void *)ethtool_wol_get_ntf_free,
- },
- [ETHTOOL_MSG_FEATURES_NTF] = {
- .alloc_sz = sizeof(struct ethtool_features_get_ntf),
- .cb = ethtool_features_get_rsp_parse,
- .policy = &ethtool_features_nest,
- .free = (void *)ethtool_features_get_ntf_free,
- },
- [ETHTOOL_MSG_PRIVFLAGS_NTF] = {
- .alloc_sz = sizeof(struct ethtool_privflags_get_ntf),
- .cb = ethtool_privflags_get_rsp_parse,
- .policy = &ethtool_privflags_nest,
- .free = (void *)ethtool_privflags_get_ntf_free,
- },
- [ETHTOOL_MSG_RINGS_NTF] = {
- .alloc_sz = sizeof(struct ethtool_rings_get_ntf),
- .cb = ethtool_rings_get_rsp_parse,
- .policy = &ethtool_rings_nest,
- .free = (void *)ethtool_rings_get_ntf_free,
- },
- [ETHTOOL_MSG_CHANNELS_NTF] = {
- .alloc_sz = sizeof(struct ethtool_channels_get_ntf),
- .cb = ethtool_channels_get_rsp_parse,
- .policy = &ethtool_channels_nest,
- .free = (void *)ethtool_channels_get_ntf_free,
- },
- [ETHTOOL_MSG_COALESCE_NTF] = {
- .alloc_sz = sizeof(struct ethtool_coalesce_get_ntf),
- .cb = ethtool_coalesce_get_rsp_parse,
- .policy = &ethtool_coalesce_nest,
- .free = (void *)ethtool_coalesce_get_ntf_free,
- },
- [ETHTOOL_MSG_PAUSE_NTF] = {
- .alloc_sz = sizeof(struct ethtool_pause_get_ntf),
- .cb = ethtool_pause_get_rsp_parse,
- .policy = &ethtool_pause_nest,
- .free = (void *)ethtool_pause_get_ntf_free,
- },
- [ETHTOOL_MSG_EEE_NTF] = {
- .alloc_sz = sizeof(struct ethtool_eee_get_ntf),
- .cb = ethtool_eee_get_rsp_parse,
- .policy = &ethtool_eee_nest,
- .free = (void *)ethtool_eee_get_ntf_free,
- },
- [ETHTOOL_MSG_CABLE_TEST_NTF] = {
- .alloc_sz = sizeof(struct ethtool_cable_test_ntf),
- .cb = ethtool_cable_test_ntf_rsp_parse,
- .policy = &ethtool_cable_test_ntf_nest,
- .free = (void *)ethtool_cable_test_ntf_free,
- },
- [ETHTOOL_MSG_CABLE_TEST_TDR_NTF] = {
- .alloc_sz = sizeof(struct ethtool_cable_test_tdr_ntf),
- .cb = ethtool_cable_test_tdr_ntf_rsp_parse,
- .policy = &ethtool_cable_test_tdr_ntf_nest,
- .free = (void *)ethtool_cable_test_tdr_ntf_free,
- },
- [ETHTOOL_MSG_FEC_NTF] = {
- .alloc_sz = sizeof(struct ethtool_fec_get_ntf),
- .cb = ethtool_fec_get_rsp_parse,
- .policy = &ethtool_fec_nest,
- .free = (void *)ethtool_fec_get_ntf_free,
- },
- [ETHTOOL_MSG_MODULE_NTF] = {
- .alloc_sz = sizeof(struct ethtool_module_get_ntf),
- .cb = ethtool_module_get_rsp_parse,
- .policy = &ethtool_module_nest,
- .free = (void *)ethtool_module_get_ntf_free,
- },
- [ETHTOOL_MSG_PLCA_NTF] = {
- .alloc_sz = sizeof(struct ethtool_plca_get_cfg_ntf),
- .cb = ethtool_plca_get_cfg_rsp_parse,
- .policy = &ethtool_plca_nest,
- .free = (void *)ethtool_plca_get_cfg_ntf_free,
- },
- [ETHTOOL_MSG_MM_NTF] = {
- .alloc_sz = sizeof(struct ethtool_mm_get_ntf),
- .cb = ethtool_mm_get_rsp_parse,
- .policy = &ethtool_mm_nest,
- .free = (void *)ethtool_mm_get_ntf_free,
- },
-};
-
-const struct ynl_family ynl_ethtool_family = {
- .name = "ethtool",
- .ntf_info = ethtool_ntf_info,
- .ntf_info_size = MNL_ARRAY_SIZE(ethtool_ntf_info),
-};
diff --git a/tools/net/ynl/generated/ethtool-user.h b/tools/net/ynl/generated/ethtool-user.h
deleted file mode 100644
index ddc1a5209992..000000000000
--- a/tools/net/ynl/generated/ethtool-user.h
+++ /dev/null
@@ -1,5535 +0,0 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/ethtool.yaml */
-/* YNL-GEN user header */
-/* YNL-ARG --user-header linux/ethtool_netlink.h --exclude-op stats-get */
-
-#ifndef _LINUX_ETHTOOL_GEN_H
-#define _LINUX_ETHTOOL_GEN_H
-
-#include <stdlib.h>
-#include <string.h>
-#include <linux/types.h>
-#include <linux/ethtool.h>
-
-struct ynl_sock;
-
-extern const struct ynl_family ynl_ethtool_family;
-
-/* Enums */
-const char *ethtool_op_str(int op);
-const char *ethtool_udp_tunnel_type_str(int value);
-const char *ethtool_stringset_str(enum ethtool_stringset value);
-
-/* Common nested types */
-struct ethtool_header {
- struct {
- __u32 dev_index:1;
- __u32 dev_name_len;
- __u32 flags:1;
- } _present;
-
- __u32 dev_index;
- char *dev_name;
- __u32 flags;
-};
-
-struct ethtool_pause_stat {
- struct {
- __u32 tx_frames:1;
- __u32 rx_frames:1;
- } _present;
-
- __u64 tx_frames;
- __u64 rx_frames;
-};
-
-struct ethtool_cable_test_tdr_cfg {
- struct {
- __u32 first:1;
- __u32 last:1;
- __u32 step:1;
- __u32 pair:1;
- } _present;
-
- __u32 first;
- __u32 last;
- __u32 step;
- __u8 pair;
-};
-
-struct ethtool_fec_stat {
- struct {
- __u32 corrected_len;
- __u32 uncorr_len;
- __u32 corr_bits_len;
- } _present;
-
- void *corrected;
- void *uncorr;
- void *corr_bits;
-};
-
-struct ethtool_mm_stat {
- struct {
- __u32 reassembly_errors:1;
- __u32 smd_errors:1;
- __u32 reassembly_ok:1;
- __u32 rx_frag_count:1;
- __u32 tx_frag_count:1;
- __u32 hold_count:1;
- } _present;
-
- __u64 reassembly_errors;
- __u64 smd_errors;
- __u64 reassembly_ok;
- __u64 rx_frag_count;
- __u64 tx_frag_count;
- __u64 hold_count;
-};
-
-struct ethtool_cable_result {
- struct {
- __u32 pair:1;
- __u32 code:1;
- } _present;
-
- __u8 pair;
- __u8 code;
-};
-
-struct ethtool_cable_fault_length {
- struct {
- __u32 pair:1;
- __u32 cm:1;
- } _present;
-
- __u8 pair;
- __u32 cm;
-};
-
-struct ethtool_bitset_bit {
- struct {
- __u32 index:1;
- __u32 name_len;
- __u32 value:1;
- } _present;
-
- __u32 index;
- char *name;
-};
-
-struct ethtool_tunnel_udp_entry {
- struct {
- __u32 port:1;
- __u32 type:1;
- } _present;
-
- __u16 port /* big-endian */;
- __u32 type;
-};
-
-struct ethtool_string {
- struct {
- __u32 index:1;
- __u32 value_len;
- } _present;
-
- __u32 index;
- char *value;
-};
-
-struct ethtool_cable_nest {
- struct {
- __u32 result:1;
- __u32 fault_length:1;
- } _present;
-
- struct ethtool_cable_result result;
- struct ethtool_cable_fault_length fault_length;
-};
-
-struct ethtool_bitset_bits {
- unsigned int n_bit;
- struct ethtool_bitset_bit *bit;
-};
-
-struct ethtool_strings {
- unsigned int n_string;
- struct ethtool_string *string;
-};
-
-struct ethtool_bitset {
- struct {
- __u32 nomask:1;
- __u32 size:1;
- __u32 bits:1;
- } _present;
-
- __u32 size;
- struct ethtool_bitset_bits bits;
-};
-
-struct ethtool_stringset_ {
- struct {
- __u32 id:1;
- __u32 count:1;
- } _present;
-
- __u32 id;
- __u32 count;
- unsigned int n_strings;
- struct ethtool_strings *strings;
-};
-
-struct ethtool_tunnel_udp_table {
- struct {
- __u32 size:1;
- __u32 types:1;
- } _present;
-
- __u32 size;
- struct ethtool_bitset types;
- unsigned int n_entry;
- struct ethtool_tunnel_udp_entry *entry;
-};
-
-struct ethtool_stringsets {
- unsigned int n_stringset;
- struct ethtool_stringset_ *stringset;
-};
-
-struct ethtool_tunnel_udp {
- struct {
- __u32 table:1;
- } _present;
-
- struct ethtool_tunnel_udp_table table;
-};
-
-/* ============== ETHTOOL_MSG_STRSET_GET ============== */
-/* ETHTOOL_MSG_STRSET_GET - do */
-struct ethtool_strset_get_req {
- struct {
- __u32 header:1;
- __u32 stringsets:1;
- __u32 counts_only:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_stringsets stringsets;
-};
-
-static inline struct ethtool_strset_get_req *ethtool_strset_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_strset_get_req));
-}
-void ethtool_strset_get_req_free(struct ethtool_strset_get_req *req);
-
-static inline void
-ethtool_strset_get_req_set_header_dev_index(struct ethtool_strset_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_strset_get_req_set_header_dev_name(struct ethtool_strset_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_strset_get_req_set_header_flags(struct ethtool_strset_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-__ethtool_strset_get_req_set_stringsets_stringset(struct ethtool_strset_get_req *req,
- struct ethtool_stringset_ *stringset,
- unsigned int n_stringset)
-{
- free(req->stringsets.stringset);
- req->stringsets.stringset = stringset;
- req->stringsets.n_stringset = n_stringset;
-}
-static inline void
-ethtool_strset_get_req_set_counts_only(struct ethtool_strset_get_req *req)
-{
- req->_present.counts_only = 1;
-}
-
-struct ethtool_strset_get_rsp {
- struct {
- __u32 header:1;
- __u32 stringsets:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_stringsets stringsets;
-};
-
-void ethtool_strset_get_rsp_free(struct ethtool_strset_get_rsp *rsp);
-
-/*
- * Get string set from the kernel.
- */
-struct ethtool_strset_get_rsp *
-ethtool_strset_get(struct ynl_sock *ys, struct ethtool_strset_get_req *req);
-
-/* ETHTOOL_MSG_STRSET_GET - dump */
-struct ethtool_strset_get_req_dump {
- struct {
- __u32 header:1;
- __u32 stringsets:1;
- __u32 counts_only:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_stringsets stringsets;
-};
-
-static inline struct ethtool_strset_get_req_dump *
-ethtool_strset_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_strset_get_req_dump));
-}
-void ethtool_strset_get_req_dump_free(struct ethtool_strset_get_req_dump *req);
-
-static inline void
-ethtool_strset_get_req_dump_set_header_dev_index(struct ethtool_strset_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_strset_get_req_dump_set_header_dev_name(struct ethtool_strset_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_strset_get_req_dump_set_header_flags(struct ethtool_strset_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-__ethtool_strset_get_req_dump_set_stringsets_stringset(struct ethtool_strset_get_req_dump *req,
- struct ethtool_stringset_ *stringset,
- unsigned int n_stringset)
-{
- free(req->stringsets.stringset);
- req->stringsets.stringset = stringset;
- req->stringsets.n_stringset = n_stringset;
-}
-static inline void
-ethtool_strset_get_req_dump_set_counts_only(struct ethtool_strset_get_req_dump *req)
-{
- req->_present.counts_only = 1;
-}
-
-struct ethtool_strset_get_list {
- struct ethtool_strset_get_list *next;
- struct ethtool_strset_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_strset_get_list_free(struct ethtool_strset_get_list *rsp);
-
-struct ethtool_strset_get_list *
-ethtool_strset_get_dump(struct ynl_sock *ys,
- struct ethtool_strset_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_LINKINFO_GET ============== */
-/* ETHTOOL_MSG_LINKINFO_GET - do */
-struct ethtool_linkinfo_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkinfo_get_req *
-ethtool_linkinfo_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkinfo_get_req));
-}
-void ethtool_linkinfo_get_req_free(struct ethtool_linkinfo_get_req *req);
-
-static inline void
-ethtool_linkinfo_get_req_set_header_dev_index(struct ethtool_linkinfo_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkinfo_get_req_set_header_dev_name(struct ethtool_linkinfo_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkinfo_get_req_set_header_flags(struct ethtool_linkinfo_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkinfo_get_rsp {
- struct {
- __u32 header:1;
- __u32 port:1;
- __u32 phyaddr:1;
- __u32 tp_mdix:1;
- __u32 tp_mdix_ctrl:1;
- __u32 transceiver:1;
- } _present;
-
- struct ethtool_header header;
- __u8 port;
- __u8 phyaddr;
- __u8 tp_mdix;
- __u8 tp_mdix_ctrl;
- __u8 transceiver;
-};
-
-void ethtool_linkinfo_get_rsp_free(struct ethtool_linkinfo_get_rsp *rsp);
-
-/*
- * Get link info.
- */
-struct ethtool_linkinfo_get_rsp *
-ethtool_linkinfo_get(struct ynl_sock *ys, struct ethtool_linkinfo_get_req *req);
-
-/* ETHTOOL_MSG_LINKINFO_GET - dump */
-struct ethtool_linkinfo_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkinfo_get_req_dump *
-ethtool_linkinfo_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkinfo_get_req_dump));
-}
-void
-ethtool_linkinfo_get_req_dump_free(struct ethtool_linkinfo_get_req_dump *req);
-
-static inline void
-ethtool_linkinfo_get_req_dump_set_header_dev_index(struct ethtool_linkinfo_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkinfo_get_req_dump_set_header_dev_name(struct ethtool_linkinfo_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkinfo_get_req_dump_set_header_flags(struct ethtool_linkinfo_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkinfo_get_list {
- struct ethtool_linkinfo_get_list *next;
- struct ethtool_linkinfo_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_linkinfo_get_list_free(struct ethtool_linkinfo_get_list *rsp);
-
-struct ethtool_linkinfo_get_list *
-ethtool_linkinfo_get_dump(struct ynl_sock *ys,
- struct ethtool_linkinfo_get_req_dump *req);
-
-/* ETHTOOL_MSG_LINKINFO_GET - notify */
-struct ethtool_linkinfo_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_linkinfo_get_ntf *ntf);
- struct ethtool_linkinfo_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_linkinfo_get_ntf_free(struct ethtool_linkinfo_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_LINKINFO_SET ============== */
-/* ETHTOOL_MSG_LINKINFO_SET - do */
-struct ethtool_linkinfo_set_req {
- struct {
- __u32 header:1;
- __u32 port:1;
- __u32 phyaddr:1;
- __u32 tp_mdix:1;
- __u32 tp_mdix_ctrl:1;
- __u32 transceiver:1;
- } _present;
-
- struct ethtool_header header;
- __u8 port;
- __u8 phyaddr;
- __u8 tp_mdix;
- __u8 tp_mdix_ctrl;
- __u8 transceiver;
-};
-
-static inline struct ethtool_linkinfo_set_req *
-ethtool_linkinfo_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkinfo_set_req));
-}
-void ethtool_linkinfo_set_req_free(struct ethtool_linkinfo_set_req *req);
-
-static inline void
-ethtool_linkinfo_set_req_set_header_dev_index(struct ethtool_linkinfo_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkinfo_set_req_set_header_dev_name(struct ethtool_linkinfo_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkinfo_set_req_set_header_flags(struct ethtool_linkinfo_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_linkinfo_set_req_set_port(struct ethtool_linkinfo_set_req *req,
- __u8 port)
-{
- req->_present.port = 1;
- req->port = port;
-}
-static inline void
-ethtool_linkinfo_set_req_set_phyaddr(struct ethtool_linkinfo_set_req *req,
- __u8 phyaddr)
-{
- req->_present.phyaddr = 1;
- req->phyaddr = phyaddr;
-}
-static inline void
-ethtool_linkinfo_set_req_set_tp_mdix(struct ethtool_linkinfo_set_req *req,
- __u8 tp_mdix)
-{
- req->_present.tp_mdix = 1;
- req->tp_mdix = tp_mdix;
-}
-static inline void
-ethtool_linkinfo_set_req_set_tp_mdix_ctrl(struct ethtool_linkinfo_set_req *req,
- __u8 tp_mdix_ctrl)
-{
- req->_present.tp_mdix_ctrl = 1;
- req->tp_mdix_ctrl = tp_mdix_ctrl;
-}
-static inline void
-ethtool_linkinfo_set_req_set_transceiver(struct ethtool_linkinfo_set_req *req,
- __u8 transceiver)
-{
- req->_present.transceiver = 1;
- req->transceiver = transceiver;
-}
-
-/*
- * Set link info.
- */
-int ethtool_linkinfo_set(struct ynl_sock *ys,
- struct ethtool_linkinfo_set_req *req);
-
-/* ============== ETHTOOL_MSG_LINKMODES_GET ============== */
-/* ETHTOOL_MSG_LINKMODES_GET - do */
-struct ethtool_linkmodes_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkmodes_get_req *
-ethtool_linkmodes_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkmodes_get_req));
-}
-void ethtool_linkmodes_get_req_free(struct ethtool_linkmodes_get_req *req);
-
-static inline void
-ethtool_linkmodes_get_req_set_header_dev_index(struct ethtool_linkmodes_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkmodes_get_req_set_header_dev_name(struct ethtool_linkmodes_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkmodes_get_req_set_header_flags(struct ethtool_linkmodes_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkmodes_get_rsp {
- struct {
- __u32 header:1;
- __u32 autoneg:1;
- __u32 ours:1;
- __u32 peer:1;
- __u32 speed:1;
- __u32 duplex:1;
- __u32 master_slave_cfg:1;
- __u32 master_slave_state:1;
- __u32 lanes:1;
- __u32 rate_matching:1;
- } _present;
-
- struct ethtool_header header;
- __u8 autoneg;
- struct ethtool_bitset ours;
- struct ethtool_bitset peer;
- __u32 speed;
- __u8 duplex;
- __u8 master_slave_cfg;
- __u8 master_slave_state;
- __u32 lanes;
- __u8 rate_matching;
-};
-
-void ethtool_linkmodes_get_rsp_free(struct ethtool_linkmodes_get_rsp *rsp);
-
-/*
- * Get link modes.
- */
-struct ethtool_linkmodes_get_rsp *
-ethtool_linkmodes_get(struct ynl_sock *ys,
- struct ethtool_linkmodes_get_req *req);
-
-/* ETHTOOL_MSG_LINKMODES_GET - dump */
-struct ethtool_linkmodes_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkmodes_get_req_dump *
-ethtool_linkmodes_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkmodes_get_req_dump));
-}
-void
-ethtool_linkmodes_get_req_dump_free(struct ethtool_linkmodes_get_req_dump *req);
-
-static inline void
-ethtool_linkmodes_get_req_dump_set_header_dev_index(struct ethtool_linkmodes_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkmodes_get_req_dump_set_header_dev_name(struct ethtool_linkmodes_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkmodes_get_req_dump_set_header_flags(struct ethtool_linkmodes_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkmodes_get_list {
- struct ethtool_linkmodes_get_list *next;
- struct ethtool_linkmodes_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_linkmodes_get_list_free(struct ethtool_linkmodes_get_list *rsp);
-
-struct ethtool_linkmodes_get_list *
-ethtool_linkmodes_get_dump(struct ynl_sock *ys,
- struct ethtool_linkmodes_get_req_dump *req);
-
-/* ETHTOOL_MSG_LINKMODES_GET - notify */
-struct ethtool_linkmodes_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_linkmodes_get_ntf *ntf);
- struct ethtool_linkmodes_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_linkmodes_get_ntf_free(struct ethtool_linkmodes_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_LINKMODES_SET ============== */
-/* ETHTOOL_MSG_LINKMODES_SET - do */
-struct ethtool_linkmodes_set_req {
- struct {
- __u32 header:1;
- __u32 autoneg:1;
- __u32 ours:1;
- __u32 peer:1;
- __u32 speed:1;
- __u32 duplex:1;
- __u32 master_slave_cfg:1;
- __u32 master_slave_state:1;
- __u32 lanes:1;
- __u32 rate_matching:1;
- } _present;
-
- struct ethtool_header header;
- __u8 autoneg;
- struct ethtool_bitset ours;
- struct ethtool_bitset peer;
- __u32 speed;
- __u8 duplex;
- __u8 master_slave_cfg;
- __u8 master_slave_state;
- __u32 lanes;
- __u8 rate_matching;
-};
-
-static inline struct ethtool_linkmodes_set_req *
-ethtool_linkmodes_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkmodes_set_req));
-}
-void ethtool_linkmodes_set_req_free(struct ethtool_linkmodes_set_req *req);
-
-static inline void
-ethtool_linkmodes_set_req_set_header_dev_index(struct ethtool_linkmodes_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkmodes_set_req_set_header_dev_name(struct ethtool_linkmodes_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkmodes_set_req_set_header_flags(struct ethtool_linkmodes_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_linkmodes_set_req_set_autoneg(struct ethtool_linkmodes_set_req *req,
- __u8 autoneg)
-{
- req->_present.autoneg = 1;
- req->autoneg = autoneg;
-}
-static inline void
-ethtool_linkmodes_set_req_set_ours_nomask(struct ethtool_linkmodes_set_req *req)
-{
- req->_present.ours = 1;
- req->ours._present.nomask = 1;
-}
-static inline void
-ethtool_linkmodes_set_req_set_ours_size(struct ethtool_linkmodes_set_req *req,
- __u32 size)
-{
- req->_present.ours = 1;
- req->ours._present.size = 1;
- req->ours.size = size;
-}
-static inline void
-__ethtool_linkmodes_set_req_set_ours_bits_bit(struct ethtool_linkmodes_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->ours.bits.bit);
- req->ours.bits.bit = bit;
- req->ours.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_linkmodes_set_req_set_peer_nomask(struct ethtool_linkmodes_set_req *req)
-{
- req->_present.peer = 1;
- req->peer._present.nomask = 1;
-}
-static inline void
-ethtool_linkmodes_set_req_set_peer_size(struct ethtool_linkmodes_set_req *req,
- __u32 size)
-{
- req->_present.peer = 1;
- req->peer._present.size = 1;
- req->peer.size = size;
-}
-static inline void
-__ethtool_linkmodes_set_req_set_peer_bits_bit(struct ethtool_linkmodes_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->peer.bits.bit);
- req->peer.bits.bit = bit;
- req->peer.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_linkmodes_set_req_set_speed(struct ethtool_linkmodes_set_req *req,
- __u32 speed)
-{
- req->_present.speed = 1;
- req->speed = speed;
-}
-static inline void
-ethtool_linkmodes_set_req_set_duplex(struct ethtool_linkmodes_set_req *req,
- __u8 duplex)
-{
- req->_present.duplex = 1;
- req->duplex = duplex;
-}
-static inline void
-ethtool_linkmodes_set_req_set_master_slave_cfg(struct ethtool_linkmodes_set_req *req,
- __u8 master_slave_cfg)
-{
- req->_present.master_slave_cfg = 1;
- req->master_slave_cfg = master_slave_cfg;
-}
-static inline void
-ethtool_linkmodes_set_req_set_master_slave_state(struct ethtool_linkmodes_set_req *req,
- __u8 master_slave_state)
-{
- req->_present.master_slave_state = 1;
- req->master_slave_state = master_slave_state;
-}
-static inline void
-ethtool_linkmodes_set_req_set_lanes(struct ethtool_linkmodes_set_req *req,
- __u32 lanes)
-{
- req->_present.lanes = 1;
- req->lanes = lanes;
-}
-static inline void
-ethtool_linkmodes_set_req_set_rate_matching(struct ethtool_linkmodes_set_req *req,
- __u8 rate_matching)
-{
- req->_present.rate_matching = 1;
- req->rate_matching = rate_matching;
-}
-
-/*
- * Set link modes.
- */
-int ethtool_linkmodes_set(struct ynl_sock *ys,
- struct ethtool_linkmodes_set_req *req);
-
-/* ============== ETHTOOL_MSG_LINKSTATE_GET ============== */
-/* ETHTOOL_MSG_LINKSTATE_GET - do */
-struct ethtool_linkstate_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkstate_get_req *
-ethtool_linkstate_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkstate_get_req));
-}
-void ethtool_linkstate_get_req_free(struct ethtool_linkstate_get_req *req);
-
-static inline void
-ethtool_linkstate_get_req_set_header_dev_index(struct ethtool_linkstate_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkstate_get_req_set_header_dev_name(struct ethtool_linkstate_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkstate_get_req_set_header_flags(struct ethtool_linkstate_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkstate_get_rsp {
- struct {
- __u32 header:1;
- __u32 link:1;
- __u32 sqi:1;
- __u32 sqi_max:1;
- __u32 ext_state:1;
- __u32 ext_substate:1;
- __u32 ext_down_cnt:1;
- } _present;
-
- struct ethtool_header header;
- __u8 link;
- __u32 sqi;
- __u32 sqi_max;
- __u8 ext_state;
- __u8 ext_substate;
- __u32 ext_down_cnt;
-};
-
-void ethtool_linkstate_get_rsp_free(struct ethtool_linkstate_get_rsp *rsp);
-
-/*
- * Get link state.
- */
-struct ethtool_linkstate_get_rsp *
-ethtool_linkstate_get(struct ynl_sock *ys,
- struct ethtool_linkstate_get_req *req);
-
-/* ETHTOOL_MSG_LINKSTATE_GET - dump */
-struct ethtool_linkstate_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_linkstate_get_req_dump *
-ethtool_linkstate_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_linkstate_get_req_dump));
-}
-void
-ethtool_linkstate_get_req_dump_free(struct ethtool_linkstate_get_req_dump *req);
-
-static inline void
-ethtool_linkstate_get_req_dump_set_header_dev_index(struct ethtool_linkstate_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_linkstate_get_req_dump_set_header_dev_name(struct ethtool_linkstate_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_linkstate_get_req_dump_set_header_flags(struct ethtool_linkstate_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_linkstate_get_list {
- struct ethtool_linkstate_get_list *next;
- struct ethtool_linkstate_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_linkstate_get_list_free(struct ethtool_linkstate_get_list *rsp);
-
-struct ethtool_linkstate_get_list *
-ethtool_linkstate_get_dump(struct ynl_sock *ys,
- struct ethtool_linkstate_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_DEBUG_GET ============== */
-/* ETHTOOL_MSG_DEBUG_GET - do */
-struct ethtool_debug_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_debug_get_req *ethtool_debug_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_debug_get_req));
-}
-void ethtool_debug_get_req_free(struct ethtool_debug_get_req *req);
-
-static inline void
-ethtool_debug_get_req_set_header_dev_index(struct ethtool_debug_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_debug_get_req_set_header_dev_name(struct ethtool_debug_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_debug_get_req_set_header_flags(struct ethtool_debug_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_debug_get_rsp {
- struct {
- __u32 header:1;
- __u32 msgmask:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset msgmask;
-};
-
-void ethtool_debug_get_rsp_free(struct ethtool_debug_get_rsp *rsp);
-
-/*
- * Get debug message mask.
- */
-struct ethtool_debug_get_rsp *
-ethtool_debug_get(struct ynl_sock *ys, struct ethtool_debug_get_req *req);
-
-/* ETHTOOL_MSG_DEBUG_GET - dump */
-struct ethtool_debug_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_debug_get_req_dump *
-ethtool_debug_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_debug_get_req_dump));
-}
-void ethtool_debug_get_req_dump_free(struct ethtool_debug_get_req_dump *req);
-
-static inline void
-ethtool_debug_get_req_dump_set_header_dev_index(struct ethtool_debug_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_debug_get_req_dump_set_header_dev_name(struct ethtool_debug_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_debug_get_req_dump_set_header_flags(struct ethtool_debug_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_debug_get_list {
- struct ethtool_debug_get_list *next;
- struct ethtool_debug_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_debug_get_list_free(struct ethtool_debug_get_list *rsp);
-
-struct ethtool_debug_get_list *
-ethtool_debug_get_dump(struct ynl_sock *ys,
- struct ethtool_debug_get_req_dump *req);
-
-/* ETHTOOL_MSG_DEBUG_GET - notify */
-struct ethtool_debug_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_debug_get_ntf *ntf);
- struct ethtool_debug_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_debug_get_ntf_free(struct ethtool_debug_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_DEBUG_SET ============== */
-/* ETHTOOL_MSG_DEBUG_SET - do */
-struct ethtool_debug_set_req {
- struct {
- __u32 header:1;
- __u32 msgmask:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset msgmask;
-};
-
-static inline struct ethtool_debug_set_req *ethtool_debug_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_debug_set_req));
-}
-void ethtool_debug_set_req_free(struct ethtool_debug_set_req *req);
-
-static inline void
-ethtool_debug_set_req_set_header_dev_index(struct ethtool_debug_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_debug_set_req_set_header_dev_name(struct ethtool_debug_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_debug_set_req_set_header_flags(struct ethtool_debug_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_debug_set_req_set_msgmask_nomask(struct ethtool_debug_set_req *req)
-{
- req->_present.msgmask = 1;
- req->msgmask._present.nomask = 1;
-}
-static inline void
-ethtool_debug_set_req_set_msgmask_size(struct ethtool_debug_set_req *req,
- __u32 size)
-{
- req->_present.msgmask = 1;
- req->msgmask._present.size = 1;
- req->msgmask.size = size;
-}
-static inline void
-__ethtool_debug_set_req_set_msgmask_bits_bit(struct ethtool_debug_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->msgmask.bits.bit);
- req->msgmask.bits.bit = bit;
- req->msgmask.bits.n_bit = n_bit;
-}
-
-/*
- * Set debug message mask.
- */
-int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req);
-
-/* ============== ETHTOOL_MSG_WOL_GET ============== */
-/* ETHTOOL_MSG_WOL_GET - do */
-struct ethtool_wol_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_wol_get_req *ethtool_wol_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_wol_get_req));
-}
-void ethtool_wol_get_req_free(struct ethtool_wol_get_req *req);
-
-static inline void
-ethtool_wol_get_req_set_header_dev_index(struct ethtool_wol_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_wol_get_req_set_header_dev_name(struct ethtool_wol_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_wol_get_req_set_header_flags(struct ethtool_wol_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_wol_get_rsp {
- struct {
- __u32 header:1;
- __u32 modes:1;
- __u32 sopass_len;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes;
- void *sopass;
-};
-
-void ethtool_wol_get_rsp_free(struct ethtool_wol_get_rsp *rsp);
-
-/*
- * Get WOL params.
- */
-struct ethtool_wol_get_rsp *
-ethtool_wol_get(struct ynl_sock *ys, struct ethtool_wol_get_req *req);
-
-/* ETHTOOL_MSG_WOL_GET - dump */
-struct ethtool_wol_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_wol_get_req_dump *
-ethtool_wol_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_wol_get_req_dump));
-}
-void ethtool_wol_get_req_dump_free(struct ethtool_wol_get_req_dump *req);
-
-static inline void
-ethtool_wol_get_req_dump_set_header_dev_index(struct ethtool_wol_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_wol_get_req_dump_set_header_dev_name(struct ethtool_wol_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_wol_get_req_dump_set_header_flags(struct ethtool_wol_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_wol_get_list {
- struct ethtool_wol_get_list *next;
- struct ethtool_wol_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_wol_get_list_free(struct ethtool_wol_get_list *rsp);
-
-struct ethtool_wol_get_list *
-ethtool_wol_get_dump(struct ynl_sock *ys, struct ethtool_wol_get_req_dump *req);
-
-/* ETHTOOL_MSG_WOL_GET - notify */
-struct ethtool_wol_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_wol_get_ntf *ntf);
- struct ethtool_wol_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_wol_get_ntf_free(struct ethtool_wol_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_WOL_SET ============== */
-/* ETHTOOL_MSG_WOL_SET - do */
-struct ethtool_wol_set_req {
- struct {
- __u32 header:1;
- __u32 modes:1;
- __u32 sopass_len;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes;
- void *sopass;
-};
-
-static inline struct ethtool_wol_set_req *ethtool_wol_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_wol_set_req));
-}
-void ethtool_wol_set_req_free(struct ethtool_wol_set_req *req);
-
-static inline void
-ethtool_wol_set_req_set_header_dev_index(struct ethtool_wol_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_wol_set_req_set_header_dev_name(struct ethtool_wol_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_wol_set_req_set_header_flags(struct ethtool_wol_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_wol_set_req_set_modes_nomask(struct ethtool_wol_set_req *req)
-{
- req->_present.modes = 1;
- req->modes._present.nomask = 1;
-}
-static inline void
-ethtool_wol_set_req_set_modes_size(struct ethtool_wol_set_req *req, __u32 size)
-{
- req->_present.modes = 1;
- req->modes._present.size = 1;
- req->modes.size = size;
-}
-static inline void
-__ethtool_wol_set_req_set_modes_bits_bit(struct ethtool_wol_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->modes.bits.bit);
- req->modes.bits.bit = bit;
- req->modes.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_wol_set_req_set_sopass(struct ethtool_wol_set_req *req,
- const void *sopass, size_t len)
-{
- free(req->sopass);
- req->_present.sopass_len = len;
- req->sopass = malloc(req->_present.sopass_len);
- memcpy(req->sopass, sopass, req->_present.sopass_len);
-}
-
-/*
- * Set WOL params.
- */
-int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req);
-
-/* ============== ETHTOOL_MSG_FEATURES_GET ============== */
-/* ETHTOOL_MSG_FEATURES_GET - do */
-struct ethtool_features_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_features_get_req *
-ethtool_features_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_features_get_req));
-}
-void ethtool_features_get_req_free(struct ethtool_features_get_req *req);
-
-static inline void
-ethtool_features_get_req_set_header_dev_index(struct ethtool_features_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_features_get_req_set_header_dev_name(struct ethtool_features_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_features_get_req_set_header_flags(struct ethtool_features_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_features_get_rsp {
- struct {
- __u32 header:1;
- __u32 hw:1;
- __u32 wanted:1;
- __u32 active:1;
- __u32 nochange:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset hw;
- struct ethtool_bitset wanted;
- struct ethtool_bitset active;
- struct ethtool_bitset nochange;
-};
-
-void ethtool_features_get_rsp_free(struct ethtool_features_get_rsp *rsp);
-
-/*
- * Get features.
- */
-struct ethtool_features_get_rsp *
-ethtool_features_get(struct ynl_sock *ys, struct ethtool_features_get_req *req);
-
-/* ETHTOOL_MSG_FEATURES_GET - dump */
-struct ethtool_features_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_features_get_req_dump *
-ethtool_features_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_features_get_req_dump));
-}
-void
-ethtool_features_get_req_dump_free(struct ethtool_features_get_req_dump *req);
-
-static inline void
-ethtool_features_get_req_dump_set_header_dev_index(struct ethtool_features_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_features_get_req_dump_set_header_dev_name(struct ethtool_features_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_features_get_req_dump_set_header_flags(struct ethtool_features_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_features_get_list {
- struct ethtool_features_get_list *next;
- struct ethtool_features_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_features_get_list_free(struct ethtool_features_get_list *rsp);
-
-struct ethtool_features_get_list *
-ethtool_features_get_dump(struct ynl_sock *ys,
- struct ethtool_features_get_req_dump *req);
-
-/* ETHTOOL_MSG_FEATURES_GET - notify */
-struct ethtool_features_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_features_get_ntf *ntf);
- struct ethtool_features_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_features_get_ntf_free(struct ethtool_features_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_FEATURES_SET ============== */
-/* ETHTOOL_MSG_FEATURES_SET - do */
-struct ethtool_features_set_req {
- struct {
- __u32 header:1;
- __u32 hw:1;
- __u32 wanted:1;
- __u32 active:1;
- __u32 nochange:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset hw;
- struct ethtool_bitset wanted;
- struct ethtool_bitset active;
- struct ethtool_bitset nochange;
-};
-
-static inline struct ethtool_features_set_req *
-ethtool_features_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_features_set_req));
-}
-void ethtool_features_set_req_free(struct ethtool_features_set_req *req);
-
-static inline void
-ethtool_features_set_req_set_header_dev_index(struct ethtool_features_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_features_set_req_set_header_dev_name(struct ethtool_features_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_features_set_req_set_header_flags(struct ethtool_features_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_features_set_req_set_hw_nomask(struct ethtool_features_set_req *req)
-{
- req->_present.hw = 1;
- req->hw._present.nomask = 1;
-}
-static inline void
-ethtool_features_set_req_set_hw_size(struct ethtool_features_set_req *req,
- __u32 size)
-{
- req->_present.hw = 1;
- req->hw._present.size = 1;
- req->hw.size = size;
-}
-static inline void
-__ethtool_features_set_req_set_hw_bits_bit(struct ethtool_features_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->hw.bits.bit);
- req->hw.bits.bit = bit;
- req->hw.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_features_set_req_set_wanted_nomask(struct ethtool_features_set_req *req)
-{
- req->_present.wanted = 1;
- req->wanted._present.nomask = 1;
-}
-static inline void
-ethtool_features_set_req_set_wanted_size(struct ethtool_features_set_req *req,
- __u32 size)
-{
- req->_present.wanted = 1;
- req->wanted._present.size = 1;
- req->wanted.size = size;
-}
-static inline void
-__ethtool_features_set_req_set_wanted_bits_bit(struct ethtool_features_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->wanted.bits.bit);
- req->wanted.bits.bit = bit;
- req->wanted.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_features_set_req_set_active_nomask(struct ethtool_features_set_req *req)
-{
- req->_present.active = 1;
- req->active._present.nomask = 1;
-}
-static inline void
-ethtool_features_set_req_set_active_size(struct ethtool_features_set_req *req,
- __u32 size)
-{
- req->_present.active = 1;
- req->active._present.size = 1;
- req->active.size = size;
-}
-static inline void
-__ethtool_features_set_req_set_active_bits_bit(struct ethtool_features_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->active.bits.bit);
- req->active.bits.bit = bit;
- req->active.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_features_set_req_set_nochange_nomask(struct ethtool_features_set_req *req)
-{
- req->_present.nochange = 1;
- req->nochange._present.nomask = 1;
-}
-static inline void
-ethtool_features_set_req_set_nochange_size(struct ethtool_features_set_req *req,
- __u32 size)
-{
- req->_present.nochange = 1;
- req->nochange._present.size = 1;
- req->nochange.size = size;
-}
-static inline void
-__ethtool_features_set_req_set_nochange_bits_bit(struct ethtool_features_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->nochange.bits.bit);
- req->nochange.bits.bit = bit;
- req->nochange.bits.n_bit = n_bit;
-}
-
-struct ethtool_features_set_rsp {
- struct {
- __u32 header:1;
- __u32 hw:1;
- __u32 wanted:1;
- __u32 active:1;
- __u32 nochange:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset hw;
- struct ethtool_bitset wanted;
- struct ethtool_bitset active;
- struct ethtool_bitset nochange;
-};
-
-void ethtool_features_set_rsp_free(struct ethtool_features_set_rsp *rsp);
-
-/*
- * Set features.
- */
-struct ethtool_features_set_rsp *
-ethtool_features_set(struct ynl_sock *ys, struct ethtool_features_set_req *req);
-
-/* ============== ETHTOOL_MSG_PRIVFLAGS_GET ============== */
-/* ETHTOOL_MSG_PRIVFLAGS_GET - do */
-struct ethtool_privflags_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_privflags_get_req *
-ethtool_privflags_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_privflags_get_req));
-}
-void ethtool_privflags_get_req_free(struct ethtool_privflags_get_req *req);
-
-static inline void
-ethtool_privflags_get_req_set_header_dev_index(struct ethtool_privflags_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_privflags_get_req_set_header_dev_name(struct ethtool_privflags_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_privflags_get_req_set_header_flags(struct ethtool_privflags_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_privflags_get_rsp {
- struct {
- __u32 header:1;
- __u32 flags:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset flags;
-};
-
-void ethtool_privflags_get_rsp_free(struct ethtool_privflags_get_rsp *rsp);
-
-/*
- * Get device private flags.
- */
-struct ethtool_privflags_get_rsp *
-ethtool_privflags_get(struct ynl_sock *ys,
- struct ethtool_privflags_get_req *req);
-
-/* ETHTOOL_MSG_PRIVFLAGS_GET - dump */
-struct ethtool_privflags_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_privflags_get_req_dump *
-ethtool_privflags_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_privflags_get_req_dump));
-}
-void
-ethtool_privflags_get_req_dump_free(struct ethtool_privflags_get_req_dump *req);
-
-static inline void
-ethtool_privflags_get_req_dump_set_header_dev_index(struct ethtool_privflags_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_privflags_get_req_dump_set_header_dev_name(struct ethtool_privflags_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_privflags_get_req_dump_set_header_flags(struct ethtool_privflags_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_privflags_get_list {
- struct ethtool_privflags_get_list *next;
- struct ethtool_privflags_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_privflags_get_list_free(struct ethtool_privflags_get_list *rsp);
-
-struct ethtool_privflags_get_list *
-ethtool_privflags_get_dump(struct ynl_sock *ys,
- struct ethtool_privflags_get_req_dump *req);
-
-/* ETHTOOL_MSG_PRIVFLAGS_GET - notify */
-struct ethtool_privflags_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_privflags_get_ntf *ntf);
- struct ethtool_privflags_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_privflags_get_ntf_free(struct ethtool_privflags_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_PRIVFLAGS_SET ============== */
-/* ETHTOOL_MSG_PRIVFLAGS_SET - do */
-struct ethtool_privflags_set_req {
- struct {
- __u32 header:1;
- __u32 flags:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset flags;
-};
-
-static inline struct ethtool_privflags_set_req *
-ethtool_privflags_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_privflags_set_req));
-}
-void ethtool_privflags_set_req_free(struct ethtool_privflags_set_req *req);
-
-static inline void
-ethtool_privflags_set_req_set_header_dev_index(struct ethtool_privflags_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_privflags_set_req_set_header_dev_name(struct ethtool_privflags_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_privflags_set_req_set_header_flags(struct ethtool_privflags_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_privflags_set_req_set_flags_nomask(struct ethtool_privflags_set_req *req)
-{
- req->_present.flags = 1;
- req->flags._present.nomask = 1;
-}
-static inline void
-ethtool_privflags_set_req_set_flags_size(struct ethtool_privflags_set_req *req,
- __u32 size)
-{
- req->_present.flags = 1;
- req->flags._present.size = 1;
- req->flags.size = size;
-}
-static inline void
-__ethtool_privflags_set_req_set_flags_bits_bit(struct ethtool_privflags_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->flags.bits.bit);
- req->flags.bits.bit = bit;
- req->flags.bits.n_bit = n_bit;
-}
-
-/*
- * Set device private flags.
- */
-int ethtool_privflags_set(struct ynl_sock *ys,
- struct ethtool_privflags_set_req *req);
-
-/* ============== ETHTOOL_MSG_RINGS_GET ============== */
-/* ETHTOOL_MSG_RINGS_GET - do */
-struct ethtool_rings_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_rings_get_req *ethtool_rings_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_rings_get_req));
-}
-void ethtool_rings_get_req_free(struct ethtool_rings_get_req *req);
-
-static inline void
-ethtool_rings_get_req_set_header_dev_index(struct ethtool_rings_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_rings_get_req_set_header_dev_name(struct ethtool_rings_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_rings_get_req_set_header_flags(struct ethtool_rings_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_rings_get_rsp {
- struct {
- __u32 header:1;
- __u32 rx_max:1;
- __u32 rx_mini_max:1;
- __u32 rx_jumbo_max:1;
- __u32 tx_max:1;
- __u32 rx:1;
- __u32 rx_mini:1;
- __u32 rx_jumbo:1;
- __u32 tx:1;
- __u32 rx_buf_len:1;
- __u32 tcp_data_split:1;
- __u32 cqe_size:1;
- __u32 tx_push:1;
- __u32 rx_push:1;
- __u32 tx_push_buf_len:1;
- __u32 tx_push_buf_len_max:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_max;
- __u32 rx_mini_max;
- __u32 rx_jumbo_max;
- __u32 tx_max;
- __u32 rx;
- __u32 rx_mini;
- __u32 rx_jumbo;
- __u32 tx;
- __u32 rx_buf_len;
- __u8 tcp_data_split;
- __u32 cqe_size;
- __u8 tx_push;
- __u8 rx_push;
- __u32 tx_push_buf_len;
- __u32 tx_push_buf_len_max;
-};
-
-void ethtool_rings_get_rsp_free(struct ethtool_rings_get_rsp *rsp);
-
-/*
- * Get ring params.
- */
-struct ethtool_rings_get_rsp *
-ethtool_rings_get(struct ynl_sock *ys, struct ethtool_rings_get_req *req);
-
-/* ETHTOOL_MSG_RINGS_GET - dump */
-struct ethtool_rings_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_rings_get_req_dump *
-ethtool_rings_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_rings_get_req_dump));
-}
-void ethtool_rings_get_req_dump_free(struct ethtool_rings_get_req_dump *req);
-
-static inline void
-ethtool_rings_get_req_dump_set_header_dev_index(struct ethtool_rings_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_rings_get_req_dump_set_header_dev_name(struct ethtool_rings_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_rings_get_req_dump_set_header_flags(struct ethtool_rings_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_rings_get_list {
- struct ethtool_rings_get_list *next;
- struct ethtool_rings_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_rings_get_list_free(struct ethtool_rings_get_list *rsp);
-
-struct ethtool_rings_get_list *
-ethtool_rings_get_dump(struct ynl_sock *ys,
- struct ethtool_rings_get_req_dump *req);
-
-/* ETHTOOL_MSG_RINGS_GET - notify */
-struct ethtool_rings_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_rings_get_ntf *ntf);
- struct ethtool_rings_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_rings_get_ntf_free(struct ethtool_rings_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_RINGS_SET ============== */
-/* ETHTOOL_MSG_RINGS_SET - do */
-struct ethtool_rings_set_req {
- struct {
- __u32 header:1;
- __u32 rx_max:1;
- __u32 rx_mini_max:1;
- __u32 rx_jumbo_max:1;
- __u32 tx_max:1;
- __u32 rx:1;
- __u32 rx_mini:1;
- __u32 rx_jumbo:1;
- __u32 tx:1;
- __u32 rx_buf_len:1;
- __u32 tcp_data_split:1;
- __u32 cqe_size:1;
- __u32 tx_push:1;
- __u32 rx_push:1;
- __u32 tx_push_buf_len:1;
- __u32 tx_push_buf_len_max:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_max;
- __u32 rx_mini_max;
- __u32 rx_jumbo_max;
- __u32 tx_max;
- __u32 rx;
- __u32 rx_mini;
- __u32 rx_jumbo;
- __u32 tx;
- __u32 rx_buf_len;
- __u8 tcp_data_split;
- __u32 cqe_size;
- __u8 tx_push;
- __u8 rx_push;
- __u32 tx_push_buf_len;
- __u32 tx_push_buf_len_max;
-};
-
-static inline struct ethtool_rings_set_req *ethtool_rings_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_rings_set_req));
-}
-void ethtool_rings_set_req_free(struct ethtool_rings_set_req *req);
-
-static inline void
-ethtool_rings_set_req_set_header_dev_index(struct ethtool_rings_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_rings_set_req_set_header_dev_name(struct ethtool_rings_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_rings_set_req_set_header_flags(struct ethtool_rings_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_rings_set_req_set_rx_max(struct ethtool_rings_set_req *req,
- __u32 rx_max)
-{
- req->_present.rx_max = 1;
- req->rx_max = rx_max;
-}
-static inline void
-ethtool_rings_set_req_set_rx_mini_max(struct ethtool_rings_set_req *req,
- __u32 rx_mini_max)
-{
- req->_present.rx_mini_max = 1;
- req->rx_mini_max = rx_mini_max;
-}
-static inline void
-ethtool_rings_set_req_set_rx_jumbo_max(struct ethtool_rings_set_req *req,
- __u32 rx_jumbo_max)
-{
- req->_present.rx_jumbo_max = 1;
- req->rx_jumbo_max = rx_jumbo_max;
-}
-static inline void
-ethtool_rings_set_req_set_tx_max(struct ethtool_rings_set_req *req,
- __u32 tx_max)
-{
- req->_present.tx_max = 1;
- req->tx_max = tx_max;
-}
-static inline void
-ethtool_rings_set_req_set_rx(struct ethtool_rings_set_req *req, __u32 rx)
-{
- req->_present.rx = 1;
- req->rx = rx;
-}
-static inline void
-ethtool_rings_set_req_set_rx_mini(struct ethtool_rings_set_req *req,
- __u32 rx_mini)
-{
- req->_present.rx_mini = 1;
- req->rx_mini = rx_mini;
-}
-static inline void
-ethtool_rings_set_req_set_rx_jumbo(struct ethtool_rings_set_req *req,
- __u32 rx_jumbo)
-{
- req->_present.rx_jumbo = 1;
- req->rx_jumbo = rx_jumbo;
-}
-static inline void
-ethtool_rings_set_req_set_tx(struct ethtool_rings_set_req *req, __u32 tx)
-{
- req->_present.tx = 1;
- req->tx = tx;
-}
-static inline void
-ethtool_rings_set_req_set_rx_buf_len(struct ethtool_rings_set_req *req,
- __u32 rx_buf_len)
-{
- req->_present.rx_buf_len = 1;
- req->rx_buf_len = rx_buf_len;
-}
-static inline void
-ethtool_rings_set_req_set_tcp_data_split(struct ethtool_rings_set_req *req,
- __u8 tcp_data_split)
-{
- req->_present.tcp_data_split = 1;
- req->tcp_data_split = tcp_data_split;
-}
-static inline void
-ethtool_rings_set_req_set_cqe_size(struct ethtool_rings_set_req *req,
- __u32 cqe_size)
-{
- req->_present.cqe_size = 1;
- req->cqe_size = cqe_size;
-}
-static inline void
-ethtool_rings_set_req_set_tx_push(struct ethtool_rings_set_req *req,
- __u8 tx_push)
-{
- req->_present.tx_push = 1;
- req->tx_push = tx_push;
-}
-static inline void
-ethtool_rings_set_req_set_rx_push(struct ethtool_rings_set_req *req,
- __u8 rx_push)
-{
- req->_present.rx_push = 1;
- req->rx_push = rx_push;
-}
-static inline void
-ethtool_rings_set_req_set_tx_push_buf_len(struct ethtool_rings_set_req *req,
- __u32 tx_push_buf_len)
-{
- req->_present.tx_push_buf_len = 1;
- req->tx_push_buf_len = tx_push_buf_len;
-}
-static inline void
-ethtool_rings_set_req_set_tx_push_buf_len_max(struct ethtool_rings_set_req *req,
- __u32 tx_push_buf_len_max)
-{
- req->_present.tx_push_buf_len_max = 1;
- req->tx_push_buf_len_max = tx_push_buf_len_max;
-}
-
-/*
- * Set ring params.
- */
-int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req);
-
-/* ============== ETHTOOL_MSG_CHANNELS_GET ============== */
-/* ETHTOOL_MSG_CHANNELS_GET - do */
-struct ethtool_channels_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_channels_get_req *
-ethtool_channels_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_channels_get_req));
-}
-void ethtool_channels_get_req_free(struct ethtool_channels_get_req *req);
-
-static inline void
-ethtool_channels_get_req_set_header_dev_index(struct ethtool_channels_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_channels_get_req_set_header_dev_name(struct ethtool_channels_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_channels_get_req_set_header_flags(struct ethtool_channels_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_channels_get_rsp {
- struct {
- __u32 header:1;
- __u32 rx_max:1;
- __u32 tx_max:1;
- __u32 other_max:1;
- __u32 combined_max:1;
- __u32 rx_count:1;
- __u32 tx_count:1;
- __u32 other_count:1;
- __u32 combined_count:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_max;
- __u32 tx_max;
- __u32 other_max;
- __u32 combined_max;
- __u32 rx_count;
- __u32 tx_count;
- __u32 other_count;
- __u32 combined_count;
-};
-
-void ethtool_channels_get_rsp_free(struct ethtool_channels_get_rsp *rsp);
-
-/*
- * Get channel params.
- */
-struct ethtool_channels_get_rsp *
-ethtool_channels_get(struct ynl_sock *ys, struct ethtool_channels_get_req *req);
-
-/* ETHTOOL_MSG_CHANNELS_GET - dump */
-struct ethtool_channels_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_channels_get_req_dump *
-ethtool_channels_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_channels_get_req_dump));
-}
-void
-ethtool_channels_get_req_dump_free(struct ethtool_channels_get_req_dump *req);
-
-static inline void
-ethtool_channels_get_req_dump_set_header_dev_index(struct ethtool_channels_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_channels_get_req_dump_set_header_dev_name(struct ethtool_channels_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_channels_get_req_dump_set_header_flags(struct ethtool_channels_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_channels_get_list {
- struct ethtool_channels_get_list *next;
- struct ethtool_channels_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_channels_get_list_free(struct ethtool_channels_get_list *rsp);
-
-struct ethtool_channels_get_list *
-ethtool_channels_get_dump(struct ynl_sock *ys,
- struct ethtool_channels_get_req_dump *req);
-
-/* ETHTOOL_MSG_CHANNELS_GET - notify */
-struct ethtool_channels_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_channels_get_ntf *ntf);
- struct ethtool_channels_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_channels_get_ntf_free(struct ethtool_channels_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_CHANNELS_SET ============== */
-/* ETHTOOL_MSG_CHANNELS_SET - do */
-struct ethtool_channels_set_req {
- struct {
- __u32 header:1;
- __u32 rx_max:1;
- __u32 tx_max:1;
- __u32 other_max:1;
- __u32 combined_max:1;
- __u32 rx_count:1;
- __u32 tx_count:1;
- __u32 other_count:1;
- __u32 combined_count:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_max;
- __u32 tx_max;
- __u32 other_max;
- __u32 combined_max;
- __u32 rx_count;
- __u32 tx_count;
- __u32 other_count;
- __u32 combined_count;
-};
-
-static inline struct ethtool_channels_set_req *
-ethtool_channels_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_channels_set_req));
-}
-void ethtool_channels_set_req_free(struct ethtool_channels_set_req *req);
-
-static inline void
-ethtool_channels_set_req_set_header_dev_index(struct ethtool_channels_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_channels_set_req_set_header_dev_name(struct ethtool_channels_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_channels_set_req_set_header_flags(struct ethtool_channels_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_channels_set_req_set_rx_max(struct ethtool_channels_set_req *req,
- __u32 rx_max)
-{
- req->_present.rx_max = 1;
- req->rx_max = rx_max;
-}
-static inline void
-ethtool_channels_set_req_set_tx_max(struct ethtool_channels_set_req *req,
- __u32 tx_max)
-{
- req->_present.tx_max = 1;
- req->tx_max = tx_max;
-}
-static inline void
-ethtool_channels_set_req_set_other_max(struct ethtool_channels_set_req *req,
- __u32 other_max)
-{
- req->_present.other_max = 1;
- req->other_max = other_max;
-}
-static inline void
-ethtool_channels_set_req_set_combined_max(struct ethtool_channels_set_req *req,
- __u32 combined_max)
-{
- req->_present.combined_max = 1;
- req->combined_max = combined_max;
-}
-static inline void
-ethtool_channels_set_req_set_rx_count(struct ethtool_channels_set_req *req,
- __u32 rx_count)
-{
- req->_present.rx_count = 1;
- req->rx_count = rx_count;
-}
-static inline void
-ethtool_channels_set_req_set_tx_count(struct ethtool_channels_set_req *req,
- __u32 tx_count)
-{
- req->_present.tx_count = 1;
- req->tx_count = tx_count;
-}
-static inline void
-ethtool_channels_set_req_set_other_count(struct ethtool_channels_set_req *req,
- __u32 other_count)
-{
- req->_present.other_count = 1;
- req->other_count = other_count;
-}
-static inline void
-ethtool_channels_set_req_set_combined_count(struct ethtool_channels_set_req *req,
- __u32 combined_count)
-{
- req->_present.combined_count = 1;
- req->combined_count = combined_count;
-}
-
-/*
- * Set channel params.
- */
-int ethtool_channels_set(struct ynl_sock *ys,
- struct ethtool_channels_set_req *req);
-
-/* ============== ETHTOOL_MSG_COALESCE_GET ============== */
-/* ETHTOOL_MSG_COALESCE_GET - do */
-struct ethtool_coalesce_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_coalesce_get_req *
-ethtool_coalesce_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_coalesce_get_req));
-}
-void ethtool_coalesce_get_req_free(struct ethtool_coalesce_get_req *req);
-
-static inline void
-ethtool_coalesce_get_req_set_header_dev_index(struct ethtool_coalesce_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_coalesce_get_req_set_header_dev_name(struct ethtool_coalesce_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_coalesce_get_req_set_header_flags(struct ethtool_coalesce_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_coalesce_get_rsp {
- struct {
- __u32 header:1;
- __u32 rx_usecs:1;
- __u32 rx_max_frames:1;
- __u32 rx_usecs_irq:1;
- __u32 rx_max_frames_irq:1;
- __u32 tx_usecs:1;
- __u32 tx_max_frames:1;
- __u32 tx_usecs_irq:1;
- __u32 tx_max_frames_irq:1;
- __u32 stats_block_usecs:1;
- __u32 use_adaptive_rx:1;
- __u32 use_adaptive_tx:1;
- __u32 pkt_rate_low:1;
- __u32 rx_usecs_low:1;
- __u32 rx_max_frames_low:1;
- __u32 tx_usecs_low:1;
- __u32 tx_max_frames_low:1;
- __u32 pkt_rate_high:1;
- __u32 rx_usecs_high:1;
- __u32 rx_max_frames_high:1;
- __u32 tx_usecs_high:1;
- __u32 tx_max_frames_high:1;
- __u32 rate_sample_interval:1;
- __u32 use_cqe_mode_tx:1;
- __u32 use_cqe_mode_rx:1;
- __u32 tx_aggr_max_bytes:1;
- __u32 tx_aggr_max_frames:1;
- __u32 tx_aggr_time_usecs:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_usecs;
- __u32 rx_max_frames;
- __u32 rx_usecs_irq;
- __u32 rx_max_frames_irq;
- __u32 tx_usecs;
- __u32 tx_max_frames;
- __u32 tx_usecs_irq;
- __u32 tx_max_frames_irq;
- __u32 stats_block_usecs;
- __u8 use_adaptive_rx;
- __u8 use_adaptive_tx;
- __u32 pkt_rate_low;
- __u32 rx_usecs_low;
- __u32 rx_max_frames_low;
- __u32 tx_usecs_low;
- __u32 tx_max_frames_low;
- __u32 pkt_rate_high;
- __u32 rx_usecs_high;
- __u32 rx_max_frames_high;
- __u32 tx_usecs_high;
- __u32 tx_max_frames_high;
- __u32 rate_sample_interval;
- __u8 use_cqe_mode_tx;
- __u8 use_cqe_mode_rx;
- __u32 tx_aggr_max_bytes;
- __u32 tx_aggr_max_frames;
- __u32 tx_aggr_time_usecs;
-};
-
-void ethtool_coalesce_get_rsp_free(struct ethtool_coalesce_get_rsp *rsp);
-
-/*
- * Get coalesce params.
- */
-struct ethtool_coalesce_get_rsp *
-ethtool_coalesce_get(struct ynl_sock *ys, struct ethtool_coalesce_get_req *req);
-
-/* ETHTOOL_MSG_COALESCE_GET - dump */
-struct ethtool_coalesce_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_coalesce_get_req_dump *
-ethtool_coalesce_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_coalesce_get_req_dump));
-}
-void
-ethtool_coalesce_get_req_dump_free(struct ethtool_coalesce_get_req_dump *req);
-
-static inline void
-ethtool_coalesce_get_req_dump_set_header_dev_index(struct ethtool_coalesce_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_coalesce_get_req_dump_set_header_dev_name(struct ethtool_coalesce_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_coalesce_get_req_dump_set_header_flags(struct ethtool_coalesce_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_coalesce_get_list {
- struct ethtool_coalesce_get_list *next;
- struct ethtool_coalesce_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_coalesce_get_list_free(struct ethtool_coalesce_get_list *rsp);
-
-struct ethtool_coalesce_get_list *
-ethtool_coalesce_get_dump(struct ynl_sock *ys,
- struct ethtool_coalesce_get_req_dump *req);
-
-/* ETHTOOL_MSG_COALESCE_GET - notify */
-struct ethtool_coalesce_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_coalesce_get_ntf *ntf);
- struct ethtool_coalesce_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_coalesce_get_ntf_free(struct ethtool_coalesce_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_COALESCE_SET ============== */
-/* ETHTOOL_MSG_COALESCE_SET - do */
-struct ethtool_coalesce_set_req {
- struct {
- __u32 header:1;
- __u32 rx_usecs:1;
- __u32 rx_max_frames:1;
- __u32 rx_usecs_irq:1;
- __u32 rx_max_frames_irq:1;
- __u32 tx_usecs:1;
- __u32 tx_max_frames:1;
- __u32 tx_usecs_irq:1;
- __u32 tx_max_frames_irq:1;
- __u32 stats_block_usecs:1;
- __u32 use_adaptive_rx:1;
- __u32 use_adaptive_tx:1;
- __u32 pkt_rate_low:1;
- __u32 rx_usecs_low:1;
- __u32 rx_max_frames_low:1;
- __u32 tx_usecs_low:1;
- __u32 tx_max_frames_low:1;
- __u32 pkt_rate_high:1;
- __u32 rx_usecs_high:1;
- __u32 rx_max_frames_high:1;
- __u32 tx_usecs_high:1;
- __u32 tx_max_frames_high:1;
- __u32 rate_sample_interval:1;
- __u32 use_cqe_mode_tx:1;
- __u32 use_cqe_mode_rx:1;
- __u32 tx_aggr_max_bytes:1;
- __u32 tx_aggr_max_frames:1;
- __u32 tx_aggr_time_usecs:1;
- } _present;
-
- struct ethtool_header header;
- __u32 rx_usecs;
- __u32 rx_max_frames;
- __u32 rx_usecs_irq;
- __u32 rx_max_frames_irq;
- __u32 tx_usecs;
- __u32 tx_max_frames;
- __u32 tx_usecs_irq;
- __u32 tx_max_frames_irq;
- __u32 stats_block_usecs;
- __u8 use_adaptive_rx;
- __u8 use_adaptive_tx;
- __u32 pkt_rate_low;
- __u32 rx_usecs_low;
- __u32 rx_max_frames_low;
- __u32 tx_usecs_low;
- __u32 tx_max_frames_low;
- __u32 pkt_rate_high;
- __u32 rx_usecs_high;
- __u32 rx_max_frames_high;
- __u32 tx_usecs_high;
- __u32 tx_max_frames_high;
- __u32 rate_sample_interval;
- __u8 use_cqe_mode_tx;
- __u8 use_cqe_mode_rx;
- __u32 tx_aggr_max_bytes;
- __u32 tx_aggr_max_frames;
- __u32 tx_aggr_time_usecs;
-};
-
-static inline struct ethtool_coalesce_set_req *
-ethtool_coalesce_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_coalesce_set_req));
-}
-void ethtool_coalesce_set_req_free(struct ethtool_coalesce_set_req *req);
-
-static inline void
-ethtool_coalesce_set_req_set_header_dev_index(struct ethtool_coalesce_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_coalesce_set_req_set_header_dev_name(struct ethtool_coalesce_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_coalesce_set_req_set_header_flags(struct ethtool_coalesce_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_usecs(struct ethtool_coalesce_set_req *req,
- __u32 rx_usecs)
-{
- req->_present.rx_usecs = 1;
- req->rx_usecs = rx_usecs;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_max_frames(struct ethtool_coalesce_set_req *req,
- __u32 rx_max_frames)
-{
- req->_present.rx_max_frames = 1;
- req->rx_max_frames = rx_max_frames;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_usecs_irq(struct ethtool_coalesce_set_req *req,
- __u32 rx_usecs_irq)
-{
- req->_present.rx_usecs_irq = 1;
- req->rx_usecs_irq = rx_usecs_irq;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_max_frames_irq(struct ethtool_coalesce_set_req *req,
- __u32 rx_max_frames_irq)
-{
- req->_present.rx_max_frames_irq = 1;
- req->rx_max_frames_irq = rx_max_frames_irq;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_usecs(struct ethtool_coalesce_set_req *req,
- __u32 tx_usecs)
-{
- req->_present.tx_usecs = 1;
- req->tx_usecs = tx_usecs;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_max_frames(struct ethtool_coalesce_set_req *req,
- __u32 tx_max_frames)
-{
- req->_present.tx_max_frames = 1;
- req->tx_max_frames = tx_max_frames;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_usecs_irq(struct ethtool_coalesce_set_req *req,
- __u32 tx_usecs_irq)
-{
- req->_present.tx_usecs_irq = 1;
- req->tx_usecs_irq = tx_usecs_irq;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_max_frames_irq(struct ethtool_coalesce_set_req *req,
- __u32 tx_max_frames_irq)
-{
- req->_present.tx_max_frames_irq = 1;
- req->tx_max_frames_irq = tx_max_frames_irq;
-}
-static inline void
-ethtool_coalesce_set_req_set_stats_block_usecs(struct ethtool_coalesce_set_req *req,
- __u32 stats_block_usecs)
-{
- req->_present.stats_block_usecs = 1;
- req->stats_block_usecs = stats_block_usecs;
-}
-static inline void
-ethtool_coalesce_set_req_set_use_adaptive_rx(struct ethtool_coalesce_set_req *req,
- __u8 use_adaptive_rx)
-{
- req->_present.use_adaptive_rx = 1;
- req->use_adaptive_rx = use_adaptive_rx;
-}
-static inline void
-ethtool_coalesce_set_req_set_use_adaptive_tx(struct ethtool_coalesce_set_req *req,
- __u8 use_adaptive_tx)
-{
- req->_present.use_adaptive_tx = 1;
- req->use_adaptive_tx = use_adaptive_tx;
-}
-static inline void
-ethtool_coalesce_set_req_set_pkt_rate_low(struct ethtool_coalesce_set_req *req,
- __u32 pkt_rate_low)
-{
- req->_present.pkt_rate_low = 1;
- req->pkt_rate_low = pkt_rate_low;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_usecs_low(struct ethtool_coalesce_set_req *req,
- __u32 rx_usecs_low)
-{
- req->_present.rx_usecs_low = 1;
- req->rx_usecs_low = rx_usecs_low;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_max_frames_low(struct ethtool_coalesce_set_req *req,
- __u32 rx_max_frames_low)
-{
- req->_present.rx_max_frames_low = 1;
- req->rx_max_frames_low = rx_max_frames_low;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_usecs_low(struct ethtool_coalesce_set_req *req,
- __u32 tx_usecs_low)
-{
- req->_present.tx_usecs_low = 1;
- req->tx_usecs_low = tx_usecs_low;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_max_frames_low(struct ethtool_coalesce_set_req *req,
- __u32 tx_max_frames_low)
-{
- req->_present.tx_max_frames_low = 1;
- req->tx_max_frames_low = tx_max_frames_low;
-}
-static inline void
-ethtool_coalesce_set_req_set_pkt_rate_high(struct ethtool_coalesce_set_req *req,
- __u32 pkt_rate_high)
-{
- req->_present.pkt_rate_high = 1;
- req->pkt_rate_high = pkt_rate_high;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_usecs_high(struct ethtool_coalesce_set_req *req,
- __u32 rx_usecs_high)
-{
- req->_present.rx_usecs_high = 1;
- req->rx_usecs_high = rx_usecs_high;
-}
-static inline void
-ethtool_coalesce_set_req_set_rx_max_frames_high(struct ethtool_coalesce_set_req *req,
- __u32 rx_max_frames_high)
-{
- req->_present.rx_max_frames_high = 1;
- req->rx_max_frames_high = rx_max_frames_high;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_usecs_high(struct ethtool_coalesce_set_req *req,
- __u32 tx_usecs_high)
-{
- req->_present.tx_usecs_high = 1;
- req->tx_usecs_high = tx_usecs_high;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_max_frames_high(struct ethtool_coalesce_set_req *req,
- __u32 tx_max_frames_high)
-{
- req->_present.tx_max_frames_high = 1;
- req->tx_max_frames_high = tx_max_frames_high;
-}
-static inline void
-ethtool_coalesce_set_req_set_rate_sample_interval(struct ethtool_coalesce_set_req *req,
- __u32 rate_sample_interval)
-{
- req->_present.rate_sample_interval = 1;
- req->rate_sample_interval = rate_sample_interval;
-}
-static inline void
-ethtool_coalesce_set_req_set_use_cqe_mode_tx(struct ethtool_coalesce_set_req *req,
- __u8 use_cqe_mode_tx)
-{
- req->_present.use_cqe_mode_tx = 1;
- req->use_cqe_mode_tx = use_cqe_mode_tx;
-}
-static inline void
-ethtool_coalesce_set_req_set_use_cqe_mode_rx(struct ethtool_coalesce_set_req *req,
- __u8 use_cqe_mode_rx)
-{
- req->_present.use_cqe_mode_rx = 1;
- req->use_cqe_mode_rx = use_cqe_mode_rx;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_aggr_max_bytes(struct ethtool_coalesce_set_req *req,
- __u32 tx_aggr_max_bytes)
-{
- req->_present.tx_aggr_max_bytes = 1;
- req->tx_aggr_max_bytes = tx_aggr_max_bytes;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_aggr_max_frames(struct ethtool_coalesce_set_req *req,
- __u32 tx_aggr_max_frames)
-{
- req->_present.tx_aggr_max_frames = 1;
- req->tx_aggr_max_frames = tx_aggr_max_frames;
-}
-static inline void
-ethtool_coalesce_set_req_set_tx_aggr_time_usecs(struct ethtool_coalesce_set_req *req,
- __u32 tx_aggr_time_usecs)
-{
- req->_present.tx_aggr_time_usecs = 1;
- req->tx_aggr_time_usecs = tx_aggr_time_usecs;
-}
-
-/*
- * Set coalesce params.
- */
-int ethtool_coalesce_set(struct ynl_sock *ys,
- struct ethtool_coalesce_set_req *req);
-
-/* ============== ETHTOOL_MSG_PAUSE_GET ============== */
-/* ETHTOOL_MSG_PAUSE_GET - do */
-struct ethtool_pause_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_pause_get_req *ethtool_pause_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pause_get_req));
-}
-void ethtool_pause_get_req_free(struct ethtool_pause_get_req *req);
-
-static inline void
-ethtool_pause_get_req_set_header_dev_index(struct ethtool_pause_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pause_get_req_set_header_dev_name(struct ethtool_pause_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pause_get_req_set_header_flags(struct ethtool_pause_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_pause_get_rsp {
- struct {
- __u32 header:1;
- __u32 autoneg:1;
- __u32 rx:1;
- __u32 tx:1;
- __u32 stats:1;
- __u32 stats_src:1;
- } _present;
-
- struct ethtool_header header;
- __u8 autoneg;
- __u8 rx;
- __u8 tx;
- struct ethtool_pause_stat stats;
- __u32 stats_src;
-};
-
-void ethtool_pause_get_rsp_free(struct ethtool_pause_get_rsp *rsp);
-
-/*
- * Get pause params.
- */
-struct ethtool_pause_get_rsp *
-ethtool_pause_get(struct ynl_sock *ys, struct ethtool_pause_get_req *req);
-
-/* ETHTOOL_MSG_PAUSE_GET - dump */
-struct ethtool_pause_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_pause_get_req_dump *
-ethtool_pause_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pause_get_req_dump));
-}
-void ethtool_pause_get_req_dump_free(struct ethtool_pause_get_req_dump *req);
-
-static inline void
-ethtool_pause_get_req_dump_set_header_dev_index(struct ethtool_pause_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pause_get_req_dump_set_header_dev_name(struct ethtool_pause_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pause_get_req_dump_set_header_flags(struct ethtool_pause_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_pause_get_list {
- struct ethtool_pause_get_list *next;
- struct ethtool_pause_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_pause_get_list_free(struct ethtool_pause_get_list *rsp);
-
-struct ethtool_pause_get_list *
-ethtool_pause_get_dump(struct ynl_sock *ys,
- struct ethtool_pause_get_req_dump *req);
-
-/* ETHTOOL_MSG_PAUSE_GET - notify */
-struct ethtool_pause_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_pause_get_ntf *ntf);
- struct ethtool_pause_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_pause_get_ntf_free(struct ethtool_pause_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_PAUSE_SET ============== */
-/* ETHTOOL_MSG_PAUSE_SET - do */
-struct ethtool_pause_set_req {
- struct {
- __u32 header:1;
- __u32 autoneg:1;
- __u32 rx:1;
- __u32 tx:1;
- __u32 stats:1;
- __u32 stats_src:1;
- } _present;
-
- struct ethtool_header header;
- __u8 autoneg;
- __u8 rx;
- __u8 tx;
- struct ethtool_pause_stat stats;
- __u32 stats_src;
-};
-
-static inline struct ethtool_pause_set_req *ethtool_pause_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pause_set_req));
-}
-void ethtool_pause_set_req_free(struct ethtool_pause_set_req *req);
-
-static inline void
-ethtool_pause_set_req_set_header_dev_index(struct ethtool_pause_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pause_set_req_set_header_dev_name(struct ethtool_pause_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pause_set_req_set_header_flags(struct ethtool_pause_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_pause_set_req_set_autoneg(struct ethtool_pause_set_req *req,
- __u8 autoneg)
-{
- req->_present.autoneg = 1;
- req->autoneg = autoneg;
-}
-static inline void
-ethtool_pause_set_req_set_rx(struct ethtool_pause_set_req *req, __u8 rx)
-{
- req->_present.rx = 1;
- req->rx = rx;
-}
-static inline void
-ethtool_pause_set_req_set_tx(struct ethtool_pause_set_req *req, __u8 tx)
-{
- req->_present.tx = 1;
- req->tx = tx;
-}
-static inline void
-ethtool_pause_set_req_set_stats_tx_frames(struct ethtool_pause_set_req *req,
- __u64 tx_frames)
-{
- req->_present.stats = 1;
- req->stats._present.tx_frames = 1;
- req->stats.tx_frames = tx_frames;
-}
-static inline void
-ethtool_pause_set_req_set_stats_rx_frames(struct ethtool_pause_set_req *req,
- __u64 rx_frames)
-{
- req->_present.stats = 1;
- req->stats._present.rx_frames = 1;
- req->stats.rx_frames = rx_frames;
-}
-static inline void
-ethtool_pause_set_req_set_stats_src(struct ethtool_pause_set_req *req,
- __u32 stats_src)
-{
- req->_present.stats_src = 1;
- req->stats_src = stats_src;
-}
-
-/*
- * Set pause params.
- */
-int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req);
-
-/* ============== ETHTOOL_MSG_EEE_GET ============== */
-/* ETHTOOL_MSG_EEE_GET - do */
-struct ethtool_eee_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_eee_get_req *ethtool_eee_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_eee_get_req));
-}
-void ethtool_eee_get_req_free(struct ethtool_eee_get_req *req);
-
-static inline void
-ethtool_eee_get_req_set_header_dev_index(struct ethtool_eee_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_eee_get_req_set_header_dev_name(struct ethtool_eee_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_eee_get_req_set_header_flags(struct ethtool_eee_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_eee_get_rsp {
- struct {
- __u32 header:1;
- __u32 modes_ours:1;
- __u32 modes_peer:1;
- __u32 active:1;
- __u32 enabled:1;
- __u32 tx_lpi_enabled:1;
- __u32 tx_lpi_timer:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes_ours;
- struct ethtool_bitset modes_peer;
- __u8 active;
- __u8 enabled;
- __u8 tx_lpi_enabled;
- __u32 tx_lpi_timer;
-};
-
-void ethtool_eee_get_rsp_free(struct ethtool_eee_get_rsp *rsp);
-
-/*
- * Get eee params.
- */
-struct ethtool_eee_get_rsp *
-ethtool_eee_get(struct ynl_sock *ys, struct ethtool_eee_get_req *req);
-
-/* ETHTOOL_MSG_EEE_GET - dump */
-struct ethtool_eee_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_eee_get_req_dump *
-ethtool_eee_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_eee_get_req_dump));
-}
-void ethtool_eee_get_req_dump_free(struct ethtool_eee_get_req_dump *req);
-
-static inline void
-ethtool_eee_get_req_dump_set_header_dev_index(struct ethtool_eee_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_eee_get_req_dump_set_header_dev_name(struct ethtool_eee_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_eee_get_req_dump_set_header_flags(struct ethtool_eee_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_eee_get_list {
- struct ethtool_eee_get_list *next;
- struct ethtool_eee_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_eee_get_list_free(struct ethtool_eee_get_list *rsp);
-
-struct ethtool_eee_get_list *
-ethtool_eee_get_dump(struct ynl_sock *ys, struct ethtool_eee_get_req_dump *req);
-
-/* ETHTOOL_MSG_EEE_GET - notify */
-struct ethtool_eee_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_eee_get_ntf *ntf);
- struct ethtool_eee_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_eee_get_ntf_free(struct ethtool_eee_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_EEE_SET ============== */
-/* ETHTOOL_MSG_EEE_SET - do */
-struct ethtool_eee_set_req {
- struct {
- __u32 header:1;
- __u32 modes_ours:1;
- __u32 modes_peer:1;
- __u32 active:1;
- __u32 enabled:1;
- __u32 tx_lpi_enabled:1;
- __u32 tx_lpi_timer:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes_ours;
- struct ethtool_bitset modes_peer;
- __u8 active;
- __u8 enabled;
- __u8 tx_lpi_enabled;
- __u32 tx_lpi_timer;
-};
-
-static inline struct ethtool_eee_set_req *ethtool_eee_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_eee_set_req));
-}
-void ethtool_eee_set_req_free(struct ethtool_eee_set_req *req);
-
-static inline void
-ethtool_eee_set_req_set_header_dev_index(struct ethtool_eee_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_eee_set_req_set_header_dev_name(struct ethtool_eee_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_eee_set_req_set_header_flags(struct ethtool_eee_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_eee_set_req_set_modes_ours_nomask(struct ethtool_eee_set_req *req)
-{
- req->_present.modes_ours = 1;
- req->modes_ours._present.nomask = 1;
-}
-static inline void
-ethtool_eee_set_req_set_modes_ours_size(struct ethtool_eee_set_req *req,
- __u32 size)
-{
- req->_present.modes_ours = 1;
- req->modes_ours._present.size = 1;
- req->modes_ours.size = size;
-}
-static inline void
-__ethtool_eee_set_req_set_modes_ours_bits_bit(struct ethtool_eee_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->modes_ours.bits.bit);
- req->modes_ours.bits.bit = bit;
- req->modes_ours.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_eee_set_req_set_modes_peer_nomask(struct ethtool_eee_set_req *req)
-{
- req->_present.modes_peer = 1;
- req->modes_peer._present.nomask = 1;
-}
-static inline void
-ethtool_eee_set_req_set_modes_peer_size(struct ethtool_eee_set_req *req,
- __u32 size)
-{
- req->_present.modes_peer = 1;
- req->modes_peer._present.size = 1;
- req->modes_peer.size = size;
-}
-static inline void
-__ethtool_eee_set_req_set_modes_peer_bits_bit(struct ethtool_eee_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->modes_peer.bits.bit);
- req->modes_peer.bits.bit = bit;
- req->modes_peer.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_eee_set_req_set_active(struct ethtool_eee_set_req *req, __u8 active)
-{
- req->_present.active = 1;
- req->active = active;
-}
-static inline void
-ethtool_eee_set_req_set_enabled(struct ethtool_eee_set_req *req, __u8 enabled)
-{
- req->_present.enabled = 1;
- req->enabled = enabled;
-}
-static inline void
-ethtool_eee_set_req_set_tx_lpi_enabled(struct ethtool_eee_set_req *req,
- __u8 tx_lpi_enabled)
-{
- req->_present.tx_lpi_enabled = 1;
- req->tx_lpi_enabled = tx_lpi_enabled;
-}
-static inline void
-ethtool_eee_set_req_set_tx_lpi_timer(struct ethtool_eee_set_req *req,
- __u32 tx_lpi_timer)
-{
- req->_present.tx_lpi_timer = 1;
- req->tx_lpi_timer = tx_lpi_timer;
-}
-
-/*
- * Set eee params.
- */
-int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req);
-
-/* ============== ETHTOOL_MSG_TSINFO_GET ============== */
-/* ETHTOOL_MSG_TSINFO_GET - do */
-struct ethtool_tsinfo_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_tsinfo_get_req *ethtool_tsinfo_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_tsinfo_get_req));
-}
-void ethtool_tsinfo_get_req_free(struct ethtool_tsinfo_get_req *req);
-
-static inline void
-ethtool_tsinfo_get_req_set_header_dev_index(struct ethtool_tsinfo_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_tsinfo_get_req_set_header_dev_name(struct ethtool_tsinfo_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_tsinfo_get_req_set_header_flags(struct ethtool_tsinfo_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_tsinfo_get_rsp {
- struct {
- __u32 header:1;
- __u32 timestamping:1;
- __u32 tx_types:1;
- __u32 rx_filters:1;
- __u32 phc_index:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset timestamping;
- struct ethtool_bitset tx_types;
- struct ethtool_bitset rx_filters;
- __u32 phc_index;
-};
-
-void ethtool_tsinfo_get_rsp_free(struct ethtool_tsinfo_get_rsp *rsp);
-
-/*
- * Get tsinfo params.
- */
-struct ethtool_tsinfo_get_rsp *
-ethtool_tsinfo_get(struct ynl_sock *ys, struct ethtool_tsinfo_get_req *req);
-
-/* ETHTOOL_MSG_TSINFO_GET - dump */
-struct ethtool_tsinfo_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_tsinfo_get_req_dump *
-ethtool_tsinfo_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_tsinfo_get_req_dump));
-}
-void ethtool_tsinfo_get_req_dump_free(struct ethtool_tsinfo_get_req_dump *req);
-
-static inline void
-ethtool_tsinfo_get_req_dump_set_header_dev_index(struct ethtool_tsinfo_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_tsinfo_get_req_dump_set_header_dev_name(struct ethtool_tsinfo_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_tsinfo_get_req_dump_set_header_flags(struct ethtool_tsinfo_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_tsinfo_get_list {
- struct ethtool_tsinfo_get_list *next;
- struct ethtool_tsinfo_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_tsinfo_get_list_free(struct ethtool_tsinfo_get_list *rsp);
-
-struct ethtool_tsinfo_get_list *
-ethtool_tsinfo_get_dump(struct ynl_sock *ys,
- struct ethtool_tsinfo_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_CABLE_TEST_ACT ============== */
-/* ETHTOOL_MSG_CABLE_TEST_ACT - do */
-struct ethtool_cable_test_act_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_cable_test_act_req *
-ethtool_cable_test_act_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_cable_test_act_req));
-}
-void ethtool_cable_test_act_req_free(struct ethtool_cable_test_act_req *req);
-
-static inline void
-ethtool_cable_test_act_req_set_header_dev_index(struct ethtool_cable_test_act_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_cable_test_act_req_set_header_dev_name(struct ethtool_cable_test_act_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_cable_test_act_req_set_header_flags(struct ethtool_cable_test_act_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-/*
- * Cable test.
- */
-int ethtool_cable_test_act(struct ynl_sock *ys,
- struct ethtool_cable_test_act_req *req);
-
-/* ============== ETHTOOL_MSG_CABLE_TEST_TDR_ACT ============== */
-/* ETHTOOL_MSG_CABLE_TEST_TDR_ACT - do */
-struct ethtool_cable_test_tdr_act_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_cable_test_tdr_act_req *
-ethtool_cable_test_tdr_act_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_cable_test_tdr_act_req));
-}
-void
-ethtool_cable_test_tdr_act_req_free(struct ethtool_cable_test_tdr_act_req *req);
-
-static inline void
-ethtool_cable_test_tdr_act_req_set_header_dev_index(struct ethtool_cable_test_tdr_act_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_cable_test_tdr_act_req_set_header_dev_name(struct ethtool_cable_test_tdr_act_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_cable_test_tdr_act_req_set_header_flags(struct ethtool_cable_test_tdr_act_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-/*
- * Cable test TDR.
- */
-int ethtool_cable_test_tdr_act(struct ynl_sock *ys,
- struct ethtool_cable_test_tdr_act_req *req);
-
-/* ============== ETHTOOL_MSG_TUNNEL_INFO_GET ============== */
-/* ETHTOOL_MSG_TUNNEL_INFO_GET - do */
-struct ethtool_tunnel_info_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_tunnel_info_get_req *
-ethtool_tunnel_info_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_tunnel_info_get_req));
-}
-void ethtool_tunnel_info_get_req_free(struct ethtool_tunnel_info_get_req *req);
-
-static inline void
-ethtool_tunnel_info_get_req_set_header_dev_index(struct ethtool_tunnel_info_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_tunnel_info_get_req_set_header_dev_name(struct ethtool_tunnel_info_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_tunnel_info_get_req_set_header_flags(struct ethtool_tunnel_info_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_tunnel_info_get_rsp {
- struct {
- __u32 header:1;
- __u32 udp_ports:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_tunnel_udp udp_ports;
-};
-
-void ethtool_tunnel_info_get_rsp_free(struct ethtool_tunnel_info_get_rsp *rsp);
-
-/*
- * Get tsinfo params.
- */
-struct ethtool_tunnel_info_get_rsp *
-ethtool_tunnel_info_get(struct ynl_sock *ys,
- struct ethtool_tunnel_info_get_req *req);
-
-/* ETHTOOL_MSG_TUNNEL_INFO_GET - dump */
-struct ethtool_tunnel_info_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_tunnel_info_get_req_dump *
-ethtool_tunnel_info_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_tunnel_info_get_req_dump));
-}
-void
-ethtool_tunnel_info_get_req_dump_free(struct ethtool_tunnel_info_get_req_dump *req);
-
-static inline void
-ethtool_tunnel_info_get_req_dump_set_header_dev_index(struct ethtool_tunnel_info_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_tunnel_info_get_req_dump_set_header_dev_name(struct ethtool_tunnel_info_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_tunnel_info_get_req_dump_set_header_flags(struct ethtool_tunnel_info_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_tunnel_info_get_list {
- struct ethtool_tunnel_info_get_list *next;
- struct ethtool_tunnel_info_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-ethtool_tunnel_info_get_list_free(struct ethtool_tunnel_info_get_list *rsp);
-
-struct ethtool_tunnel_info_get_list *
-ethtool_tunnel_info_get_dump(struct ynl_sock *ys,
- struct ethtool_tunnel_info_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_FEC_GET ============== */
-/* ETHTOOL_MSG_FEC_GET - do */
-struct ethtool_fec_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_fec_get_req *ethtool_fec_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_fec_get_req));
-}
-void ethtool_fec_get_req_free(struct ethtool_fec_get_req *req);
-
-static inline void
-ethtool_fec_get_req_set_header_dev_index(struct ethtool_fec_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_fec_get_req_set_header_dev_name(struct ethtool_fec_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_fec_get_req_set_header_flags(struct ethtool_fec_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_fec_get_rsp {
- struct {
- __u32 header:1;
- __u32 modes:1;
- __u32 auto_:1;
- __u32 active:1;
- __u32 stats:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes;
- __u8 auto_;
- __u32 active;
- struct ethtool_fec_stat stats;
-};
-
-void ethtool_fec_get_rsp_free(struct ethtool_fec_get_rsp *rsp);
-
-/*
- * Get FEC params.
- */
-struct ethtool_fec_get_rsp *
-ethtool_fec_get(struct ynl_sock *ys, struct ethtool_fec_get_req *req);
-
-/* ETHTOOL_MSG_FEC_GET - dump */
-struct ethtool_fec_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_fec_get_req_dump *
-ethtool_fec_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_fec_get_req_dump));
-}
-void ethtool_fec_get_req_dump_free(struct ethtool_fec_get_req_dump *req);
-
-static inline void
-ethtool_fec_get_req_dump_set_header_dev_index(struct ethtool_fec_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_fec_get_req_dump_set_header_dev_name(struct ethtool_fec_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_fec_get_req_dump_set_header_flags(struct ethtool_fec_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_fec_get_list {
- struct ethtool_fec_get_list *next;
- struct ethtool_fec_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_fec_get_list_free(struct ethtool_fec_get_list *rsp);
-
-struct ethtool_fec_get_list *
-ethtool_fec_get_dump(struct ynl_sock *ys, struct ethtool_fec_get_req_dump *req);
-
-/* ETHTOOL_MSG_FEC_GET - notify */
-struct ethtool_fec_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_fec_get_ntf *ntf);
- struct ethtool_fec_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_fec_get_ntf_free(struct ethtool_fec_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_FEC_SET ============== */
-/* ETHTOOL_MSG_FEC_SET - do */
-struct ethtool_fec_set_req {
- struct {
- __u32 header:1;
- __u32 modes:1;
- __u32 auto_:1;
- __u32 active:1;
- __u32 stats:1;
- } _present;
-
- struct ethtool_header header;
- struct ethtool_bitset modes;
- __u8 auto_;
- __u32 active;
- struct ethtool_fec_stat stats;
-};
-
-static inline struct ethtool_fec_set_req *ethtool_fec_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_fec_set_req));
-}
-void ethtool_fec_set_req_free(struct ethtool_fec_set_req *req);
-
-static inline void
-ethtool_fec_set_req_set_header_dev_index(struct ethtool_fec_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_fec_set_req_set_header_dev_name(struct ethtool_fec_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_fec_set_req_set_header_flags(struct ethtool_fec_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_fec_set_req_set_modes_nomask(struct ethtool_fec_set_req *req)
-{
- req->_present.modes = 1;
- req->modes._present.nomask = 1;
-}
-static inline void
-ethtool_fec_set_req_set_modes_size(struct ethtool_fec_set_req *req, __u32 size)
-{
- req->_present.modes = 1;
- req->modes._present.size = 1;
- req->modes.size = size;
-}
-static inline void
-__ethtool_fec_set_req_set_modes_bits_bit(struct ethtool_fec_set_req *req,
- struct ethtool_bitset_bit *bit,
- unsigned int n_bit)
-{
- free(req->modes.bits.bit);
- req->modes.bits.bit = bit;
- req->modes.bits.n_bit = n_bit;
-}
-static inline void
-ethtool_fec_set_req_set_auto_(struct ethtool_fec_set_req *req, __u8 auto_)
-{
- req->_present.auto_ = 1;
- req->auto_ = auto_;
-}
-static inline void
-ethtool_fec_set_req_set_active(struct ethtool_fec_set_req *req, __u32 active)
-{
- req->_present.active = 1;
- req->active = active;
-}
-static inline void
-ethtool_fec_set_req_set_stats_corrected(struct ethtool_fec_set_req *req,
- const void *corrected, size_t len)
-{
- free(req->stats.corrected);
- req->stats._present.corrected_len = len;
- req->stats.corrected = malloc(req->stats._present.corrected_len);
- memcpy(req->stats.corrected, corrected, req->stats._present.corrected_len);
-}
-static inline void
-ethtool_fec_set_req_set_stats_uncorr(struct ethtool_fec_set_req *req,
- const void *uncorr, size_t len)
-{
- free(req->stats.uncorr);
- req->stats._present.uncorr_len = len;
- req->stats.uncorr = malloc(req->stats._present.uncorr_len);
- memcpy(req->stats.uncorr, uncorr, req->stats._present.uncorr_len);
-}
-static inline void
-ethtool_fec_set_req_set_stats_corr_bits(struct ethtool_fec_set_req *req,
- const void *corr_bits, size_t len)
-{
- free(req->stats.corr_bits);
- req->stats._present.corr_bits_len = len;
- req->stats.corr_bits = malloc(req->stats._present.corr_bits_len);
- memcpy(req->stats.corr_bits, corr_bits, req->stats._present.corr_bits_len);
-}
-
-/*
- * Set FEC params.
- */
-int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req);
-
-/* ============== ETHTOOL_MSG_MODULE_EEPROM_GET ============== */
-/* ETHTOOL_MSG_MODULE_EEPROM_GET - do */
-struct ethtool_module_eeprom_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_module_eeprom_get_req *
-ethtool_module_eeprom_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_module_eeprom_get_req));
-}
-void
-ethtool_module_eeprom_get_req_free(struct ethtool_module_eeprom_get_req *req);
-
-static inline void
-ethtool_module_eeprom_get_req_set_header_dev_index(struct ethtool_module_eeprom_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_module_eeprom_get_req_set_header_dev_name(struct ethtool_module_eeprom_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_module_eeprom_get_req_set_header_flags(struct ethtool_module_eeprom_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_module_eeprom_get_rsp {
- struct {
- __u32 header:1;
- __u32 offset:1;
- __u32 length:1;
- __u32 page:1;
- __u32 bank:1;
- __u32 i2c_address:1;
- __u32 data_len;
- } _present;
-
- struct ethtool_header header;
- __u32 offset;
- __u32 length;
- __u8 page;
- __u8 bank;
- __u8 i2c_address;
- void *data;
-};
-
-void
-ethtool_module_eeprom_get_rsp_free(struct ethtool_module_eeprom_get_rsp *rsp);
-
-/*
- * Get module EEPROM params.
- */
-struct ethtool_module_eeprom_get_rsp *
-ethtool_module_eeprom_get(struct ynl_sock *ys,
- struct ethtool_module_eeprom_get_req *req);
-
-/* ETHTOOL_MSG_MODULE_EEPROM_GET - dump */
-struct ethtool_module_eeprom_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_module_eeprom_get_req_dump *
-ethtool_module_eeprom_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_module_eeprom_get_req_dump));
-}
-void
-ethtool_module_eeprom_get_req_dump_free(struct ethtool_module_eeprom_get_req_dump *req);
-
-static inline void
-ethtool_module_eeprom_get_req_dump_set_header_dev_index(struct ethtool_module_eeprom_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_module_eeprom_get_req_dump_set_header_dev_name(struct ethtool_module_eeprom_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_module_eeprom_get_req_dump_set_header_flags(struct ethtool_module_eeprom_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_module_eeprom_get_list {
- struct ethtool_module_eeprom_get_list *next;
- struct ethtool_module_eeprom_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-ethtool_module_eeprom_get_list_free(struct ethtool_module_eeprom_get_list *rsp);
-
-struct ethtool_module_eeprom_get_list *
-ethtool_module_eeprom_get_dump(struct ynl_sock *ys,
- struct ethtool_module_eeprom_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_PHC_VCLOCKS_GET ============== */
-/* ETHTOOL_MSG_PHC_VCLOCKS_GET - do */
-struct ethtool_phc_vclocks_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_phc_vclocks_get_req *
-ethtool_phc_vclocks_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_phc_vclocks_get_req));
-}
-void ethtool_phc_vclocks_get_req_free(struct ethtool_phc_vclocks_get_req *req);
-
-static inline void
-ethtool_phc_vclocks_get_req_set_header_dev_index(struct ethtool_phc_vclocks_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_phc_vclocks_get_req_set_header_dev_name(struct ethtool_phc_vclocks_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_phc_vclocks_get_req_set_header_flags(struct ethtool_phc_vclocks_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_phc_vclocks_get_rsp {
- struct {
- __u32 header:1;
- __u32 num:1;
- } _present;
-
- struct ethtool_header header;
- __u32 num;
-};
-
-void ethtool_phc_vclocks_get_rsp_free(struct ethtool_phc_vclocks_get_rsp *rsp);
-
-/*
- * Get PHC VCLOCKs.
- */
-struct ethtool_phc_vclocks_get_rsp *
-ethtool_phc_vclocks_get(struct ynl_sock *ys,
- struct ethtool_phc_vclocks_get_req *req);
-
-/* ETHTOOL_MSG_PHC_VCLOCKS_GET - dump */
-struct ethtool_phc_vclocks_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_phc_vclocks_get_req_dump *
-ethtool_phc_vclocks_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_phc_vclocks_get_req_dump));
-}
-void
-ethtool_phc_vclocks_get_req_dump_free(struct ethtool_phc_vclocks_get_req_dump *req);
-
-static inline void
-ethtool_phc_vclocks_get_req_dump_set_header_dev_index(struct ethtool_phc_vclocks_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_phc_vclocks_get_req_dump_set_header_dev_name(struct ethtool_phc_vclocks_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_phc_vclocks_get_req_dump_set_header_flags(struct ethtool_phc_vclocks_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_phc_vclocks_get_list {
- struct ethtool_phc_vclocks_get_list *next;
- struct ethtool_phc_vclocks_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-ethtool_phc_vclocks_get_list_free(struct ethtool_phc_vclocks_get_list *rsp);
-
-struct ethtool_phc_vclocks_get_list *
-ethtool_phc_vclocks_get_dump(struct ynl_sock *ys,
- struct ethtool_phc_vclocks_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_MODULE_GET ============== */
-/* ETHTOOL_MSG_MODULE_GET - do */
-struct ethtool_module_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_module_get_req *ethtool_module_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_module_get_req));
-}
-void ethtool_module_get_req_free(struct ethtool_module_get_req *req);
-
-static inline void
-ethtool_module_get_req_set_header_dev_index(struct ethtool_module_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_module_get_req_set_header_dev_name(struct ethtool_module_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_module_get_req_set_header_flags(struct ethtool_module_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_module_get_rsp {
- struct {
- __u32 header:1;
- __u32 power_mode_policy:1;
- __u32 power_mode:1;
- } _present;
-
- struct ethtool_header header;
- __u8 power_mode_policy;
- __u8 power_mode;
-};
-
-void ethtool_module_get_rsp_free(struct ethtool_module_get_rsp *rsp);
-
-/*
- * Get module params.
- */
-struct ethtool_module_get_rsp *
-ethtool_module_get(struct ynl_sock *ys, struct ethtool_module_get_req *req);
-
-/* ETHTOOL_MSG_MODULE_GET - dump */
-struct ethtool_module_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_module_get_req_dump *
-ethtool_module_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_module_get_req_dump));
-}
-void ethtool_module_get_req_dump_free(struct ethtool_module_get_req_dump *req);
-
-static inline void
-ethtool_module_get_req_dump_set_header_dev_index(struct ethtool_module_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_module_get_req_dump_set_header_dev_name(struct ethtool_module_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_module_get_req_dump_set_header_flags(struct ethtool_module_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_module_get_list {
- struct ethtool_module_get_list *next;
- struct ethtool_module_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_module_get_list_free(struct ethtool_module_get_list *rsp);
-
-struct ethtool_module_get_list *
-ethtool_module_get_dump(struct ynl_sock *ys,
- struct ethtool_module_get_req_dump *req);
-
-/* ETHTOOL_MSG_MODULE_GET - notify */
-struct ethtool_module_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_module_get_ntf *ntf);
- struct ethtool_module_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_module_get_ntf_free(struct ethtool_module_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_MODULE_SET ============== */
-/* ETHTOOL_MSG_MODULE_SET - do */
-struct ethtool_module_set_req {
- struct {
- __u32 header:1;
- __u32 power_mode_policy:1;
- __u32 power_mode:1;
- } _present;
-
- struct ethtool_header header;
- __u8 power_mode_policy;
- __u8 power_mode;
-};
-
-static inline struct ethtool_module_set_req *ethtool_module_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_module_set_req));
-}
-void ethtool_module_set_req_free(struct ethtool_module_set_req *req);
-
-static inline void
-ethtool_module_set_req_set_header_dev_index(struct ethtool_module_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_module_set_req_set_header_dev_name(struct ethtool_module_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_module_set_req_set_header_flags(struct ethtool_module_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_module_set_req_set_power_mode_policy(struct ethtool_module_set_req *req,
- __u8 power_mode_policy)
-{
- req->_present.power_mode_policy = 1;
- req->power_mode_policy = power_mode_policy;
-}
-static inline void
-ethtool_module_set_req_set_power_mode(struct ethtool_module_set_req *req,
- __u8 power_mode)
-{
- req->_present.power_mode = 1;
- req->power_mode = power_mode;
-}
-
-/*
- * Set module params.
- */
-int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req);
-
-/* ============== ETHTOOL_MSG_PSE_GET ============== */
-/* ETHTOOL_MSG_PSE_GET - do */
-struct ethtool_pse_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_pse_get_req *ethtool_pse_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pse_get_req));
-}
-void ethtool_pse_get_req_free(struct ethtool_pse_get_req *req);
-
-static inline void
-ethtool_pse_get_req_set_header_dev_index(struct ethtool_pse_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pse_get_req_set_header_dev_name(struct ethtool_pse_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pse_get_req_set_header_flags(struct ethtool_pse_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_pse_get_rsp {
- struct {
- __u32 header:1;
- __u32 admin_state:1;
- __u32 admin_control:1;
- __u32 pw_d_status:1;
- } _present;
-
- struct ethtool_header header;
- __u32 admin_state;
- __u32 admin_control;
- __u32 pw_d_status;
-};
-
-void ethtool_pse_get_rsp_free(struct ethtool_pse_get_rsp *rsp);
-
-/*
- * Get Power Sourcing Equipment params.
- */
-struct ethtool_pse_get_rsp *
-ethtool_pse_get(struct ynl_sock *ys, struct ethtool_pse_get_req *req);
-
-/* ETHTOOL_MSG_PSE_GET - dump */
-struct ethtool_pse_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_pse_get_req_dump *
-ethtool_pse_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pse_get_req_dump));
-}
-void ethtool_pse_get_req_dump_free(struct ethtool_pse_get_req_dump *req);
-
-static inline void
-ethtool_pse_get_req_dump_set_header_dev_index(struct ethtool_pse_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pse_get_req_dump_set_header_dev_name(struct ethtool_pse_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pse_get_req_dump_set_header_flags(struct ethtool_pse_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_pse_get_list {
- struct ethtool_pse_get_list *next;
- struct ethtool_pse_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_pse_get_list_free(struct ethtool_pse_get_list *rsp);
-
-struct ethtool_pse_get_list *
-ethtool_pse_get_dump(struct ynl_sock *ys, struct ethtool_pse_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_PSE_SET ============== */
-/* ETHTOOL_MSG_PSE_SET - do */
-struct ethtool_pse_set_req {
- struct {
- __u32 header:1;
- __u32 admin_state:1;
- __u32 admin_control:1;
- __u32 pw_d_status:1;
- } _present;
-
- struct ethtool_header header;
- __u32 admin_state;
- __u32 admin_control;
- __u32 pw_d_status;
-};
-
-static inline struct ethtool_pse_set_req *ethtool_pse_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_pse_set_req));
-}
-void ethtool_pse_set_req_free(struct ethtool_pse_set_req *req);
-
-static inline void
-ethtool_pse_set_req_set_header_dev_index(struct ethtool_pse_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_pse_set_req_set_header_dev_name(struct ethtool_pse_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_pse_set_req_set_header_flags(struct ethtool_pse_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_pse_set_req_set_admin_state(struct ethtool_pse_set_req *req,
- __u32 admin_state)
-{
- req->_present.admin_state = 1;
- req->admin_state = admin_state;
-}
-static inline void
-ethtool_pse_set_req_set_admin_control(struct ethtool_pse_set_req *req,
- __u32 admin_control)
-{
- req->_present.admin_control = 1;
- req->admin_control = admin_control;
-}
-static inline void
-ethtool_pse_set_req_set_pw_d_status(struct ethtool_pse_set_req *req,
- __u32 pw_d_status)
-{
- req->_present.pw_d_status = 1;
- req->pw_d_status = pw_d_status;
-}
-
-/*
- * Set Power Sourcing Equipment params.
- */
-int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req);
-
-/* ============== ETHTOOL_MSG_RSS_GET ============== */
-/* ETHTOOL_MSG_RSS_GET - do */
-struct ethtool_rss_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_rss_get_req *ethtool_rss_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_rss_get_req));
-}
-void ethtool_rss_get_req_free(struct ethtool_rss_get_req *req);
-
-static inline void
-ethtool_rss_get_req_set_header_dev_index(struct ethtool_rss_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_rss_get_req_set_header_dev_name(struct ethtool_rss_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_rss_get_req_set_header_flags(struct ethtool_rss_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_rss_get_rsp {
- struct {
- __u32 header:1;
- __u32 context:1;
- __u32 hfunc:1;
- __u32 indir_len;
- __u32 hkey_len;
- } _present;
-
- struct ethtool_header header;
- __u32 context;
- __u32 hfunc;
- void *indir;
- void *hkey;
-};
-
-void ethtool_rss_get_rsp_free(struct ethtool_rss_get_rsp *rsp);
-
-/*
- * Get RSS params.
- */
-struct ethtool_rss_get_rsp *
-ethtool_rss_get(struct ynl_sock *ys, struct ethtool_rss_get_req *req);
-
-/* ETHTOOL_MSG_RSS_GET - dump */
-struct ethtool_rss_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_rss_get_req_dump *
-ethtool_rss_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_rss_get_req_dump));
-}
-void ethtool_rss_get_req_dump_free(struct ethtool_rss_get_req_dump *req);
-
-static inline void
-ethtool_rss_get_req_dump_set_header_dev_index(struct ethtool_rss_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_rss_get_req_dump_set_header_dev_name(struct ethtool_rss_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_rss_get_req_dump_set_header_flags(struct ethtool_rss_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_rss_get_list {
- struct ethtool_rss_get_list *next;
- struct ethtool_rss_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_rss_get_list_free(struct ethtool_rss_get_list *rsp);
-
-struct ethtool_rss_get_list *
-ethtool_rss_get_dump(struct ynl_sock *ys, struct ethtool_rss_get_req_dump *req);
-
-/* ============== ETHTOOL_MSG_PLCA_GET_CFG ============== */
-/* ETHTOOL_MSG_PLCA_GET_CFG - do */
-struct ethtool_plca_get_cfg_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_plca_get_cfg_req *
-ethtool_plca_get_cfg_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_plca_get_cfg_req));
-}
-void ethtool_plca_get_cfg_req_free(struct ethtool_plca_get_cfg_req *req);
-
-static inline void
-ethtool_plca_get_cfg_req_set_header_dev_index(struct ethtool_plca_get_cfg_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_plca_get_cfg_req_set_header_dev_name(struct ethtool_plca_get_cfg_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_plca_get_cfg_req_set_header_flags(struct ethtool_plca_get_cfg_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_plca_get_cfg_rsp {
- struct {
- __u32 header:1;
- __u32 version:1;
- __u32 enabled:1;
- __u32 status:1;
- __u32 node_cnt:1;
- __u32 node_id:1;
- __u32 to_tmr:1;
- __u32 burst_cnt:1;
- __u32 burst_tmr:1;
- } _present;
-
- struct ethtool_header header;
- __u16 version;
- __u8 enabled;
- __u8 status;
- __u32 node_cnt;
- __u32 node_id;
- __u32 to_tmr;
- __u32 burst_cnt;
- __u32 burst_tmr;
-};
-
-void ethtool_plca_get_cfg_rsp_free(struct ethtool_plca_get_cfg_rsp *rsp);
-
-/*
- * Get PLCA params.
- */
-struct ethtool_plca_get_cfg_rsp *
-ethtool_plca_get_cfg(struct ynl_sock *ys, struct ethtool_plca_get_cfg_req *req);
-
-/* ETHTOOL_MSG_PLCA_GET_CFG - dump */
-struct ethtool_plca_get_cfg_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_plca_get_cfg_req_dump *
-ethtool_plca_get_cfg_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_plca_get_cfg_req_dump));
-}
-void
-ethtool_plca_get_cfg_req_dump_free(struct ethtool_plca_get_cfg_req_dump *req);
-
-static inline void
-ethtool_plca_get_cfg_req_dump_set_header_dev_index(struct ethtool_plca_get_cfg_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_plca_get_cfg_req_dump_set_header_dev_name(struct ethtool_plca_get_cfg_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_plca_get_cfg_req_dump_set_header_flags(struct ethtool_plca_get_cfg_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_plca_get_cfg_list {
- struct ethtool_plca_get_cfg_list *next;
- struct ethtool_plca_get_cfg_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_plca_get_cfg_list_free(struct ethtool_plca_get_cfg_list *rsp);
-
-struct ethtool_plca_get_cfg_list *
-ethtool_plca_get_cfg_dump(struct ynl_sock *ys,
- struct ethtool_plca_get_cfg_req_dump *req);
-
-/* ETHTOOL_MSG_PLCA_GET_CFG - notify */
-struct ethtool_plca_get_cfg_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_plca_get_cfg_ntf *ntf);
- struct ethtool_plca_get_cfg_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_plca_get_cfg_ntf_free(struct ethtool_plca_get_cfg_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_PLCA_SET_CFG ============== */
-/* ETHTOOL_MSG_PLCA_SET_CFG - do */
-struct ethtool_plca_set_cfg_req {
- struct {
- __u32 header:1;
- __u32 version:1;
- __u32 enabled:1;
- __u32 status:1;
- __u32 node_cnt:1;
- __u32 node_id:1;
- __u32 to_tmr:1;
- __u32 burst_cnt:1;
- __u32 burst_tmr:1;
- } _present;
-
- struct ethtool_header header;
- __u16 version;
- __u8 enabled;
- __u8 status;
- __u32 node_cnt;
- __u32 node_id;
- __u32 to_tmr;
- __u32 burst_cnt;
- __u32 burst_tmr;
-};
-
-static inline struct ethtool_plca_set_cfg_req *
-ethtool_plca_set_cfg_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_plca_set_cfg_req));
-}
-void ethtool_plca_set_cfg_req_free(struct ethtool_plca_set_cfg_req *req);
-
-static inline void
-ethtool_plca_set_cfg_req_set_header_dev_index(struct ethtool_plca_set_cfg_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_header_dev_name(struct ethtool_plca_set_cfg_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_header_flags(struct ethtool_plca_set_cfg_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_version(struct ethtool_plca_set_cfg_req *req,
- __u16 version)
-{
- req->_present.version = 1;
- req->version = version;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_enabled(struct ethtool_plca_set_cfg_req *req,
- __u8 enabled)
-{
- req->_present.enabled = 1;
- req->enabled = enabled;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_status(struct ethtool_plca_set_cfg_req *req,
- __u8 status)
-{
- req->_present.status = 1;
- req->status = status;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_node_cnt(struct ethtool_plca_set_cfg_req *req,
- __u32 node_cnt)
-{
- req->_present.node_cnt = 1;
- req->node_cnt = node_cnt;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_node_id(struct ethtool_plca_set_cfg_req *req,
- __u32 node_id)
-{
- req->_present.node_id = 1;
- req->node_id = node_id;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_to_tmr(struct ethtool_plca_set_cfg_req *req,
- __u32 to_tmr)
-{
- req->_present.to_tmr = 1;
- req->to_tmr = to_tmr;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_burst_cnt(struct ethtool_plca_set_cfg_req *req,
- __u32 burst_cnt)
-{
- req->_present.burst_cnt = 1;
- req->burst_cnt = burst_cnt;
-}
-static inline void
-ethtool_plca_set_cfg_req_set_burst_tmr(struct ethtool_plca_set_cfg_req *req,
- __u32 burst_tmr)
-{
- req->_present.burst_tmr = 1;
- req->burst_tmr = burst_tmr;
-}
-
-/*
- * Set PLCA params.
- */
-int ethtool_plca_set_cfg(struct ynl_sock *ys,
- struct ethtool_plca_set_cfg_req *req);
-
-/* ============== ETHTOOL_MSG_PLCA_GET_STATUS ============== */
-/* ETHTOOL_MSG_PLCA_GET_STATUS - do */
-struct ethtool_plca_get_status_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_plca_get_status_req *
-ethtool_plca_get_status_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_plca_get_status_req));
-}
-void ethtool_plca_get_status_req_free(struct ethtool_plca_get_status_req *req);
-
-static inline void
-ethtool_plca_get_status_req_set_header_dev_index(struct ethtool_plca_get_status_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_plca_get_status_req_set_header_dev_name(struct ethtool_plca_get_status_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_plca_get_status_req_set_header_flags(struct ethtool_plca_get_status_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_plca_get_status_rsp {
- struct {
- __u32 header:1;
- __u32 version:1;
- __u32 enabled:1;
- __u32 status:1;
- __u32 node_cnt:1;
- __u32 node_id:1;
- __u32 to_tmr:1;
- __u32 burst_cnt:1;
- __u32 burst_tmr:1;
- } _present;
-
- struct ethtool_header header;
- __u16 version;
- __u8 enabled;
- __u8 status;
- __u32 node_cnt;
- __u32 node_id;
- __u32 to_tmr;
- __u32 burst_cnt;
- __u32 burst_tmr;
-};
-
-void ethtool_plca_get_status_rsp_free(struct ethtool_plca_get_status_rsp *rsp);
-
-/*
- * Get PLCA status params.
- */
-struct ethtool_plca_get_status_rsp *
-ethtool_plca_get_status(struct ynl_sock *ys,
- struct ethtool_plca_get_status_req *req);
-
-/* ETHTOOL_MSG_PLCA_GET_STATUS - dump */
-struct ethtool_plca_get_status_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_plca_get_status_req_dump *
-ethtool_plca_get_status_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_plca_get_status_req_dump));
-}
-void
-ethtool_plca_get_status_req_dump_free(struct ethtool_plca_get_status_req_dump *req);
-
-static inline void
-ethtool_plca_get_status_req_dump_set_header_dev_index(struct ethtool_plca_get_status_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_plca_get_status_req_dump_set_header_dev_name(struct ethtool_plca_get_status_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_plca_get_status_req_dump_set_header_flags(struct ethtool_plca_get_status_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_plca_get_status_list {
- struct ethtool_plca_get_status_list *next;
- struct ethtool_plca_get_status_rsp obj __attribute__ ((aligned (8)));
-};
-
-void
-ethtool_plca_get_status_list_free(struct ethtool_plca_get_status_list *rsp);
-
-struct ethtool_plca_get_status_list *
-ethtool_plca_get_status_dump(struct ynl_sock *ys,
- struct ethtool_plca_get_status_req_dump *req);
-
-/* ============== ETHTOOL_MSG_MM_GET ============== */
-/* ETHTOOL_MSG_MM_GET - do */
-struct ethtool_mm_get_req {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_mm_get_req *ethtool_mm_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_mm_get_req));
-}
-void ethtool_mm_get_req_free(struct ethtool_mm_get_req *req);
-
-static inline void
-ethtool_mm_get_req_set_header_dev_index(struct ethtool_mm_get_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_mm_get_req_set_header_dev_name(struct ethtool_mm_get_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_mm_get_req_set_header_flags(struct ethtool_mm_get_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_mm_get_rsp {
- struct {
- __u32 header:1;
- __u32 pmac_enabled:1;
- __u32 tx_enabled:1;
- __u32 tx_active:1;
- __u32 tx_min_frag_size:1;
- __u32 rx_min_frag_size:1;
- __u32 verify_enabled:1;
- __u32 verify_time:1;
- __u32 max_verify_time:1;
- __u32 stats:1;
- } _present;
-
- struct ethtool_header header;
- __u8 pmac_enabled;
- __u8 tx_enabled;
- __u8 tx_active;
- __u32 tx_min_frag_size;
- __u32 rx_min_frag_size;
- __u8 verify_enabled;
- __u32 verify_time;
- __u32 max_verify_time;
- struct ethtool_mm_stat stats;
-};
-
-void ethtool_mm_get_rsp_free(struct ethtool_mm_get_rsp *rsp);
-
-/*
- * Get MAC Merge configuration and state
- */
-struct ethtool_mm_get_rsp *
-ethtool_mm_get(struct ynl_sock *ys, struct ethtool_mm_get_req *req);
-
-/* ETHTOOL_MSG_MM_GET - dump */
-struct ethtool_mm_get_req_dump {
- struct {
- __u32 header:1;
- } _present;
-
- struct ethtool_header header;
-};
-
-static inline struct ethtool_mm_get_req_dump *
-ethtool_mm_get_req_dump_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_mm_get_req_dump));
-}
-void ethtool_mm_get_req_dump_free(struct ethtool_mm_get_req_dump *req);
-
-static inline void
-ethtool_mm_get_req_dump_set_header_dev_index(struct ethtool_mm_get_req_dump *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_mm_get_req_dump_set_header_dev_name(struct ethtool_mm_get_req_dump *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_mm_get_req_dump_set_header_flags(struct ethtool_mm_get_req_dump *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-
-struct ethtool_mm_get_list {
- struct ethtool_mm_get_list *next;
- struct ethtool_mm_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_mm_get_list_free(struct ethtool_mm_get_list *rsp);
-
-struct ethtool_mm_get_list *
-ethtool_mm_get_dump(struct ynl_sock *ys, struct ethtool_mm_get_req_dump *req);
-
-/* ETHTOOL_MSG_MM_GET - notify */
-struct ethtool_mm_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_mm_get_ntf *ntf);
- struct ethtool_mm_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_mm_get_ntf_free(struct ethtool_mm_get_ntf *rsp);
-
-/* ============== ETHTOOL_MSG_MM_SET ============== */
-/* ETHTOOL_MSG_MM_SET - do */
-struct ethtool_mm_set_req {
- struct {
- __u32 header:1;
- __u32 verify_enabled:1;
- __u32 verify_time:1;
- __u32 tx_enabled:1;
- __u32 pmac_enabled:1;
- __u32 tx_min_frag_size:1;
- } _present;
-
- struct ethtool_header header;
- __u8 verify_enabled;
- __u32 verify_time;
- __u8 tx_enabled;
- __u8 pmac_enabled;
- __u32 tx_min_frag_size;
-};
-
-static inline struct ethtool_mm_set_req *ethtool_mm_set_req_alloc(void)
-{
- return calloc(1, sizeof(struct ethtool_mm_set_req));
-}
-void ethtool_mm_set_req_free(struct ethtool_mm_set_req *req);
-
-static inline void
-ethtool_mm_set_req_set_header_dev_index(struct ethtool_mm_set_req *req,
- __u32 dev_index)
-{
- req->_present.header = 1;
- req->header._present.dev_index = 1;
- req->header.dev_index = dev_index;
-}
-static inline void
-ethtool_mm_set_req_set_header_dev_name(struct ethtool_mm_set_req *req,
- const char *dev_name)
-{
- free(req->header.dev_name);
- req->header._present.dev_name_len = strlen(dev_name);
- req->header.dev_name = malloc(req->header._present.dev_name_len + 1);
- memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len);
- req->header.dev_name[req->header._present.dev_name_len] = 0;
-}
-static inline void
-ethtool_mm_set_req_set_header_flags(struct ethtool_mm_set_req *req,
- __u32 flags)
-{
- req->_present.header = 1;
- req->header._present.flags = 1;
- req->header.flags = flags;
-}
-static inline void
-ethtool_mm_set_req_set_verify_enabled(struct ethtool_mm_set_req *req,
- __u8 verify_enabled)
-{
- req->_present.verify_enabled = 1;
- req->verify_enabled = verify_enabled;
-}
-static inline void
-ethtool_mm_set_req_set_verify_time(struct ethtool_mm_set_req *req,
- __u32 verify_time)
-{
- req->_present.verify_time = 1;
- req->verify_time = verify_time;
-}
-static inline void
-ethtool_mm_set_req_set_tx_enabled(struct ethtool_mm_set_req *req,
- __u8 tx_enabled)
-{
- req->_present.tx_enabled = 1;
- req->tx_enabled = tx_enabled;
-}
-static inline void
-ethtool_mm_set_req_set_pmac_enabled(struct ethtool_mm_set_req *req,
- __u8 pmac_enabled)
-{
- req->_present.pmac_enabled = 1;
- req->pmac_enabled = pmac_enabled;
-}
-static inline void
-ethtool_mm_set_req_set_tx_min_frag_size(struct ethtool_mm_set_req *req,
- __u32 tx_min_frag_size)
-{
- req->_present.tx_min_frag_size = 1;
- req->tx_min_frag_size = tx_min_frag_size;
-}
-
-/*
- * Set MAC Merge configuration
- */
-int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req);
-
-/* ETHTOOL_MSG_CABLE_TEST_NTF - event */
-struct ethtool_cable_test_ntf_rsp {
- struct {
- __u32 header:1;
- __u32 status:1;
- } _present;
-
- struct ethtool_header header;
- __u8 status;
-};
-
-struct ethtool_cable_test_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_cable_test_ntf *ntf);
- struct ethtool_cable_test_ntf_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_cable_test_ntf_free(struct ethtool_cable_test_ntf *rsp);
-
-/* ETHTOOL_MSG_CABLE_TEST_TDR_NTF - event */
-struct ethtool_cable_test_tdr_ntf_rsp {
- struct {
- __u32 header:1;
- __u32 status:1;
- __u32 nest:1;
- } _present;
-
- struct ethtool_header header;
- __u8 status;
- struct ethtool_cable_nest nest;
-};
-
-struct ethtool_cable_test_tdr_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ethtool_cable_test_tdr_ntf *ntf);
- struct ethtool_cable_test_tdr_ntf_rsp obj __attribute__ ((aligned (8)));
-};
-
-void ethtool_cable_test_tdr_ntf_free(struct ethtool_cable_test_tdr_ntf *rsp);
-
-#endif /* _LINUX_ETHTOOL_GEN_H */
diff --git a/tools/net/ynl/generated/fou-user.c b/tools/net/ynl/generated/fou-user.c
deleted file mode 100644
index 4271b5d43c58..000000000000
--- a/tools/net/ynl/generated/fou-user.c
+++ /dev/null
@@ -1,328 +0,0 @@
-// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/fou.yaml */
-/* YNL-GEN user source */
-
-#include <stdlib.h>
-#include <string.h>
-#include "fou-user.h"
-#include "ynl.h"
-#include <linux/fou.h>
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-
-/* Enums */
-static const char * const fou_op_strmap[] = {
- [FOU_CMD_ADD] = "add",
- [FOU_CMD_DEL] = "del",
- [FOU_CMD_GET] = "get",
-};
-
-const char *fou_op_str(int op)
-{
- if (op < 0 || op >= (int)MNL_ARRAY_SIZE(fou_op_strmap))
- return NULL;
- return fou_op_strmap[op];
-}
-
-static const char * const fou_encap_type_strmap[] = {
- [0] = "unspec",
- [1] = "direct",
- [2] = "gue",
-};
-
-const char *fou_encap_type_str(int value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(fou_encap_type_strmap))
- return NULL;
- return fou_encap_type_strmap[value];
-}
-
-/* Policies */
-struct ynl_policy_attr fou_policy[FOU_ATTR_MAX + 1] = {
- [FOU_ATTR_UNSPEC] = { .name = "unspec", .type = YNL_PT_REJECT, },
- [FOU_ATTR_PORT] = { .name = "port", .type = YNL_PT_U16, },
- [FOU_ATTR_AF] = { .name = "af", .type = YNL_PT_U8, },
- [FOU_ATTR_IPPROTO] = { .name = "ipproto", .type = YNL_PT_U8, },
- [FOU_ATTR_TYPE] = { .name = "type", .type = YNL_PT_U8, },
- [FOU_ATTR_REMCSUM_NOPARTIAL] = { .name = "remcsum_nopartial", .type = YNL_PT_FLAG, },
- [FOU_ATTR_LOCAL_V4] = { .name = "local_v4", .type = YNL_PT_U32, },
- [FOU_ATTR_LOCAL_V6] = { .name = "local_v6", .type = YNL_PT_BINARY,},
- [FOU_ATTR_PEER_V4] = { .name = "peer_v4", .type = YNL_PT_U32, },
- [FOU_ATTR_PEER_V6] = { .name = "peer_v6", .type = YNL_PT_BINARY,},
- [FOU_ATTR_PEER_PORT] = { .name = "peer_port", .type = YNL_PT_U16, },
- [FOU_ATTR_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest fou_nest = {
- .max_attr = FOU_ATTR_MAX,
- .table = fou_policy,
-};
-
-/* Common nested types */
-/* ============== FOU_CMD_ADD ============== */
-/* FOU_CMD_ADD - do */
-void fou_add_req_free(struct fou_add_req *req)
-{
- free(req->local_v6);
- free(req->peer_v6);
- free(req);
-}
-
-int fou_add(struct ynl_sock *ys, struct fou_add_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, FOU_CMD_ADD, 1);
- ys->req_policy = &fou_nest;
-
- if (req->_present.port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PORT, req->port);
- if (req->_present.ipproto)
- mnl_attr_put_u8(nlh, FOU_ATTR_IPPROTO, req->ipproto);
- if (req->_present.type)
- mnl_attr_put_u8(nlh, FOU_ATTR_TYPE, req->type);
- if (req->_present.remcsum_nopartial)
- mnl_attr_put(nlh, FOU_ATTR_REMCSUM_NOPARTIAL, 0, NULL);
- if (req->_present.local_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_LOCAL_V4, req->local_v4);
- if (req->_present.peer_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_PEER_V4, req->peer_v4);
- if (req->_present.local_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_LOCAL_V6, req->_present.local_v6_len, req->local_v6);
- if (req->_present.peer_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_PEER_V6, req->_present.peer_v6_len, req->peer_v6);
- if (req->_present.peer_port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PEER_PORT, req->peer_port);
- if (req->_present.ifindex)
- mnl_attr_put_u32(nlh, FOU_ATTR_IFINDEX, req->ifindex);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== FOU_CMD_DEL ============== */
-/* FOU_CMD_DEL - do */
-void fou_del_req_free(struct fou_del_req *req)
-{
- free(req->local_v6);
- free(req->peer_v6);
- free(req);
-}
-
-int fou_del(struct ynl_sock *ys, struct fou_del_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, FOU_CMD_DEL, 1);
- ys->req_policy = &fou_nest;
-
- if (req->_present.af)
- mnl_attr_put_u8(nlh, FOU_ATTR_AF, req->af);
- if (req->_present.ifindex)
- mnl_attr_put_u32(nlh, FOU_ATTR_IFINDEX, req->ifindex);
- if (req->_present.port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PORT, req->port);
- if (req->_present.peer_port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PEER_PORT, req->peer_port);
- if (req->_present.local_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_LOCAL_V4, req->local_v4);
- if (req->_present.peer_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_PEER_V4, req->peer_v4);
- if (req->_present.local_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_LOCAL_V6, req->_present.local_v6_len, req->local_v6);
- if (req->_present.peer_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_PEER_V6, req->_present.peer_v6_len, req->peer_v6);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-/* ============== FOU_CMD_GET ============== */
-/* FOU_CMD_GET - do */
-void fou_get_req_free(struct fou_get_req *req)
-{
- free(req->local_v6);
- free(req->peer_v6);
- free(req);
-}
-
-void fou_get_rsp_free(struct fou_get_rsp *rsp)
-{
- free(rsp->local_v6);
- free(rsp->peer_v6);
- free(rsp);
-}
-
-int fou_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- const struct nlattr *attr;
- struct fou_get_rsp *dst;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == FOU_ATTR_PORT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.port = 1;
- dst->port = mnl_attr_get_u16(attr);
- } else if (type == FOU_ATTR_IPPROTO) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ipproto = 1;
- dst->ipproto = mnl_attr_get_u8(attr);
- } else if (type == FOU_ATTR_TYPE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.type = 1;
- dst->type = mnl_attr_get_u8(attr);
- } else if (type == FOU_ATTR_REMCSUM_NOPARTIAL) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.remcsum_nopartial = 1;
- } else if (type == FOU_ATTR_LOCAL_V4) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.local_v4 = 1;
- dst->local_v4 = mnl_attr_get_u32(attr);
- } else if (type == FOU_ATTR_PEER_V4) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.peer_v4 = 1;
- dst->peer_v4 = mnl_attr_get_u32(attr);
- } else if (type == FOU_ATTR_LOCAL_V6) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.local_v6_len = len;
- dst->local_v6 = malloc(len);
- memcpy(dst->local_v6, mnl_attr_get_payload(attr), len);
- } else if (type == FOU_ATTR_PEER_V6) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = mnl_attr_get_payload_len(attr);
- dst->_present.peer_v6_len = len;
- dst->peer_v6 = malloc(len);
- memcpy(dst->peer_v6, mnl_attr_get_payload(attr), len);
- } else if (type == FOU_ATTR_PEER_PORT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.peer_port = 1;
- dst->peer_port = mnl_attr_get_u16(attr);
- } else if (type == FOU_ATTR_IFINDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ifindex = 1;
- dst->ifindex = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct fou_get_rsp *fou_get(struct ynl_sock *ys, struct fou_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct fou_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, FOU_CMD_GET, 1);
- ys->req_policy = &fou_nest;
- yrs.yarg.rsp_policy = &fou_nest;
-
- if (req->_present.af)
- mnl_attr_put_u8(nlh, FOU_ATTR_AF, req->af);
- if (req->_present.ifindex)
- mnl_attr_put_u32(nlh, FOU_ATTR_IFINDEX, req->ifindex);
- if (req->_present.port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PORT, req->port);
- if (req->_present.peer_port)
- mnl_attr_put_u16(nlh, FOU_ATTR_PEER_PORT, req->peer_port);
- if (req->_present.local_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_LOCAL_V4, req->local_v4);
- if (req->_present.peer_v4)
- mnl_attr_put_u32(nlh, FOU_ATTR_PEER_V4, req->peer_v4);
- if (req->_present.local_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_LOCAL_V6, req->_present.local_v6_len, req->local_v6);
- if (req->_present.peer_v6_len)
- mnl_attr_put(nlh, FOU_ATTR_PEER_V6, req->_present.peer_v6_len, req->peer_v6);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = fou_get_rsp_parse;
- yrs.rsp_cmd = FOU_CMD_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- fou_get_rsp_free(rsp);
- return NULL;
-}
-
-/* FOU_CMD_GET - dump */
-void fou_get_list_free(struct fou_get_list *rsp)
-{
- struct fou_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp->obj.local_v6);
- free(rsp->obj.peer_v6);
- free(rsp);
- }
-}
-
-struct fou_get_list *fou_get_dump(struct ynl_sock *ys)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct fou_get_list);
- yds.cb = fou_get_rsp_parse;
- yds.rsp_cmd = FOU_CMD_GET;
- yds.rsp_policy = &fou_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, FOU_CMD_GET, 1);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- fou_get_list_free(yds.first);
- return NULL;
-}
-
-const struct ynl_family ynl_fou_family = {
- .name = "fou",
-};
diff --git a/tools/net/ynl/generated/fou-user.h b/tools/net/ynl/generated/fou-user.h
deleted file mode 100644
index a8f860892540..000000000000
--- a/tools/net/ynl/generated/fou-user.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/fou.yaml */
-/* YNL-GEN user header */
-
-#ifndef _LINUX_FOU_GEN_H
-#define _LINUX_FOU_GEN_H
-
-#include <stdlib.h>
-#include <string.h>
-#include <linux/types.h>
-#include <linux/fou.h>
-
-struct ynl_sock;
-
-extern const struct ynl_family ynl_fou_family;
-
-/* Enums */
-const char *fou_op_str(int op);
-const char *fou_encap_type_str(int value);
-
-/* Common nested types */
-/* ============== FOU_CMD_ADD ============== */
-/* FOU_CMD_ADD - do */
-struct fou_add_req {
- struct {
- __u32 port:1;
- __u32 ipproto:1;
- __u32 type:1;
- __u32 remcsum_nopartial:1;
- __u32 local_v4:1;
- __u32 peer_v4:1;
- __u32 local_v6_len;
- __u32 peer_v6_len;
- __u32 peer_port:1;
- __u32 ifindex:1;
- } _present;
-
- __u16 port /* big-endian */;
- __u8 ipproto;
- __u8 type;
- __u32 local_v4;
- __u32 peer_v4;
- void *local_v6;
- void *peer_v6;
- __u16 peer_port /* big-endian */;
- __s32 ifindex;
-};
-
-static inline struct fou_add_req *fou_add_req_alloc(void)
-{
- return calloc(1, sizeof(struct fou_add_req));
-}
-void fou_add_req_free(struct fou_add_req *req);
-
-static inline void
-fou_add_req_set_port(struct fou_add_req *req, __u16 port /* big-endian */)
-{
- req->_present.port = 1;
- req->port = port;
-}
-static inline void
-fou_add_req_set_ipproto(struct fou_add_req *req, __u8 ipproto)
-{
- req->_present.ipproto = 1;
- req->ipproto = ipproto;
-}
-static inline void fou_add_req_set_type(struct fou_add_req *req, __u8 type)
-{
- req->_present.type = 1;
- req->type = type;
-}
-static inline void fou_add_req_set_remcsum_nopartial(struct fou_add_req *req)
-{
- req->_present.remcsum_nopartial = 1;
-}
-static inline void
-fou_add_req_set_local_v4(struct fou_add_req *req, __u32 local_v4)
-{
- req->_present.local_v4 = 1;
- req->local_v4 = local_v4;
-}
-static inline void
-fou_add_req_set_peer_v4(struct fou_add_req *req, __u32 peer_v4)
-{
- req->_present.peer_v4 = 1;
- req->peer_v4 = peer_v4;
-}
-static inline void
-fou_add_req_set_local_v6(struct fou_add_req *req, const void *local_v6,
- size_t len)
-{
- free(req->local_v6);
- req->_present.local_v6_len = len;
- req->local_v6 = malloc(req->_present.local_v6_len);
- memcpy(req->local_v6, local_v6, req->_present.local_v6_len);
-}
-static inline void
-fou_add_req_set_peer_v6(struct fou_add_req *req, const void *peer_v6,
- size_t len)
-{
- free(req->peer_v6);
- req->_present.peer_v6_len = len;
- req->peer_v6 = malloc(req->_present.peer_v6_len);
- memcpy(req->peer_v6, peer_v6, req->_present.peer_v6_len);
-}
-static inline void
-fou_add_req_set_peer_port(struct fou_add_req *req,
- __u16 peer_port /* big-endian */)
-{
- req->_present.peer_port = 1;
- req->peer_port = peer_port;
-}
-static inline void
-fou_add_req_set_ifindex(struct fou_add_req *req, __s32 ifindex)
-{
- req->_present.ifindex = 1;
- req->ifindex = ifindex;
-}
-
-/*
- * Add port.
- */
-int fou_add(struct ynl_sock *ys, struct fou_add_req *req);
-
-/* ============== FOU_CMD_DEL ============== */
-/* FOU_CMD_DEL - do */
-struct fou_del_req {
- struct {
- __u32 af:1;
- __u32 ifindex:1;
- __u32 port:1;
- __u32 peer_port:1;
- __u32 local_v4:1;
- __u32 peer_v4:1;
- __u32 local_v6_len;
- __u32 peer_v6_len;
- } _present;
-
- __u8 af;
- __s32 ifindex;
- __u16 port /* big-endian */;
- __u16 peer_port /* big-endian */;
- __u32 local_v4;
- __u32 peer_v4;
- void *local_v6;
- void *peer_v6;
-};
-
-static inline struct fou_del_req *fou_del_req_alloc(void)
-{
- return calloc(1, sizeof(struct fou_del_req));
-}
-void fou_del_req_free(struct fou_del_req *req);
-
-static inline void fou_del_req_set_af(struct fou_del_req *req, __u8 af)
-{
- req->_present.af = 1;
- req->af = af;
-}
-static inline void
-fou_del_req_set_ifindex(struct fou_del_req *req, __s32 ifindex)
-{
- req->_present.ifindex = 1;
- req->ifindex = ifindex;
-}
-static inline void
-fou_del_req_set_port(struct fou_del_req *req, __u16 port /* big-endian */)
-{
- req->_present.port = 1;
- req->port = port;
-}
-static inline void
-fou_del_req_set_peer_port(struct fou_del_req *req,
- __u16 peer_port /* big-endian */)
-{
- req->_present.peer_port = 1;
- req->peer_port = peer_port;
-}
-static inline void
-fou_del_req_set_local_v4(struct fou_del_req *req, __u32 local_v4)
-{
- req->_present.local_v4 = 1;
- req->local_v4 = local_v4;
-}
-static inline void
-fou_del_req_set_peer_v4(struct fou_del_req *req, __u32 peer_v4)
-{
- req->_present.peer_v4 = 1;
- req->peer_v4 = peer_v4;
-}
-static inline void
-fou_del_req_set_local_v6(struct fou_del_req *req, const void *local_v6,
- size_t len)
-{
- free(req->local_v6);
- req->_present.local_v6_len = len;
- req->local_v6 = malloc(req->_present.local_v6_len);
- memcpy(req->local_v6, local_v6, req->_present.local_v6_len);
-}
-static inline void
-fou_del_req_set_peer_v6(struct fou_del_req *req, const void *peer_v6,
- size_t len)
-{
- free(req->peer_v6);
- req->_present.peer_v6_len = len;
- req->peer_v6 = malloc(req->_present.peer_v6_len);
- memcpy(req->peer_v6, peer_v6, req->_present.peer_v6_len);
-}
-
-/*
- * Delete port.
- */
-int fou_del(struct ynl_sock *ys, struct fou_del_req *req);
-
-/* ============== FOU_CMD_GET ============== */
-/* FOU_CMD_GET - do */
-struct fou_get_req {
- struct {
- __u32 af:1;
- __u32 ifindex:1;
- __u32 port:1;
- __u32 peer_port:1;
- __u32 local_v4:1;
- __u32 peer_v4:1;
- __u32 local_v6_len;
- __u32 peer_v6_len;
- } _present;
-
- __u8 af;
- __s32 ifindex;
- __u16 port /* big-endian */;
- __u16 peer_port /* big-endian */;
- __u32 local_v4;
- __u32 peer_v4;
- void *local_v6;
- void *peer_v6;
-};
-
-static inline struct fou_get_req *fou_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct fou_get_req));
-}
-void fou_get_req_free(struct fou_get_req *req);
-
-static inline void fou_get_req_set_af(struct fou_get_req *req, __u8 af)
-{
- req->_present.af = 1;
- req->af = af;
-}
-static inline void
-fou_get_req_set_ifindex(struct fou_get_req *req, __s32 ifindex)
-{
- req->_present.ifindex = 1;
- req->ifindex = ifindex;
-}
-static inline void
-fou_get_req_set_port(struct fou_get_req *req, __u16 port /* big-endian */)
-{
- req->_present.port = 1;
- req->port = port;
-}
-static inline void
-fou_get_req_set_peer_port(struct fou_get_req *req,
- __u16 peer_port /* big-endian */)
-{
- req->_present.peer_port = 1;
- req->peer_port = peer_port;
-}
-static inline void
-fou_get_req_set_local_v4(struct fou_get_req *req, __u32 local_v4)
-{
- req->_present.local_v4 = 1;
- req->local_v4 = local_v4;
-}
-static inline void
-fou_get_req_set_peer_v4(struct fou_get_req *req, __u32 peer_v4)
-{
- req->_present.peer_v4 = 1;
- req->peer_v4 = peer_v4;
-}
-static inline void
-fou_get_req_set_local_v6(struct fou_get_req *req, const void *local_v6,
- size_t len)
-{
- free(req->local_v6);
- req->_present.local_v6_len = len;
- req->local_v6 = malloc(req->_present.local_v6_len);
- memcpy(req->local_v6, local_v6, req->_present.local_v6_len);
-}
-static inline void
-fou_get_req_set_peer_v6(struct fou_get_req *req, const void *peer_v6,
- size_t len)
-{
- free(req->peer_v6);
- req->_present.peer_v6_len = len;
- req->peer_v6 = malloc(req->_present.peer_v6_len);
- memcpy(req->peer_v6, peer_v6, req->_present.peer_v6_len);
-}
-
-struct fou_get_rsp {
- struct {
- __u32 port:1;
- __u32 ipproto:1;
- __u32 type:1;
- __u32 remcsum_nopartial:1;
- __u32 local_v4:1;
- __u32 peer_v4:1;
- __u32 local_v6_len;
- __u32 peer_v6_len;
- __u32 peer_port:1;
- __u32 ifindex:1;
- } _present;
-
- __u16 port /* big-endian */;
- __u8 ipproto;
- __u8 type;
- __u32 local_v4;
- __u32 peer_v4;
- void *local_v6;
- void *peer_v6;
- __u16 peer_port /* big-endian */;
- __s32 ifindex;
-};
-
-void fou_get_rsp_free(struct fou_get_rsp *rsp);
-
-/*
- * Get tunnel info.
- */
-struct fou_get_rsp *fou_get(struct ynl_sock *ys, struct fou_get_req *req);
-
-/* FOU_CMD_GET - dump */
-struct fou_get_list {
- struct fou_get_list *next;
- struct fou_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void fou_get_list_free(struct fou_get_list *rsp);
-
-struct fou_get_list *fou_get_dump(struct ynl_sock *ys);
-
-#endif /* _LINUX_FOU_GEN_H */
diff --git a/tools/net/ynl/generated/handshake-user.c b/tools/net/ynl/generated/handshake-user.c
deleted file mode 100644
index 7c67765daf90..000000000000
--- a/tools/net/ynl/generated/handshake-user.c
+++ /dev/null
@@ -1,331 +0,0 @@
-// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/handshake.yaml */
-/* YNL-GEN user source */
-
-#include <stdlib.h>
-#include <string.h>
-#include "handshake-user.h"
-#include "ynl.h"
-#include <linux/handshake.h>
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-
-/* Enums */
-static const char * const handshake_op_strmap[] = {
- [HANDSHAKE_CMD_READY] = "ready",
- [HANDSHAKE_CMD_ACCEPT] = "accept",
- [HANDSHAKE_CMD_DONE] = "done",
-};
-
-const char *handshake_op_str(int op)
-{
- if (op < 0 || op >= (int)MNL_ARRAY_SIZE(handshake_op_strmap))
- return NULL;
- return handshake_op_strmap[op];
-}
-
-static const char * const handshake_handler_class_strmap[] = {
- [0] = "none",
- [1] = "tlshd",
- [2] = "max",
-};
-
-const char *handshake_handler_class_str(enum handshake_handler_class value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_handler_class_strmap))
- return NULL;
- return handshake_handler_class_strmap[value];
-}
-
-static const char * const handshake_msg_type_strmap[] = {
- [0] = "unspec",
- [1] = "clienthello",
- [2] = "serverhello",
-};
-
-const char *handshake_msg_type_str(enum handshake_msg_type value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_msg_type_strmap))
- return NULL;
- return handshake_msg_type_strmap[value];
-}
-
-static const char * const handshake_auth_strmap[] = {
- [0] = "unspec",
- [1] = "unauth",
- [2] = "psk",
- [3] = "x509",
-};
-
-const char *handshake_auth_str(enum handshake_auth value)
-{
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(handshake_auth_strmap))
- return NULL;
- return handshake_auth_strmap[value];
-}
-
-/* Policies */
-struct ynl_policy_attr handshake_x509_policy[HANDSHAKE_A_X509_MAX + 1] = {
- [HANDSHAKE_A_X509_CERT] = { .name = "cert", .type = YNL_PT_U32, },
- [HANDSHAKE_A_X509_PRIVKEY] = { .name = "privkey", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest handshake_x509_nest = {
- .max_attr = HANDSHAKE_A_X509_MAX,
- .table = handshake_x509_policy,
-};
-
-struct ynl_policy_attr handshake_accept_policy[HANDSHAKE_A_ACCEPT_MAX + 1] = {
- [HANDSHAKE_A_ACCEPT_SOCKFD] = { .name = "sockfd", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_HANDLER_CLASS] = { .name = "handler-class", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_MESSAGE_TYPE] = { .name = "message-type", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_TIMEOUT] = { .name = "timeout", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_AUTH_MODE] = { .name = "auth-mode", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_PEER_IDENTITY] = { .name = "peer-identity", .type = YNL_PT_U32, },
- [HANDSHAKE_A_ACCEPT_CERTIFICATE] = { .name = "certificate", .type = YNL_PT_NEST, .nest = &handshake_x509_nest, },
- [HANDSHAKE_A_ACCEPT_PEERNAME] = { .name = "peername", .type = YNL_PT_NUL_STR, },
-};
-
-struct ynl_policy_nest handshake_accept_nest = {
- .max_attr = HANDSHAKE_A_ACCEPT_MAX,
- .table = handshake_accept_policy,
-};
-
-struct ynl_policy_attr handshake_done_policy[HANDSHAKE_A_DONE_MAX + 1] = {
- [HANDSHAKE_A_DONE_STATUS] = { .name = "status", .type = YNL_PT_U32, },
- [HANDSHAKE_A_DONE_SOCKFD] = { .name = "sockfd", .type = YNL_PT_U32, },
- [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .name = "remote-auth", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest handshake_done_nest = {
- .max_attr = HANDSHAKE_A_DONE_MAX,
- .table = handshake_done_policy,
-};
-
-/* Common nested types */
-void handshake_x509_free(struct handshake_x509 *obj)
-{
-}
-
-int handshake_x509_parse(struct ynl_parse_arg *yarg,
- const struct nlattr *nested)
-{
- struct handshake_x509 *dst = yarg->data;
- const struct nlattr *attr;
-
- mnl_attr_for_each_nested(attr, nested) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == HANDSHAKE_A_X509_CERT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.cert = 1;
- dst->cert = mnl_attr_get_u32(attr);
- } else if (type == HANDSHAKE_A_X509_PRIVKEY) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.privkey = 1;
- dst->privkey = mnl_attr_get_u32(attr);
- }
- }
-
- return 0;
-}
-
-/* ============== HANDSHAKE_CMD_ACCEPT ============== */
-/* HANDSHAKE_CMD_ACCEPT - do */
-void handshake_accept_req_free(struct handshake_accept_req *req)
-{
- free(req);
-}
-
-void handshake_accept_rsp_free(struct handshake_accept_rsp *rsp)
-{
- unsigned int i;
-
- free(rsp->peer_identity);
- for (i = 0; i < rsp->n_certificate; i++)
- handshake_x509_free(&rsp->certificate[i]);
- free(rsp->certificate);
- free(rsp->peername);
- free(rsp);
-}
-
-int handshake_accept_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct handshake_accept_rsp *dst;
- unsigned int n_peer_identity = 0;
- unsigned int n_certificate = 0;
- const struct nlattr *attr;
- struct ynl_parse_arg parg;
- int i;
-
- dst = yarg->data;
- parg.ys = yarg->ys;
-
- if (dst->certificate)
- return ynl_error_parse(yarg, "attribute already present (accept.certificate)");
- if (dst->peer_identity)
- return ynl_error_parse(yarg, "attribute already present (accept.peer-identity)");
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == HANDSHAKE_A_ACCEPT_SOCKFD) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.sockfd = 1;
- dst->sockfd = mnl_attr_get_u32(attr);
- } else if (type == HANDSHAKE_A_ACCEPT_MESSAGE_TYPE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.message_type = 1;
- dst->message_type = mnl_attr_get_u32(attr);
- } else if (type == HANDSHAKE_A_ACCEPT_TIMEOUT) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.timeout = 1;
- dst->timeout = mnl_attr_get_u32(attr);
- } else if (type == HANDSHAKE_A_ACCEPT_AUTH_MODE) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.auth_mode = 1;
- dst->auth_mode = mnl_attr_get_u32(attr);
- } else if (type == HANDSHAKE_A_ACCEPT_PEER_IDENTITY) {
- n_peer_identity++;
- } else if (type == HANDSHAKE_A_ACCEPT_CERTIFICATE) {
- n_certificate++;
- } else if (type == HANDSHAKE_A_ACCEPT_PEERNAME) {
- unsigned int len;
-
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
-
- len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));
- dst->_present.peername_len = len;
- dst->peername = malloc(len + 1);
- memcpy(dst->peername, mnl_attr_get_str(attr), len);
- dst->peername[len] = 0;
- }
- }
-
- if (n_certificate) {
- dst->certificate = calloc(n_certificate, sizeof(*dst->certificate));
- dst->n_certificate = n_certificate;
- i = 0;
- parg.rsp_policy = &handshake_x509_nest;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == HANDSHAKE_A_ACCEPT_CERTIFICATE) {
- parg.data = &dst->certificate[i];
- if (handshake_x509_parse(&parg, attr))
- return MNL_CB_ERROR;
- i++;
- }
- }
- }
- if (n_peer_identity) {
- dst->peer_identity = calloc(n_peer_identity, sizeof(*dst->peer_identity));
- dst->n_peer_identity = n_peer_identity;
- i = 0;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == HANDSHAKE_A_ACCEPT_PEER_IDENTITY) {
- dst->peer_identity[i] = mnl_attr_get_u32(attr);
- i++;
- }
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct handshake_accept_rsp *
-handshake_accept(struct ynl_sock *ys, struct handshake_accept_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct handshake_accept_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, HANDSHAKE_CMD_ACCEPT, 1);
- ys->req_policy = &handshake_accept_nest;
- yrs.yarg.rsp_policy = &handshake_accept_nest;
-
- if (req->_present.handler_class)
- mnl_attr_put_u32(nlh, HANDSHAKE_A_ACCEPT_HANDLER_CLASS, req->handler_class);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = handshake_accept_rsp_parse;
- yrs.rsp_cmd = HANDSHAKE_CMD_ACCEPT;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- handshake_accept_rsp_free(rsp);
- return NULL;
-}
-
-/* HANDSHAKE_CMD_ACCEPT - notify */
-void handshake_accept_ntf_free(struct handshake_accept_ntf *rsp)
-{
- unsigned int i;
-
- free(rsp->obj.peer_identity);
- for (i = 0; i < rsp->obj.n_certificate; i++)
- handshake_x509_free(&rsp->obj.certificate[i]);
- free(rsp->obj.certificate);
- free(rsp->obj.peername);
- free(rsp);
-}
-
-/* ============== HANDSHAKE_CMD_DONE ============== */
-/* HANDSHAKE_CMD_DONE - do */
-void handshake_done_req_free(struct handshake_done_req *req)
-{
- free(req->remote_auth);
- free(req);
-}
-
-int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req)
-{
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, HANDSHAKE_CMD_DONE, 1);
- ys->req_policy = &handshake_done_nest;
-
- if (req->_present.status)
- mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_STATUS, req->status);
- if (req->_present.sockfd)
- mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_SOCKFD, req->sockfd);
- for (unsigned int i = 0; i < req->n_remote_auth; i++)
- mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_REMOTE_AUTH, req->remote_auth[i]);
-
- err = ynl_exec(ys, nlh, NULL);
- if (err < 0)
- return -1;
-
- return 0;
-}
-
-static const struct ynl_ntf_info handshake_ntf_info[] = {
- [HANDSHAKE_CMD_READY] = {
- .alloc_sz = sizeof(struct handshake_accept_ntf),
- .cb = handshake_accept_rsp_parse,
- .policy = &handshake_accept_nest,
- .free = (void *)handshake_accept_ntf_free,
- },
-};
-
-const struct ynl_family ynl_handshake_family = {
- .name = "handshake",
- .ntf_info = handshake_ntf_info,
- .ntf_info_size = MNL_ARRAY_SIZE(handshake_ntf_info),
-};
diff --git a/tools/net/ynl/generated/handshake-user.h b/tools/net/ynl/generated/handshake-user.h
deleted file mode 100644
index 47646bb91cea..000000000000
--- a/tools/net/ynl/generated/handshake-user.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/handshake.yaml */
-/* YNL-GEN user header */
-
-#ifndef _LINUX_HANDSHAKE_GEN_H
-#define _LINUX_HANDSHAKE_GEN_H
-
-#include <stdlib.h>
-#include <string.h>
-#include <linux/types.h>
-#include <linux/handshake.h>
-
-struct ynl_sock;
-
-extern const struct ynl_family ynl_handshake_family;
-
-/* Enums */
-const char *handshake_op_str(int op);
-const char *handshake_handler_class_str(enum handshake_handler_class value);
-const char *handshake_msg_type_str(enum handshake_msg_type value);
-const char *handshake_auth_str(enum handshake_auth value);
-
-/* Common nested types */
-struct handshake_x509 {
- struct {
- __u32 cert:1;
- __u32 privkey:1;
- } _present;
-
- __u32 cert;
- __u32 privkey;
-};
-
-/* ============== HANDSHAKE_CMD_ACCEPT ============== */
-/* HANDSHAKE_CMD_ACCEPT - do */
-struct handshake_accept_req {
- struct {
- __u32 handler_class:1;
- } _present;
-
- enum handshake_handler_class handler_class;
-};
-
-static inline struct handshake_accept_req *handshake_accept_req_alloc(void)
-{
- return calloc(1, sizeof(struct handshake_accept_req));
-}
-void handshake_accept_req_free(struct handshake_accept_req *req);
-
-static inline void
-handshake_accept_req_set_handler_class(struct handshake_accept_req *req,
- enum handshake_handler_class handler_class)
-{
- req->_present.handler_class = 1;
- req->handler_class = handler_class;
-}
-
-struct handshake_accept_rsp {
- struct {
- __u32 sockfd:1;
- __u32 message_type:1;
- __u32 timeout:1;
- __u32 auth_mode:1;
- __u32 peername_len;
- } _present;
-
- __u32 sockfd;
- enum handshake_msg_type message_type;
- __u32 timeout;
- enum handshake_auth auth_mode;
- unsigned int n_peer_identity;
- __u32 *peer_identity;
- unsigned int n_certificate;
- struct handshake_x509 *certificate;
- char *peername;
-};
-
-void handshake_accept_rsp_free(struct handshake_accept_rsp *rsp);
-
-/*
- * Handler retrieves next queued handshake request
- */
-struct handshake_accept_rsp *
-handshake_accept(struct ynl_sock *ys, struct handshake_accept_req *req);
-
-/* HANDSHAKE_CMD_ACCEPT - notify */
-struct handshake_accept_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct handshake_accept_ntf *ntf);
- struct handshake_accept_rsp obj __attribute__ ((aligned (8)));
-};
-
-void handshake_accept_ntf_free(struct handshake_accept_ntf *rsp);
-
-/* ============== HANDSHAKE_CMD_DONE ============== */
-/* HANDSHAKE_CMD_DONE - do */
-struct handshake_done_req {
- struct {
- __u32 status:1;
- __u32 sockfd:1;
- } _present;
-
- __u32 status;
- __u32 sockfd;
- unsigned int n_remote_auth;
- __u32 *remote_auth;
-};
-
-static inline struct handshake_done_req *handshake_done_req_alloc(void)
-{
- return calloc(1, sizeof(struct handshake_done_req));
-}
-void handshake_done_req_free(struct handshake_done_req *req);
-
-static inline void
-handshake_done_req_set_status(struct handshake_done_req *req, __u32 status)
-{
- req->_present.status = 1;
- req->status = status;
-}
-static inline void
-handshake_done_req_set_sockfd(struct handshake_done_req *req, __u32 sockfd)
-{
- req->_present.sockfd = 1;
- req->sockfd = sockfd;
-}
-static inline void
-__handshake_done_req_set_remote_auth(struct handshake_done_req *req,
- __u32 *remote_auth,
- unsigned int n_remote_auth)
-{
- free(req->remote_auth);
- req->remote_auth = remote_auth;
- req->n_remote_auth = n_remote_auth;
-}
-
-/*
- * Handler reports handshake completion
- */
-int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req);
-
-#endif /* _LINUX_HANDSHAKE_GEN_H */
diff --git a/tools/net/ynl/generated/netdev-user.c b/tools/net/ynl/generated/netdev-user.c
deleted file mode 100644
index 68b408ca0f7f..000000000000
--- a/tools/net/ynl/generated/netdev-user.c
+++ /dev/null
@@ -1,206 +0,0 @@
-// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/netdev.yaml */
-/* YNL-GEN user source */
-
-#include <stdlib.h>
-#include <string.h>
-#include "netdev-user.h"
-#include "ynl.h"
-#include <linux/netdev.h>
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-
-/* Enums */
-static const char * const netdev_op_strmap[] = {
- [NETDEV_CMD_DEV_GET] = "dev-get",
- [NETDEV_CMD_DEV_ADD_NTF] = "dev-add-ntf",
- [NETDEV_CMD_DEV_DEL_NTF] = "dev-del-ntf",
- [NETDEV_CMD_DEV_CHANGE_NTF] = "dev-change-ntf",
-};
-
-const char *netdev_op_str(int op)
-{
- if (op < 0 || op >= (int)MNL_ARRAY_SIZE(netdev_op_strmap))
- return NULL;
- return netdev_op_strmap[op];
-}
-
-static const char * const netdev_xdp_act_strmap[] = {
- [0] = "basic",
- [1] = "redirect",
- [2] = "ndo-xmit",
- [3] = "xsk-zerocopy",
- [4] = "hw-offload",
- [5] = "rx-sg",
- [6] = "ndo-xmit-sg",
-};
-
-const char *netdev_xdp_act_str(enum netdev_xdp_act value)
-{
- value = ffs(value) - 1;
- if (value < 0 || value >= (int)MNL_ARRAY_SIZE(netdev_xdp_act_strmap))
- return NULL;
- return netdev_xdp_act_strmap[value];
-}
-
-/* Policies */
-struct ynl_policy_attr netdev_dev_policy[NETDEV_A_DEV_MAX + 1] = {
- [NETDEV_A_DEV_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
- [NETDEV_A_DEV_PAD] = { .name = "pad", .type = YNL_PT_IGNORE, },
- [NETDEV_A_DEV_XDP_FEATURES] = { .name = "xdp-features", .type = YNL_PT_U64, },
- [NETDEV_A_DEV_XDP_ZC_MAX_SEGS] = { .name = "xdp-zc-max-segs", .type = YNL_PT_U32, },
-};
-
-struct ynl_policy_nest netdev_dev_nest = {
- .max_attr = NETDEV_A_DEV_MAX,
- .table = netdev_dev_policy,
-};
-
-/* Common nested types */
-/* ============== NETDEV_CMD_DEV_GET ============== */
-/* NETDEV_CMD_DEV_GET - do */
-void netdev_dev_get_req_free(struct netdev_dev_get_req *req)
-{
- free(req);
-}
-
-void netdev_dev_get_rsp_free(struct netdev_dev_get_rsp *rsp)
-{
- free(rsp);
-}
-
-int netdev_dev_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
-{
- struct ynl_parse_arg *yarg = data;
- struct netdev_dev_get_rsp *dst;
- const struct nlattr *attr;
-
- dst = yarg->data;
-
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- unsigned int type = mnl_attr_get_type(attr);
-
- if (type == NETDEV_A_DEV_IFINDEX) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.ifindex = 1;
- dst->ifindex = mnl_attr_get_u32(attr);
- } else if (type == NETDEV_A_DEV_XDP_FEATURES) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.xdp_features = 1;
- dst->xdp_features = mnl_attr_get_u64(attr);
- } else if (type == NETDEV_A_DEV_XDP_ZC_MAX_SEGS) {
- if (ynl_attr_validate(yarg, attr))
- return MNL_CB_ERROR;
- dst->_present.xdp_zc_max_segs = 1;
- dst->xdp_zc_max_segs = mnl_attr_get_u32(attr);
- }
- }
-
- return MNL_CB_OK;
-}
-
-struct netdev_dev_get_rsp *
-netdev_dev_get(struct ynl_sock *ys, struct netdev_dev_get_req *req)
-{
- struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
- struct netdev_dev_get_rsp *rsp;
- struct nlmsghdr *nlh;
- int err;
-
- nlh = ynl_gemsg_start_req(ys, ys->family_id, NETDEV_CMD_DEV_GET, 1);
- ys->req_policy = &netdev_dev_nest;
- yrs.yarg.rsp_policy = &netdev_dev_nest;
-
- if (req->_present.ifindex)
- mnl_attr_put_u32(nlh, NETDEV_A_DEV_IFINDEX, req->ifindex);
-
- rsp = calloc(1, sizeof(*rsp));
- yrs.yarg.data = rsp;
- yrs.cb = netdev_dev_get_rsp_parse;
- yrs.rsp_cmd = NETDEV_CMD_DEV_GET;
-
- err = ynl_exec(ys, nlh, &yrs);
- if (err < 0)
- goto err_free;
-
- return rsp;
-
-err_free:
- netdev_dev_get_rsp_free(rsp);
- return NULL;
-}
-
-/* NETDEV_CMD_DEV_GET - dump */
-void netdev_dev_get_list_free(struct netdev_dev_get_list *rsp)
-{
- struct netdev_dev_get_list *next = rsp;
-
- while ((void *)next != YNL_LIST_END) {
- rsp = next;
- next = rsp->next;
-
- free(rsp);
- }
-}
-
-struct netdev_dev_get_list *netdev_dev_get_dump(struct ynl_sock *ys)
-{
- struct ynl_dump_state yds = {};
- struct nlmsghdr *nlh;
- int err;
-
- yds.ys = ys;
- yds.alloc_sz = sizeof(struct netdev_dev_get_list);
- yds.cb = netdev_dev_get_rsp_parse;
- yds.rsp_cmd = NETDEV_CMD_DEV_GET;
- yds.rsp_policy = &netdev_dev_nest;
-
- nlh = ynl_gemsg_start_dump(ys, ys->family_id, NETDEV_CMD_DEV_GET, 1);
-
- err = ynl_exec_dump(ys, nlh, &yds);
- if (err < 0)
- goto free_list;
-
- return yds.first;
-
-free_list:
- netdev_dev_get_list_free(yds.first);
- return NULL;
-}
-
-/* NETDEV_CMD_DEV_GET - notify */
-void netdev_dev_get_ntf_free(struct netdev_dev_get_ntf *rsp)
-{
- free(rsp);
-}
-
-static const struct ynl_ntf_info netdev_ntf_info[] = {
- [NETDEV_CMD_DEV_ADD_NTF] = {
- .alloc_sz = sizeof(struct netdev_dev_get_ntf),
- .cb = netdev_dev_get_rsp_parse,
- .policy = &netdev_dev_nest,
- .free = (void *)netdev_dev_get_ntf_free,
- },
- [NETDEV_CMD_DEV_DEL_NTF] = {
- .alloc_sz = sizeof(struct netdev_dev_get_ntf),
- .cb = netdev_dev_get_rsp_parse,
- .policy = &netdev_dev_nest,
- .free = (void *)netdev_dev_get_ntf_free,
- },
- [NETDEV_CMD_DEV_CHANGE_NTF] = {
- .alloc_sz = sizeof(struct netdev_dev_get_ntf),
- .cb = netdev_dev_get_rsp_parse,
- .policy = &netdev_dev_nest,
- .free = (void *)netdev_dev_get_ntf_free,
- },
-};
-
-const struct ynl_family ynl_netdev_family = {
- .name = "netdev",
- .ntf_info = netdev_ntf_info,
- .ntf_info_size = MNL_ARRAY_SIZE(netdev_ntf_info),
-};
diff --git a/tools/net/ynl/generated/netdev-user.h b/tools/net/ynl/generated/netdev-user.h
deleted file mode 100644
index 0952d3261f4d..000000000000
--- a/tools/net/ynl/generated/netdev-user.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
-/* Do not edit directly, auto-generated from: */
-/* Documentation/netlink/specs/netdev.yaml */
-/* YNL-GEN user header */
-
-#ifndef _LINUX_NETDEV_GEN_H
-#define _LINUX_NETDEV_GEN_H
-
-#include <stdlib.h>
-#include <string.h>
-#include <linux/types.h>
-#include <linux/netdev.h>
-
-struct ynl_sock;
-
-extern const struct ynl_family ynl_netdev_family;
-
-/* Enums */
-const char *netdev_op_str(int op);
-const char *netdev_xdp_act_str(enum netdev_xdp_act value);
-
-/* Common nested types */
-/* ============== NETDEV_CMD_DEV_GET ============== */
-/* NETDEV_CMD_DEV_GET - do */
-struct netdev_dev_get_req {
- struct {
- __u32 ifindex:1;
- } _present;
-
- __u32 ifindex;
-};
-
-static inline struct netdev_dev_get_req *netdev_dev_get_req_alloc(void)
-{
- return calloc(1, sizeof(struct netdev_dev_get_req));
-}
-void netdev_dev_get_req_free(struct netdev_dev_get_req *req);
-
-static inline void
-netdev_dev_get_req_set_ifindex(struct netdev_dev_get_req *req, __u32 ifindex)
-{
- req->_present.ifindex = 1;
- req->ifindex = ifindex;
-}
-
-struct netdev_dev_get_rsp {
- struct {
- __u32 ifindex:1;
- __u32 xdp_features:1;
- __u32 xdp_zc_max_segs:1;
- } _present;
-
- __u32 ifindex;
- __u64 xdp_features;
- __u32 xdp_zc_max_segs;
-};
-
-void netdev_dev_get_rsp_free(struct netdev_dev_get_rsp *rsp);
-
-/*
- * Get / dump information about a netdev.
- */
-struct netdev_dev_get_rsp *
-netdev_dev_get(struct ynl_sock *ys, struct netdev_dev_get_req *req);
-
-/* NETDEV_CMD_DEV_GET - dump */
-struct netdev_dev_get_list {
- struct netdev_dev_get_list *next;
- struct netdev_dev_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void netdev_dev_get_list_free(struct netdev_dev_get_list *rsp);
-
-struct netdev_dev_get_list *netdev_dev_get_dump(struct ynl_sock *ys);
-
-/* NETDEV_CMD_DEV_GET - notify */
-struct netdev_dev_get_ntf {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct netdev_dev_get_ntf *ntf);
- struct netdev_dev_get_rsp obj __attribute__ ((aligned (8)));
-};
-
-void netdev_dev_get_ntf_free(struct netdev_dev_get_ntf *rsp);
-
-#endif /* _LINUX_NETDEV_GEN_H */
diff --git a/tools/net/ynl/lib/.gitignore b/tools/net/ynl/lib/.gitignore
index c18dd8d83cee..a4383358ec72 100644
--- a/tools/net/ynl/lib/.gitignore
+++ b/tools/net/ynl/lib/.gitignore
@@ -1 +1 @@
-__pycache__/
+*.d
diff --git a/tools/net/ynl/lib/Makefile b/tools/net/ynl/lib/Makefile
index d2e50fd0a52d..4b2b98704ff9 100644
--- a/tools/net/ynl/lib/Makefile
+++ b/tools/net/ynl/lib/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
CC=gcc
-CFLAGS=-std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow
+CFLAGS += -std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow
ifeq ("$(DEBUG)","1")
CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
endif
@@ -14,15 +14,17 @@ include $(wildcard *.d)
all: ynl.a
ynl.a: $(OBJS)
- ar rcs $@ $(OBJS)
+ @echo -e "\tAR $@"
+ @ar rcs $@ $(OBJS)
+
clean:
rm -f *.o *.d *~
-hardclean: clean
+distclean: clean
rm -f *.a
%.o: %.c
$(COMPILE.c) -MMD -c -o $@ $<
-.PHONY: all clean
+.PHONY: all clean distclean
.DEFAULT_GOAL=all
diff --git a/tools/net/ynl/lib/__init__.py b/tools/net/ynl/lib/__init__.py
deleted file mode 100644
index f7eaa07783e7..000000000000
--- a/tools/net/ynl/lib/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-
-from .nlspec import SpecAttr, SpecAttrSet, SpecEnumEntry, SpecEnumSet, \
- SpecFamily, SpecOperation
-from .ynl import YnlFamily, Netlink
-
-__all__ = ["SpecAttr", "SpecAttrSet", "SpecEnumEntry", "SpecEnumSet",
- "SpecFamily", "SpecOperation", "YnlFamily", "Netlink"]
diff --git a/tools/net/ynl/lib/ynl-priv.h b/tools/net/ynl/lib/ynl-priv.h
new file mode 100644
index 000000000000..ced7dce44efb
--- /dev/null
+++ b/tools/net/ynl/lib/ynl-priv.h
@@ -0,0 +1,478 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+#ifndef __YNL_C_PRIV_H
+#define __YNL_C_PRIV_H 1
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <linux/types.h>
+
+struct ynl_parse_arg;
+
+/*
+ * YNL internals / low level stuff
+ */
+
+enum ynl_policy_type {
+ YNL_PT_REJECT = 1,
+ YNL_PT_IGNORE,
+ YNL_PT_NEST,
+ YNL_PT_FLAG,
+ YNL_PT_BINARY,
+ YNL_PT_U8,
+ YNL_PT_U16,
+ YNL_PT_U32,
+ YNL_PT_U64,
+ YNL_PT_UINT,
+ YNL_PT_NUL_STR,
+ YNL_PT_BITFIELD32,
+ YNL_PT_SUBMSG,
+};
+
+enum ynl_parse_result {
+ YNL_PARSE_CB_ERROR = -1,
+ YNL_PARSE_CB_STOP = 0,
+ YNL_PARSE_CB_OK = 1,
+};
+
+#define YNL_SOCKET_BUFFER_SIZE (1 << 17)
+
+#define YNL_ARRAY_SIZE(array) (sizeof(array) ? \
+ sizeof(array) / sizeof(array[0]) : 0)
+
+typedef int (*ynl_parse_cb_t)(const struct nlmsghdr *nlh,
+ struct ynl_parse_arg *yarg);
+
+struct ynl_policy_attr {
+ enum ynl_policy_type type:8;
+ __u8 is_submsg:1;
+ __u8 is_selector:1;
+ __u16 selector_type;
+ unsigned int len;
+ const char *name;
+ const struct ynl_policy_nest *nest;
+};
+
+struct ynl_policy_nest {
+ unsigned int max_attr;
+ const struct ynl_policy_attr *table;
+};
+
+struct ynl_parse_arg {
+ struct ynl_sock *ys;
+ const struct ynl_policy_nest *rsp_policy;
+ void *data;
+};
+
+struct ynl_dump_list_type {
+ struct ynl_dump_list_type *next;
+ unsigned char data[] __attribute__((aligned(8)));
+};
+extern struct ynl_dump_list_type *YNL_LIST_END;
+
+static inline bool ynl_dump_obj_is_last(void *obj)
+{
+ unsigned long uptr = (unsigned long)obj;
+
+ uptr -= offsetof(struct ynl_dump_list_type, data);
+ return uptr == (unsigned long)YNL_LIST_END;
+}
+
+static inline void *ynl_dump_obj_next(void *obj)
+{
+ unsigned long uptr = (unsigned long)obj;
+ struct ynl_dump_list_type *list;
+
+ uptr -= offsetof(struct ynl_dump_list_type, data);
+ list = (struct ynl_dump_list_type *)uptr;
+ uptr = (unsigned long)list->next;
+ uptr += offsetof(struct ynl_dump_list_type, data);
+
+ return (void *)uptr;
+}
+
+struct ynl_ntf_base_type {
+ __u16 family;
+ __u8 cmd;
+ struct ynl_ntf_base_type *next;
+ void (*free)(struct ynl_ntf_base_type *ntf);
+ unsigned char data[] __attribute__((aligned(8)));
+};
+
+struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags);
+struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id);
+
+struct nlmsghdr *
+ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
+struct nlmsghdr *
+ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
+
+int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
+ const char *sel_name);
+
+/* YNL specific helpers used by the auto-generated code */
+
+struct ynl_req_state {
+ struct ynl_parse_arg yarg;
+ ynl_parse_cb_t cb;
+ __u32 rsp_cmd;
+};
+
+struct ynl_dump_state {
+ struct ynl_parse_arg yarg;
+ void *first;
+ struct ynl_dump_list_type *last;
+ size_t alloc_sz;
+ ynl_parse_cb_t cb;
+ __u32 rsp_cmd;
+};
+
+struct ynl_ntf_info {
+ const struct ynl_policy_nest *policy;
+ ynl_parse_cb_t cb;
+ size_t alloc_sz;
+ void (*free)(struct ynl_ntf_base_type *ntf);
+};
+
+int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
+ struct ynl_req_state *yrs);
+int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
+ struct ynl_dump_state *yds);
+
+void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
+int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
+
+/* Netlink message handling helpers */
+
+#define YNL_MSG_OVERFLOW 1
+
+static inline struct nlmsghdr *ynl_nlmsg_put_header(void *buf)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
+
+ memset(nlh, 0, sizeof(*nlh));
+ nlh->nlmsg_len = NLMSG_HDRLEN;
+
+ return nlh;
+}
+
+static inline unsigned int ynl_nlmsg_data_len(const struct nlmsghdr *nlh)
+{
+ return nlh->nlmsg_len - NLMSG_HDRLEN;
+}
+
+static inline void *ynl_nlmsg_data(const struct nlmsghdr *nlh)
+{
+ return (unsigned char *)nlh + NLMSG_HDRLEN;
+}
+
+static inline void *
+ynl_nlmsg_data_offset(const struct nlmsghdr *nlh, unsigned int offset)
+{
+ return (unsigned char *)nlh + NLMSG_HDRLEN + offset;
+}
+
+static inline void *ynl_nlmsg_end_addr(const struct nlmsghdr *nlh)
+{
+ return (char *)nlh + nlh->nlmsg_len;
+}
+
+static inline void *
+ynl_nlmsg_put_extra_header(struct nlmsghdr *nlh, unsigned int size)
+{
+ void *tail = ynl_nlmsg_end_addr(nlh);
+
+ nlh->nlmsg_len += NLMSG_ALIGN(size);
+ return tail;
+}
+
+/* Netlink attribute helpers */
+
+static inline unsigned int ynl_attr_type(const struct nlattr *attr)
+{
+ return attr->nla_type & NLA_TYPE_MASK;
+}
+
+static inline unsigned int ynl_attr_data_len(const struct nlattr *attr)
+{
+ return attr->nla_len - NLA_HDRLEN;
+}
+
+static inline void *ynl_attr_data(const struct nlattr *attr)
+{
+ return (unsigned char *)attr + NLA_HDRLEN;
+}
+
+static inline void *ynl_attr_data_end(const struct nlattr *attr)
+{
+ return (char *)ynl_attr_data(attr) + ynl_attr_data_len(attr);
+}
+
+#define ynl_attr_for_each(attr, nlh, fixed_hdr_sz) \
+ for ((attr) = ynl_attr_first(nlh, (nlh)->nlmsg_len, \
+ NLMSG_HDRLEN + fixed_hdr_sz); attr; \
+ (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr))
+
+#define ynl_attr_for_each_nested_off(attr, outer, offset) \
+ for ((attr) = ynl_attr_first(outer, outer->nla_len, \
+ sizeof(struct nlattr) + offset); \
+ attr; \
+ (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr))
+
+#define ynl_attr_for_each_nested(attr, outer) \
+ ynl_attr_for_each_nested_off(attr, outer, 0)
+
+#define ynl_attr_for_each_payload(start, len, attr) \
+ for ((attr) = ynl_attr_first(start, len, 0); attr; \
+ (attr) = ynl_attr_next(start + len, attr))
+
+static inline struct nlattr *
+ynl_attr_if_good(const void *end, struct nlattr *attr)
+{
+ if (attr + 1 > (const struct nlattr *)end)
+ return NULL;
+ if (ynl_attr_data_end(attr) > end)
+ return NULL;
+ return attr;
+}
+
+static inline struct nlattr *
+ynl_attr_next(const void *end, const struct nlattr *prev)
+{
+ struct nlattr *attr;
+
+ attr = (struct nlattr *)((char *)prev + NLA_ALIGN(prev->nla_len));
+ return ynl_attr_if_good(end, attr);
+}
+
+static inline struct nlattr *
+ynl_attr_first(const void *start, size_t len, size_t skip)
+{
+ struct nlattr *attr;
+
+ attr = (struct nlattr *)((char *)start + NLMSG_ALIGN(skip));
+ return ynl_attr_if_good((char *)start + len, attr);
+}
+
+static inline bool
+__ynl_attr_put_overflow(struct nlmsghdr *nlh, size_t size)
+{
+ bool o;
+
+ /* ynl_msg_start() stashed buffer length in nlmsg_pid. */
+ o = nlh->nlmsg_len + NLA_HDRLEN + NLMSG_ALIGN(size) > nlh->nlmsg_pid;
+ if (o)
+ /* YNL_MSG_OVERFLOW is < NLMSG_HDRLEN, all subsequent checks
+ * are guaranteed to fail.
+ */
+ nlh->nlmsg_pid = YNL_MSG_OVERFLOW;
+ return o;
+}
+
+static inline struct nlattr *
+ynl_attr_nest_start(struct nlmsghdr *nlh, unsigned int attr_type)
+{
+ struct nlattr *attr;
+
+ if (__ynl_attr_put_overflow(nlh, 0))
+ return (struct nlattr *)ynl_nlmsg_end_addr(nlh) - 1;
+
+ attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
+ attr->nla_type = attr_type | NLA_F_NESTED;
+ nlh->nlmsg_len += NLA_HDRLEN;
+
+ return attr;
+}
+
+static inline void
+ynl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *attr)
+{
+ attr->nla_len = (char *)ynl_nlmsg_end_addr(nlh) - (char *)attr;
+}
+
+static inline void
+ynl_attr_put(struct nlmsghdr *nlh, unsigned int attr_type,
+ const void *value, size_t size)
+{
+ struct nlattr *attr;
+
+ if (__ynl_attr_put_overflow(nlh, size))
+ return;
+
+ attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
+ attr->nla_type = attr_type;
+ attr->nla_len = NLA_HDRLEN + size;
+
+ memcpy(ynl_attr_data(attr), value, size);
+
+ nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
+}
+
+static inline void
+ynl_attr_put_str(struct nlmsghdr *nlh, unsigned int attr_type, const char *str)
+{
+ struct nlattr *attr;
+ size_t len;
+
+ len = strlen(str) + 1;
+ if (__ynl_attr_put_overflow(nlh, len))
+ return;
+
+ attr = (struct nlattr *)ynl_nlmsg_end_addr(nlh);
+ attr->nla_type = attr_type;
+
+ strcpy((char *)ynl_attr_data(attr), str);
+ attr->nla_len = NLA_HDRLEN + len;
+
+ nlh->nlmsg_len += NLMSG_ALIGN(attr->nla_len);
+}
+
+static inline const char *ynl_attr_get_str(const struct nlattr *attr)
+{
+ return (const char *)ynl_attr_data(attr);
+}
+
+static inline __s8 ynl_attr_get_s8(const struct nlattr *attr)
+{
+ return *(__s8 *)ynl_attr_data(attr);
+}
+
+static inline __s16 ynl_attr_get_s16(const struct nlattr *attr)
+{
+ return *(__s16 *)ynl_attr_data(attr);
+}
+
+static inline __s32 ynl_attr_get_s32(const struct nlattr *attr)
+{
+ return *(__s32 *)ynl_attr_data(attr);
+}
+
+static inline __s64 ynl_attr_get_s64(const struct nlattr *attr)
+{
+ __s64 tmp;
+
+ memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
+ return tmp;
+}
+
+static inline __u8 ynl_attr_get_u8(const struct nlattr *attr)
+{
+ return *(__u8 *)ynl_attr_data(attr);
+}
+
+static inline __u16 ynl_attr_get_u16(const struct nlattr *attr)
+{
+ return *(__u16 *)ynl_attr_data(attr);
+}
+
+static inline __u32 ynl_attr_get_u32(const struct nlattr *attr)
+{
+ return *(__u32 *)ynl_attr_data(attr);
+}
+
+static inline __u64 ynl_attr_get_u64(const struct nlattr *attr)
+{
+ __u64 tmp;
+
+ memcpy(&tmp, (unsigned char *)(attr + 1), sizeof(tmp));
+ return tmp;
+}
+
+static inline void
+ynl_attr_put_s8(struct nlmsghdr *nlh, unsigned int attr_type, __s8 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_s16(struct nlmsghdr *nlh, unsigned int attr_type, __s16 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_s32(struct nlmsghdr *nlh, unsigned int attr_type, __s32 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_s64(struct nlmsghdr *nlh, unsigned int attr_type, __s64 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_u8(struct nlmsghdr *nlh, unsigned int attr_type, __u8 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_u16(struct nlmsghdr *nlh, unsigned int attr_type, __u16 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_u32(struct nlmsghdr *nlh, unsigned int attr_type, __u32 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline void
+ynl_attr_put_u64(struct nlmsghdr *nlh, unsigned int attr_type, __u64 value)
+{
+ ynl_attr_put(nlh, attr_type, &value, sizeof(value));
+}
+
+static inline __u64 ynl_attr_get_uint(const struct nlattr *attr)
+{
+ switch (ynl_attr_data_len(attr)) {
+ case 4:
+ return ynl_attr_get_u32(attr);
+ case 8:
+ return ynl_attr_get_u64(attr);
+ default:
+ return 0;
+ }
+}
+
+static inline __s64 ynl_attr_get_sint(const struct nlattr *attr)
+{
+ switch (ynl_attr_data_len(attr)) {
+ case 4:
+ return ynl_attr_get_s32(attr);
+ case 8:
+ return ynl_attr_get_s64(attr);
+ default:
+ return 0;
+ }
+}
+
+static inline void
+ynl_attr_put_uint(struct nlmsghdr *nlh, __u16 type, __u64 data)
+{
+ if ((__u32)data == (__u64)data)
+ ynl_attr_put_u32(nlh, type, data);
+ else
+ ynl_attr_put_u64(nlh, type, data);
+}
+
+static inline void
+ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
+{
+ if ((__s32)data == (__s64)data)
+ ynl_attr_put_s32(nlh, type, data);
+ else
+ ynl_attr_put_s64(nlh, type, data);
+}
+
+int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
+ unsigned int type);
+
+static inline int ynl_attr_validate(struct ynl_parse_arg *yarg,
+ const struct nlattr *attr)
+{
+ return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr));
+}
+#endif
diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c
index 514e0d69e731..2bcd781111d7 100644
--- a/tools/net/ynl/lib/ynl.c
+++ b/tools/net/ynl/lib/ynl.c
@@ -3,10 +3,11 @@
#include <poll.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
#include <linux/types.h>
-
-#include <libmnl/libmnl.h>
#include <linux/genetlink.h>
+#include <sys/socket.h>
#include "ynl.h"
@@ -44,8 +45,39 @@
#define perr(_ys, _msg) __yerr(&(_ys)->err, errno, _msg)
/* -- Netlink boiler plate */
+static bool
+ynl_err_walk_is_sel(const struct ynl_policy_nest *policy,
+ const struct nlattr *attr)
+{
+ unsigned int type = ynl_attr_type(attr);
+
+ return policy && type <= policy->max_attr &&
+ policy->table[type].is_selector;
+}
+
+static const struct ynl_policy_nest *
+ynl_err_walk_sel_policy(const struct ynl_policy_attr *policy_attr,
+ const struct nlattr *selector)
+{
+ const struct ynl_policy_nest *policy = policy_attr->nest;
+ const char *sel;
+ unsigned int i;
+
+ if (!policy_attr->is_submsg)
+ return policy;
+
+ sel = ynl_attr_get_str(selector);
+ for (i = 0; i <= policy->max_attr; i++) {
+ if (!strcmp(sel, policy->table[i].name))
+ return policy->table[i].nest;
+ }
+
+ return NULL;
+}
+
static int
-ynl_err_walk_report_one(struct ynl_policy_nest *policy, unsigned int type,
+ynl_err_walk_report_one(const struct ynl_policy_nest *policy,
+ const struct nlattr *selector, unsigned int type,
char *str, int str_sz, int *n)
{
if (!policy) {
@@ -66,17 +98,44 @@ ynl_err_walk_report_one(struct ynl_policy_nest *policy, unsigned int type,
return 1;
}
- if (*n < str_sz)
- *n += snprintf(str, str_sz - *n,
- ".%s", policy->table[type].name);
+ if (*n < str_sz) {
+ int sz;
+
+ sz = snprintf(str, str_sz - *n,
+ ".%s", policy->table[type].name);
+ *n += sz;
+ str += sz;
+ }
+
+ if (policy->table[type].is_submsg) {
+ if (!selector) {
+ if (*n < str_sz)
+ *n += snprintf(str, str_sz, "(!selector)");
+ return 1;
+ }
+
+ if (ynl_attr_type(selector) !=
+ policy->table[type].selector_type) {
+ if (*n < str_sz)
+ *n += snprintf(str, str_sz, "(!=selector)");
+ return 1;
+ }
+
+ if (*n < str_sz)
+ *n += snprintf(str, str_sz - *n, "(%s)",
+ ynl_attr_get_str(selector));
+ }
+
return 0;
}
static int
ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
- struct ynl_policy_nest *policy, char *str, int str_sz,
- struct ynl_policy_nest **nest_pol)
+ const struct ynl_policy_nest *policy, char *str, int str_sz,
+ const struct ynl_policy_nest **nest_pol)
{
+ const struct ynl_policy_nest *next_pol;
+ const struct nlattr *selector = NULL;
unsigned int astart_off, aend_off;
const struct nlattr *attr;
unsigned int data_len;
@@ -92,9 +151,13 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
data_len = end - start;
- mnl_attr_for_each_payload(start, data_len) {
+ ynl_attr_for_each_payload(start, data_len, attr) {
astart_off = (char *)attr - (char *)start;
- aend_off = astart_off + mnl_attr_get_payload_len(attr);
+ aend_off = (char *)ynl_attr_data_end(attr) - (char *)start;
+
+ if (ynl_err_walk_is_sel(policy, attr))
+ selector = attr;
+
if (aend_off <= off)
continue;
@@ -106,28 +169,32 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
off -= astart_off;
- type = mnl_attr_get_type(attr);
+ type = ynl_attr_type(attr);
+
+ if (ynl_err_walk_report_one(policy, selector, type, str, str_sz, &n))
+ return n;
- if (ynl_err_walk_report_one(policy, type, str, str_sz, &n))
+ next_pol = ynl_err_walk_sel_policy(&policy->table[type], selector);
+ if (!next_pol)
return n;
if (!off) {
if (nest_pol)
- *nest_pol = policy->table[type].nest;
+ *nest_pol = next_pol;
return n;
}
- if (!policy->table[type].nest) {
+ if (!next_pol) {
if (n < str_sz)
n += snprintf(str, str_sz, "!nest");
return n;
}
off -= sizeof(struct nlattr);
- start = mnl_attr_get_payload(attr);
- end = start + mnl_attr_get_payload_len(attr);
+ start = ynl_attr_data(attr);
+ end = start + ynl_attr_data_len(attr);
- return n + ynl_err_walk(ys, start, end, off, policy->table[type].nest,
+ return n + ynl_err_walk(ys, start, end, off, next_pol,
&str[n], str_sz - n, nest_pol);
}
@@ -145,14 +212,16 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
const struct nlattr *attr;
const char *str = NULL;
- if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
- return MNL_CB_OK;
+ if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) {
+ yerr_msg(ys, "%s", strerror(ys->err.code));
+ return YNL_PARSE_CB_OK;
+ }
- mnl_attr_for_each(attr, nlh, hlen) {
+ ynl_attr_for_each(attr, nlh, hlen) {
unsigned int len, type;
- len = mnl_attr_get_payload_len(attr);
- type = mnl_attr_get_type(attr);
+ len = ynl_attr_data_len(attr);
+ type = ynl_attr_type(attr);
if (type > NLMSGERR_ATTR_MAX)
continue;
@@ -164,12 +233,12 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
case NLMSGERR_ATTR_MISS_TYPE:
case NLMSGERR_ATTR_MISS_NEST:
if (len != sizeof(__u32))
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
break;
case NLMSGERR_ATTR_MSG:
- str = mnl_attr_get_payload(attr);
+ str = ynl_attr_get_str(attr);
if (str[len - 1])
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
break;
default:
break;
@@ -183,18 +252,17 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
unsigned int n, off;
void *start, *end;
- ys->err.attr_offs = mnl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
+ ys->err.attr_offs = ynl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
n = snprintf(bad_attr, sizeof(bad_attr), "%sbad attribute: ",
str ? " (" : "");
- start = mnl_nlmsg_get_payload_offset(ys->nlh,
- sizeof(struct genlmsghdr));
- end = mnl_nlmsg_get_payload_tail(ys->nlh);
+ start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
+ end = ynl_nlmsg_end_addr(ys->nlh);
off = ys->err.attr_offs;
off -= sizeof(struct nlmsghdr);
- off -= sizeof(struct genlmsghdr);
+ off -= ys->req_hdr_len;
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
&bad_attr[n], sizeof(bad_attr) - n, NULL);
@@ -204,25 +272,24 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
bad_attr[n] = '\0';
}
if (tb[NLMSGERR_ATTR_MISS_TYPE]) {
- struct ynl_policy_nest *nest_pol = NULL;
+ const struct ynl_policy_nest *nest_pol = NULL;
unsigned int n, off, type;
void *start, *end;
int n2;
- type = mnl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_TYPE]);
+ type = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_TYPE]);
n = snprintf(miss_attr, sizeof(miss_attr), "%smissing attribute: ",
bad_attr[0] ? ", " : (str ? " (" : ""));
- start = mnl_nlmsg_get_payload_offset(ys->nlh,
- sizeof(struct genlmsghdr));
- end = mnl_nlmsg_get_payload_tail(ys->nlh);
+ start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
+ end = ynl_nlmsg_end_addr(ys->nlh);
nest_pol = ys->req_policy;
if (tb[NLMSGERR_ATTR_MISS_NEST]) {
- off = mnl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
+ off = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
off -= sizeof(struct nlmsghdr);
- off -= sizeof(struct genlmsghdr);
+ off -= ys->req_hdr_len;
n += ynl_err_walk(ys, start, end, off, ys->req_policy,
&miss_attr[n], sizeof(miss_attr) - n,
@@ -230,7 +297,7 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
}
n2 = 0;
- ynl_err_walk_report_one(nest_pol, type, &miss_attr[n],
+ ynl_err_walk_report_one(nest_pol, NULL, type, &miss_attr[n],
sizeof(miss_attr) - n, &n2);
n += n2;
@@ -249,14 +316,16 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
yerr_msg(ys, "Kernel %s: %s%s",
ys->err.code ? "error" : "warning",
bad_attr, miss_attr);
+ else
+ yerr_msg(ys, "%s", strerror(ys->err.code));
- return MNL_CB_OK;
+ return YNL_PARSE_CB_OK;
}
-static int ynl_cb_error(const struct nlmsghdr *nlh, void *data)
+static int
+ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
- struct ynl_parse_arg *yarg = data;
+ const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
unsigned int hlen;
int code;
@@ -266,16 +335,15 @@ static int ynl_cb_error(const struct nlmsghdr *nlh, void *data)
hlen = sizeof(*err);
if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
- hlen += mnl_nlmsg_get_payload_len(&err->msg);
+ hlen += ynl_nlmsg_data_len(&err->msg);
ynl_ext_ack_check(yarg->ys, nlh, hlen);
- return code ? MNL_CB_ERROR : MNL_CB_STOP;
+ return code ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_STOP;
}
-static int ynl_cb_done(const struct nlmsghdr *nlh, void *data)
+static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- struct ynl_parse_arg *yarg = data;
int err;
err = *(int *)NLMSG_DATA(nlh);
@@ -285,34 +353,22 @@ static int ynl_cb_done(const struct nlmsghdr *nlh, void *data)
ynl_ext_ack_check(yarg->ys, nlh, sizeof(int));
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
}
- return MNL_CB_STOP;
+ return YNL_PARSE_CB_STOP;
}
-static int ynl_cb_noop(const struct nlmsghdr *nlh, void *data)
-{
- return MNL_CB_OK;
-}
-
-mnl_cb_t ynl_cb_array[NLMSG_MIN_TYPE] = {
- [NLMSG_NOOP] = ynl_cb_noop,
- [NLMSG_ERROR] = ynl_cb_error,
- [NLMSG_DONE] = ynl_cb_done,
- [NLMSG_OVERRUN] = ynl_cb_noop,
-};
-
/* Attribute validation */
-int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
+int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
+ unsigned int type)
{
- struct ynl_policy_attr *policy;
- unsigned int type, len;
+ const struct ynl_policy_attr *policy;
unsigned char *data;
+ unsigned int len;
- data = mnl_attr_get_payload(attr);
- len = mnl_attr_get_payload_len(attr);
- type = mnl_attr_get_type(attr);
+ data = ynl_attr_data(attr);
+ len = ynl_attr_data_len(attr);
if (type > yarg->rsp_policy->max_attr) {
yerr(yarg->ys, YNL_ERROR_INTERNAL,
"Internal error, validating unknown attribute");
@@ -352,6 +408,12 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
"Invalid attribute (u64 %s)", policy->name);
return -1;
+ case YNL_PT_UINT:
+ if (len == sizeof(__u32) || len == sizeof(__u64))
+ break;
+ yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
+ "Invalid attribute (uint %s)", policy->name);
+ return -1;
case YNL_PT_FLAG:
/* Let flags grow into real attrs, why not.. */
break;
@@ -368,11 +430,17 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
"Invalid attribute (binary %s)", policy->name);
return -1;
case YNL_PT_NUL_STR:
- if ((!policy->len || len <= policy->len) && !data[len - 1])
+ if (len && (!policy->len || len <= policy->len) && !data[len - 1])
break;
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
"Invalid attribute (string %s)", policy->name);
return -1;
+ case YNL_PT_BITFIELD32:
+ if (len == sizeof(struct nla_bitfield32))
+ break;
+ yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
+ "Invalid attribute (bitfield32 %s)", policy->name);
+ return -1;
default:
yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
"Invalid attribute (unknown %s)", policy->name);
@@ -382,6 +450,15 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
return 0;
}
+int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
+ const char *sel_name)
+{
+ yerr(yarg->ys, YNL_ERROR_SUBMSG_KEY,
+ "Parsing error: Sub-message key not set (msg %s, key %s)",
+ field_name, sel_name);
+ return YNL_PARSE_CB_ERROR;
+}
+
/* Generic code */
static void ynl_err_reset(struct ynl_sock *ys)
@@ -397,14 +474,38 @@ struct nlmsghdr *ynl_msg_start(struct ynl_sock *ys, __u32 id, __u16 flags)
ynl_err_reset(ys);
- nlh = ys->nlh = mnl_nlmsg_put_header(ys->tx_buf);
+ nlh = ys->nlh = ynl_nlmsg_put_header(ys->tx_buf);
nlh->nlmsg_type = id;
nlh->nlmsg_flags = flags;
nlh->nlmsg_seq = ++ys->seq;
+ /* This is a local YNL hack for length checking, we put the buffer
+ * length in nlmsg_pid, since messages sent to the kernel always use
+ * PID 0. Message needs to be terminated with ynl_msg_end().
+ */
+ nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE;
+
return nlh;
}
+static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh)
+{
+ /* We stash buffer length in nlmsg_pid. */
+ if (nlh->nlmsg_pid == 0) {
+ yerr(ys, YNL_ERROR_INPUT_INVALID,
+ "Unknown input buffer length");
+ return -EINVAL;
+ }
+ if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) {
+ yerr(ys, YNL_ERROR_INPUT_TOO_BIG,
+ "Constructed message longer than internal buffer");
+ return -EMSGSIZE;
+ }
+
+ nlh->nlmsg_pid = 0;
+ return 0;
+}
+
struct nlmsghdr *
ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
__u8 cmd, __u8 version)
@@ -419,20 +520,20 @@ ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
gehdr.cmd = cmd;
gehdr.version = version;
- data = mnl_nlmsg_put_extra_header(nlh, sizeof(gehdr));
+ data = ynl_nlmsg_put_extra_header(nlh, sizeof(gehdr));
memcpy(data, &gehdr, sizeof(gehdr));
return nlh;
}
-void ynl_msg_start_req(struct ynl_sock *ys, __u32 id)
+struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags)
{
- ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK);
+ return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | flags);
}
-void ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)
+struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)
{
- ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
+ return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
}
struct nlmsghdr *
@@ -448,31 +549,85 @@ ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
cmd, version);
}
-int ynl_recv_ack(struct ynl_sock *ys, int ret)
+static int ynl_cb_null(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- if (!ret) {
- yerr(ys, YNL_ERROR_EXPECT_ACK,
- "Expecting an ACK but nothing received");
- return -1;
+ yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,
+ "Received a message when none were expected");
+
+ return YNL_PARSE_CB_ERROR;
+}
+
+static int
+__ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb, int flags)
+{
+ struct ynl_sock *ys = yarg->ys;
+ const struct nlmsghdr *nlh;
+ ssize_t len, rem;
+ int ret;
+
+ len = recv(ys->socket, ys->rx_buf, YNL_SOCKET_BUFFER_SIZE, flags);
+ if (len < 0) {
+ if (flags & MSG_DONTWAIT && errno == EAGAIN)
+ return YNL_PARSE_CB_STOP;
+ return len;
}
- ret = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);
- if (ret < 0) {
- perr(ys, "Socket receive failed");
- return ret;
+ ret = YNL_PARSE_CB_STOP;
+ for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) {
+ nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem];
+ if (!NLMSG_OK(nlh, rem)) {
+ yerr(yarg->ys, YNL_ERROR_INV_RESP,
+ "Invalid message or trailing data in the response.");
+ return YNL_PARSE_CB_ERROR;
+ }
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
+ /* TODO: handle this better */
+ yerr(yarg->ys, YNL_ERROR_DUMP_INTER,
+ "Dump interrupted / inconsistent, please retry.");
+ return YNL_PARSE_CB_ERROR;
+ }
+
+ switch (nlh->nlmsg_type) {
+ case 0:
+ yerr(yarg->ys, YNL_ERROR_INV_RESP,
+ "Invalid message type in the response.");
+ return YNL_PARSE_CB_ERROR;
+ case NLMSG_NOOP:
+ case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1:
+ ret = YNL_PARSE_CB_OK;
+ break;
+ case NLMSG_ERROR:
+ ret = ynl_cb_error(nlh, yarg);
+ break;
+ case NLMSG_DONE:
+ ret = ynl_cb_done(nlh, yarg);
+ break;
+ default:
+ ret = cb(nlh, yarg);
+ break;
+ }
}
- return mnl_cb_run(ys->rx_buf, ret, ys->seq, ys->portid,
- ynl_cb_null, ys);
+
+ return ret;
}
-int ynl_cb_null(const struct nlmsghdr *nlh, void *data)
+static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb)
{
- struct ynl_parse_arg *yarg = data;
+ return __ynl_sock_read_msgs(yarg, cb, 0);
+}
- yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,
- "Received a message when none were expected");
+static int ynl_recv_ack(struct ynl_sock *ys, int ret)
+{
+ struct ynl_parse_arg yarg = { .ys = ys, };
+
+ if (!ret) {
+ yerr(ys, YNL_ERROR_EXPECT_ACK,
+ "Expecting an ACK but nothing received");
+ return -1;
+ }
- return MNL_CB_ERROR;
+ return ynl_sock_read_msgs(&yarg, ynl_cb_null);
}
/* Init/fini and genetlink boiler plate */
@@ -482,7 +637,7 @@ ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
const struct nlattr *entry, *attr;
unsigned int i;
- mnl_attr_for_each_nested(attr, mcasts)
+ ynl_attr_for_each_nested(attr, mcasts)
ys->n_mcast_groups++;
if (!ys->n_mcast_groups)
@@ -491,54 +646,55 @@ ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
ys->mcast_groups = calloc(ys->n_mcast_groups,
sizeof(*ys->mcast_groups));
if (!ys->mcast_groups)
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
i = 0;
- mnl_attr_for_each_nested(entry, mcasts) {
- mnl_attr_for_each_nested(attr, entry) {
- if (mnl_attr_get_type(attr) == CTRL_ATTR_MCAST_GRP_ID)
- ys->mcast_groups[i].id = mnl_attr_get_u32(attr);
- if (mnl_attr_get_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) {
+ ynl_attr_for_each_nested(entry, mcasts) {
+ ynl_attr_for_each_nested(attr, entry) {
+ if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_ID)
+ ys->mcast_groups[i].id = ynl_attr_get_u32(attr);
+ if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) {
strncpy(ys->mcast_groups[i].name,
- mnl_attr_get_str(attr),
+ ynl_attr_get_str(attr),
GENL_NAMSIZ - 1);
ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0;
}
}
+ i++;
}
return 0;
}
-static int ynl_get_family_info_cb(const struct nlmsghdr *nlh, void *data)
+static int
+ynl_get_family_info_cb(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- struct ynl_parse_arg *yarg = data;
struct ynl_sock *ys = yarg->ys;
const struct nlattr *attr;
bool found_id = true;
- mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
- if (mnl_attr_get_type(attr) == CTRL_ATTR_MCAST_GROUPS)
+ ynl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
+ if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GROUPS)
if (ynl_get_family_info_mcast(ys, attr))
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
- if (mnl_attr_get_type(attr) != CTRL_ATTR_FAMILY_ID)
+ if (ynl_attr_type(attr) != CTRL_ATTR_FAMILY_ID)
continue;
- if (mnl_attr_get_payload_len(attr) != sizeof(__u16)) {
+ if (ynl_attr_data_len(attr) != sizeof(__u16)) {
yerr(ys, YNL_ERROR_ATTR_INVALID, "Invalid family ID");
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
}
- ys->family_id = mnl_attr_get_u16(attr);
+ ys->family_id = ynl_attr_get_u16(attr);
found_id = true;
}
if (!found_id) {
yerr(ys, YNL_ERROR_ATTR_MISSING, "Family ID missing");
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
}
- return MNL_CB_OK;
+ return YNL_PARSE_CB_OK;
}
static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name)
@@ -548,68 +704,91 @@ static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name)
int err;
nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1);
- mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
+ ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
+
+ err = ynl_msg_end(ys, nlh);
+ if (err < 0)
+ return err;
- err = mnl_socket_sendto(ys->sock, nlh, nlh->nlmsg_len);
+ err = send(ys->socket, nlh, nlh->nlmsg_len, 0);
if (err < 0) {
perr(ys, "failed to request socket family info");
return err;
}
- err = mnl_socket_recvfrom(ys->sock, ys->rx_buf, MNL_SOCKET_BUFFER_SIZE);
- if (err <= 0) {
- perr(ys, "failed to receive the socket family info");
+ err = ynl_sock_read_msgs(&yarg, ynl_get_family_info_cb);
+ if (err < 0) {
+ free(ys->mcast_groups);
+ perr(ys, "failed to receive the socket family info - no such family?");
return err;
}
- err = mnl_cb_run2(ys->rx_buf, err, ys->seq, ys->portid,
- ynl_get_family_info_cb, &yarg,
- ynl_cb_array, ARRAY_SIZE(ynl_cb_array));
+
+ err = ynl_recv_ack(ys, err);
if (err < 0) {
free(ys->mcast_groups);
- perr(ys, "failed to receive the socket family info - no such family?");
return err;
}
- return ynl_recv_ack(ys, err);
+ return 0;
}
struct ynl_sock *
ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
{
+ struct sockaddr_nl addr;
struct ynl_sock *ys;
+ socklen_t addrlen;
+ int sock_type;
int one = 1;
- ys = malloc(sizeof(*ys) + 2 * MNL_SOCKET_BUFFER_SIZE);
+ ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE);
if (!ys)
return NULL;
memset(ys, 0, sizeof(*ys));
ys->family = yf;
ys->tx_buf = &ys->raw_buf[0];
- ys->rx_buf = &ys->raw_buf[MNL_SOCKET_BUFFER_SIZE];
+ ys->rx_buf = &ys->raw_buf[YNL_SOCKET_BUFFER_SIZE];
ys->ntf_last_next = &ys->ntf_first;
- ys->sock = mnl_socket_open(NETLINK_GENERIC);
- if (!ys->sock) {
+ sock_type = yf->is_classic ? yf->classic_id : NETLINK_GENERIC;
+
+ ys->socket = socket(AF_NETLINK, SOCK_RAW, sock_type);
+ if (ys->socket < 0) {
__perr(yse, "failed to create a netlink socket");
goto err_free_sock;
}
- if (mnl_socket_setsockopt(ys->sock, NETLINK_CAP_ACK,
- &one, sizeof(one))) {
+ if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_CAP_ACK,
+ &one, sizeof(one))) {
__perr(yse, "failed to enable netlink ACK");
goto err_close_sock;
}
- if (mnl_socket_setsockopt(ys->sock, NETLINK_EXT_ACK,
- &one, sizeof(one))) {
+ if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_EXT_ACK,
+ &one, sizeof(one))) {
__perr(yse, "failed to enable netlink ext ACK");
goto err_close_sock;
}
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ if (bind(ys->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ __perr(yse, "unable to bind to a socket address");
+ goto err_close_sock;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addrlen = sizeof(addr);
+ if (getsockname(ys->socket, (struct sockaddr *)&addr, &addrlen) < 0) {
+ __perr(yse, "unable to read socket address");
+ goto err_close_sock;
+ }
+ ys->portid = addr.nl_pid;
ys->seq = random();
- ys->portid = mnl_socket_get_portid(ys->sock);
- if (ynl_sock_read_family(ys, yf->name)) {
+ if (yf->is_classic) {
+ ys->family_id = yf->classic_id;
+ } else if (ynl_sock_read_family(ys, yf->name)) {
if (yse)
memcpy(yse, &ys->err, sizeof(*yse));
goto err_close_sock;
@@ -618,7 +797,7 @@ ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
return ys;
err_close_sock:
- mnl_socket_close(ys->sock);
+ close(ys->socket);
err_free_sock:
free(ys);
return NULL;
@@ -628,7 +807,7 @@ void ynl_sock_destroy(struct ynl_sock *ys)
{
struct ynl_ntf_base_type *ntf;
- mnl_socket_close(ys->sock);
+ close(ys->socket);
while ((ntf = ynl_ntf_dequeue(ys)))
ynl_ntf_free(ntf);
free(ys->mcast_groups);
@@ -655,9 +834,9 @@ int ynl_subscribe(struct ynl_sock *ys, const char *grp_name)
return -1;
}
- err = mnl_socket_setsockopt(ys->sock, NETLINK_ADD_MEMBERSHIP,
- &ys->mcast_groups[i].id,
- sizeof(ys->mcast_groups[i].id));
+ err = setsockopt(ys->socket, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+ &ys->mcast_groups[i].id,
+ sizeof(ys->mcast_groups[i].id));
if (err < 0) {
perr(ys, "Subscribing to multicast group failed");
return -1;
@@ -668,7 +847,7 @@ int ynl_subscribe(struct ynl_sock *ys, const char *grp_name)
int ynl_socket_get_fd(struct ynl_sock *ys)
{
- return mnl_socket_get_fd(ys->sock);
+ return ys->socket;
}
struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys)
@@ -691,15 +870,23 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
struct ynl_parse_arg yarg = { .ys = ys, };
const struct ynl_ntf_info *info;
struct ynl_ntf_base_type *rsp;
- struct genlmsghdr *gehdr;
+ __u32 cmd;
int ret;
- gehdr = mnl_nlmsg_get_payload(nlh);
- if (gehdr->cmd >= ys->family->ntf_info_size)
- return MNL_CB_ERROR;
- info = &ys->family->ntf_info[gehdr->cmd];
+ if (ys->family->is_classic) {
+ cmd = nlh->nlmsg_type;
+ } else {
+ struct genlmsghdr *gehdr;
+
+ gehdr = ynl_nlmsg_data(nlh);
+ cmd = gehdr->cmd;
+ }
+
+ if (cmd >= ys->family->ntf_info_size)
+ return YNL_PARSE_CB_ERROR;
+ info = &ys->family->ntf_info[cmd];
if (!info->cb)
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
rsp = calloc(1, info->alloc_sz);
rsp->free = info->free;
@@ -707,52 +894,36 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
yarg.rsp_policy = info->policy;
ret = info->cb(nlh, &yarg);
- if (ret <= MNL_CB_STOP)
+ if (ret <= YNL_PARSE_CB_STOP)
goto err_free;
rsp->family = nlh->nlmsg_type;
- rsp->cmd = gehdr->cmd;
+ rsp->cmd = cmd;
*ys->ntf_last_next = rsp;
ys->ntf_last_next = &rsp->next;
- return MNL_CB_OK;
+ return YNL_PARSE_CB_OK;
err_free:
info->free(rsp);
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
}
-static int ynl_ntf_trampoline(const struct nlmsghdr *nlh, void *data)
+static int
+ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- return ynl_ntf_parse((struct ynl_sock *)data, nlh);
+ return ynl_ntf_parse(yarg->ys, nlh);
}
int ynl_ntf_check(struct ynl_sock *ys)
{
- ssize_t len;
+ struct ynl_parse_arg yarg = { .ys = ys, };
int err;
do {
- /* libmnl doesn't let us pass flags to the recv to make
- * it non-blocking so we need to poll() or peek() :|
- */
- struct pollfd pfd = { };
-
- pfd.fd = mnl_socket_get_fd(ys->sock);
- pfd.events = POLLIN;
- err = poll(&pfd, 1, 1);
- if (err < 1)
- return err;
-
- len = mnl_socket_recvfrom(ys->sock, ys->rx_buf,
- MNL_SOCKET_BUFFER_SIZE);
- if (len < 0)
- return len;
-
- err = mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,
- ynl_ntf_trampoline, ys,
- ynl_cb_array, NLMSG_MIN_TYPE);
+ err = __ynl_sock_read_msgs(&yarg, ynl_ntf_trampoline,
+ MSG_DONTWAIT);
if (err < 0)
return err;
} while (err > 0);
@@ -773,35 +944,41 @@ void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd)
int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg)
{
yerr(yarg->ys, YNL_ERROR_INV_RESP, "Error parsing response: %s", msg);
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
}
static int
ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
{
- struct genlmsghdr *gehdr;
+ if (ys->family->is_classic) {
+ if (nlh->nlmsg_type != rsp_cmd)
+ return ynl_ntf_parse(ys, nlh);
+ } else {
+ struct genlmsghdr *gehdr;
+
+ if (ynl_nlmsg_data_len(nlh) < sizeof(*gehdr)) {
+ yerr(ys, YNL_ERROR_INV_RESP,
+ "Kernel responded with truncated message");
+ return -1;
+ }
- if (mnl_nlmsg_get_payload_len(nlh) < sizeof(*gehdr)) {
- yerr(ys, YNL_ERROR_INV_RESP,
- "Kernel responded with truncated message");
- return -1;
+ gehdr = ynl_nlmsg_data(nlh);
+ if (gehdr->cmd != rsp_cmd)
+ return ynl_ntf_parse(ys, nlh);
}
- gehdr = mnl_nlmsg_get_payload(nlh);
- if (gehdr->cmd != rsp_cmd)
- return ynl_ntf_parse(ys, nlh);
-
return 0;
}
-static int ynl_req_trampoline(const struct nlmsghdr *nlh, void *data)
+static
+int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- struct ynl_req_state *yrs = data;
+ struct ynl_req_state *yrs = (void *)yarg;
int ret;
ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd);
if (ret)
- return ret < 0 ? MNL_CB_ERROR : MNL_CB_OK;
+ return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
return yrs->cb(nlh, &yrs->yarg);
}
@@ -809,43 +986,38 @@ static int ynl_req_trampoline(const struct nlmsghdr *nlh, void *data)
int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
struct ynl_req_state *yrs)
{
- ssize_t len;
int err;
- err = mnl_socket_sendto(ys->sock, req_nlh, req_nlh->nlmsg_len);
+ err = ynl_msg_end(ys, req_nlh);
+ if (err < 0)
+ return err;
+
+ err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
if (err < 0)
return err;
do {
- len = mnl_socket_recvfrom(ys->sock, ys->rx_buf,
- MNL_SOCKET_BUFFER_SIZE);
- if (len < 0)
- return len;
-
- err = mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,
- ynl_req_trampoline, yrs,
- ynl_cb_array, NLMSG_MIN_TYPE);
- if (err < 0)
- return err;
+ err = ynl_sock_read_msgs(&yrs->yarg, ynl_req_trampoline);
} while (err > 0);
- return 0;
+ return err;
}
-static int ynl_dump_trampoline(const struct nlmsghdr *nlh, void *data)
+static int
+ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
{
- struct ynl_dump_state *ds = data;
+ struct ynl_dump_state *ds = (void *)data;
struct ynl_dump_list_type *obj;
struct ynl_parse_arg yarg = {};
int ret;
- ret = ynl_check_alien(ds->ys, nlh, ds->rsp_cmd);
+ ret = ynl_check_alien(ds->yarg.ys, nlh, ds->rsp_cmd);
if (ret)
- return ret < 0 ? MNL_CB_ERROR : MNL_CB_OK;
+ return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
obj = calloc(1, ds->alloc_sz);
if (!obj)
- return MNL_CB_ERROR;
+ return YNL_PARSE_CB_ERROR;
if (!ds->first)
ds->first = obj;
@@ -853,8 +1025,7 @@ static int ynl_dump_trampoline(const struct nlmsghdr *nlh, void *data)
ds->last->next = obj;
ds->last = obj;
- yarg.ys = ds->ys;
- yarg.rsp_policy = ds->rsp_policy;
+ yarg = ds->yarg;
yarg.data = &obj->data;
return ds->cb(nlh, &yarg);
@@ -872,22 +1043,18 @@ static void *ynl_dump_end(struct ynl_dump_state *ds)
int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
struct ynl_dump_state *yds)
{
- ssize_t len;
int err;
- err = mnl_socket_sendto(ys->sock, req_nlh, req_nlh->nlmsg_len);
+ err = ynl_msg_end(ys, req_nlh);
if (err < 0)
return err;
- do {
- len = mnl_socket_recvfrom(ys->sock, ys->rx_buf,
- MNL_SOCKET_BUFFER_SIZE);
- if (len < 0)
- goto err_close_list;
+ err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
+ if (err < 0)
+ return err;
- err = mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,
- ynl_dump_trampoline, yds,
- ynl_cb_array, NLMSG_MIN_TYPE);
+ do {
+ err = ynl_sock_read_msgs(&yds->yarg, ynl_dump_trampoline);
if (err < 0)
goto err_close_list;
} while (err > 0);
diff --git a/tools/net/ynl/lib/ynl.h b/tools/net/ynl/lib/ynl.h
index 9eafa3552c16..db7c0591a63f 100644
--- a/tools/net/ynl/lib/ynl.h
+++ b/tools/net/ynl/lib/ynl.h
@@ -2,26 +2,18 @@
#ifndef __YNL_C_H
#define __YNL_C_H 1
+#include <stdbool.h>
#include <stddef.h>
-#include <libmnl/libmnl.h>
#include <linux/genetlink.h>
#include <linux/types.h>
-struct mnl_socket;
-struct nlmsghdr;
-
-/*
- * User facing code
- */
-
-struct ynl_ntf_base_type;
-struct ynl_ntf_info;
-struct ynl_sock;
+#include "ynl-priv.h"
enum ynl_error_code {
YNL_ERROR_NONE = 0,
__YNL_ERRNO_END = 4096,
YNL_ERROR_INTERNAL,
+ YNL_ERROR_DUMP_INTER,
YNL_ERROR_EXPECT_ACK,
YNL_ERROR_EXPECT_MSG,
YNL_ERROR_UNEXPECT_MSG,
@@ -29,6 +21,9 @@ enum ynl_error_code {
YNL_ERROR_ATTR_INVALID,
YNL_ERROR_UNKNOWN_NTF,
YNL_ERROR_INV_RESP,
+ YNL_ERROR_INPUT_INVALID,
+ YNL_ERROR_INPUT_TOO_BIG,
+ YNL_ERROR_SUBMSG_KEY,
};
/**
@@ -54,6 +49,9 @@ struct ynl_error {
struct ynl_family {
/* private: */
const char *name;
+ size_t hdr_len;
+ bool is_classic;
+ __u16 classic_id;
const struct ynl_ntf_info *ntf_info;
unsigned int ntf_info_size;
};
@@ -67,7 +65,7 @@ struct ynl_sock {
/* private: */
const struct ynl_family *family;
- struct mnl_socket *sock;
+ int socket;
__u32 seq;
__u32 portid;
__u16 family_id;
@@ -82,12 +80,26 @@ struct ynl_sock {
struct ynl_ntf_base_type **ntf_last_next;
struct nlmsghdr *nlh;
- struct ynl_policy_nest *req_policy;
+ const struct ynl_policy_nest *req_policy;
+ size_t req_hdr_len;
unsigned char *tx_buf;
unsigned char *rx_buf;
unsigned char raw_buf[];
};
+/**
+ * struct ynl_string - parsed individual string
+ * @len: length of the string (excluding terminating character)
+ * @str: value of the string
+ *
+ * Parsed and nul-terminated string. This struct is only used for arrays of
+ * strings. Non-array string members are placed directly in respective types.
+ */
+struct ynl_string {
+ unsigned int len;
+ char str[];
+};
+
struct ynl_sock *
ynl_sock_create(const struct ynl_family *yf, struct ynl_error *e);
void ynl_sock_destroy(struct ynl_sock *ys);
@@ -97,6 +109,18 @@ void ynl_sock_destroy(struct ynl_sock *ys);
!ynl_dump_obj_is_last(iter); \
iter = ynl_dump_obj_next(iter))
+/**
+ * ynl_dump_empty() - does the dump have no entries
+ * @dump: pointer to the dump list, as returned by a dump call
+ *
+ * Check if the dump is empty, i.e. contains no objects.
+ * Dump calls return NULL on error, and terminator element if empty.
+ */
+static inline bool ynl_dump_empty(void *dump)
+{
+ return dump == (void *)YNL_LIST_END;
+}
+
int ynl_subscribe(struct ynl_sock *ys, const char *grp_name);
int ynl_socket_get_fd(struct ynl_sock *ys);
int ynl_ntf_check(struct ynl_sock *ys);
@@ -116,122 +140,4 @@ static inline bool ynl_has_ntf(struct ynl_sock *ys)
struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys);
void ynl_ntf_free(struct ynl_ntf_base_type *ntf);
-
-/*
- * YNL internals / low level stuff
- */
-
-/* Generic mnl helper code */
-
-enum ynl_policy_type {
- YNL_PT_REJECT = 1,
- YNL_PT_IGNORE,
- YNL_PT_NEST,
- YNL_PT_FLAG,
- YNL_PT_BINARY,
- YNL_PT_U8,
- YNL_PT_U16,
- YNL_PT_U32,
- YNL_PT_U64,
- YNL_PT_NUL_STR,
-};
-
-struct ynl_policy_attr {
- enum ynl_policy_type type;
- unsigned int len;
- const char *name;
- struct ynl_policy_nest *nest;
-};
-
-struct ynl_policy_nest {
- unsigned int max_attr;
- struct ynl_policy_attr *table;
-};
-
-struct ynl_parse_arg {
- struct ynl_sock *ys;
- struct ynl_policy_nest *rsp_policy;
- void *data;
-};
-
-struct ynl_dump_list_type {
- struct ynl_dump_list_type *next;
- unsigned char data[] __attribute__ ((aligned (8)));
-};
-extern struct ynl_dump_list_type *YNL_LIST_END;
-
-static inline bool ynl_dump_obj_is_last(void *obj)
-{
- unsigned long uptr = (unsigned long)obj;
-
- uptr -= offsetof(struct ynl_dump_list_type, data);
- return uptr == (unsigned long)YNL_LIST_END;
-}
-
-static inline void *ynl_dump_obj_next(void *obj)
-{
- unsigned long uptr = (unsigned long)obj;
- struct ynl_dump_list_type *list;
-
- uptr -= offsetof(struct ynl_dump_list_type, data);
- list = (void *)uptr;
- uptr = (unsigned long)list->next;
- uptr += offsetof(struct ynl_dump_list_type, data);
-
- return (void *)uptr;
-}
-
-struct ynl_ntf_base_type {
- __u16 family;
- __u8 cmd;
- struct ynl_ntf_base_type *next;
- void (*free)(struct ynl_ntf_base_type *ntf);
- unsigned char data[] __attribute__ ((aligned (8)));
-};
-
-extern mnl_cb_t ynl_cb_array[NLMSG_MIN_TYPE];
-
-struct nlmsghdr *
-ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
-struct nlmsghdr *
-ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
-
-int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr);
-
-int ynl_recv_ack(struct ynl_sock *ys, int ret);
-int ynl_cb_null(const struct nlmsghdr *nlh, void *data);
-
-/* YNL specific helpers used by the auto-generated code */
-
-struct ynl_req_state {
- struct ynl_parse_arg yarg;
- mnl_cb_t cb;
- __u32 rsp_cmd;
-};
-
-struct ynl_dump_state {
- struct ynl_sock *ys;
- struct ynl_policy_nest *rsp_policy;
- void *first;
- struct ynl_dump_list_type *last;
- size_t alloc_sz;
- mnl_cb_t cb;
- __u32 rsp_cmd;
-};
-
-struct ynl_ntf_info {
- struct ynl_policy_nest *policy;
- mnl_cb_t cb;
- size_t alloc_sz;
- void (*free)(struct ynl_ntf_base_type *ntf);
-};
-
-int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
- struct ynl_req_state *yrs);
-int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
- struct ynl_dump_state *yds);
-
-void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd);
-int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg);
-
#endif
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
deleted file mode 100644
index 13c4b019a881..000000000000
--- a/tools/net/ynl/lib/ynl.py
+++ /dev/null
@@ -1,729 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-
-from collections import namedtuple
-import functools
-import os
-import random
-import socket
-import struct
-from struct import Struct
-import yaml
-import ipaddress
-import uuid
-
-from .nlspec import SpecFamily
-
-#
-# Generic Netlink code which should really be in some library, but I can't quickly find one.
-#
-
-
-class Netlink:
- # Netlink socket
- SOL_NETLINK = 270
-
- NETLINK_ADD_MEMBERSHIP = 1
- NETLINK_CAP_ACK = 10
- NETLINK_EXT_ACK = 11
- NETLINK_GET_STRICT_CHK = 12
-
- # Netlink message
- NLMSG_ERROR = 2
- NLMSG_DONE = 3
-
- NLM_F_REQUEST = 1
- NLM_F_ACK = 4
- NLM_F_ROOT = 0x100
- NLM_F_MATCH = 0x200
-
- NLM_F_REPLACE = 0x100
- NLM_F_EXCL = 0x200
- NLM_F_CREATE = 0x400
- NLM_F_APPEND = 0x800
-
- NLM_F_CAPPED = 0x100
- NLM_F_ACK_TLVS = 0x200
-
- NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH
-
- NLA_F_NESTED = 0x8000
- NLA_F_NET_BYTEORDER = 0x4000
-
- NLA_TYPE_MASK = NLA_F_NESTED | NLA_F_NET_BYTEORDER
-
- # Genetlink defines
- NETLINK_GENERIC = 16
-
- GENL_ID_CTRL = 0x10
-
- # nlctrl
- CTRL_CMD_GETFAMILY = 3
-
- CTRL_ATTR_FAMILY_ID = 1
- CTRL_ATTR_FAMILY_NAME = 2
- CTRL_ATTR_MAXATTR = 5
- CTRL_ATTR_MCAST_GROUPS = 7
-
- CTRL_ATTR_MCAST_GRP_NAME = 1
- CTRL_ATTR_MCAST_GRP_ID = 2
-
- # Extack types
- NLMSGERR_ATTR_MSG = 1
- NLMSGERR_ATTR_OFFS = 2
- NLMSGERR_ATTR_COOKIE = 3
- NLMSGERR_ATTR_POLICY = 4
- NLMSGERR_ATTR_MISS_TYPE = 5
- NLMSGERR_ATTR_MISS_NEST = 6
-
-
-class NlError(Exception):
- def __init__(self, nl_msg):
- self.nl_msg = nl_msg
-
- def __str__(self):
- return f"Netlink error: {os.strerror(-self.nl_msg.error)}\n{self.nl_msg}"
-
-
-class NlAttr:
- ScalarFormat = namedtuple('ScalarFormat', ['native', 'big', 'little'])
- type_formats = {
- 'u8' : ScalarFormat(Struct('B'), Struct("B"), Struct("B")),
- 's8' : ScalarFormat(Struct('b'), Struct("b"), Struct("b")),
- 'u16': ScalarFormat(Struct('H'), Struct(">H"), Struct("<H")),
- 's16': ScalarFormat(Struct('h'), Struct(">h"), Struct("<h")),
- 'u32': ScalarFormat(Struct('I'), Struct(">I"), Struct("<I")),
- 's32': ScalarFormat(Struct('i'), Struct(">i"), Struct("<i")),
- 'u64': ScalarFormat(Struct('Q'), Struct(">Q"), Struct("<Q")),
- 's64': ScalarFormat(Struct('q'), Struct(">q"), Struct("<q"))
- }
-
- def __init__(self, raw, offset):
- self._len, self._type = struct.unpack("HH", raw[offset:offset + 4])
- self.type = self._type & ~Netlink.NLA_TYPE_MASK
- self.payload_len = self._len
- self.full_len = (self.payload_len + 3) & ~3
- self.raw = raw[offset + 4:offset + self.payload_len]
-
- @classmethod
- def get_format(cls, attr_type, byte_order=None):
- format = cls.type_formats[attr_type]
- if byte_order:
- return format.big if byte_order == "big-endian" \
- else format.little
- return format.native
-
- @classmethod
- def formatted_string(cls, raw, display_hint):
- if display_hint == 'mac':
- formatted = ':'.join('%02x' % b for b in raw)
- elif display_hint == 'hex':
- formatted = bytes.hex(raw, ' ')
- elif display_hint in [ 'ipv4', 'ipv6' ]:
- formatted = format(ipaddress.ip_address(raw))
- elif display_hint == 'uuid':
- formatted = str(uuid.UUID(bytes=raw))
- else:
- formatted = raw
- return formatted
-
- def as_scalar(self, attr_type, byte_order=None):
- format = self.get_format(attr_type, byte_order)
- return format.unpack(self.raw)[0]
-
- def as_strz(self):
- return self.raw.decode('ascii')[:-1]
-
- def as_bin(self):
- return self.raw
-
- def as_c_array(self, type):
- format = self.get_format(type)
- return [ x[0] for x in format.iter_unpack(self.raw) ]
-
- def as_struct(self, members):
- value = dict()
- offset = 0
- for m in members:
- # TODO: handle non-scalar members
- if m.type == 'binary':
- decoded = self.raw[offset:offset+m['len']]
- offset += m['len']
- elif m.type in NlAttr.type_formats:
- format = self.get_format(m.type, m.byte_order)
- [ decoded ] = format.unpack_from(self.raw, offset)
- offset += format.size
- if m.display_hint:
- decoded = self.formatted_string(decoded, m.display_hint)
- value[m.name] = decoded
- return value
-
- def __repr__(self):
- return f"[type:{self.type} len:{self._len}] {self.raw}"
-
-
-class NlAttrs:
- def __init__(self, msg):
- self.attrs = []
-
- offset = 0
- while offset < len(msg):
- attr = NlAttr(msg, offset)
- offset += attr.full_len
- self.attrs.append(attr)
-
- def __iter__(self):
- yield from self.attrs
-
- def __repr__(self):
- msg = ''
- for a in self.attrs:
- if msg:
- msg += '\n'
- msg += repr(a)
- return msg
-
-
-class NlMsg:
- def __init__(self, msg, offset, attr_space=None):
- self.hdr = msg[offset:offset + 16]
-
- self.nl_len, self.nl_type, self.nl_flags, self.nl_seq, self.nl_portid = \
- struct.unpack("IHHII", self.hdr)
-
- self.raw = msg[offset + 16:offset + self.nl_len]
-
- self.error = 0
- self.done = 0
-
- extack_off = None
- if self.nl_type == Netlink.NLMSG_ERROR:
- self.error = struct.unpack("i", self.raw[0:4])[0]
- self.done = 1
- extack_off = 20
- elif self.nl_type == Netlink.NLMSG_DONE:
- self.done = 1
- extack_off = 4
-
- self.extack = None
- if self.nl_flags & Netlink.NLM_F_ACK_TLVS and extack_off:
- self.extack = dict()
- extack_attrs = NlAttrs(self.raw[extack_off:])
- for extack in extack_attrs:
- if extack.type == Netlink.NLMSGERR_ATTR_MSG:
- self.extack['msg'] = extack.as_strz()
- elif extack.type == Netlink.NLMSGERR_ATTR_MISS_TYPE:
- self.extack['miss-type'] = extack.as_scalar('u32')
- elif extack.type == Netlink.NLMSGERR_ATTR_MISS_NEST:
- self.extack['miss-nest'] = extack.as_scalar('u32')
- elif extack.type == Netlink.NLMSGERR_ATTR_OFFS:
- self.extack['bad-attr-offs'] = extack.as_scalar('u32')
- else:
- if 'unknown' not in self.extack:
- self.extack['unknown'] = []
- self.extack['unknown'].append(extack)
-
- if attr_space:
- # We don't have the ability to parse nests yet, so only do global
- if 'miss-type' in self.extack and 'miss-nest' not in self.extack:
- miss_type = self.extack['miss-type']
- if miss_type in attr_space.attrs_by_val:
- spec = attr_space.attrs_by_val[miss_type]
- desc = spec['name']
- if 'doc' in spec:
- desc += f" ({spec['doc']})"
- self.extack['miss-type'] = desc
-
- def cmd(self):
- return self.nl_type
-
- def __repr__(self):
- msg = f"nl_len = {self.nl_len} ({len(self.raw)}) nl_flags = 0x{self.nl_flags:x} nl_type = {self.nl_type}\n"
- if self.error:
- msg += '\terror: ' + str(self.error)
- if self.extack:
- msg += '\textack: ' + repr(self.extack)
- return msg
-
-
-class NlMsgs:
- def __init__(self, data, attr_space=None):
- self.msgs = []
-
- offset = 0
- while offset < len(data):
- msg = NlMsg(data, offset, attr_space=attr_space)
- offset += msg.nl_len
- self.msgs.append(msg)
-
- def __iter__(self):
- yield from self.msgs
-
-
-genl_family_name_to_id = None
-
-
-def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None):
- # we prepend length in _genl_msg_finalize()
- if seq is None:
- seq = random.randint(1, 1024)
- nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
- genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0)
- return nlmsg + genlmsg
-
-
-def _genl_msg_finalize(msg):
- return struct.pack("I", len(msg) + 4) + msg
-
-
-def _genl_load_families():
- with socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, Netlink.NETLINK_GENERIC) as sock:
- sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1)
-
- msg = _genl_msg(Netlink.GENL_ID_CTRL,
- Netlink.NLM_F_REQUEST | Netlink.NLM_F_ACK | Netlink.NLM_F_DUMP,
- Netlink.CTRL_CMD_GETFAMILY, 1)
- msg = _genl_msg_finalize(msg)
-
- sock.send(msg, 0)
-
- global genl_family_name_to_id
- genl_family_name_to_id = dict()
-
- while True:
- reply = sock.recv(128 * 1024)
- nms = NlMsgs(reply)
- for nl_msg in nms:
- if nl_msg.error:
- print("Netlink error:", nl_msg.error)
- return
- if nl_msg.done:
- return
-
- gm = GenlMsg(nl_msg)
- fam = dict()
- for attr in NlAttrs(gm.raw):
- if attr.type == Netlink.CTRL_ATTR_FAMILY_ID:
- fam['id'] = attr.as_scalar('u16')
- elif attr.type == Netlink.CTRL_ATTR_FAMILY_NAME:
- fam['name'] = attr.as_strz()
- elif attr.type == Netlink.CTRL_ATTR_MAXATTR:
- fam['maxattr'] = attr.as_scalar('u32')
- elif attr.type == Netlink.CTRL_ATTR_MCAST_GROUPS:
- fam['mcast'] = dict()
- for entry in NlAttrs(attr.raw):
- mcast_name = None
- mcast_id = None
- for entry_attr in NlAttrs(entry.raw):
- if entry_attr.type == Netlink.CTRL_ATTR_MCAST_GRP_NAME:
- mcast_name = entry_attr.as_strz()
- elif entry_attr.type == Netlink.CTRL_ATTR_MCAST_GRP_ID:
- mcast_id = entry_attr.as_scalar('u32')
- if mcast_name and mcast_id is not None:
- fam['mcast'][mcast_name] = mcast_id
- if 'name' in fam and 'id' in fam:
- genl_family_name_to_id[fam['name']] = fam
-
-
-class GenlMsg:
- def __init__(self, nl_msg):
- self.nl = nl_msg
- self.genl_cmd, self.genl_version, _ = struct.unpack_from("BBH", nl_msg.raw, 0)
- self.raw = nl_msg.raw[4:]
-
- def cmd(self):
- return self.genl_cmd
-
- def __repr__(self):
- msg = repr(self.nl)
- msg += f"\tgenl_cmd = {self.genl_cmd} genl_ver = {self.genl_version}\n"
- for a in self.raw_attrs:
- msg += '\t\t' + repr(a) + '\n'
- return msg
-
-
-class NetlinkProtocol:
- def __init__(self, family_name, proto_num):
- self.family_name = family_name
- self.proto_num = proto_num
-
- def _message(self, nl_type, nl_flags, seq=None):
- if seq is None:
- seq = random.randint(1, 1024)
- nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
- return nlmsg
-
- def message(self, flags, command, version, seq=None):
- return self._message(command, flags, seq)
-
- def _decode(self, nl_msg):
- return nl_msg
-
- def decode(self, ynl, nl_msg):
- msg = self._decode(nl_msg)
- fixed_header_size = 0
- if ynl:
- op = ynl.rsp_by_value[msg.cmd()]
- fixed_header_size = ynl._fixed_header_size(op)
- msg.raw_attrs = NlAttrs(msg.raw[fixed_header_size:])
- return msg
-
- def get_mcast_id(self, mcast_name, mcast_groups):
- if mcast_name not in mcast_groups:
- raise Exception(f'Multicast group "{mcast_name}" not present in the spec')
- return mcast_groups[mcast_name].value
-
-
-class GenlProtocol(NetlinkProtocol):
- def __init__(self, family_name):
- super().__init__(family_name, Netlink.NETLINK_GENERIC)
-
- global genl_family_name_to_id
- if genl_family_name_to_id is None:
- _genl_load_families()
-
- self.genl_family = genl_family_name_to_id[family_name]
- self.family_id = genl_family_name_to_id[family_name]['id']
-
- def message(self, flags, command, version, seq=None):
- nlmsg = self._message(self.family_id, flags, seq)
- genlmsg = struct.pack("BBH", command, version, 0)
- return nlmsg + genlmsg
-
- def _decode(self, nl_msg):
- return GenlMsg(nl_msg)
-
- def get_mcast_id(self, mcast_name, mcast_groups):
- if mcast_name not in self.genl_family['mcast']:
- raise Exception(f'Multicast group "{mcast_name}" not present in the family')
- return self.genl_family['mcast'][mcast_name]
-
-
-#
-# YNL implementation details.
-#
-
-
-class YnlFamily(SpecFamily):
- def __init__(self, def_path, schema=None):
- super().__init__(def_path, schema)
-
- self.include_raw = False
-
- try:
- if self.proto == "netlink-raw":
- self.nlproto = NetlinkProtocol(self.yaml['name'],
- self.yaml['protonum'])
- else:
- self.nlproto = GenlProtocol(self.yaml['name'])
- except KeyError:
- raise Exception(f"Family '{self.yaml['name']}' not supported by the kernel")
-
- self.sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, self.nlproto.proto_num)
- self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1)
- self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_EXT_ACK, 1)
- self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_GET_STRICT_CHK, 1)
-
- self.async_msg_ids = set()
- self.async_msg_queue = []
-
- for msg in self.msgs.values():
- if msg.is_async:
- self.async_msg_ids.add(msg.rsp_value)
-
- for op_name, op in self.ops.items():
- bound_f = functools.partial(self._op, op_name)
- setattr(self, op.ident_name, bound_f)
-
-
- def ntf_subscribe(self, mcast_name):
- mcast_id = self.nlproto.get_mcast_id(mcast_name, self.mcast_groups)
- self.sock.bind((0, 0))
- self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_ADD_MEMBERSHIP,
- mcast_id)
-
- def _add_attr(self, space, name, value):
- try:
- attr = self.attr_sets[space][name]
- except KeyError:
- raise Exception(f"Space '{space}' has no attribute '{name}'")
- nl_type = attr.value
- if attr["type"] == 'nest':
- nl_type |= Netlink.NLA_F_NESTED
- attr_payload = b''
- for subname, subvalue in value.items():
- attr_payload += self._add_attr(attr['nested-attributes'], subname, subvalue)
- elif attr["type"] == 'flag':
- attr_payload = b''
- elif attr["type"] == 'string':
- attr_payload = str(value).encode('ascii') + b'\x00'
- elif attr["type"] == 'binary':
- if isinstance(value, bytes):
- attr_payload = value
- elif isinstance(value, str):
- attr_payload = bytes.fromhex(value)
- else:
- raise Exception(f'Unknown type for binary attribute, value: {value}')
- elif attr['type'] in NlAttr.type_formats:
- format = NlAttr.get_format(attr['type'], attr.byte_order)
- attr_payload = format.pack(int(value))
- else:
- raise Exception(f'Unknown type at {space} {name} {value} {attr["type"]}')
-
- pad = b'\x00' * ((4 - len(attr_payload) % 4) % 4)
- return struct.pack('HH', len(attr_payload) + 4, nl_type) + attr_payload + pad
-
- def _decode_enum(self, raw, attr_spec):
- enum = self.consts[attr_spec['enum']]
- if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']:
- i = 0
- value = set()
- while raw:
- if raw & 1:
- value.add(enum.entries_by_val[i].name)
- raw >>= 1
- i += 1
- else:
- value = enum.entries_by_val[raw].name
- return value
-
- def _decode_binary(self, attr, attr_spec):
- if attr_spec.struct_name:
- members = self.consts[attr_spec.struct_name]
- decoded = attr.as_struct(members)
- for m in members:
- if m.enum:
- decoded[m.name] = self._decode_enum(decoded[m.name], m)
- elif attr_spec.sub_type:
- decoded = attr.as_c_array(attr_spec.sub_type)
- else:
- decoded = attr.as_bin()
- if attr_spec.display_hint:
- decoded = NlAttr.formatted_string(decoded, attr_spec.display_hint)
- return decoded
-
- def _decode_array_nest(self, attr, attr_spec):
- decoded = []
- offset = 0
- while offset < len(attr.raw):
- item = NlAttr(attr.raw, offset)
- offset += item.full_len
-
- subattrs = self._decode(NlAttrs(item.raw), attr_spec['nested-attributes'])
- decoded.append({ item.type: subattrs })
- return decoded
-
- def _decode(self, attrs, space):
- attr_space = self.attr_sets[space]
- rsp = dict()
- for attr in attrs:
- try:
- attr_spec = attr_space.attrs_by_val[attr.type]
- except KeyError:
- raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
- if attr_spec["type"] == 'nest':
- subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'])
- decoded = subdict
- elif attr_spec["type"] == 'string':
- decoded = attr.as_strz()
- elif attr_spec["type"] == 'binary':
- decoded = self._decode_binary(attr, attr_spec)
- elif attr_spec["type"] == 'flag':
- decoded = True
- elif attr_spec["type"] in NlAttr.type_formats:
- decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
- elif attr_spec["type"] == 'array-nest':
- decoded = self._decode_array_nest(attr, attr_spec)
- else:
- raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
-
- if 'enum' in attr_spec:
- decoded = self._decode_enum(decoded, attr_spec)
-
- if not attr_spec.is_multi:
- rsp[attr_spec['name']] = decoded
- elif attr_spec.name in rsp:
- rsp[attr_spec.name].append(decoded)
- else:
- rsp[attr_spec.name] = [decoded]
-
- return rsp
-
- def _decode_extack_path(self, attrs, attr_set, offset, target):
- for attr in attrs:
- try:
- attr_spec = attr_set.attrs_by_val[attr.type]
- except KeyError:
- raise Exception(f"Space '{attr_set.name}' has no attribute with value '{attr.type}'")
- if offset > target:
- break
- if offset == target:
- return '.' + attr_spec.name
-
- if offset + attr.full_len <= target:
- offset += attr.full_len
- continue
- if attr_spec['type'] != 'nest':
- raise Exception(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack")
- offset += 4
- subpath = self._decode_extack_path(NlAttrs(attr.raw),
- self.attr_sets[attr_spec['nested-attributes']],
- offset, target)
- if subpath is None:
- return None
- return '.' + attr_spec.name + subpath
-
- return None
-
- def _decode_extack(self, request, op, extack):
- if 'bad-attr-offs' not in extack:
- return
-
- msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set))
- offset = 20 + self._fixed_header_size(op)
- path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset,
- extack['bad-attr-offs'])
- if path:
- del extack['bad-attr-offs']
- extack['bad-attr'] = path
-
- def _fixed_header_size(self, op):
- if op.fixed_header:
- fixed_header_members = self.consts[op.fixed_header].members
- size = 0
- for m in fixed_header_members:
- format = NlAttr.get_format(m.type, m.byte_order)
- size += format.size
- return size
- else:
- return 0
-
- def _decode_fixed_header(self, msg, name):
- fixed_header_members = self.consts[name].members
- fixed_header_attrs = dict()
- offset = 0
- for m in fixed_header_members:
- format = NlAttr.get_format(m.type, m.byte_order)
- [ value ] = format.unpack_from(msg.raw, offset)
- offset += format.size
- if m.enum:
- value = self._decode_enum(value, m)
- fixed_header_attrs[m.name] = value
- return fixed_header_attrs
-
- def handle_ntf(self, decoded):
- msg = dict()
- if self.include_raw:
- msg['raw'] = decoded
- op = self.rsp_by_value[decoded.cmd()]
- attrs = self._decode(decoded.raw_attrs, op.attr_set.name)
- if op.fixed_header:
- attrs.update(self._decode_fixed_header(decoded, op.fixed_header))
-
- msg['name'] = op['name']
- msg['msg'] = attrs
- self.async_msg_queue.append(msg)
-
- def check_ntf(self):
- while True:
- try:
- reply = self.sock.recv(128 * 1024, socket.MSG_DONTWAIT)
- except BlockingIOError:
- return
-
- nms = NlMsgs(reply)
- for nl_msg in nms:
- if nl_msg.error:
- print("Netlink error in ntf!?", os.strerror(-nl_msg.error))
- print(nl_msg)
- continue
- if nl_msg.done:
- print("Netlink done while checking for ntf!?")
- continue
-
- decoded = self.nlproto.decode(self, nl_msg)
- if decoded.cmd() not in self.async_msg_ids:
- print("Unexpected msg id done while checking for ntf", decoded)
- continue
-
- self.handle_ntf(decoded)
-
- def operation_do_attributes(self, name):
- """
- For a given operation name, find and return a supported
- set of attributes (as a dict).
- """
- op = self.find_operation(name)
- if not op:
- return None
-
- return op['do']['request']['attributes'].copy()
-
- def _op(self, method, vals, flags, dump=False):
- op = self.ops[method]
-
- nl_flags = Netlink.NLM_F_REQUEST | Netlink.NLM_F_ACK
- for flag in flags or []:
- nl_flags |= flag
- if dump:
- nl_flags |= Netlink.NLM_F_DUMP
-
- req_seq = random.randint(1024, 65535)
- msg = self.nlproto.message(nl_flags, op.req_value, 1, req_seq)
- fixed_header_members = []
- if op.fixed_header:
- fixed_header_members = self.consts[op.fixed_header].members
- for m in fixed_header_members:
- value = vals.pop(m.name) if m.name in vals else 0
- format = NlAttr.get_format(m.type, m.byte_order)
- msg += format.pack(value)
- for name, value in vals.items():
- msg += self._add_attr(op.attr_set.name, name, value)
- msg = _genl_msg_finalize(msg)
-
- self.sock.send(msg, 0)
-
- done = False
- rsp = []
- while not done:
- reply = self.sock.recv(128 * 1024)
- nms = NlMsgs(reply, attr_space=op.attr_set)
- for nl_msg in nms:
- if nl_msg.extack:
- self._decode_extack(msg, op, nl_msg.extack)
-
- if nl_msg.error:
- raise NlError(nl_msg)
- if nl_msg.done:
- if nl_msg.extack:
- print("Netlink warning:")
- print(nl_msg)
- done = True
- break
-
- decoded = self.nlproto.decode(self, nl_msg)
-
- # Check if this is a reply to our request
- if nl_msg.nl_seq != req_seq or decoded.cmd() != op.rsp_value:
- if decoded.cmd() in self.async_msg_ids:
- self.handle_ntf(decoded)
- continue
- else:
- print('Unexpected message: ' + repr(decoded))
- continue
-
- rsp_msg = self._decode(decoded.raw_attrs, op.attr_set.name)
- if op.fixed_header:
- rsp_msg.update(self._decode_fixed_header(decoded, op.fixed_header))
- rsp.append(rsp_msg)
-
- if not rsp:
- return None
- if not dump and len(rsp) == 1:
- return rsp[0]
- return rsp
-
- def do(self, method, vals, flags):
- return self._op(method, vals, flags)
-
- def dump(self, method, vals):
- return self._op(method, vals, [], dump=True)
diff --git a/tools/net/ynl/pyproject.toml b/tools/net/ynl/pyproject.toml
new file mode 100644
index 000000000000..a81d8779b0e0
--- /dev/null
+++ b/tools/net/ynl/pyproject.toml
@@ -0,0 +1,24 @@
+[build-system]
+requires = ["setuptools>=61.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "pyynl"
+authors = [
+ {name = "Donald Hunter", email = "donald.hunter@gmail.com"},
+ {name = "Jakub Kicinski", email = "kuba@kernel.org"},
+]
+description = "yaml netlink (ynl)"
+version = "0.0.1"
+requires-python = ">=3.9"
+dependencies = [
+ "pyyaml==6.*",
+ "jsonschema==4.*"
+]
+
+[tool.setuptools.packages.find]
+include = ["pyynl", "pyynl.lib"]
+
+[project.scripts]
+ynl = "pyynl.cli:main"
+ynl-ethtool = "pyynl.ethtool:main"
diff --git a/tools/net/ynl/pyynl/.gitignore b/tools/net/ynl/pyynl/.gitignore
new file mode 100644
index 000000000000..b801cd2d016e
--- /dev/null
+++ b/tools/net/ynl/pyynl/.gitignore
@@ -0,0 +1,2 @@
+__pycache__/
+lib/__pycache__/
diff --git a/tools/net/ynl/pyynl/__init__.py b/tools/net/ynl/pyynl/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/net/ynl/pyynl/__init__.py
diff --git a/tools/net/ynl/pyynl/cli.py b/tools/net/ynl/pyynl/cli.py
new file mode 100755
index 000000000000..af02a5b7e5a2
--- /dev/null
+++ b/tools/net/ynl/pyynl/cli.py
@@ -0,0 +1,253 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+import argparse
+import json
+import os
+import pathlib
+import pprint
+import sys
+import textwrap
+
+sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
+from lib import YnlFamily, Netlink, NlError, SpecFamily
+
+sys_schema_dir='/usr/share/ynl'
+relative_schema_dir='../../../../Documentation/netlink'
+
+def schema_dir():
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ schema_dir = os.path.abspath(f"{script_dir}/{relative_schema_dir}")
+ if not os.path.isdir(schema_dir):
+ schema_dir = sys_schema_dir
+ if not os.path.isdir(schema_dir):
+ raise Exception(f"Schema directory {schema_dir} does not exist")
+ return schema_dir
+
+def spec_dir():
+ spec_dir = schema_dir() + '/specs'
+ if not os.path.isdir(spec_dir):
+ raise Exception(f"Spec directory {spec_dir} does not exist")
+ return spec_dir
+
+
+class YnlEncoder(json.JSONEncoder):
+ def default(self, obj):
+ if isinstance(obj, bytes):
+ return bytes.hex(obj)
+ if isinstance(obj, set):
+ return list(obj)
+ return json.JSONEncoder.default(self, obj)
+
+
+def print_attr_list(ynl, attr_names, attr_set, indent=2):
+ """Print a list of attributes with their types and documentation."""
+ prefix = ' ' * indent
+ for attr_name in attr_names:
+ if attr_name in attr_set.attrs:
+ attr = attr_set.attrs[attr_name]
+ attr_info = f'{prefix}- {attr_name}: {attr.type}'
+ if 'enum' in attr.yaml:
+ enum_name = attr.yaml['enum']
+ attr_info += f" (enum: {enum_name})"
+ # Print enum values if available
+ if enum_name in ynl.consts:
+ const = ynl.consts[enum_name]
+ enum_values = list(const.entries.keys())
+ attr_info += f"\n{prefix} {const.type.capitalize()}: {', '.join(enum_values)}"
+
+ # Show nested attributes reference and recursively display them
+ nested_set_name = None
+ if attr.type == 'nest' and 'nested-attributes' in attr.yaml:
+ nested_set_name = attr.yaml['nested-attributes']
+ attr_info += f" -> {nested_set_name}"
+
+ if attr.yaml.get('doc'):
+ doc_text = textwrap.indent(attr.yaml['doc'], prefix + ' ')
+ attr_info += f"\n{doc_text}"
+ print(attr_info)
+
+ # Recursively show nested attributes
+ if nested_set_name in ynl.attr_sets:
+ nested_set = ynl.attr_sets[nested_set_name]
+ # Filter out 'unspec' and other unused attrs
+ nested_names = [n for n in nested_set.attrs.keys()
+ if nested_set.attrs[n].type != 'unused']
+ if nested_names:
+ print_attr_list(ynl, nested_names, nested_set, indent + 4)
+
+
+def print_mode_attrs(ynl, mode, mode_spec, attr_set, print_request=True):
+ """Print a given mode (do/dump/event/notify)."""
+ mode_title = mode.capitalize()
+
+ if print_request and 'request' in mode_spec and 'attributes' in mode_spec['request']:
+ print(f'\n{mode_title} request attributes:')
+ print_attr_list(ynl, mode_spec['request']['attributes'], attr_set)
+
+ if 'reply' in mode_spec and 'attributes' in mode_spec['reply']:
+ print(f'\n{mode_title} reply attributes:')
+ print_attr_list(ynl, mode_spec['reply']['attributes'], attr_set)
+
+ if 'attributes' in mode_spec:
+ print(f'\n{mode_title} attributes:')
+ print_attr_list(ynl, mode_spec['attributes'], attr_set)
+
+
+def main():
+ description = """
+ YNL CLI utility - a general purpose netlink utility that uses YAML
+ specs to drive protocol encoding and decoding.
+ """
+ epilog = """
+ The --multi option can be repeated to include several do operations
+ in the same netlink payload.
+ """
+
+ parser = argparse.ArgumentParser(description=description,
+ epilog=epilog)
+ spec_group = parser.add_mutually_exclusive_group(required=True)
+ spec_group.add_argument('--family', dest='family', type=str,
+ help='name of the netlink FAMILY')
+ spec_group.add_argument('--list-families', action='store_true',
+ help='list all netlink families supported by YNL (has spec)')
+ spec_group.add_argument('--spec', dest='spec', type=str,
+ help='choose the family by SPEC file path')
+
+ parser.add_argument('--schema', dest='schema', type=str)
+ parser.add_argument('--no-schema', action='store_true')
+ parser.add_argument('--json', dest='json_text', type=str)
+
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument('--do', dest='do', metavar='DO-OPERATION', type=str)
+ group.add_argument('--multi', dest='multi', nargs=2, action='append',
+ metavar=('DO-OPERATION', 'JSON_TEXT'), type=str)
+ group.add_argument('--dump', dest='dump', metavar='DUMP-OPERATION', type=str)
+ group.add_argument('--list-ops', action='store_true')
+ group.add_argument('--list-msgs', action='store_true')
+ group.add_argument('--list-attrs', dest='list_attrs', metavar='OPERATION', type=str,
+ help='List attributes for an operation')
+ group.add_argument('--validate', action='store_true')
+
+ parser.add_argument('--duration', dest='duration', type=int,
+ help='when subscribed, watch for DURATION seconds')
+ parser.add_argument('--sleep', dest='duration', type=int,
+ help='alias for duration')
+ parser.add_argument('--subscribe', dest='ntf', type=str)
+ parser.add_argument('--replace', dest='flags', action='append_const',
+ const=Netlink.NLM_F_REPLACE)
+ parser.add_argument('--excl', dest='flags', action='append_const',
+ const=Netlink.NLM_F_EXCL)
+ parser.add_argument('--create', dest='flags', action='append_const',
+ const=Netlink.NLM_F_CREATE)
+ parser.add_argument('--append', dest='flags', action='append_const',
+ const=Netlink.NLM_F_APPEND)
+ parser.add_argument('--process-unknown', action=argparse.BooleanOptionalAction)
+ parser.add_argument('--output-json', action='store_true')
+ parser.add_argument('--dbg-small-recv', default=0, const=4000,
+ action='store', nargs='?', type=int)
+ args = parser.parse_args()
+
+ def output(msg):
+ if args.output_json:
+ print(json.dumps(msg, cls=YnlEncoder))
+ else:
+ pprint.PrettyPrinter().pprint(msg)
+
+ if args.list_families:
+ for filename in sorted(os.listdir(spec_dir())):
+ if filename.endswith('.yaml'):
+ print(filename.removesuffix('.yaml'))
+ return
+
+ if args.no_schema:
+ args.schema = ''
+
+ attrs = {}
+ if args.json_text:
+ attrs = json.loads(args.json_text)
+
+ if args.family:
+ spec = f"{spec_dir()}/{args.family}.yaml"
+ else:
+ spec = args.spec
+ if not os.path.isfile(spec):
+ raise Exception(f"Spec file {spec} does not exist")
+
+ if args.validate:
+ try:
+ SpecFamily(spec, args.schema)
+ except Exception as error:
+ print(error)
+ exit(1)
+ return
+
+ if args.family: # set behaviour when using installed specs
+ if args.schema is None and spec.startswith(sys_schema_dir):
+ args.schema = '' # disable schema validation when installed
+ if args.process_unknown is None:
+ args.process_unknown = True
+
+ ynl = YnlFamily(spec, args.schema, args.process_unknown,
+ recv_size=args.dbg_small_recv)
+ if args.dbg_small_recv:
+ ynl.set_recv_dbg(True)
+
+ if args.ntf:
+ ynl.ntf_subscribe(args.ntf)
+
+ if args.list_ops:
+ for op_name, op in ynl.ops.items():
+ print(op_name, " [", ", ".join(op.modes), "]")
+ if args.list_msgs:
+ for op_name, op in ynl.msgs.items():
+ print(op_name, " [", ", ".join(op.modes), "]")
+
+ if args.list_attrs:
+ op = ynl.msgs.get(args.list_attrs)
+ if not op:
+ print(f'Operation {args.list_attrs} not found')
+ exit(1)
+
+ print(f'Operation: {op.name}')
+ print(op.yaml['doc'])
+
+ for mode in ['do', 'dump', 'event']:
+ if mode in op.yaml:
+ print_mode_attrs(ynl, mode, op.yaml[mode], op.attr_set, True)
+
+ if 'notify' in op.yaml:
+ mode_spec = op.yaml['notify']
+ ref_spec = ynl.msgs.get(mode_spec).yaml.get('do')
+ if ref_spec:
+ print_mode_attrs(ynl, 'notify', ref_spec, op.attr_set, False)
+
+ if 'mcgrp' in op.yaml:
+ print(f"\nMulticast group: {op.yaml['mcgrp']}")
+
+ try:
+ if args.do:
+ reply = ynl.do(args.do, attrs, args.flags)
+ output(reply)
+ if args.dump:
+ reply = ynl.dump(args.dump, attrs)
+ output(reply)
+ if args.multi:
+ ops = [ (item[0], json.loads(item[1]), args.flags or []) for item in args.multi ]
+ reply = ynl.do_multi(ops)
+ output(reply)
+
+ if args.ntf:
+ for msg in ynl.poll_ntf(duration=args.duration):
+ output(msg)
+ except NlError as e:
+ print(e)
+ exit(1)
+ except KeyboardInterrupt:
+ pass
+ except BrokenPipeError:
+ pass
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/net/ynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py
index 6c9f7e31250c..fd0f6b8d54d1 100755
--- a/tools/net/ynl/ethtool.py
+++ b/tools/net/ynl/pyynl/ethtool.py
@@ -2,12 +2,15 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
import argparse
-import json
+import pathlib
import pprint
import sys
import re
+import os
+sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
from lib import YnlFamily
+from cli import schema_dir, spec_dir
def args_to_req(ynl, op_name, args, req):
"""
@@ -41,13 +44,16 @@ def print_field(reply, *desc):
Pretty-print a set of fields from the reply. desc specifies the
fields and the optional type (bool/yn).
"""
+ if not reply:
+ return
+
if len(desc) == 0:
return print_field(reply, *zip(reply.keys(), reply.keys()))
for spec in desc:
try:
field, name, tp = spec
- except:
+ except ValueError:
field, name = spec
tp = 'int'
@@ -152,8 +158,8 @@ def main():
global args
args = parser.parse_args()
- spec = '../../../Documentation/netlink/specs/ethtool.yaml'
- schema = '../../../Documentation/netlink/genetlink-legacy.yaml'
+ spec = os.path.join(spec_dir(), 'ethtool.yaml')
+ schema = os.path.join(schema_dir(), 'genetlink-legacy.yaml')
ynl = YnlFamily(spec, schema)
@@ -250,14 +256,14 @@ def main():
reply = dumpit(ynl, args, 'channels-get')
print(f'Channel parameters for {args.device}:')
- print(f'Pre-set maximums:')
+ print('Pre-set maximums:')
print_field(reply,
('rx-max', 'RX'),
('tx-max', 'TX'),
('other-max', 'Other'),
('combined-max', 'Combined'))
- print(f'Current hardware settings:')
+ print('Current hardware settings:')
print_field(reply,
('rx-count', 'RX'),
('tx-count', 'TX'),
@@ -271,14 +277,14 @@ def main():
print(f'Ring parameters for {args.device}:')
- print(f'Pre-set maximums:')
+ print('Pre-set maximums:')
print_field(reply,
('rx-max', 'RX'),
('rx-mini-max', 'RX Mini'),
('rx-jumbo-max', 'RX Jumbo'),
('tx-max', 'TX'))
- print(f'Current hardware settings:')
+ print('Current hardware settings:')
print_field(reply,
('rx', 'RX'),
('rx-mini', 'RX Mini'),
@@ -293,7 +299,7 @@ def main():
return
if args.statistics:
- print(f'NIC statistics:')
+ print('NIC statistics:')
# TODO: pass id?
strset = dumpit(ynl, args, 'strset-get')
@@ -320,20 +326,37 @@ def main():
return
if args.show_time_stamping:
- tsinfo = dumpit(ynl, args, 'tsinfo-get')
+ req = {
+ 'header': {
+ 'flags': 'stats',
+ },
+ }
+
+ tsinfo = dumpit(ynl, args, 'tsinfo-get', req)
print(f'Time stamping parameters for {args.device}:')
print('Capabilities:')
[print(f'\t{v}') for v in bits_to_dict(tsinfo['timestamping'])]
- print(f'PTP Hardware Clock: {tsinfo["phc-index"]}')
+ print(f'PTP Hardware Clock: {tsinfo.get("phc-index", "none")}')
+
+ if 'tx-types' in tsinfo:
+ print('Hardware Transmit Timestamp Modes:')
+ [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])]
+ else:
+ print('Hardware Transmit Timestamp Modes: none')
+
+ if 'rx-filters' in tsinfo:
+ print('Hardware Receive Filter Modes:')
+ [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])]
+ else:
+ print('Hardware Receive Filter Modes: none')
- print('Hardware Transmit Timestamp Modes:')
- [print(f'\t{v}') for v in bits_to_dict(tsinfo['tx-types'])]
+ if 'stats' in tsinfo and tsinfo['stats']:
+ print('Statistics:')
+ [print(f'\t{k}: {v}') for k, v in tsinfo['stats'].items()]
- print('Hardware Receive Filter Modes:')
- [print(f'\t{v}') for v in bits_to_dict(tsinfo['rx-filters'])]
return
print(f'Settings for {args.device}:')
diff --git a/tools/net/ynl/pyynl/lib/__init__.py b/tools/net/ynl/pyynl/lib/__init__.py
new file mode 100644
index 000000000000..ec9ea00071be
--- /dev/null
+++ b/tools/net/ynl/pyynl/lib/__init__.py
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+from .nlspec import SpecAttr, SpecAttrSet, SpecEnumEntry, SpecEnumSet, \
+ SpecFamily, SpecOperation, SpecSubMessage, SpecSubMessageFormat
+from .ynl import YnlFamily, Netlink, NlError
+
+from .doc_generator import YnlDocGenerator
+
+__all__ = ["SpecAttr", "SpecAttrSet", "SpecEnumEntry", "SpecEnumSet",
+ "SpecFamily", "SpecOperation", "SpecSubMessage", "SpecSubMessageFormat",
+ "YnlFamily", "Netlink", "NlError", "YnlDocGenerator"]
diff --git a/tools/net/ynl/pyynl/lib/doc_generator.py b/tools/net/ynl/pyynl/lib/doc_generator.py
new file mode 100644
index 000000000000..3a16b8eb01ca
--- /dev/null
+++ b/tools/net/ynl/pyynl/lib/doc_generator.py
@@ -0,0 +1,402 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8; mode: python -*-
+
+"""
+ Class to auto generate the documentation for Netlink specifications.
+
+ :copyright: Copyright (C) 2023 Breno Leitao <leitao@debian.org>
+ :license: GPL Version 2, June 1991 see linux/COPYING for details.
+
+ This class performs extensive parsing to the Linux kernel's netlink YAML
+ spec files, in an effort to avoid needing to heavily mark up the original
+ YAML file.
+
+ This code is split in two classes:
+ 1) RST formatters: Use to convert a string to a RST output
+ 2) YAML Netlink (YNL) doc generator: Generate docs from YAML data
+"""
+
+from typing import Any, Dict, List
+import yaml
+
+LINE_STR = '__lineno__'
+
+class NumberedSafeLoader(yaml.SafeLoader): # pylint: disable=R0901
+ """Override the SafeLoader class to add line number to parsed data"""
+
+ def construct_mapping(self, node, *args, **kwargs):
+ mapping = super().construct_mapping(node, *args, **kwargs)
+ mapping[LINE_STR] = node.start_mark.line
+
+ return mapping
+
+class RstFormatters:
+ """RST Formatters"""
+
+ SPACE_PER_LEVEL = 4
+
+ @staticmethod
+ def headroom(level: int) -> str:
+ """Return space to format"""
+ return " " * (level * RstFormatters.SPACE_PER_LEVEL)
+
+ @staticmethod
+ def bold(text: str) -> str:
+ """Format bold text"""
+ return f"**{text}**"
+
+ @staticmethod
+ def inline(text: str) -> str:
+ """Format inline text"""
+ return f"``{text}``"
+
+ @staticmethod
+ def sanitize(text: str) -> str:
+ """Remove newlines and multiple spaces"""
+ # This is useful for some fields that are spread across multiple lines
+ return str(text).replace("\n", " ").strip()
+
+ def rst_fields(self, key: str, value: str, level: int = 0) -> str:
+ """Return a RST formatted field"""
+ return self.headroom(level) + f":{key}: {value}"
+
+ def rst_definition(self, key: str, value: Any, level: int = 0) -> str:
+ """Format a single rst definition"""
+ return self.headroom(level) + key + "\n" + self.headroom(level + 1) + str(value)
+
+ def rst_paragraph(self, paragraph: str, level: int = 0) -> str:
+ """Return a formatted paragraph"""
+ return self.headroom(level) + paragraph
+
+ def rst_bullet(self, item: str, level: int = 0) -> str:
+ """Return a formatted a bullet"""
+ return self.headroom(level) + f"- {item}"
+
+ @staticmethod
+ def rst_subsection(title: str) -> str:
+ """Add a sub-section to the document"""
+ return f"{title}\n" + "-" * len(title)
+
+ @staticmethod
+ def rst_subsubsection(title: str) -> str:
+ """Add a sub-sub-section to the document"""
+ return f"{title}\n" + "~" * len(title)
+
+ @staticmethod
+ def rst_section(namespace: str, prefix: str, title: str) -> str:
+ """Add a section to the document"""
+ return f".. _{namespace}-{prefix}-{title}:\n\n{title}\n" + "=" * len(title)
+
+ @staticmethod
+ def rst_subtitle(title: str) -> str:
+ """Add a subtitle to the document"""
+ return "\n" + "-" * len(title) + f"\n{title}\n" + "-" * len(title) + "\n\n"
+
+ @staticmethod
+ def rst_title(title: str) -> str:
+ """Add a title to the document"""
+ return "=" * len(title) + f"\n{title}\n" + "=" * len(title) + "\n\n"
+
+ def rst_list_inline(self, list_: List[str], level: int = 0) -> str:
+ """Format a list using inlines"""
+ return self.headroom(level) + "[" + ", ".join(self.inline(i) for i in list_) + "]"
+
+ @staticmethod
+ def rst_ref(namespace: str, prefix: str, name: str) -> str:
+ """Add a hyperlink to the document"""
+ mappings = {'enum': 'definition',
+ 'fixed-header': 'definition',
+ 'nested-attributes': 'attribute-set',
+ 'struct': 'definition'}
+ if prefix in mappings:
+ prefix = mappings[prefix]
+ return f":ref:`{namespace}-{prefix}-{name}`"
+
+ def rst_header(self) -> str:
+ """The headers for all the auto generated RST files"""
+ lines = []
+
+ lines.append(self.rst_paragraph(".. SPDX-License-Identifier: GPL-2.0"))
+ lines.append(self.rst_paragraph(".. NOTE: This document was auto-generated.\n\n"))
+
+ return "\n".join(lines)
+
+ @staticmethod
+ def rst_toctree(maxdepth: int = 2) -> str:
+ """Generate a toctree RST primitive"""
+ lines = []
+
+ lines.append(".. toctree::")
+ lines.append(f" :maxdepth: {maxdepth}\n\n")
+
+ return "\n".join(lines)
+
+ @staticmethod
+ def rst_label(title: str) -> str:
+ """Return a formatted label"""
+ return f".. _{title}:\n\n"
+
+ @staticmethod
+ def rst_lineno(lineno: int) -> str:
+ """Return a lineno comment"""
+ return f".. LINENO {lineno}\n"
+
+class YnlDocGenerator:
+ """YAML Netlink specs Parser"""
+
+ fmt = RstFormatters()
+
+ def parse_mcast_group(self, mcast_group: List[Dict[str, Any]]) -> str:
+ """Parse 'multicast' group list and return a formatted string"""
+ lines = []
+ for group in mcast_group:
+ lines.append(self.fmt.rst_bullet(group["name"]))
+
+ return "\n".join(lines)
+
+ def parse_do(self, do_dict: Dict[str, Any], level: int = 0) -> str:
+ """Parse 'do' section and return a formatted string"""
+ lines = []
+ if LINE_STR in do_dict:
+ lines.append(self.fmt.rst_lineno(do_dict[LINE_STR]))
+
+ for key in do_dict.keys():
+ if key == LINE_STR:
+ continue
+ lines.append(self.fmt.rst_paragraph(self.fmt.bold(key), level + 1))
+ if key in ['request', 'reply']:
+ lines.append(self.parse_do_attributes(do_dict[key], level + 1) + "\n")
+ else:
+ lines.append(self.fmt.headroom(level + 2) + do_dict[key] + "\n")
+
+ return "\n".join(lines)
+
+ def parse_do_attributes(self, attrs: Dict[str, Any], level: int = 0) -> str:
+ """Parse 'attributes' section"""
+ if "attributes" not in attrs:
+ return ""
+ lines = [self.fmt.rst_fields("attributes",
+ self.fmt.rst_list_inline(attrs["attributes"]),
+ level + 1)]
+
+ return "\n".join(lines)
+
+ def parse_operations(self, operations: List[Dict[str, Any]], namespace: str) -> str:
+ """Parse operations block"""
+ preprocessed = ["name", "doc", "title", "do", "dump", "flags"]
+ linkable = ["fixed-header", "attribute-set"]
+ lines = []
+
+ for operation in operations:
+ if LINE_STR in operation:
+ lines.append(self.fmt.rst_lineno(operation[LINE_STR]))
+
+ lines.append(self.fmt.rst_section(namespace, 'operation',
+ operation["name"]))
+ lines.append(self.fmt.rst_paragraph(operation["doc"]) + "\n")
+
+ for key in operation.keys():
+ if key == LINE_STR:
+ continue
+
+ if key in preprocessed:
+ # Skip the special fields
+ continue
+ value = operation[key]
+ if key in linkable:
+ value = self.fmt.rst_ref(namespace, key, value)
+ lines.append(self.fmt.rst_fields(key, value, 0))
+ if 'flags' in operation:
+ lines.append(self.fmt.rst_fields('flags',
+ self.fmt.rst_list_inline(operation['flags'])))
+
+ if "do" in operation:
+ lines.append(self.fmt.rst_paragraph(":do:", 0))
+ lines.append(self.parse_do(operation["do"], 0))
+ if "dump" in operation:
+ lines.append(self.fmt.rst_paragraph(":dump:", 0))
+ lines.append(self.parse_do(operation["dump"], 0))
+
+ # New line after fields
+ lines.append("\n")
+
+ return "\n".join(lines)
+
+ def parse_entries(self, entries: List[Dict[str, Any]], level: int) -> str:
+ """Parse a list of entries"""
+ ignored = ["pad"]
+ lines = []
+ for entry in entries:
+ if isinstance(entry, dict):
+ # entries could be a list or a dictionary
+ field_name = entry.get("name", "")
+ if field_name in ignored:
+ continue
+ type_ = entry.get("type")
+ if type_:
+ field_name += f" ({self.fmt.inline(type_)})"
+ lines.append(
+ self.fmt.rst_fields(field_name,
+ self.fmt.sanitize(entry.get("doc", "")),
+ level)
+ )
+ elif isinstance(entry, list):
+ lines.append(self.fmt.rst_list_inline(entry, level))
+ else:
+ lines.append(self.fmt.rst_bullet(self.fmt.inline(self.fmt.sanitize(entry)),
+ level))
+
+ lines.append("\n")
+ return "\n".join(lines)
+
+ def parse_definitions(self, defs: Dict[str, Any], namespace: str) -> str:
+ """Parse definitions section"""
+ preprocessed = ["name", "entries", "members"]
+ ignored = ["render-max"] # This is not printed
+ lines = []
+
+ for definition in defs:
+ if LINE_STR in definition:
+ lines.append(self.fmt.rst_lineno(definition[LINE_STR]))
+
+ lines.append(self.fmt.rst_section(namespace, 'definition', definition["name"]))
+ for k in definition.keys():
+ if k == LINE_STR:
+ continue
+ if k in preprocessed + ignored:
+ continue
+ lines.append(self.fmt.rst_fields(k, self.fmt.sanitize(definition[k]), 0))
+
+ # Field list needs to finish with a new line
+ lines.append("\n")
+ if "entries" in definition:
+ lines.append(self.fmt.rst_paragraph(":entries:", 0))
+ lines.append(self.parse_entries(definition["entries"], 1))
+ if "members" in definition:
+ lines.append(self.fmt.rst_paragraph(":members:", 0))
+ lines.append(self.parse_entries(definition["members"], 1))
+
+ return "\n".join(lines)
+
+ def parse_attr_sets(self, entries: List[Dict[str, Any]], namespace: str) -> str:
+ """Parse attribute from attribute-set"""
+ preprocessed = ["name", "type"]
+ linkable = ["enum", "nested-attributes", "struct", "sub-message"]
+ ignored = ["checks"]
+ lines = []
+
+ for entry in entries:
+ lines.append(self.fmt.rst_section(namespace, 'attribute-set',
+ entry["name"]))
+
+ if "doc" in entry:
+ lines.append(self.fmt.rst_paragraph(entry["doc"], 0) + "\n")
+
+ for attr in entry["attributes"]:
+ if LINE_STR in attr:
+ lines.append(self.fmt.rst_lineno(attr[LINE_STR]))
+
+ type_ = attr.get("type")
+ attr_line = attr["name"]
+ if type_:
+ # Add the attribute type in the same line
+ attr_line += f" ({self.fmt.inline(type_)})"
+
+ lines.append(self.fmt.rst_subsubsection(attr_line))
+
+ for k in attr.keys():
+ if k == LINE_STR:
+ continue
+ if k in preprocessed + ignored:
+ continue
+ if k in linkable:
+ value = self.fmt.rst_ref(namespace, k, attr[k])
+ else:
+ value = self.fmt.sanitize(attr[k])
+ lines.append(self.fmt.rst_fields(k, value, 0))
+ lines.append("\n")
+
+ return "\n".join(lines)
+
+ def parse_sub_messages(self, entries: List[Dict[str, Any]], namespace: str) -> str:
+ """Parse sub-message definitions"""
+ lines = []
+
+ for entry in entries:
+ lines.append(self.fmt.rst_section(namespace, 'sub-message',
+ entry["name"]))
+ for fmt in entry["formats"]:
+ value = fmt["value"]
+
+ lines.append(self.fmt.rst_bullet(self.fmt.bold(value)))
+ for attr in ['fixed-header', 'attribute-set']:
+ if attr in fmt:
+ lines.append(self.fmt.rst_fields(attr,
+ self.fmt.rst_ref(namespace,
+ attr,
+ fmt[attr]),
+ 1))
+ lines.append("\n")
+
+ return "\n".join(lines)
+
+ def parse_yaml(self, obj: Dict[str, Any]) -> str:
+ """Format the whole YAML into a RST string"""
+ lines = []
+
+ # Main header
+ lineno = obj.get('__lineno__', 0)
+ lines.append(self.fmt.rst_lineno(lineno))
+
+ family = obj['name']
+
+ lines.append(self.fmt.rst_header())
+ lines.append(self.fmt.rst_label("netlink-" + family))
+
+ title = f"Family ``{family}`` netlink specification"
+ lines.append(self.fmt.rst_title(title))
+ lines.append(self.fmt.rst_paragraph(".. contents:: :depth: 3\n"))
+
+ if "doc" in obj:
+ lines.append(self.fmt.rst_subtitle("Summary"))
+ lines.append(self.fmt.rst_paragraph(obj["doc"], 0))
+
+ # Operations
+ if "operations" in obj:
+ lines.append(self.fmt.rst_subtitle("Operations"))
+ lines.append(self.parse_operations(obj["operations"]["list"],
+ family))
+
+ # Multicast groups
+ if "mcast-groups" in obj:
+ lines.append(self.fmt.rst_subtitle("Multicast groups"))
+ lines.append(self.parse_mcast_group(obj["mcast-groups"]["list"]))
+
+ # Definitions
+ if "definitions" in obj:
+ lines.append(self.fmt.rst_subtitle("Definitions"))
+ lines.append(self.parse_definitions(obj["definitions"], family))
+
+ # Attributes set
+ if "attribute-sets" in obj:
+ lines.append(self.fmt.rst_subtitle("Attribute sets"))
+ lines.append(self.parse_attr_sets(obj["attribute-sets"], family))
+
+ # Sub-messages
+ if "sub-messages" in obj:
+ lines.append(self.fmt.rst_subtitle("Sub-messages"))
+ lines.append(self.parse_sub_messages(obj["sub-messages"], family))
+
+ return "\n".join(lines)
+
+ # Main functions
+ # ==============
+
+ def parse_yaml_file(self, filename: str) -> str:
+ """Transform the YAML specified by filename into an RST-formatted string"""
+ with open(filename, "r", encoding="utf-8") as spec_file:
+ numbered_yaml = yaml.load(spec_file, Loader=NumberedSafeLoader)
+ content = self.parse_yaml(numbered_yaml)
+
+ return content
diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/pyynl/lib/nlspec.py
index 37bcb4d8b37b..85c17fe01e35 100644
--- a/tools/net/ynl/lib/nlspec.py
+++ b/tools/net/ynl/pyynl/lib/nlspec.py
@@ -131,6 +131,9 @@ class SpecEnumSet(SpecElement):
def has_doc(self):
if 'doc' in self.yaml:
return True
+ return self.has_entry_doc()
+
+ def has_entry_doc(self):
for entry in self.entries.values():
if entry.has_doc():
return True
@@ -144,11 +147,12 @@ class SpecEnumSet(SpecElement):
class SpecAttr(SpecElement):
- """ Single Netlink atttribute type
+ """ Single Netlink attribute type
Represents a single attribute type within an attr space.
Attributes:
+ type string, attribute type
value numerical ID when serialized
attr_set Attribute Set containing this attr
is_multi bool, attr may repeat multiple times
@@ -157,10 +161,16 @@ class SpecAttr(SpecElement):
len integer, optional byte length of binary types
display_hint string, hint to help choose format specifier
when displaying the value
+ sub_message string, name of sub message type
+ selector string, name of attribute used to select
+ sub-message type
+
+ is_auto_scalar bool, attr is a variable-size scalar
"""
def __init__(self, family, attr_set, yaml, value):
super().__init__(family, yaml)
+ self.type = yaml['type']
self.value = value
self.attr_set = attr_set
self.is_multi = yaml.get('multi-attr', False)
@@ -169,6 +179,10 @@ class SpecAttr(SpecElement):
self.byte_order = yaml.get('byte-order')
self.len = yaml.get('len')
self.display_hint = yaml.get('display-hint')
+ self.sub_message = yaml.get('sub-message')
+ self.selector = yaml.get('selector')
+
+ self.is_auto_scalar = self.type == "sint" or self.type == "uint"
class SpecAttrSet(SpecElement):
@@ -205,7 +219,10 @@ class SpecAttrSet(SpecElement):
else:
real_set = family.attr_sets[self.subset_of]
for elem in self.yaml['attributes']:
- attr = real_set[elem['name']]
+ real_attr = real_set[elem['name']]
+ combined_elem = real_attr.yaml | elem
+ attr = self.new_attr(combined_elem, real_attr.value)
+
self.attrs[attr.name] = attr
self.attrs_by_val[attr.value] = attr
@@ -237,6 +254,7 @@ class SpecStructMember(SpecElement):
len integer, optional byte length of binary types
display_hint string, hint to help choose format specifier
when displaying the value
+ struct string, name of nested struct type
"""
def __init__(self, family, yaml):
super().__init__(family, yaml)
@@ -245,6 +263,7 @@ class SpecStructMember(SpecElement):
self.enum = yaml.get('enum')
self.len = yaml.get('len')
self.display_hint = yaml.get('display-hint')
+ self.struct = yaml.get('struct')
class SpecStruct(SpecElement):
@@ -272,6 +291,46 @@ class SpecStruct(SpecElement):
return self.members.items()
+class SpecSubMessage(SpecElement):
+ """ Netlink sub-message definition
+
+ Represents a set of sub-message formats for polymorphic nlattrs
+ that contain type-specific sub messages.
+
+ Attributes:
+ name string, name of sub-message definition
+ formats dict of sub-message formats indexed by match value
+ """
+ def __init__(self, family, yaml):
+ super().__init__(family, yaml)
+
+ self.formats = collections.OrderedDict()
+ for elem in self.yaml['formats']:
+ format = self.new_format(family, elem)
+ self.formats[format.value] = format
+
+ def new_format(self, family, format):
+ return SpecSubMessageFormat(family, format)
+
+
+class SpecSubMessageFormat(SpecElement):
+ """ Netlink sub-message format definition
+
+ Represents a single format for a sub-message.
+
+ Attributes:
+ value attribute value to match against type selector
+ fixed_header string, name of fixed header, or None
+ attr_set string, name of attribute set, or None
+ """
+ def __init__(self, family, yaml):
+ super().__init__(family, yaml)
+
+ self.value = yaml.get('value')
+ self.fixed_header = yaml.get('fixed-header')
+ self.attr_set = yaml.get('attribute-set')
+
+
class SpecOperation(SpecElement):
"""Netlink Operation
@@ -282,6 +341,7 @@ class SpecOperation(SpecElement):
req_value numerical ID when serialized, user -> kernel
rsp_value numerical ID when serialized, user <- kernel
+ modes supported operation modes (do, dump, event etc.)
is_call bool, whether the operation is a call
is_async bool, whether the operation is a notification
is_resv bool, whether the operation does not exist (it's just a reserved ID)
@@ -297,6 +357,7 @@ class SpecOperation(SpecElement):
self.req_value = req_value
self.rsp_value = rsp_value
+ self.modes = yaml.keys() & {'do', 'dump', 'event', 'notify'}
self.is_call = 'do' in yaml or 'dump' in yaml
self.is_async = 'notify' in yaml or 'event' in yaml
self.is_resv = not self.is_async and not self.is_call
@@ -359,11 +420,13 @@ class SpecFamily(SpecElement):
attr_sets dict of attribute sets
msgs dict of all messages (index by name)
+ sub_msgs dict of all sub messages (index by name)
ops dict of all valid requests / responses
ntfs dict of all async events
consts dict of all constants/enums
fixed_header string, optional name of family default fixed header struct
mcast_groups dict of all multicast groups (index by name)
+ kernel_family dict of kernel family attributes
"""
def __init__(self, spec_path, schema_path=None, exclude_ops=None):
with open(spec_path, "r") as stream:
@@ -399,6 +462,7 @@ class SpecFamily(SpecElement):
jsonschema.validate(self.yaml, schema)
self.attr_sets = collections.OrderedDict()
+ self.sub_msgs = collections.OrderedDict()
self.msgs = collections.OrderedDict()
self.req_by_value = collections.OrderedDict()
self.rsp_by_value = collections.OrderedDict()
@@ -406,6 +470,7 @@ class SpecFamily(SpecElement):
self.ntfs = collections.OrderedDict()
self.consts = collections.OrderedDict()
self.mcast_groups = collections.OrderedDict()
+ self.kernel_family = collections.OrderedDict(self.yaml.get('kernel-family', {}))
last_exception = None
while len(self._resolution_list) > 0:
@@ -435,6 +500,9 @@ class SpecFamily(SpecElement):
def new_struct(self, elem):
return SpecStruct(self, elem)
+ def new_sub_message(self, elem):
+ return SpecSubMessage(self, elem)
+
def new_operation(self, elem, req_val, rsp_val):
return SpecOperation(self, elem, req_val, rsp_val)
@@ -523,6 +591,10 @@ class SpecFamily(SpecElement):
attr_set = self.new_attr_set(elem)
self.attr_sets[elem['name']] = attr_set
+ for elem in self.yaml.get('sub-messages', []):
+ sub_message = self.new_sub_message(elem)
+ self.sub_msgs[sub_message.name] = sub_message
+
if self.msg_id_model == 'unified':
self._dictify_ops_unified()
elif self.msg_id_model == 'directional':
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py
new file mode 100644
index 000000000000..36d36eb7e3b8
--- /dev/null
+++ b/tools/net/ynl/pyynl/lib/ynl.py
@@ -0,0 +1,1168 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+from collections import namedtuple
+from enum import Enum
+import functools
+import os
+import random
+import socket
+import struct
+from struct import Struct
+import sys
+import ipaddress
+import uuid
+import queue
+import selectors
+import time
+
+from .nlspec import SpecFamily
+
+#
+# Generic Netlink code which should really be in some library, but I can't quickly find one.
+#
+
+
+class Netlink:
+ # Netlink socket
+ SOL_NETLINK = 270
+
+ NETLINK_ADD_MEMBERSHIP = 1
+ NETLINK_CAP_ACK = 10
+ NETLINK_EXT_ACK = 11
+ NETLINK_GET_STRICT_CHK = 12
+
+ # Netlink message
+ NLMSG_ERROR = 2
+ NLMSG_DONE = 3
+
+ NLM_F_REQUEST = 1
+ NLM_F_ACK = 4
+ NLM_F_ROOT = 0x100
+ NLM_F_MATCH = 0x200
+
+ NLM_F_REPLACE = 0x100
+ NLM_F_EXCL = 0x200
+ NLM_F_CREATE = 0x400
+ NLM_F_APPEND = 0x800
+
+ NLM_F_CAPPED = 0x100
+ NLM_F_ACK_TLVS = 0x200
+
+ NLM_F_DUMP = NLM_F_ROOT | NLM_F_MATCH
+
+ NLA_F_NESTED = 0x8000
+ NLA_F_NET_BYTEORDER = 0x4000
+
+ NLA_TYPE_MASK = NLA_F_NESTED | NLA_F_NET_BYTEORDER
+
+ # Genetlink defines
+ NETLINK_GENERIC = 16
+
+ GENL_ID_CTRL = 0x10
+
+ # nlctrl
+ CTRL_CMD_GETFAMILY = 3
+
+ CTRL_ATTR_FAMILY_ID = 1
+ CTRL_ATTR_FAMILY_NAME = 2
+ CTRL_ATTR_MAXATTR = 5
+ CTRL_ATTR_MCAST_GROUPS = 7
+
+ CTRL_ATTR_MCAST_GRP_NAME = 1
+ CTRL_ATTR_MCAST_GRP_ID = 2
+
+ # Extack types
+ NLMSGERR_ATTR_MSG = 1
+ NLMSGERR_ATTR_OFFS = 2
+ NLMSGERR_ATTR_COOKIE = 3
+ NLMSGERR_ATTR_POLICY = 4
+ NLMSGERR_ATTR_MISS_TYPE = 5
+ NLMSGERR_ATTR_MISS_NEST = 6
+
+ # Policy types
+ NL_POLICY_TYPE_ATTR_TYPE = 1
+ NL_POLICY_TYPE_ATTR_MIN_VALUE_S = 2
+ NL_POLICY_TYPE_ATTR_MAX_VALUE_S = 3
+ NL_POLICY_TYPE_ATTR_MIN_VALUE_U = 4
+ NL_POLICY_TYPE_ATTR_MAX_VALUE_U = 5
+ NL_POLICY_TYPE_ATTR_MIN_LENGTH = 6
+ NL_POLICY_TYPE_ATTR_MAX_LENGTH = 7
+ NL_POLICY_TYPE_ATTR_POLICY_IDX = 8
+ NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE = 9
+ NL_POLICY_TYPE_ATTR_BITFIELD32_MASK = 10
+ NL_POLICY_TYPE_ATTR_PAD = 11
+ NL_POLICY_TYPE_ATTR_MASK = 12
+
+ AttrType = Enum('AttrType', ['flag', 'u8', 'u16', 'u32', 'u64',
+ 's8', 's16', 's32', 's64',
+ 'binary', 'string', 'nul-string',
+ 'nested', 'nested-array',
+ 'bitfield32', 'sint', 'uint'])
+
+class NlError(Exception):
+ def __init__(self, nl_msg):
+ self.nl_msg = nl_msg
+ self.error = -nl_msg.error
+
+ def __str__(self):
+ msg = "Netlink error: "
+
+ extack = self.nl_msg.extack.copy() if self.nl_msg.extack else {}
+ if 'msg' in extack:
+ msg += extack['msg'] + ': '
+ del extack['msg']
+ msg += os.strerror(self.error)
+ if extack:
+ msg += ' ' + str(extack)
+ return msg
+
+
+class ConfigError(Exception):
+ pass
+
+
+class NlAttr:
+ ScalarFormat = namedtuple('ScalarFormat', ['native', 'big', 'little'])
+ type_formats = {
+ 'u8' : ScalarFormat(Struct('B'), Struct("B"), Struct("B")),
+ 's8' : ScalarFormat(Struct('b'), Struct("b"), Struct("b")),
+ 'u16': ScalarFormat(Struct('H'), Struct(">H"), Struct("<H")),
+ 's16': ScalarFormat(Struct('h'), Struct(">h"), Struct("<h")),
+ 'u32': ScalarFormat(Struct('I'), Struct(">I"), Struct("<I")),
+ 's32': ScalarFormat(Struct('i'), Struct(">i"), Struct("<i")),
+ 'u64': ScalarFormat(Struct('Q'), Struct(">Q"), Struct("<Q")),
+ 's64': ScalarFormat(Struct('q'), Struct(">q"), Struct("<q"))
+ }
+
+ def __init__(self, raw, offset):
+ self._len, self._type = struct.unpack("HH", raw[offset : offset + 4])
+ self.type = self._type & ~Netlink.NLA_TYPE_MASK
+ self.is_nest = self._type & Netlink.NLA_F_NESTED
+ self.payload_len = self._len
+ self.full_len = (self.payload_len + 3) & ~3
+ self.raw = raw[offset + 4 : offset + self.payload_len]
+
+ @classmethod
+ def get_format(cls, attr_type, byte_order=None):
+ format = cls.type_formats[attr_type]
+ if byte_order:
+ return format.big if byte_order == "big-endian" \
+ else format.little
+ return format.native
+
+ def as_scalar(self, attr_type, byte_order=None):
+ format = self.get_format(attr_type, byte_order)
+ return format.unpack(self.raw)[0]
+
+ def as_auto_scalar(self, attr_type, byte_order=None):
+ if len(self.raw) != 4 and len(self.raw) != 8:
+ raise Exception(f"Auto-scalar len payload be 4 or 8 bytes, got {len(self.raw)}")
+ real_type = attr_type[0] + str(len(self.raw) * 8)
+ format = self.get_format(real_type, byte_order)
+ return format.unpack(self.raw)[0]
+
+ def as_strz(self):
+ return self.raw.decode('ascii')[:-1]
+
+ def as_bin(self):
+ return self.raw
+
+ def as_c_array(self, type):
+ format = self.get_format(type)
+ return [ x[0] for x in format.iter_unpack(self.raw) ]
+
+ def __repr__(self):
+ return f"[type:{self.type} len:{self._len}] {self.raw}"
+
+
+class NlAttrs:
+ def __init__(self, msg, offset=0):
+ self.attrs = []
+
+ while offset < len(msg):
+ attr = NlAttr(msg, offset)
+ offset += attr.full_len
+ self.attrs.append(attr)
+
+ def __iter__(self):
+ yield from self.attrs
+
+ def __repr__(self):
+ msg = ''
+ for a in self.attrs:
+ if msg:
+ msg += '\n'
+ msg += repr(a)
+ return msg
+
+
+class NlMsg:
+ def __init__(self, msg, offset, attr_space=None):
+ self.hdr = msg[offset : offset + 16]
+
+ self.nl_len, self.nl_type, self.nl_flags, self.nl_seq, self.nl_portid = \
+ struct.unpack("IHHII", self.hdr)
+
+ self.raw = msg[offset + 16 : offset + self.nl_len]
+
+ self.error = 0
+ self.done = 0
+
+ extack_off = None
+ if self.nl_type == Netlink.NLMSG_ERROR:
+ self.error = struct.unpack("i", self.raw[0:4])[0]
+ self.done = 1
+ extack_off = 20
+ elif self.nl_type == Netlink.NLMSG_DONE:
+ self.error = struct.unpack("i", self.raw[0:4])[0]
+ self.done = 1
+ extack_off = 4
+
+ self.extack = None
+ if self.nl_flags & Netlink.NLM_F_ACK_TLVS and extack_off:
+ self.extack = dict()
+ extack_attrs = NlAttrs(self.raw[extack_off:])
+ for extack in extack_attrs:
+ if extack.type == Netlink.NLMSGERR_ATTR_MSG:
+ self.extack['msg'] = extack.as_strz()
+ elif extack.type == Netlink.NLMSGERR_ATTR_MISS_TYPE:
+ self.extack['miss-type'] = extack.as_scalar('u32')
+ elif extack.type == Netlink.NLMSGERR_ATTR_MISS_NEST:
+ self.extack['miss-nest'] = extack.as_scalar('u32')
+ elif extack.type == Netlink.NLMSGERR_ATTR_OFFS:
+ self.extack['bad-attr-offs'] = extack.as_scalar('u32')
+ elif extack.type == Netlink.NLMSGERR_ATTR_POLICY:
+ self.extack['policy'] = self._decode_policy(extack.raw)
+ else:
+ if 'unknown' not in self.extack:
+ self.extack['unknown'] = []
+ self.extack['unknown'].append(extack)
+
+ if attr_space:
+ self.annotate_extack(attr_space)
+
+ def _decode_policy(self, raw):
+ policy = {}
+ for attr in NlAttrs(raw):
+ if attr.type == Netlink.NL_POLICY_TYPE_ATTR_TYPE:
+ type = attr.as_scalar('u32')
+ policy['type'] = Netlink.AttrType(type).name
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MIN_VALUE_S:
+ policy['min-value'] = attr.as_scalar('s64')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MAX_VALUE_S:
+ policy['max-value'] = attr.as_scalar('s64')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MIN_VALUE_U:
+ policy['min-value'] = attr.as_scalar('u64')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MAX_VALUE_U:
+ policy['max-value'] = attr.as_scalar('u64')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MIN_LENGTH:
+ policy['min-length'] = attr.as_scalar('u32')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MAX_LENGTH:
+ policy['max-length'] = attr.as_scalar('u32')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_BITFIELD32_MASK:
+ policy['bitfield32-mask'] = attr.as_scalar('u32')
+ elif attr.type == Netlink.NL_POLICY_TYPE_ATTR_MASK:
+ policy['mask'] = attr.as_scalar('u64')
+ return policy
+
+ def annotate_extack(self, attr_space):
+ """ Make extack more human friendly with attribute information """
+
+ # We don't have the ability to parse nests yet, so only do global
+ if 'miss-type' in self.extack and 'miss-nest' not in self.extack:
+ miss_type = self.extack['miss-type']
+ if miss_type in attr_space.attrs_by_val:
+ spec = attr_space.attrs_by_val[miss_type]
+ self.extack['miss-type'] = spec['name']
+ if 'doc' in spec:
+ self.extack['miss-type-doc'] = spec['doc']
+
+ def cmd(self):
+ return self.nl_type
+
+ def __repr__(self):
+ msg = f"nl_len = {self.nl_len} ({len(self.raw)}) nl_flags = 0x{self.nl_flags:x} nl_type = {self.nl_type}"
+ if self.error:
+ msg += '\n\terror: ' + str(self.error)
+ if self.extack:
+ msg += '\n\textack: ' + repr(self.extack)
+ return msg
+
+
+class NlMsgs:
+ def __init__(self, data):
+ self.msgs = []
+
+ offset = 0
+ while offset < len(data):
+ msg = NlMsg(data, offset)
+ offset += msg.nl_len
+ self.msgs.append(msg)
+
+ def __iter__(self):
+ yield from self.msgs
+
+
+genl_family_name_to_id = None
+
+
+def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None):
+ # we prepend length in _genl_msg_finalize()
+ if seq is None:
+ seq = random.randint(1, 1024)
+ nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
+ genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0)
+ return nlmsg + genlmsg
+
+
+def _genl_msg_finalize(msg):
+ return struct.pack("I", len(msg) + 4) + msg
+
+
+def _genl_load_families():
+ with socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, Netlink.NETLINK_GENERIC) as sock:
+ sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1)
+
+ msg = _genl_msg(Netlink.GENL_ID_CTRL,
+ Netlink.NLM_F_REQUEST | Netlink.NLM_F_ACK | Netlink.NLM_F_DUMP,
+ Netlink.CTRL_CMD_GETFAMILY, 1)
+ msg = _genl_msg_finalize(msg)
+
+ sock.send(msg, 0)
+
+ global genl_family_name_to_id
+ genl_family_name_to_id = dict()
+
+ while True:
+ reply = sock.recv(128 * 1024)
+ nms = NlMsgs(reply)
+ for nl_msg in nms:
+ if nl_msg.error:
+ print("Netlink error:", nl_msg.error)
+ return
+ if nl_msg.done:
+ return
+
+ gm = GenlMsg(nl_msg)
+ fam = dict()
+ for attr in NlAttrs(gm.raw):
+ if attr.type == Netlink.CTRL_ATTR_FAMILY_ID:
+ fam['id'] = attr.as_scalar('u16')
+ elif attr.type == Netlink.CTRL_ATTR_FAMILY_NAME:
+ fam['name'] = attr.as_strz()
+ elif attr.type == Netlink.CTRL_ATTR_MAXATTR:
+ fam['maxattr'] = attr.as_scalar('u32')
+ elif attr.type == Netlink.CTRL_ATTR_MCAST_GROUPS:
+ fam['mcast'] = dict()
+ for entry in NlAttrs(attr.raw):
+ mcast_name = None
+ mcast_id = None
+ for entry_attr in NlAttrs(entry.raw):
+ if entry_attr.type == Netlink.CTRL_ATTR_MCAST_GRP_NAME:
+ mcast_name = entry_attr.as_strz()
+ elif entry_attr.type == Netlink.CTRL_ATTR_MCAST_GRP_ID:
+ mcast_id = entry_attr.as_scalar('u32')
+ if mcast_name and mcast_id is not None:
+ fam['mcast'][mcast_name] = mcast_id
+ if 'name' in fam and 'id' in fam:
+ genl_family_name_to_id[fam['name']] = fam
+
+
+class GenlMsg:
+ def __init__(self, nl_msg):
+ self.nl = nl_msg
+ self.genl_cmd, self.genl_version, _ = struct.unpack_from("BBH", nl_msg.raw, 0)
+ self.raw = nl_msg.raw[4:]
+
+ def cmd(self):
+ return self.genl_cmd
+
+ def __repr__(self):
+ msg = repr(self.nl)
+ msg += f"\tgenl_cmd = {self.genl_cmd} genl_ver = {self.genl_version}\n"
+ for a in self.raw_attrs:
+ msg += '\t\t' + repr(a) + '\n'
+ return msg
+
+
+class NetlinkProtocol:
+ def __init__(self, family_name, proto_num):
+ self.family_name = family_name
+ self.proto_num = proto_num
+
+ def _message(self, nl_type, nl_flags, seq=None):
+ if seq is None:
+ seq = random.randint(1, 1024)
+ nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
+ return nlmsg
+
+ def message(self, flags, command, version, seq=None):
+ return self._message(command, flags, seq)
+
+ def _decode(self, nl_msg):
+ return nl_msg
+
+ def decode(self, ynl, nl_msg, op):
+ msg = self._decode(nl_msg)
+ if op is None:
+ op = ynl.rsp_by_value[msg.cmd()]
+ fixed_header_size = ynl._struct_size(op.fixed_header)
+ msg.raw_attrs = NlAttrs(msg.raw, fixed_header_size)
+ return msg
+
+ def get_mcast_id(self, mcast_name, mcast_groups):
+ if mcast_name not in mcast_groups:
+ raise Exception(f'Multicast group "{mcast_name}" not present in the spec')
+ return mcast_groups[mcast_name].value
+
+ def msghdr_size(self):
+ return 16
+
+
+class GenlProtocol(NetlinkProtocol):
+ def __init__(self, family_name):
+ super().__init__(family_name, Netlink.NETLINK_GENERIC)
+
+ global genl_family_name_to_id
+ if genl_family_name_to_id is None:
+ _genl_load_families()
+
+ self.genl_family = genl_family_name_to_id[family_name]
+ self.family_id = genl_family_name_to_id[family_name]['id']
+
+ def message(self, flags, command, version, seq=None):
+ nlmsg = self._message(self.family_id, flags, seq)
+ genlmsg = struct.pack("BBH", command, version, 0)
+ return nlmsg + genlmsg
+
+ def _decode(self, nl_msg):
+ return GenlMsg(nl_msg)
+
+ def get_mcast_id(self, mcast_name, mcast_groups):
+ if mcast_name not in self.genl_family['mcast']:
+ raise Exception(f'Multicast group "{mcast_name}" not present in the family')
+ return self.genl_family['mcast'][mcast_name]
+
+ def msghdr_size(self):
+ return super().msghdr_size() + 4
+
+
+class SpaceAttrs:
+ SpecValuesPair = namedtuple('SpecValuesPair', ['spec', 'values'])
+
+ def __init__(self, attr_space, attrs, outer = None):
+ outer_scopes = outer.scopes if outer else []
+ inner_scope = self.SpecValuesPair(attr_space, attrs)
+ self.scopes = [inner_scope] + outer_scopes
+
+ def lookup(self, name):
+ for scope in self.scopes:
+ if name in scope.spec:
+ if name in scope.values:
+ return scope.values[name]
+ spec_name = scope.spec.yaml['name']
+ raise Exception(
+ f"No value for '{name}' in attribute space '{spec_name}'")
+ raise Exception(f"Attribute '{name}' not defined in any attribute-set")
+
+
+#
+# YNL implementation details.
+#
+
+
+class YnlFamily(SpecFamily):
+ def __init__(self, def_path, schema=None, process_unknown=False,
+ recv_size=0):
+ super().__init__(def_path, schema)
+
+ self.include_raw = False
+ self.process_unknown = process_unknown
+
+ try:
+ if self.proto == "netlink-raw":
+ self.nlproto = NetlinkProtocol(self.yaml['name'],
+ self.yaml['protonum'])
+ else:
+ self.nlproto = GenlProtocol(self.yaml['name'])
+ except KeyError:
+ raise Exception(f"Family '{self.yaml['name']}' not supported by the kernel")
+
+ self._recv_dbg = False
+ # Note that netlink will use conservative (min) message size for
+ # the first dump recv() on the socket, our setting will only matter
+ # from the second recv() on.
+ self._recv_size = recv_size if recv_size else 131072
+ # Netlink will always allocate at least PAGE_SIZE - sizeof(skb_shinfo)
+ # for a message, so smaller receive sizes will lead to truncation.
+ # Note that the min size for other families may be larger than 4k!
+ if self._recv_size < 4000:
+ raise ConfigError()
+
+ self.sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, self.nlproto.proto_num)
+ self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_CAP_ACK, 1)
+ self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_EXT_ACK, 1)
+ self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_GET_STRICT_CHK, 1)
+
+ self.async_msg_ids = set()
+ self.async_msg_queue = queue.Queue()
+
+ for msg in self.msgs.values():
+ if msg.is_async:
+ self.async_msg_ids.add(msg.rsp_value)
+
+ for op_name, op in self.ops.items():
+ bound_f = functools.partial(self._op, op_name)
+ setattr(self, op.ident_name, bound_f)
+
+
+ def ntf_subscribe(self, mcast_name):
+ mcast_id = self.nlproto.get_mcast_id(mcast_name, self.mcast_groups)
+ self.sock.bind((0, 0))
+ self.sock.setsockopt(Netlink.SOL_NETLINK, Netlink.NETLINK_ADD_MEMBERSHIP,
+ mcast_id)
+
+ def set_recv_dbg(self, enabled):
+ self._recv_dbg = enabled
+
+ def _recv_dbg_print(self, reply, nl_msgs):
+ if not self._recv_dbg:
+ return
+ print("Recv: read", len(reply), "bytes,",
+ len(nl_msgs.msgs), "messages", file=sys.stderr)
+ for nl_msg in nl_msgs:
+ print(" ", nl_msg, file=sys.stderr)
+
+ def _encode_enum(self, attr_spec, value):
+ enum = self.consts[attr_spec['enum']]
+ if enum.type == 'flags' or attr_spec.get('enum-as-flags', False):
+ scalar = 0
+ if isinstance(value, str):
+ value = [value]
+ for single_value in value:
+ scalar += enum.entries[single_value].user_value(as_flags = True)
+ return scalar
+ else:
+ return enum.entries[value].user_value()
+
+ def _get_scalar(self, attr_spec, value):
+ try:
+ return int(value)
+ except (ValueError, TypeError) as e:
+ if 'enum' in attr_spec:
+ return self._encode_enum(attr_spec, value)
+ if attr_spec.display_hint:
+ return self._from_string(value, attr_spec)
+ raise e
+
+ def _add_attr(self, space, name, value, search_attrs):
+ try:
+ attr = self.attr_sets[space][name]
+ except KeyError:
+ raise Exception(f"Space '{space}' has no attribute '{name}'")
+ nl_type = attr.value
+
+ if attr.is_multi and isinstance(value, list):
+ attr_payload = b''
+ for subvalue in value:
+ attr_payload += self._add_attr(space, name, subvalue, search_attrs)
+ return attr_payload
+
+ if attr["type"] == 'nest':
+ nl_type |= Netlink.NLA_F_NESTED
+ sub_space = attr['nested-attributes']
+ attr_payload = self._add_nest_attrs(value, sub_space, search_attrs)
+ elif attr['type'] == 'indexed-array' and attr['sub-type'] == 'nest':
+ nl_type |= Netlink.NLA_F_NESTED
+ sub_space = attr['nested-attributes']
+ attr_payload = self._encode_indexed_array(value, sub_space,
+ search_attrs)
+ elif attr["type"] == 'flag':
+ if not value:
+ # If value is absent or false then skip attribute creation.
+ return b''
+ attr_payload = b''
+ elif attr["type"] == 'string':
+ attr_payload = str(value).encode('ascii') + b'\x00'
+ elif attr["type"] == 'binary':
+ if value is None:
+ attr_payload = b''
+ elif isinstance(value, bytes):
+ attr_payload = value
+ elif isinstance(value, str):
+ if attr.display_hint:
+ attr_payload = self._from_string(value, attr)
+ else:
+ attr_payload = bytes.fromhex(value)
+ elif isinstance(value, dict) and attr.struct_name:
+ attr_payload = self._encode_struct(attr.struct_name, value)
+ elif isinstance(value, list) and attr.sub_type in NlAttr.type_formats:
+ format = NlAttr.get_format(attr.sub_type)
+ attr_payload = b''.join([format.pack(x) for x in value])
+ else:
+ raise Exception(f'Unknown type for binary attribute, value: {value}')
+ elif attr['type'] in NlAttr.type_formats or attr.is_auto_scalar:
+ scalar = self._get_scalar(attr, value)
+ if attr.is_auto_scalar:
+ attr_type = attr["type"][0] + ('32' if scalar.bit_length() <= 32 else '64')
+ else:
+ attr_type = attr["type"]
+ format = NlAttr.get_format(attr_type, attr.byte_order)
+ attr_payload = format.pack(scalar)
+ elif attr['type'] in "bitfield32":
+ scalar_value = self._get_scalar(attr, value["value"])
+ scalar_selector = self._get_scalar(attr, value["selector"])
+ attr_payload = struct.pack("II", scalar_value, scalar_selector)
+ elif attr['type'] == 'sub-message':
+ msg_format, _ = self._resolve_selector(attr, search_attrs)
+ attr_payload = b''
+ if msg_format.fixed_header:
+ attr_payload += self._encode_struct(msg_format.fixed_header, value)
+ if msg_format.attr_set:
+ if msg_format.attr_set in self.attr_sets:
+ nl_type |= Netlink.NLA_F_NESTED
+ sub_attrs = SpaceAttrs(msg_format.attr_set, value, search_attrs)
+ for subname, subvalue in value.items():
+ attr_payload += self._add_attr(msg_format.attr_set,
+ subname, subvalue, sub_attrs)
+ else:
+ raise Exception(f"Unknown attribute-set '{msg_format.attr_set}'")
+ else:
+ raise Exception(f'Unknown type at {space} {name} {value} {attr["type"]}')
+
+ return self._add_attr_raw(nl_type, attr_payload)
+
+ def _add_attr_raw(self, nl_type, attr_payload):
+ pad = b'\x00' * ((4 - len(attr_payload) % 4) % 4)
+ return struct.pack('HH', len(attr_payload) + 4, nl_type) + attr_payload + pad
+
+ def _add_nest_attrs(self, value, sub_space, search_attrs):
+ sub_attrs = SpaceAttrs(self.attr_sets[sub_space], value, search_attrs)
+ attr_payload = b''
+ for subname, subvalue in value.items():
+ attr_payload += self._add_attr(sub_space, subname, subvalue,
+ sub_attrs)
+ return attr_payload
+
+ def _encode_indexed_array(self, vals, sub_space, search_attrs):
+ attr_payload = b''
+ for i, val in enumerate(vals):
+ idx = i | Netlink.NLA_F_NESTED
+ val_payload = self._add_nest_attrs(val, sub_space, search_attrs)
+ attr_payload += self._add_attr_raw(idx, val_payload)
+ return attr_payload
+
+ def _get_enum_or_unknown(self, enum, raw):
+ try:
+ name = enum.entries_by_val[raw].name
+ except KeyError as error:
+ if self.process_unknown:
+ name = f"Unknown({raw})"
+ else:
+ raise error
+ return name
+
+ def _decode_enum(self, raw, attr_spec):
+ enum = self.consts[attr_spec['enum']]
+ if enum.type == 'flags' or attr_spec.get('enum-as-flags', False):
+ i = 0
+ value = set()
+ while raw:
+ if raw & 1:
+ value.add(self._get_enum_or_unknown(enum, i))
+ raw >>= 1
+ i += 1
+ else:
+ value = self._get_enum_or_unknown(enum, raw)
+ return value
+
+ def _decode_binary(self, attr, attr_spec):
+ if attr_spec.struct_name:
+ decoded = self._decode_struct(attr.raw, attr_spec.struct_name)
+ elif attr_spec.sub_type:
+ decoded = attr.as_c_array(attr_spec.sub_type)
+ if 'enum' in attr_spec:
+ decoded = [ self._decode_enum(x, attr_spec) for x in decoded ]
+ elif attr_spec.display_hint:
+ decoded = [ self._formatted_string(x, attr_spec.display_hint)
+ for x in decoded ]
+ else:
+ decoded = attr.as_bin()
+ if attr_spec.display_hint:
+ decoded = self._formatted_string(decoded, attr_spec.display_hint)
+ return decoded
+
+ def _decode_array_attr(self, attr, attr_spec):
+ decoded = []
+ offset = 0
+ while offset < len(attr.raw):
+ item = NlAttr(attr.raw, offset)
+ offset += item.full_len
+
+ if attr_spec["sub-type"] == 'nest':
+ subattrs = self._decode(NlAttrs(item.raw), attr_spec['nested-attributes'])
+ decoded.append({ item.type: subattrs })
+ elif attr_spec["sub-type"] == 'binary':
+ subattr = item.as_bin()
+ if attr_spec.display_hint:
+ subattr = self._formatted_string(subattr, attr_spec.display_hint)
+ decoded.append(subattr)
+ elif attr_spec["sub-type"] in NlAttr.type_formats:
+ subattr = item.as_scalar(attr_spec['sub-type'], attr_spec.byte_order)
+ if 'enum' in attr_spec:
+ subattr = self._decode_enum(subattr, attr_spec)
+ elif attr_spec.display_hint:
+ subattr = self._formatted_string(subattr, attr_spec.display_hint)
+ decoded.append(subattr)
+ else:
+ raise Exception(f'Unknown {attr_spec["sub-type"]} with name {attr_spec["name"]}')
+ return decoded
+
+ def _decode_nest_type_value(self, attr, attr_spec):
+ decoded = {}
+ value = attr
+ for name in attr_spec['type-value']:
+ value = NlAttr(value.raw, 0)
+ decoded[name] = value.type
+ subattrs = self._decode(NlAttrs(value.raw), attr_spec['nested-attributes'])
+ decoded.update(subattrs)
+ return decoded
+
+ def _decode_unknown(self, attr):
+ if attr.is_nest:
+ return self._decode(NlAttrs(attr.raw), None)
+ else:
+ return attr.as_bin()
+
+ def _rsp_add(self, rsp, name, is_multi, decoded):
+ if is_multi is None:
+ if name in rsp and type(rsp[name]) is not list:
+ rsp[name] = [rsp[name]]
+ is_multi = True
+ else:
+ is_multi = False
+
+ if not is_multi:
+ rsp[name] = decoded
+ elif name in rsp:
+ rsp[name].append(decoded)
+ else:
+ rsp[name] = [decoded]
+
+ def _resolve_selector(self, attr_spec, search_attrs):
+ sub_msg = attr_spec.sub_message
+ if sub_msg not in self.sub_msgs:
+ raise Exception(f"No sub-message spec named {sub_msg} for {attr_spec.name}")
+ sub_msg_spec = self.sub_msgs[sub_msg]
+
+ selector = attr_spec.selector
+ value = search_attrs.lookup(selector)
+ if value not in sub_msg_spec.formats:
+ raise Exception(f"No message format for '{value}' in sub-message spec '{sub_msg}'")
+
+ spec = sub_msg_spec.formats[value]
+ return spec, value
+
+ def _decode_sub_msg(self, attr, attr_spec, search_attrs):
+ msg_format, _ = self._resolve_selector(attr_spec, search_attrs)
+ decoded = {}
+ offset = 0
+ if msg_format.fixed_header:
+ decoded.update(self._decode_struct(attr.raw, msg_format.fixed_header))
+ offset = self._struct_size(msg_format.fixed_header)
+ if msg_format.attr_set:
+ if msg_format.attr_set in self.attr_sets:
+ subdict = self._decode(NlAttrs(attr.raw, offset), msg_format.attr_set)
+ decoded.update(subdict)
+ else:
+ raise Exception(f"Unknown attribute-set '{msg_format.attr_set}' when decoding '{attr_spec.name}'")
+ return decoded
+
+ def _decode(self, attrs, space, outer_attrs = None):
+ rsp = dict()
+ if space:
+ attr_space = self.attr_sets[space]
+ search_attrs = SpaceAttrs(attr_space, rsp, outer_attrs)
+
+ for attr in attrs:
+ try:
+ attr_spec = attr_space.attrs_by_val[attr.type]
+ except (KeyError, UnboundLocalError):
+ if not self.process_unknown:
+ raise Exception(f"Space '{space}' has no attribute with value '{attr.type}'")
+ attr_name = f"UnknownAttr({attr.type})"
+ self._rsp_add(rsp, attr_name, None, self._decode_unknown(attr))
+ continue
+
+ try:
+ if attr_spec["type"] == 'nest':
+ subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs)
+ decoded = subdict
+ elif attr_spec["type"] == 'string':
+ decoded = attr.as_strz()
+ elif attr_spec["type"] == 'binary':
+ decoded = self._decode_binary(attr, attr_spec)
+ elif attr_spec["type"] == 'flag':
+ decoded = True
+ elif attr_spec.is_auto_scalar:
+ decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order)
+ if 'enum' in attr_spec:
+ decoded = self._decode_enum(decoded, attr_spec)
+ elif attr_spec["type"] in NlAttr.type_formats:
+ decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
+ if 'enum' in attr_spec:
+ decoded = self._decode_enum(decoded, attr_spec)
+ elif attr_spec.display_hint:
+ decoded = self._formatted_string(decoded, attr_spec.display_hint)
+ elif attr_spec["type"] == 'indexed-array':
+ decoded = self._decode_array_attr(attr, attr_spec)
+ elif attr_spec["type"] == 'bitfield32':
+ value, selector = struct.unpack("II", attr.raw)
+ if 'enum' in attr_spec:
+ value = self._decode_enum(value, attr_spec)
+ selector = self._decode_enum(selector, attr_spec)
+ decoded = {"value": value, "selector": selector}
+ elif attr_spec["type"] == 'sub-message':
+ decoded = self._decode_sub_msg(attr, attr_spec, search_attrs)
+ elif attr_spec["type"] == 'nest-type-value':
+ decoded = self._decode_nest_type_value(attr, attr_spec)
+ else:
+ if not self.process_unknown:
+ raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
+ decoded = self._decode_unknown(attr)
+
+ self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
+ except:
+ print(f"Error decoding '{attr_spec.name}' from '{space}'")
+ raise
+
+ return rsp
+
+ def _decode_extack_path(self, attrs, attr_set, offset, target, search_attrs):
+ for attr in attrs:
+ try:
+ attr_spec = attr_set.attrs_by_val[attr.type]
+ except KeyError:
+ raise Exception(f"Space '{attr_set.name}' has no attribute with value '{attr.type}'")
+ if offset > target:
+ break
+ if offset == target:
+ return '.' + attr_spec.name
+
+ if offset + attr.full_len <= target:
+ offset += attr.full_len
+ continue
+
+ pathname = attr_spec.name
+ if attr_spec['type'] == 'nest':
+ sub_attrs = self.attr_sets[attr_spec['nested-attributes']]
+ search_attrs = SpaceAttrs(sub_attrs, search_attrs.lookup(attr_spec['name']))
+ elif attr_spec['type'] == 'sub-message':
+ msg_format, value = self._resolve_selector(attr_spec, search_attrs)
+ if msg_format is None:
+ raise Exception(f"Can't resolve sub-message of {attr_spec['name']} for extack")
+ sub_attrs = self.attr_sets[msg_format.attr_set]
+ pathname += f"({value})"
+ else:
+ raise Exception(f"Can't dive into {attr.type} ({attr_spec['name']}) for extack")
+ offset += 4
+ subpath = self._decode_extack_path(NlAttrs(attr.raw), sub_attrs,
+ offset, target, search_attrs)
+ if subpath is None:
+ return None
+ return '.' + pathname + subpath
+
+ return None
+
+ def _decode_extack(self, request, op, extack, vals):
+ if 'bad-attr-offs' not in extack:
+ return
+
+ msg = self.nlproto.decode(self, NlMsg(request, 0, op.attr_set), op)
+ offset = self.nlproto.msghdr_size() + self._struct_size(op.fixed_header)
+ search_attrs = SpaceAttrs(op.attr_set, vals)
+ path = self._decode_extack_path(msg.raw_attrs, op.attr_set, offset,
+ extack['bad-attr-offs'], search_attrs)
+ if path:
+ del extack['bad-attr-offs']
+ extack['bad-attr'] = path
+
+ def _struct_size(self, name):
+ if name:
+ members = self.consts[name].members
+ size = 0
+ for m in members:
+ if m.type in ['pad', 'binary']:
+ if m.struct:
+ size += self._struct_size(m.struct)
+ else:
+ size += m.len
+ else:
+ format = NlAttr.get_format(m.type, m.byte_order)
+ size += format.size
+ return size
+ else:
+ return 0
+
+ def _decode_struct(self, data, name):
+ members = self.consts[name].members
+ attrs = dict()
+ offset = 0
+ for m in members:
+ value = None
+ if m.type == 'pad':
+ offset += m.len
+ elif m.type == 'binary':
+ if m.struct:
+ len = self._struct_size(m.struct)
+ value = self._decode_struct(data[offset : offset + len],
+ m.struct)
+ offset += len
+ else:
+ value = data[offset : offset + m.len]
+ offset += m.len
+ else:
+ format = NlAttr.get_format(m.type, m.byte_order)
+ [ value ] = format.unpack_from(data, offset)
+ offset += format.size
+ if value is not None:
+ if m.enum:
+ value = self._decode_enum(value, m)
+ elif m.display_hint:
+ value = self._formatted_string(value, m.display_hint)
+ attrs[m.name] = value
+ return attrs
+
+ def _encode_struct(self, name, vals):
+ members = self.consts[name].members
+ attr_payload = b''
+ for m in members:
+ value = vals.pop(m.name) if m.name in vals else None
+ if m.type == 'pad':
+ attr_payload += bytearray(m.len)
+ elif m.type == 'binary':
+ if m.struct:
+ if value is None:
+ value = dict()
+ attr_payload += self._encode_struct(m.struct, value)
+ else:
+ if value is None:
+ attr_payload += bytearray(m.len)
+ else:
+ attr_payload += bytes.fromhex(value)
+ else:
+ if value is None:
+ value = 0
+ format = NlAttr.get_format(m.type, m.byte_order)
+ attr_payload += format.pack(value)
+ return attr_payload
+
+ def _formatted_string(self, raw, display_hint):
+ if display_hint == 'mac':
+ formatted = ':'.join('%02x' % b for b in raw)
+ elif display_hint == 'hex':
+ if isinstance(raw, int):
+ formatted = hex(raw)
+ else:
+ formatted = bytes.hex(raw, ' ')
+ elif display_hint in [ 'ipv4', 'ipv6', 'ipv4-or-v6' ]:
+ formatted = format(ipaddress.ip_address(raw))
+ elif display_hint == 'uuid':
+ formatted = str(uuid.UUID(bytes=raw))
+ else:
+ formatted = raw
+ return formatted
+
+ def _from_string(self, string, attr_spec):
+ if attr_spec.display_hint in ['ipv4', 'ipv6', 'ipv4-or-v6']:
+ ip = ipaddress.ip_address(string)
+ if attr_spec['type'] == 'binary':
+ raw = ip.packed
+ else:
+ raw = int(ip)
+ elif attr_spec.display_hint == 'hex':
+ if attr_spec['type'] == 'binary':
+ raw = bytes.fromhex(string)
+ else:
+ raw = int(string, 16)
+ elif attr_spec.display_hint == 'mac':
+ # Parse MAC address in format "00:11:22:33:44:55" or "001122334455"
+ if ':' in string:
+ mac_bytes = [int(x, 16) for x in string.split(':')]
+ else:
+ if len(string) % 2 != 0:
+ raise Exception(f"Invalid MAC address format: {string}")
+ mac_bytes = [int(string[i:i+2], 16) for i in range(0, len(string), 2)]
+ raw = bytes(mac_bytes)
+ else:
+ raise Exception(f"Display hint '{attr_spec.display_hint}' not implemented"
+ f" when parsing '{attr_spec['name']}'")
+ return raw
+
+ def handle_ntf(self, decoded):
+ msg = dict()
+ if self.include_raw:
+ msg['raw'] = decoded
+ op = self.rsp_by_value[decoded.cmd()]
+ attrs = self._decode(decoded.raw_attrs, op.attr_set.name)
+ if op.fixed_header:
+ attrs.update(self._decode_struct(decoded.raw, op.fixed_header))
+
+ msg['name'] = op['name']
+ msg['msg'] = attrs
+ self.async_msg_queue.put(msg)
+
+ def check_ntf(self):
+ while True:
+ try:
+ reply = self.sock.recv(self._recv_size, socket.MSG_DONTWAIT)
+ except BlockingIOError:
+ return
+
+ nms = NlMsgs(reply)
+ self._recv_dbg_print(reply, nms)
+ for nl_msg in nms:
+ if nl_msg.error:
+ print("Netlink error in ntf!?", os.strerror(-nl_msg.error))
+ print(nl_msg)
+ continue
+ if nl_msg.done:
+ print("Netlink done while checking for ntf!?")
+ continue
+
+ decoded = self.nlproto.decode(self, nl_msg, None)
+ if decoded.cmd() not in self.async_msg_ids:
+ print("Unexpected msg id while checking for ntf", decoded)
+ continue
+
+ self.handle_ntf(decoded)
+
+ def poll_ntf(self, duration=None):
+ start_time = time.time()
+ selector = selectors.DefaultSelector()
+ selector.register(self.sock, selectors.EVENT_READ)
+
+ while True:
+ try:
+ yield self.async_msg_queue.get_nowait()
+ except queue.Empty:
+ if duration is not None:
+ timeout = start_time + duration - time.time()
+ if timeout <= 0:
+ return
+ else:
+ timeout = None
+ events = selector.select(timeout)
+ if events:
+ self.check_ntf()
+
+ def operation_do_attributes(self, name):
+ """
+ For a given operation name, find and return a supported
+ set of attributes (as a dict).
+ """
+ op = self.find_operation(name)
+ if not op:
+ return None
+
+ return op['do']['request']['attributes'].copy()
+
+ def _encode_message(self, op, vals, flags, req_seq):
+ nl_flags = Netlink.NLM_F_REQUEST | Netlink.NLM_F_ACK
+ for flag in flags or []:
+ nl_flags |= flag
+
+ msg = self.nlproto.message(nl_flags, op.req_value, 1, req_seq)
+ if op.fixed_header:
+ msg += self._encode_struct(op.fixed_header, vals)
+ search_attrs = SpaceAttrs(op.attr_set, vals)
+ for name, value in vals.items():
+ msg += self._add_attr(op.attr_set.name, name, value, search_attrs)
+ msg = _genl_msg_finalize(msg)
+ return msg
+
+ def _ops(self, ops):
+ reqs_by_seq = {}
+ req_seq = random.randint(1024, 65535)
+ payload = b''
+ for (method, vals, flags) in ops:
+ op = self.ops[method]
+ msg = self._encode_message(op, vals, flags, req_seq)
+ reqs_by_seq[req_seq] = (op, vals, msg, flags)
+ payload += msg
+ req_seq += 1
+
+ self.sock.send(payload, 0)
+
+ done = False
+ rsp = []
+ op_rsp = []
+ while not done:
+ reply = self.sock.recv(self._recv_size)
+ nms = NlMsgs(reply)
+ self._recv_dbg_print(reply, nms)
+ for nl_msg in nms:
+ if nl_msg.nl_seq in reqs_by_seq:
+ (op, vals, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq]
+ if nl_msg.extack:
+ nl_msg.annotate_extack(op.attr_set)
+ self._decode_extack(req_msg, op, nl_msg.extack, vals)
+ else:
+ op = None
+ req_flags = []
+
+ if nl_msg.error:
+ raise NlError(nl_msg)
+ if nl_msg.done:
+ if nl_msg.extack:
+ print("Netlink warning:")
+ print(nl_msg)
+
+ if Netlink.NLM_F_DUMP in req_flags:
+ rsp.append(op_rsp)
+ elif not op_rsp:
+ rsp.append(None)
+ elif len(op_rsp) == 1:
+ rsp.append(op_rsp[0])
+ else:
+ rsp.append(op_rsp)
+ op_rsp = []
+
+ del reqs_by_seq[nl_msg.nl_seq]
+ done = len(reqs_by_seq) == 0
+ break
+
+ decoded = self.nlproto.decode(self, nl_msg, op)
+
+ # Check if this is a reply to our request
+ if nl_msg.nl_seq not in reqs_by_seq or decoded.cmd() != op.rsp_value:
+ if decoded.cmd() in self.async_msg_ids:
+ self.handle_ntf(decoded)
+ continue
+ else:
+ print('Unexpected message: ' + repr(decoded))
+ continue
+
+ rsp_msg = self._decode(decoded.raw_attrs, op.attr_set.name)
+ if op.fixed_header:
+ rsp_msg.update(self._decode_struct(decoded.raw, op.fixed_header))
+ op_rsp.append(rsp_msg)
+
+ return rsp
+
+ def _op(self, method, vals, flags=None, dump=False):
+ req_flags = flags or []
+ if dump:
+ req_flags.append(Netlink.NLM_F_DUMP)
+
+ ops = [(method, vals, req_flags)]
+ return self._ops(ops)[0]
+
+ def do(self, method, vals, flags=None):
+ return self._op(method, vals, flags)
+
+ def dump(self, method, vals):
+ return self._op(method, vals, dump=True)
+
+ def do_multi(self, ops):
+ return self._ops(ops)
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index 897af958cee8..b517d0c605ad 100755
--- a/tools/net/ynl/ynl-gen-c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -2,14 +2,18 @@
# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
import argparse
-import collections
+import filecmp
+import pathlib
import os
import re
import shutil
+import sys
import tempfile
import yaml
+sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
from lib import SpecFamily, SpecAttrSet, SpecAttr, SpecOperation, SpecEnumSet, SpecEnumEntry
+from lib import SpecSubMessage
def c_upper(name):
@@ -20,18 +24,25 @@ def c_lower(name):
return name.lower().replace('-', '_')
+def limit_to_number(name):
+ """
+ Turn a string limit like u32-max or s64-min into its numerical value
+ """
+ if name[0] == 'u' and name.endswith('-min'):
+ return 0
+ width = int(name[1:-4])
+ if name[0] == 's':
+ width -= 1
+ value = (1 << width) - 1
+ if name[0] == 's' and name.endswith('-min'):
+ value = -value - 1
+ return value
+
+
class BaseNlLib:
def get_family_id(self):
return 'ys->family_id'
- def parse_cb_run(self, cb, data, is_dump=False, indent=1):
- ind = '\n\t\t' + '\t' * indent + ' '
- if is_dump:
- return f"mnl_cb_run2(ys->rx_buf, len, 0, 0, {cb}, {data},{ind}ynl_cb_array, NLMSG_MIN_TYPE)"
- else:
- return f"mnl_cb_run2(ys->rx_buf, len, ys->seq, ys->portid,{ind}{cb}, {data},{ind}" + \
- "ynl_cb_array, NLMSG_MIN_TYPE)"
-
class Type(SpecAttr):
def __init__(self, family, attr_set, attr, value):
@@ -42,14 +53,27 @@ class Type(SpecAttr):
self.type = attr['type']
self.checks = attr.get('checks', {})
+ self.request = False
+ self.reply = False
+
+ self.is_selector = False
+
if 'len' in attr:
self.len = attr['len']
+
if 'nested-attributes' in attr:
- self.nested_attrs = attr['nested-attributes']
+ nested = attr['nested-attributes']
+ elif 'sub-message' in attr:
+ nested = attr['sub-message']
+ else:
+ nested = None
+
+ if nested:
+ self.nested_attrs = nested
if self.nested_attrs == family.name:
- self.nested_render_name = f"{family.name}"
+ self.nested_render_name = c_lower(f"{family.ident_name}")
else:
- self.nested_render_name = f"{family.name}_{c_lower(self.nested_attrs)}"
+ self.nested_render_name = c_lower(f"{family.ident_name}_{self.nested_attrs}")
if self.nested_attrs in self.family.consts:
self.nested_struct_type = 'struct ' + self.nested_render_name + '_'
@@ -59,38 +83,89 @@ class Type(SpecAttr):
self.c_name = c_lower(self.name)
if self.c_name in _C_KW:
self.c_name += '_'
+ if self.c_name[0].isdigit():
+ self.c_name = '_' + self.c_name
# Added by resolve():
self.enum_name = None
delattr(self, "enum_name")
+ def _get_real_attr(self):
+ # if the attr is for a subset return the "real" attr (just one down, does not recurse)
+ return self.family.attr_sets[self.attr_set.subset_of][self.name]
+
+ def set_request(self):
+ self.request = True
+ if self.attr_set.subset_of:
+ self._get_real_attr().set_request()
+
+ def set_reply(self):
+ self.reply = True
+ if self.attr_set.subset_of:
+ self._get_real_attr().set_reply()
+
+ def get_limit(self, limit, default=None):
+ value = self.checks.get(limit, default)
+ if value is None:
+ return value
+ if isinstance(value, int):
+ return value
+ if value in self.family.consts:
+ return self.family.consts[value]["value"]
+ return limit_to_number(value)
+
+ def get_limit_str(self, limit, default=None, suffix=''):
+ value = self.checks.get(limit, default)
+ if value is None:
+ return ''
+ if isinstance(value, int):
+ return str(value) + suffix
+ if value in self.family.consts:
+ const = self.family.consts[value]
+ if const.get('header'):
+ return c_upper(value)
+ return c_upper(f"{self.family['name']}-{value}")
+ return c_upper(value)
+
def resolve(self):
- if 'name-prefix' in self.attr:
+ if 'parent-sub-message' in self.attr:
+ enum_name = self.attr['parent-sub-message'].enum_name
+ elif 'name-prefix' in self.attr:
enum_name = f"{self.attr['name-prefix']}{self.name}"
else:
enum_name = f"{self.attr_set.name_prefix}{self.name}"
self.enum_name = c_upper(enum_name)
+ if self.attr_set.subset_of:
+ if self.checks != self._get_real_attr().checks:
+ raise Exception("Overriding checks not supported by codegen, yet")
+
def is_multi_val(self):
return None
def is_scalar(self):
return self.type in {'u8', 'u16', 'u32', 'u64', 's32', 's64'}
+ def is_recursive(self):
+ return False
+
+ def is_recursive_for_op(self, ri):
+ return self.is_recursive() and not ri.op
+
def presence_type(self):
- return 'bit'
+ return 'present'
def presence_member(self, space, type_filter):
if self.presence_type() != type_filter:
return
- if self.presence_type() == 'bit':
+ if self.presence_type() == 'present':
pfx = '__' if space == 'user' else ''
return f"{pfx}u32 {self.c_name}:1;"
- if self.presence_type() == 'len':
+ if self.presence_type() in {'len', 'count'}:
pfx = '__' if space == 'user' else ''
- return f"{pfx}u32 {self.c_name}_len;"
+ return f"{pfx}u32 {self.c_name};"
def _complex_member_type(self, ri):
return None
@@ -98,26 +173,34 @@ class Type(SpecAttr):
def free_needs_iter(self):
return False
+ def _free_lines(self, ri, var, ref):
+ if self.is_multi_val() or self.presence_type() in {'count', 'len'}:
+ return [f'free({var}->{ref}{self.c_name});']
+ return []
+
def free(self, ri, var, ref):
- if self.is_multi_val() or self.presence_type() == 'len':
- ri.cw.p(f'free({var}->{ref}{self.c_name});')
+ lines = self._free_lines(ri, var, ref)
+ for line in lines:
+ ri.cw.p(line)
def arg_member(self, ri):
member = self._complex_member_type(ri)
if member:
- arg = [member + ' *' + self.c_name]
+ spc = ' ' if member[-1] != '*' else ''
+ arg = [member + spc + '*' + self.c_name]
if self.presence_type() == 'count':
arg += ['unsigned int n_' + self.c_name]
return arg
raise Exception(f"Struct member not implemented for class type {self.type}")
def struct_member(self, ri):
- if self.is_multi_val():
- ri.cw.p(f"unsigned int n_{self.c_name};")
member = self._complex_member_type(ri)
if member:
ptr = '*' if self.is_multi_val() else ''
- ri.cw.p(f"{member} {ptr}{self.c_name};")
+ if self.is_recursive_for_op(ri):
+ ptr = '*'
+ spc = ' ' if member[-1] != '*' else ''
+ ri.cw.p(f"{member}{spc}{ptr}{self.c_name};")
return
members = self.arg_member(ri)
for one in members:
@@ -127,7 +210,10 @@ class Type(SpecAttr):
return '{ .type = ' + policy + ', }'
def attr_policy(self, cw):
- policy = c_upper('nla-' + self.attr['type'])
+ policy = f'NLA_{c_upper(self.type)}'
+ if self.attr.get('byte-order') == 'big-endian':
+ if self.type in {'u16', 'u32'}:
+ policy = f'NLA_BE{self.type[1:]}'
spec = self._attr_policy(policy)
cw.p(f"\t[{self.enum_name}] = {spec},")
@@ -140,14 +226,13 @@ class Type(SpecAttr):
cw.p(f'[{self.enum_name}] = {"{"} .name = "{self.name}", {typol}{"}"},')
def _attr_put_line(self, ri, var, line):
- if self.presence_type() == 'bit':
- ri.cw.p(f"if ({var}->_present.{self.c_name})")
- elif self.presence_type() == 'len':
- ri.cw.p(f"if ({var}->_present.{self.c_name}_len)")
+ presence = self.presence_type()
+ if presence in {'present', 'len'}:
+ ri.cw.p(f"if ({var}->_{presence}.{self.c_name})")
ri.cw.p(f"{line};")
def _attr_put_simple(self, ri, var, put_type):
- line = f"mnl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name})"
+ line = f"ynl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name})"
self._attr_put_line(ri, var, line)
def attr_put(self, ri, var):
@@ -157,7 +242,7 @@ class Type(SpecAttr):
raise Exception(f"Attr get not implemented for class type {self.type}")
def attr_get(self, ri, var, first):
- lines, init_lines, local_vars = self._attr_get(ri, var)
+ lines, init_lines, _ = self._attr_get(ri, var)
if type(lines) is str:
lines = [lines]
if type(init_lines) is str:
@@ -165,15 +250,11 @@ class Type(SpecAttr):
kw = 'if' if first else 'else if'
ri.cw.block_start(line=f"{kw} (type == {self.enum_name})")
- if local_vars:
- for local in local_vars:
- ri.cw.p(local)
- ri.cw.nl()
if not self.is_multi_val():
ri.cw.p("if (ynl_attr_validate(yarg, attr))")
- ri.cw.p("return MNL_CB_ERROR;")
- if self.presence_type() == 'bit':
+ ri.cw.p("return YNL_PARSE_CB_ERROR;")
+ if self.presence_type() == 'present':
ri.cw.p(f"{var}->_present.{self.c_name} = 1;")
if init_lines:
@@ -189,17 +270,28 @@ class Type(SpecAttr):
def _setter_lines(self, ri, member, presence):
raise Exception(f"Setter not implemented for class type {self.type}")
- def setter(self, ri, space, direction, deref=False, ref=None):
+ def setter(self, ri, space, direction, deref=False, ref=None, var="req"):
ref = (ref if ref else []) + [self.c_name]
- var = "req"
member = f"{var}->{'.'.join(ref)}"
+ local_vars = []
+ if self.free_needs_iter():
+ local_vars += ['unsigned int i;']
+
code = []
presence = ''
for i in range(0, len(ref)):
presence = f"{var}->{'.'.join(ref[:i] + [''])}_present.{ref[i]}"
- if self.presence_type() == 'bit':
- code.append(presence + ' = 1;')
+ # Every layer below last is a nest, so we know it uses bit presence
+ # last layer is "self" and may be a complex type
+ if i == len(ref) - 1 and self.presence_type() != 'present':
+ presence = f"{var}->{'.'.join(ref[:i] + [''])}_{self.presence_type()}.{ref[i]}"
+ continue
+ code.append(presence + ' = 1;')
+ ref_path = '.'.join(ref[:-1])
+ if ref_path:
+ ref_path += '.'
+ code += self._free_lines(ri, var, ref_path)
code += self._setter_lines(ri, member, presence)
func_name = f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}"
@@ -207,7 +299,8 @@ class Type(SpecAttr):
alloc = bool([x for x in code if 'alloc(' in x])
if free and not alloc:
func_name = '__' + func_name
- ri.cw.write_func('static inline void', func_name, body=code,
+ ri.cw.write_func('static inline void', func_name, local_vars=local_vars,
+ body=code,
args=[f'{type_name(ri, direction, deref=deref)} *{var}'] + self.arg_member(ri))
@@ -219,7 +312,7 @@ class TypeUnused(Type):
return []
def _attr_get(self, ri, var):
- return ['return MNL_CB_ERROR;'], None, None
+ return ['return YNL_PARSE_CB_ERROR;'], None, None
def _attr_typol(self):
return '.type = YNL_PT_REJECT, '
@@ -227,6 +320,15 @@ class TypeUnused(Type):
def attr_policy(self, cw):
pass
+ def attr_put(self, ri, var):
+ pass
+
+ def attr_get(self, ri, var, first):
+ pass
+
+ def setter(self, ri, space, direction, deref=False, ref=None, var=None):
+ pass
+
class TypePad(Type):
def presence_type(self):
@@ -247,7 +349,7 @@ class TypePad(Type):
def attr_policy(self, cw):
pass
- def setter(self, ri, space, direction, deref=False, ref=None):
+ def setter(self, ri, space, direction, deref=False, ref=None, var=None):
pass
@@ -259,6 +361,11 @@ class TypeScalar(Type):
if 'byte-order' in attr:
self.byte_order_comment = f" /* {attr['byte-order']} */"
+ # Classic families have some funny enums, don't bother
+ # computing checks, since we only need them for kernel policies
+ if not family.is_classic():
+ self._init_checks()
+
# Added by resolve():
self.is_bitfield = None
delattr(self, "is_bitfield")
@@ -275,18 +382,37 @@ class TypeScalar(Type):
else:
self.is_bitfield = False
- maybe_enum = not self.is_bitfield and 'enum' in self.attr
- if maybe_enum and self.family.consts[self.attr['enum']].enum_name:
- self.type_name = f"enum {self.family.name}_{c_lower(self.attr['enum'])}"
+ if not self.is_bitfield and 'enum' in self.attr:
+ self.type_name = self.family.consts[self.attr['enum']].user_type
+ elif self.is_auto_scalar:
+ self.type_name = '__' + self.type[0] + '64'
else:
self.type_name = '__' + self.type
- def _mnl_type(self):
- t = self.type
- # mnl does not have a helper for signed types
- if t[0] == 's':
- t = 'u' + t[1:]
- return t
+ def _init_checks(self):
+ if 'enum' in self.attr:
+ enum = self.family.consts[self.attr['enum']]
+ low, high = enum.value_range()
+ if low is None and high is None:
+ self.checks['sparse'] = True
+ else:
+ if 'min' not in self.checks:
+ if low != 0 or self.type[0] == 's':
+ self.checks['min'] = low
+ if 'max' not in self.checks:
+ self.checks['max'] = high
+
+ if 'min' in self.checks and 'max' in self.checks:
+ if self.get_limit('min') > self.get_limit('max'):
+ raise Exception(f'Invalid limit for "{self.name}" min: {self.get_limit("min")} max: {self.get_limit("max")}')
+ self.checks['range'] = True
+
+ low = min(self.get_limit('min', 0), self.get_limit('max', 0))
+ high = max(self.get_limit('min', 0), self.get_limit('max', 0))
+ if low < 0 and self.type[0] == 'u':
+ raise Exception(f'Invalid limit for "{self.name}" negative limit for unsigned type')
+ if low < -32768 or high > 32767:
+ self.checks['full-range'] = True
def _attr_policy(self, policy):
if 'flags-mask' in self.checks or self.is_bitfield:
@@ -298,27 +424,29 @@ class TypeScalar(Type):
flag_cnt = len(flags['entries'])
mask = (1 << flag_cnt) - 1
return f"NLA_POLICY_MASK({policy}, 0x{mask:x})"
+ elif 'full-range' in self.checks:
+ return f"NLA_POLICY_FULL_RANGE({policy}, &{c_lower(self.enum_name)}_range)"
+ elif 'range' in self.checks:
+ return f"NLA_POLICY_RANGE({policy}, {self.get_limit_str('min')}, {self.get_limit_str('max')})"
elif 'min' in self.checks:
- return f"NLA_POLICY_MIN({policy}, {self.checks['min']})"
- elif 'enum' in self.attr:
- enum = self.family.consts[self.attr['enum']]
- low, high = enum.value_range()
- if low == 0:
- return f"NLA_POLICY_MAX({policy}, {high})"
- return f"NLA_POLICY_RANGE({policy}, {low}, {high})"
+ return f"NLA_POLICY_MIN({policy}, {self.get_limit_str('min')})"
+ elif 'max' in self.checks:
+ return f"NLA_POLICY_MAX({policy}, {self.get_limit_str('max')})"
+ elif 'sparse' in self.checks:
+ return f"NLA_POLICY_VALIDATE_FN({policy}, &{c_lower(self.enum_name)}_validate)"
return super()._attr_policy(policy)
def _attr_typol(self):
- return f'.type = YNL_PT_U{self.type[1:]}, '
+ return f'.type = YNL_PT_U{c_upper(self.type[1:])}, '
def arg_member(self, ri):
return [f'{self.type_name} {self.c_name}{self.byte_order_comment}']
def attr_put(self, ri, var):
- self._attr_put_simple(ri, var, self._mnl_type())
+ self._attr_put_simple(ri, var, self.type)
def _attr_get(self, ri, var):
- return f"{var}->{self.c_name} = mnl_attr_get_{self._mnl_type()}(attr);", None, None
+ return f"{var}->{self.c_name} = ynl_attr_get_{self.type}(attr);", None, None
def _setter_lines(self, ri, member, presence):
return [f"{member} = {self.c_name};"]
@@ -332,7 +460,7 @@ class TypeFlag(Type):
return '.type = YNL_PT_FLAG, '
def attr_put(self, ri, var):
- self._attr_put_line(ri, var, f"mnl_attr_put(nlh, {self.enum_name}, 0, NULL)")
+ self._attr_put_line(ri, var, f"ynl_attr_put(nlh, {self.enum_name}, NULL, 0)")
def _attr_get(self, ri, var):
return [], None, None
@@ -352,13 +480,19 @@ class TypeString(Type):
ri.cw.p(f"char *{self.c_name};")
def _attr_typol(self):
- return f'.type = YNL_PT_NUL_STR, '
+ typol = '.type = YNL_PT_NUL_STR, '
+ if self.is_selector:
+ typol += '.is_selector = 1, '
+ return typol
def _attr_policy(self, policy):
- mem = '{ .type = ' + policy
- if 'max-len' in self.checks:
- mem += ', .len = ' + str(self.checks['max-len'])
- mem += ', }'
+ if 'exact-len' in self.checks:
+ mem = 'NLA_POLICY_EXACT_LEN(' + self.get_limit_str('exact-len') + ')'
+ else:
+ mem = '{ .type = ' + policy
+ if 'max-len' in self.checks:
+ mem += ', .len = ' + self.get_limit_str('max-len')
+ mem += ', }'
return mem
def attr_policy(self, cw):
@@ -371,23 +505,22 @@ class TypeString(Type):
cw.p(f"\t[{self.enum_name}] = {spec},")
def attr_put(self, ri, var):
- self._attr_put_simple(ri, var, 'strz')
+ self._attr_put_simple(ri, var, 'str')
def _attr_get(self, ri, var):
- len_mem = var + '->_present.' + self.c_name + '_len'
+ len_mem = var + '->_len.' + self.c_name
return [f"{len_mem} = len;",
f"{var}->{self.c_name} = malloc(len + 1);",
- f"memcpy({var}->{self.c_name}, mnl_attr_get_str(attr), len);",
+ f"memcpy({var}->{self.c_name}, ynl_attr_get_str(attr), len);",
f"{var}->{self.c_name}[len] = 0;"], \
- ['len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr));'], \
+ ['len = strnlen(ynl_attr_get_str(attr), ynl_attr_data_len(attr));'], \
['unsigned int len;']
def _setter_lines(self, ri, member, presence):
- return [f"free({member});",
- f"{presence}_len = strlen({self.c_name});",
- f"{member} = malloc({presence}_len + 1);",
- f'memcpy({member}, {self.c_name}, {presence}_len);',
- f'{member}[{presence}_len] = 0;']
+ return [f"{presence} = strlen({self.c_name});",
+ f"{member} = malloc({presence} + 1);",
+ f'memcpy({member}, {self.c_name}, {presence});',
+ f'{member}[{presence}] = 0;']
class TypeBinary(Type):
@@ -401,44 +534,138 @@ class TypeBinary(Type):
ri.cw.p(f"void *{self.c_name};")
def _attr_typol(self):
- return f'.type = YNL_PT_BINARY,'
+ return '.type = YNL_PT_BINARY,'
def _attr_policy(self, policy):
- mem = '{ '
- if len(self.checks) == 1 and 'min-len' in self.checks:
- mem += '.len = ' + str(self.checks['min-len'])
- elif len(self.checks) == 0:
- mem += '.type = NLA_BINARY'
+ if len(self.checks) == 0:
+ pass
+ elif len(self.checks) == 1:
+ check_name = list(self.checks)[0]
+ if check_name not in {'exact-len', 'min-len', 'max-len'}:
+ raise Exception('Unsupported check for binary type: ' + check_name)
else:
- raise Exception('One or more of binary type checks not implemented, yet')
- mem += ', }'
+ raise Exception('More than one check for binary type not implemented, yet')
+
+ if len(self.checks) == 0:
+ mem = '{ .type = NLA_BINARY, }'
+ elif 'exact-len' in self.checks:
+ mem = 'NLA_POLICY_EXACT_LEN(' + self.get_limit_str('exact-len') + ')'
+ elif 'min-len' in self.checks:
+ mem = 'NLA_POLICY_MIN_LEN(' + self.get_limit_str('min-len') + ')'
+ elif 'max-len' in self.checks:
+ mem = 'NLA_POLICY_MAX_LEN(' + self.get_limit_str('max-len') + ')'
+
return mem
def attr_put(self, ri, var):
- self._attr_put_line(ri, var, f"mnl_attr_put(nlh, {self.enum_name}, " +
- f"{var}->_present.{self.c_name}_len, {var}->{self.c_name})")
+ self._attr_put_line(ri, var, f"ynl_attr_put(nlh, {self.enum_name}, " +
+ f"{var}->{self.c_name}, {var}->_len.{self.c_name})")
def _attr_get(self, ri, var):
- len_mem = var + '->_present.' + self.c_name + '_len'
+ len_mem = var + '->_len.' + self.c_name
return [f"{len_mem} = len;",
f"{var}->{self.c_name} = malloc(len);",
- f"memcpy({var}->{self.c_name}, mnl_attr_get_payload(attr), len);"], \
- ['len = mnl_attr_get_payload_len(attr);'], \
+ f"memcpy({var}->{self.c_name}, ynl_attr_data(attr), len);"], \
+ ['len = ynl_attr_data_len(attr);'], \
['unsigned int len;']
def _setter_lines(self, ri, member, presence):
- return [f"free({member});",
- f"{presence}_len = len;",
- f"{member} = malloc({presence}_len);",
- f'memcpy({member}, {self.c_name}, {presence}_len);']
+ return [f"{presence} = len;",
+ f"{member} = malloc({presence});",
+ f'memcpy({member}, {self.c_name}, {presence});']
+
+
+class TypeBinaryStruct(TypeBinary):
+ def struct_member(self, ri):
+ ri.cw.p(f'struct {c_lower(self.get("struct"))} *{self.c_name};')
+
+ def _attr_get(self, ri, var):
+ struct_sz = 'sizeof(struct ' + c_lower(self.get("struct")) + ')'
+ len_mem = var + '->_' + self.presence_type() + '.' + self.c_name
+ return [f"{len_mem} = len;",
+ f"if (len < {struct_sz})",
+ f"{var}->{self.c_name} = calloc(1, {struct_sz});",
+ "else",
+ f"{var}->{self.c_name} = malloc(len);",
+ f"memcpy({var}->{self.c_name}, ynl_attr_data(attr), len);"], \
+ ['len = ynl_attr_data_len(attr);'], \
+ ['unsigned int len;']
+
+
+class TypeBinaryScalarArray(TypeBinary):
+ def arg_member(self, ri):
+ return [f'__{self.get("sub-type")} *{self.c_name}', 'size_t count']
+
+ def presence_type(self):
+ return 'count'
+
+ def struct_member(self, ri):
+ ri.cw.p(f'__{self.get("sub-type")} *{self.c_name};')
+
+ def attr_put(self, ri, var):
+ presence = self.presence_type()
+ ri.cw.block_start(line=f"if ({var}->_{presence}.{self.c_name})")
+ ri.cw.p(f"i = {var}->_{presence}.{self.c_name} * sizeof(__{self.get('sub-type')});")
+ ri.cw.p(f"ynl_attr_put(nlh, {self.enum_name}, " +
+ f"{var}->{self.c_name}, i);")
+ ri.cw.block_end()
+
+ def _attr_get(self, ri, var):
+ len_mem = var + '->_count.' + self.c_name
+ return [f"{len_mem} = len / sizeof(__{self.get('sub-type')});",
+ f"len = {len_mem} * sizeof(__{self.get('sub-type')});",
+ f"{var}->{self.c_name} = malloc(len);",
+ f"memcpy({var}->{self.c_name}, ynl_attr_data(attr), len);"], \
+ ['len = ynl_attr_data_len(attr);'], \
+ ['unsigned int len;']
+
+ def _setter_lines(self, ri, member, presence):
+ return [f"{presence} = count;",
+ f"count *= sizeof(__{self.get('sub-type')});",
+ f"{member} = malloc(count);",
+ f'memcpy({member}, {self.c_name}, count);']
+
+
+class TypeBitfield32(Type):
+ def _complex_member_type(self, ri):
+ return "struct nla_bitfield32"
+
+ def _attr_typol(self):
+ return '.type = YNL_PT_BITFIELD32, '
+
+ def _attr_policy(self, policy):
+ if 'enum' not in self.attr:
+ raise Exception('Enum required for bitfield32 attr')
+ enum = self.family.consts[self.attr['enum']]
+ mask = enum.get_mask(as_flags=True)
+ return f"NLA_POLICY_BITFIELD32({mask})"
+
+ def attr_put(self, ri, var):
+ line = f"ynl_attr_put(nlh, {self.enum_name}, &{var}->{self.c_name}, sizeof(struct nla_bitfield32))"
+ self._attr_put_line(ri, var, line)
+
+ def _attr_get(self, ri, var):
+ return f"memcpy(&{var}->{self.c_name}, ynl_attr_data(attr), sizeof(struct nla_bitfield32));", None, None
+
+ def _setter_lines(self, ri, member, presence):
+ return [f"memcpy(&{member}, {self.c_name}, sizeof(struct nla_bitfield32));"]
class TypeNest(Type):
+ def is_recursive(self):
+ return self.family.pure_nested_structs[self.nested_attrs].recursive
+
def _complex_member_type(self, ri):
return self.nested_struct_type
- def free(self, ri, var, ref):
- ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name});')
+ def _free_lines(self, ri, var, ref):
+ lines = []
+ at = '&'
+ if self.is_recursive_for_op(ri):
+ at = ''
+ lines += [f'if ({var}->{ref}{self.c_name})']
+ lines += [f'{self.nested_render_name}_free({at}{var}->{ref}{self.c_name});']
+ return lines
def _attr_typol(self):
return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, '
@@ -447,21 +674,29 @@ class TypeNest(Type):
return 'NLA_POLICY_NESTED(' + self.nested_render_name + '_nl_policy)'
def attr_put(self, ri, var):
+ at = '' if self.is_recursive_for_op(ri) else '&'
self._attr_put_line(ri, var, f"{self.nested_render_name}_put(nlh, " +
- f"{self.enum_name}, &{var}->{self.c_name})")
+ f"{self.enum_name}, {at}{var}->{self.c_name})")
def _attr_get(self, ri, var):
- get_lines = [f"if ({self.nested_render_name}_parse(&parg, attr))",
- "return MNL_CB_ERROR;"]
+ pns = self.family.pure_nested_structs[self.nested_attrs]
+ args = ["&parg", "attr"]
+ for sel in pns.external_selectors():
+ args.append(f'{var}->{sel.name}')
+ get_lines = [f"if ({self.nested_render_name}_parse({', '.join(args)}))",
+ "return YNL_PARSE_CB_ERROR;"]
init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;",
f"parg.data = &{var}->{self.c_name};"]
return get_lines, init_lines, None
- def setter(self, ri, space, direction, deref=False, ref=None):
+ def setter(self, ri, space, direction, deref=False, ref=None, var="req"):
ref = (ref if ref else []) + [self.c_name]
for _, attr in ri.family.pure_nested_structs[self.nested_attrs].member_list():
- attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref)
+ if attr.is_recursive():
+ continue
+ attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref,
+ var=var)
class TypeMultiAttr(Type):
@@ -476,34 +711,53 @@ class TypeMultiAttr(Type):
def presence_type(self):
return 'count'
- def _mnl_type(self):
- t = self.type
- # mnl does not have a helper for signed types
- if t[0] == 's':
- t = 'u' + t[1:]
- return t
-
def _complex_member_type(self, ri):
if 'type' not in self.attr or self.attr['type'] == 'nest':
return self.nested_struct_type
+ elif self.attr['type'] == 'binary' and 'struct' in self.attr:
+ return None # use arg_member()
+ elif self.attr['type'] == 'string':
+ return 'struct ynl_string *'
elif self.attr['type'] in scalars:
scalar_pfx = '__' if ri.ku_space == 'user' else ''
- return scalar_pfx + self.attr['type']
+ if self.is_auto_scalar:
+ name = self.type[0] + '64'
+ else:
+ name = self.attr['type']
+ return scalar_pfx + name
else:
raise Exception(f"Sub-type {self.attr['type']} not supported yet")
+ def arg_member(self, ri):
+ if self.type == 'binary' and 'struct' in self.attr:
+ return [f'struct {c_lower(self.attr["struct"])} *{self.c_name}',
+ f'unsigned int n_{self.c_name}']
+ return super().arg_member(ri)
+
def free_needs_iter(self):
- return 'type' not in self.attr or self.attr['type'] == 'nest'
+ return self.attr['type'] in {'nest', 'string'}
- def free(self, ri, var, ref):
+ def _free_lines(self, ri, var, ref):
+ lines = []
if self.attr['type'] in scalars:
- ri.cw.p(f"free({var}->{ref}{self.c_name});")
+ lines += [f"free({var}->{ref}{self.c_name});"]
+ elif self.attr['type'] == 'binary':
+ lines += [f"free({var}->{ref}{self.c_name});"]
+ elif self.attr['type'] == 'string':
+ lines += [
+ f"for (i = 0; i < {var}->{ref}_count.{self.c_name}; i++)",
+ f"free({var}->{ref}{self.c_name}[i]);",
+ f"free({var}->{ref}{self.c_name});",
+ ]
elif 'type' not in self.attr or self.attr['type'] == 'nest':
- ri.cw.p(f"for (i = 0; i < {var}->{ref}n_{self.c_name}; i++)")
- ri.cw.p(f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);')
- ri.cw.p(f"free({var}->{ref}{self.c_name});")
+ lines += [
+ f"for (i = 0; i < {var}->{ref}_count.{self.c_name}; i++)",
+ f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);',
+ f"free({var}->{ref}{self.c_name});",
+ ]
else:
raise Exception(f"Free of MultiAttr sub-type {self.attr['type']} not supported yet")
+ return lines
def _attr_policy(self, policy):
return self.base_type._attr_policy(policy)
@@ -516,25 +770,28 @@ class TypeMultiAttr(Type):
def attr_put(self, ri, var):
if self.attr['type'] in scalars:
- put_type = self._mnl_type()
- ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
- ri.cw.p(f"mnl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
+ put_type = self.type
+ ri.cw.p(f"for (i = 0; i < {var}->_count.{self.c_name}; i++)")
+ ri.cw.p(f"ynl_attr_put_{put_type}(nlh, {self.enum_name}, {var}->{self.c_name}[i]);")
+ elif self.attr['type'] == 'binary' and 'struct' in self.attr:
+ ri.cw.p(f"for (i = 0; i < {var}->_count.{self.c_name}; i++)")
+ ri.cw.p(f"ynl_attr_put(nlh, {self.enum_name}, &{var}->{self.c_name}[i], sizeof(struct {c_lower(self.attr['struct'])}));")
+ elif self.attr['type'] == 'string':
+ ri.cw.p(f"for (i = 0; i < {var}->_count.{self.c_name}; i++)")
+ ri.cw.p(f"ynl_attr_put_str(nlh, {self.enum_name}, {var}->{self.c_name}[i]->str);")
elif 'type' not in self.attr or self.attr['type'] == 'nest':
- ri.cw.p(f"for (unsigned int i = 0; i < {var}->n_{self.c_name}; i++)")
+ ri.cw.p(f"for (i = 0; i < {var}->_count.{self.c_name}; i++)")
self._attr_put_line(ri, var, f"{self.nested_render_name}_put(nlh, " +
f"{self.enum_name}, &{var}->{self.c_name}[i])")
else:
raise Exception(f"Put of MultiAttr sub-type {self.attr['type']} not supported yet")
def _setter_lines(self, ri, member, presence):
- # For multi-attr we have a count, not presence, hack up the presence
- presence = presence[:-(len('_present.') + len(self.c_name))] + "n_" + self.c_name
- return [f"free({member});",
- f"{member} = {self.c_name};",
+ return [f"{member} = {self.c_name};",
f"{presence} = n_{self.c_name};"]
-class TypeArrayNest(Type):
+class TypeIndexedArray(Type):
def is_multi_val(self):
return True
@@ -547,19 +804,75 @@ class TypeArrayNest(Type):
elif self.attr['sub-type'] in scalars:
scalar_pfx = '__' if ri.ku_space == 'user' else ''
return scalar_pfx + self.attr['sub-type']
+ elif self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks:
+ return None # use arg_member()
else:
raise Exception(f"Sub-type {self.attr['sub-type']} not supported yet")
+ def arg_member(self, ri):
+ if self.sub_type == 'binary' and 'exact-len' in self.checks:
+ return [f'unsigned char (*{self.c_name})[{self.checks["exact-len"]}]',
+ f'unsigned int n_{self.c_name}']
+ return super().arg_member(ri)
+
+ def _attr_policy(self, policy):
+ if self.attr['sub-type'] == 'nest':
+ return f'NLA_POLICY_NESTED_ARRAY({self.nested_render_name}_nl_policy)'
+ return super()._attr_policy(policy)
+
def _attr_typol(self):
- return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, '
+ if self.attr['sub-type'] in scalars:
+ return f'.type = YNL_PT_U{c_upper(self.sub_type[1:])}, '
+ elif self.attr['sub-type'] == 'binary' and 'exact-len' in self.checks:
+ return f'.type = YNL_PT_BINARY, .len = {self.checks["exact-len"]}, '
+ elif self.attr['sub-type'] == 'nest':
+ return f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, '
+ else:
+ raise Exception(f"Typol for IndexedArray sub-type {self.attr['sub-type']} not supported, yet")
def _attr_get(self, ri, var):
local_vars = ['const struct nlattr *attr2;']
get_lines = [f'attr_{self.c_name} = attr;',
- 'mnl_attr_for_each_nested(attr2, attr)',
- f'\t{var}->n_{self.c_name}++;']
+ 'ynl_attr_for_each_nested(attr2, attr) {',
+ '\tif (__ynl_attr_validate(yarg, attr2, type))',
+ '\t\treturn YNL_PARSE_CB_ERROR;',
+ f'\tn_{self.c_name}++;',
+ '}']
return get_lines, None, local_vars
+ def attr_put(self, ri, var):
+ ri.cw.p(f'array = ynl_attr_nest_start(nlh, {self.enum_name});')
+ if self.sub_type in scalars:
+ put_type = self.sub_type
+ ri.cw.block_start(line=f'for (i = 0; i < {var}->_count.{self.c_name}; i++)')
+ ri.cw.p(f"ynl_attr_put_{put_type}(nlh, i, {var}->{self.c_name}[i]);")
+ ri.cw.block_end()
+ elif self.sub_type == 'binary' and 'exact-len' in self.checks:
+ ri.cw.p(f'for (i = 0; i < {var}->_count.{self.c_name}; i++)')
+ ri.cw.p(f"ynl_attr_put(nlh, i, {var}->{self.c_name}[i], {self.checks['exact-len']});")
+ elif self.sub_type == 'nest':
+ ri.cw.p(f'for (i = 0; i < {var}->_count.{self.c_name}; i++)')
+ ri.cw.p(f"{self.nested_render_name}_put(nlh, i, &{var}->{self.c_name}[i]);")
+ else:
+ raise Exception(f"Put for IndexedArray sub-type {self.attr['sub-type']} not supported, yet")
+ ri.cw.p('ynl_attr_nest_end(nlh, array);')
+
+ def _setter_lines(self, ri, member, presence):
+ return [f"{member} = {self.c_name};",
+ f"{presence} = n_{self.c_name};"]
+
+ def free_needs_iter(self):
+ return self.sub_type == 'nest'
+
+ def _free_lines(self, ri, var, ref):
+ lines = []
+ if self.sub_type == 'nest':
+ lines += [
+ f"for (i = 0; i < {var}->{ref}_count.{self.c_name}; i++)",
+ f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);',
+ ]
+ lines += f"free({var}->{ref}{self.c_name});",
+ return lines
class TypeNestTypeValue(Type):
def _complex_member_type(self, ri):
@@ -581,8 +894,8 @@ class TypeNestTypeValue(Type):
local_vars += [f'__u32 {", ".join(tv_names)};']
for level in self.attr["type-value"]:
level = c_lower(level)
- get_lines += [f'attr_{level} = mnl_attr_get_payload({prev});']
- get_lines += [f'{level} = mnl_attr_get_type(attr_{level});']
+ get_lines += [f'attr_{level} = ynl_attr_data({prev});']
+ get_lines += [f'{level} = ynl_attr_type(attr_{level});']
prev = 'attr_' + level
tv_args = f", {', '.join(tv_names)}"
@@ -591,27 +904,88 @@ class TypeNestTypeValue(Type):
return get_lines, init_lines, local_vars
+class TypeSubMessage(TypeNest):
+ def __init__(self, family, attr_set, attr, value):
+ super().__init__(family, attr_set, attr, value)
+
+ self.selector = Selector(attr, attr_set)
+
+ def _attr_typol(self):
+ typol = f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, '
+ typol += '.is_submsg = 1, '
+ # Reverse-parsing of the policy (ynl_err_walk() in ynl.c) does not
+ # support external selectors. No family uses sub-messages with external
+ # selector for requests so this is fine for now.
+ if not self.selector.is_external():
+ typol += f'.selector_type = {self.attr_set[self["selector"]].value} '
+ return typol
+
+ def _attr_get(self, ri, var):
+ sel = c_lower(self['selector'])
+ if self.selector.is_external():
+ sel_var = f"_sel_{sel}"
+ else:
+ sel_var = f"{var}->{sel}"
+ get_lines = [f'if (!{sel_var})',
+ 'return ynl_submsg_failed(yarg, "%s", "%s");' %
+ (self.name, self['selector']),
+ f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))",
+ "return YNL_PARSE_CB_ERROR;"]
+ init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;",
+ f"parg.data = &{var}->{self.c_name};"]
+ return get_lines, init_lines, None
+
+
+class Selector:
+ def __init__(self, msg_attr, attr_set):
+ self.name = msg_attr["selector"]
+
+ if self.name in attr_set:
+ self.attr = attr_set[self.name]
+ self.attr.is_selector = True
+ self._external = False
+ else:
+ # The selector will need to get passed down thru the structs
+ self.attr = None
+ self._external = True
+
+ def set_attr(self, attr):
+ self.attr = attr
+
+ def is_external(self):
+ return self._external
+
+
class Struct:
- def __init__(self, family, space_name, type_list=None, inherited=None):
+ def __init__(self, family, space_name, type_list=None, fixed_header=None,
+ inherited=None, submsg=None):
self.family = family
self.space_name = space_name
self.attr_set = family.attr_sets[space_name]
# Use list to catch comparisons with empty sets
self._inherited = inherited if inherited is not None else []
self.inherited = []
+ self.fixed_header = None
+ if fixed_header:
+ self.fixed_header = 'struct ' + c_lower(fixed_header)
+ self.submsg = submsg
self.nested = type_list is None
if family.name == c_lower(space_name):
- self.render_name = f"{family.name}"
+ self.render_name = c_lower(family.ident_name)
else:
- self.render_name = f"{family.name}_{c_lower(space_name)}"
+ self.render_name = c_lower(family.ident_name + '-' + space_name)
self.struct_name = 'struct ' + self.render_name
if self.nested and space_name in family.consts:
self.struct_name += '_'
self.ptr_name = self.struct_name + ' *'
+ # All attr sets this one contains, directly or multiple levels down
+ self.child_nests = set()
self.request = False
self.reply = False
+ self.recursive = False
+ self.in_multi_val = False # used by a MultiAttr or and legacy arrays
self.attr_list = []
self.attrs = dict()
@@ -644,6 +1018,19 @@ class Struct:
raise Exception("Inheriting different members not supported")
self.inherited = [c_lower(x) for x in sorted(self._inherited)]
+ def external_selectors(self):
+ sels = []
+ for name, attr in self.attr_list:
+ if isinstance(attr, TypeSubMessage) and attr.selector.is_external():
+ sels.append(attr.selector)
+ return sels
+
+ def free_needs_iter(self):
+ for _, attr in self.attr_list:
+ if attr.free_needs_iter():
+ return True
+ return False
+
class EnumEntry(SpecEnumEntry):
def __init__(self, enum_set, yaml, prev, value_start):
@@ -667,17 +1054,25 @@ class EnumEntry(SpecEnumEntry):
class EnumSet(SpecEnumSet):
def __init__(self, family, yaml):
- self.render_name = c_lower(family.name + '-' + yaml['name'])
+ self.render_name = c_lower(family.ident_name + '-' + yaml['name'])
if 'enum-name' in yaml:
if yaml['enum-name']:
self.enum_name = 'enum ' + c_lower(yaml['enum-name'])
+ self.user_type = self.enum_name
else:
self.enum_name = None
else:
self.enum_name = 'enum ' + self.render_name
- self.value_pfx = yaml.get('name-prefix', f"{family.name}-{yaml['name']}-")
+ if self.enum_name:
+ self.user_type = self.enum_name
+ else:
+ self.user_type = 'int'
+
+ self.value_pfx = yaml.get('name-prefix', f"{family.ident_name}-{yaml['name']}-")
+ self.header = yaml.get('header', None)
+ self.enum_cnt_name = yaml.get('enum-cnt-name', None)
super().__init__(family, yaml)
@@ -689,7 +1084,7 @@ class EnumSet(SpecEnumSet):
high = max([x.value for x in self.entries.values()])
if high - low + 1 != len(self.entries):
- raise Exception("Can't get value range for a noncontiguous enum")
+ return None, None
return low, high
@@ -702,14 +1097,16 @@ class AttrSet(SpecAttrSet):
if 'name-prefix' in yaml:
pfx = yaml['name-prefix']
elif self.name == family.name:
- pfx = family.name + '-a-'
+ pfx = family.ident_name + '-a-'
else:
- pfx = f"{family.name}-a-{self.name}-"
+ pfx = f"{family.ident_name}-a-{self.name}-"
self.name_prefix = c_upper(pfx)
self.max_name = c_upper(self.yaml.get('attr-max-name', f"{self.name_prefix}max"))
+ self.cnt_name = c_upper(self.yaml.get('attr-cnt-name', f"__{self.name_prefix}max"))
else:
self.name_prefix = family.attr_sets[self.subset_of].name_prefix
self.max_name = family.attr_sets[self.subset_of].max_name
+ self.cnt_name = family.attr_sets[self.subset_of].cnt_name
# Added by resolve:
self.c_name = None
@@ -734,13 +1131,25 @@ class AttrSet(SpecAttrSet):
elif elem['type'] == 'string':
t = TypeString(self.family, self, elem, value)
elif elem['type'] == 'binary':
- t = TypeBinary(self.family, self, elem, value)
+ if 'struct' in elem:
+ t = TypeBinaryStruct(self.family, self, elem, value)
+ elif elem.get('sub-type') in scalars:
+ t = TypeBinaryScalarArray(self.family, self, elem, value)
+ else:
+ t = TypeBinary(self.family, self, elem, value)
+ elif elem['type'] == 'bitfield32':
+ t = TypeBitfield32(self.family, self, elem, value)
elif elem['type'] == 'nest':
t = TypeNest(self.family, self, elem, value)
- elif elem['type'] == 'array-nest':
- t = TypeArrayNest(self.family, self, elem, value)
+ elif elem['type'] == 'indexed-array' and 'sub-type' in elem:
+ if elem["sub-type"] in ['binary', 'nest', 'u32']:
+ t = TypeIndexedArray(self.family, self, elem, value)
+ else:
+ raise Exception(f'new_attr: unsupported sub-type {elem["sub-type"]}')
elif elem['type'] == 'nest-type-value':
t = TypeNestTypeValue(self.family, self, elem, value)
+ elif elem['type'] == 'sub-message':
+ t = TypeSubMessage(self.family, self, elem, value)
else:
raise Exception(f"No typed class for type {elem['type']}")
@@ -752,9 +1161,17 @@ class AttrSet(SpecAttrSet):
class Operation(SpecOperation):
def __init__(self, family, yaml, req_value, rsp_value):
+ # Fill in missing operation properties (for fixed hdr-only msgs)
+ for mode in ['do', 'dump', 'event']:
+ for direction in ['request', 'reply']:
+ try:
+ yaml[mode][direction].setdefault('attributes', [])
+ except KeyError:
+ pass
+
super().__init__(family, yaml, req_value, rsp_value)
- self.render_name = family.name + '_' + c_lower(self.name)
+ self.render_name = c_lower(family.ident_name + '_' + self.name)
self.dual_policy = ('do' in yaml and 'request' in yaml['do']) and \
('dump' in yaml and 'request' in yaml['dump'])
@@ -777,8 +1194,18 @@ class Operation(SpecOperation):
self.has_ntf = True
+class SubMessage(SpecSubMessage):
+ def __init__(self, family, yaml):
+ super().__init__(family, yaml)
+
+ self.render_name = c_lower(family.ident_name + '-' + yaml['name'])
+
+ def resolve(self):
+ self.resolve_up(super())
+
+
class Family(SpecFamily):
- def __init__(self, file_name, exclude_ops):
+ def __init__(self, file_name, exclude_ops, fn_prefix):
# Added by resolve:
self.c_name = None
delattr(self, "c_name")
@@ -804,15 +1231,18 @@ class Family(SpecFamily):
if 'uapi-header' in self.yaml:
self.uapi_header = self.yaml['uapi-header']
else:
- self.uapi_header = f"linux/{self.name}.h"
+ self.uapi_header = f"linux/{self.ident_name}.h"
+ if self.uapi_header.startswith("linux/") and self.uapi_header.endswith('.h'):
+ self.uapi_header_name = self.uapi_header[6:-2]
+ else:
+ self.uapi_header_name = self.ident_name
+
+ self.fn_prefix = fn_prefix if fn_prefix else f'{self.ident_name}-nl'
def resolve(self):
self.resolve_up(super())
- if self.yaml.get('protocol', 'genetlink') not in {'genetlink', 'genetlink-c', 'genetlink-legacy'}:
- raise Exception("Codegen only supported for genetlink")
-
- self.c_name = c_lower(self.name)
+ self.c_name = c_lower(self.ident_name)
if 'name-prefix' in self.yaml['operations']:
self.op_prefix = c_upper(self.yaml['operations']['name-prefix'])
else:
@@ -834,7 +1264,7 @@ class Family(SpecFamily):
# dict space-name -> 'request': set(attrs), 'reply': set(attrs)
self.root_sets = dict()
- # dict space-name -> set('request', 'reply')
+ # dict space-name -> Struct
self.pure_nested_structs = dict()
self._mark_notify()
@@ -842,6 +1272,8 @@ class Family(SpecFamily):
self._load_root_sets()
self._load_nested_sets()
+ self._load_attr_use()
+ self._load_selector_passing()
self._load_hooks()
self.kernel_policy = self.yaml.get('kernel-policy', 'split')
@@ -857,6 +1289,12 @@ class Family(SpecFamily):
def new_operation(self, elem, req_value, rsp_value):
return Operation(self, elem, req_value, rsp_value)
+ def new_sub_message(self, elem):
+ return SubMessage(self, elem)
+
+ def is_classic(self):
+ return self.proto == 'netlink-raw'
+
def _mark_notify(self):
for op in self.msgs.values():
if 'notify' in op:
@@ -893,6 +1331,98 @@ class Family(SpecFamily):
self.root_sets[op['attribute-set']]['request'].update(req_attrs)
self.root_sets[op['attribute-set']]['reply'].update(rsp_attrs)
+ def _sort_pure_types(self):
+ # Try to reorder according to dependencies
+ pns_key_list = list(self.pure_nested_structs.keys())
+ pns_key_seen = set()
+ rounds = len(pns_key_list) ** 2 # it's basically bubble sort
+ for _ in range(rounds):
+ if len(pns_key_list) == 0:
+ break
+ name = pns_key_list.pop(0)
+ finished = True
+ for _, spec in self.attr_sets[name].items():
+ if 'nested-attributes' in spec:
+ nested = spec['nested-attributes']
+ elif 'sub-message' in spec:
+ nested = spec.sub_message
+ else:
+ continue
+
+ # If the unknown nest we hit is recursive it's fine, it'll be a pointer
+ if self.pure_nested_structs[nested].recursive:
+ continue
+ if nested not in pns_key_seen:
+ # Dicts are sorted, this will make struct last
+ struct = self.pure_nested_structs.pop(name)
+ self.pure_nested_structs[name] = struct
+ finished = False
+ break
+ if finished:
+ pns_key_seen.add(name)
+ else:
+ pns_key_list.append(name)
+
+ def _load_nested_set_nest(self, spec):
+ inherit = set()
+ nested = spec['nested-attributes']
+ if nested not in self.root_sets:
+ if nested not in self.pure_nested_structs:
+ self.pure_nested_structs[nested] = \
+ Struct(self, nested, inherited=inherit,
+ fixed_header=spec.get('fixed-header'))
+ else:
+ raise Exception(f'Using attr set as root and nested not supported - {nested}')
+
+ if 'type-value' in spec:
+ if nested in self.root_sets:
+ raise Exception("Inheriting members to a space used as root not supported")
+ inherit.update(set(spec['type-value']))
+ elif spec['type'] == 'indexed-array':
+ inherit.add('idx')
+ self.pure_nested_structs[nested].set_inherited(inherit)
+
+ return nested
+
+ def _load_nested_set_submsg(self, spec):
+ # Fake the struct type for the sub-message itself
+ # its not a attr_set but codegen wants attr_sets.
+ submsg = self.sub_msgs[spec["sub-message"]]
+ nested = submsg.name
+
+ attrs = []
+ for name, fmt in submsg.formats.items():
+ attr = {
+ "name": name,
+ "parent-sub-message": spec,
+ }
+ if 'attribute-set' in fmt:
+ attr |= {
+ "type": "nest",
+ "nested-attributes": fmt['attribute-set'],
+ }
+ if 'fixed-header' in fmt:
+ attr |= { "fixed-header": fmt["fixed-header"] }
+ elif 'fixed-header' in fmt:
+ attr |= {
+ "type": "binary",
+ "struct": fmt["fixed-header"],
+ }
+ else:
+ attr["type"] = "flag"
+ attrs.append(attr)
+
+ self.attr_sets[nested] = AttrSet(self, {
+ "name": nested,
+ "name-pfx": self.name + '-' + spec.name + '-',
+ "attributes": attrs
+ })
+
+ if nested not in self.pure_nested_structs:
+ self.pure_nested_structs[nested] = Struct(self, nested, submsg=submsg)
+
+ return nested
+
def _load_nested_sets(self):
attr_set_queue = list(self.root_sets.keys())
attr_set_seen = set(self.root_sets.keys())
@@ -900,67 +1430,102 @@ class Family(SpecFamily):
while len(attr_set_queue):
a_set = attr_set_queue.pop(0)
for attr, spec in self.attr_sets[a_set].items():
- if 'nested-attributes' not in spec:
+ if 'nested-attributes' in spec:
+ nested = self._load_nested_set_nest(spec)
+ elif 'sub-message' in spec:
+ nested = self._load_nested_set_submsg(spec)
+ else:
continue
- nested = spec['nested-attributes']
if nested not in attr_set_seen:
attr_set_queue.append(nested)
attr_set_seen.add(nested)
- inherit = set()
- if nested not in self.root_sets:
- if nested not in self.pure_nested_structs:
- self.pure_nested_structs[nested] = Struct(self, nested, inherited=inherit)
- else:
- raise Exception(f'Using attr set as root and nested not supported - {nested}')
-
- if 'type-value' in spec:
- if nested in self.root_sets:
- raise Exception("Inheriting members to a space used as root not supported")
- inherit.update(set(spec['type-value']))
- elif spec['type'] == 'array-nest':
- inherit.add('idx')
- self.pure_nested_structs[nested].set_inherited(inherit)
-
for root_set, rs_members in self.root_sets.items():
for attr, spec in self.attr_sets[root_set].items():
if 'nested-attributes' in spec:
nested = spec['nested-attributes']
+ elif 'sub-message' in spec:
+ nested = spec.sub_message
+ else:
+ nested = None
+
+ if nested:
if attr in rs_members['request']:
self.pure_nested_structs[nested].request = True
if attr in rs_members['reply']:
self.pure_nested_structs[nested].reply = True
- # Try to reorder according to dependencies
- pns_key_list = list(self.pure_nested_structs.keys())
- pns_key_seen = set()
- rounds = len(pns_key_list)**2 # it's basically bubble sort
- for _ in range(rounds):
- if len(pns_key_list) == 0:
- break
- name = pns_key_list.pop(0)
- finished = True
- for _, spec in self.attr_sets[name].items():
- if 'nested-attributes' in spec:
- if spec['nested-attributes'] not in pns_key_seen:
- # Dicts are sorted, this will make struct last
- struct = self.pure_nested_structs.pop(name)
- self.pure_nested_structs[name] = struct
- finished = False
- break
- if finished:
- pns_key_seen.add(name)
- else:
- pns_key_list.append(name)
- # Propagate the request / reply
+ if spec.is_multi_val():
+ child = self.pure_nested_structs.get(nested)
+ child.in_multi_val = True
+
+ self._sort_pure_types()
+
+ # Propagate the request / reply / recursive
for attr_set, struct in reversed(self.pure_nested_structs.items()):
for _, spec in self.attr_sets[attr_set].items():
+ if attr_set in struct.child_nests:
+ struct.recursive = True
+
if 'nested-attributes' in spec:
- child = self.pure_nested_structs.get(spec['nested-attributes'])
- if child:
- child.request |= struct.request
- child.reply |= struct.reply
+ child_name = spec['nested-attributes']
+ elif 'sub-message' in spec:
+ child_name = spec.sub_message
+ else:
+ continue
+
+ struct.child_nests.add(child_name)
+ child = self.pure_nested_structs.get(child_name)
+ if child:
+ if not child.recursive:
+ struct.child_nests.update(child.child_nests)
+ child.request |= struct.request
+ child.reply |= struct.reply
+ if spec.is_multi_val():
+ child.in_multi_val = True
+
+ self._sort_pure_types()
+
+ def _load_attr_use(self):
+ for _, struct in self.pure_nested_structs.items():
+ if struct.request:
+ for _, arg in struct.member_list():
+ arg.set_request()
+ if struct.reply:
+ for _, arg in struct.member_list():
+ arg.set_reply()
+
+ for root_set, rs_members in self.root_sets.items():
+ for attr, spec in self.attr_sets[root_set].items():
+ if attr in rs_members['request']:
+ spec.set_request()
+ if attr in rs_members['reply']:
+ spec.set_reply()
+
+ def _load_selector_passing(self):
+ def all_structs():
+ for k, v in reversed(self.pure_nested_structs.items()):
+ yield k, v
+ for k, _ in self.root_sets.items():
+ yield k, None # we don't have a struct, but it must be terminal
+
+ for attr_set, struct in all_structs():
+ for _, spec in self.attr_sets[attr_set].items():
+ if 'nested-attributes' in spec:
+ child_name = spec['nested-attributes']
+ elif 'sub-message' in spec:
+ child_name = spec.sub_message
+ else:
+ continue
+
+ child = self.pure_nested_structs.get(child_name)
+ for selector in child.external_selectors():
+ if selector.name in self.attr_sets[attr_set]:
+ sel_attr = self.attr_sets[attr_set][selector.name]
+ selector.set_attr(sel_attr)
+ else:
+ raise Exception("Passing selector thru more than one layer not supported")
def _load_global_policy(self):
global_set = set()
@@ -1011,13 +1576,28 @@ class RenderInfo:
self.op_mode = op_mode
self.op = op
+ fixed_hdr = op.fixed_header if op else None
+ self.fixed_hdr_len = 'ys->family->hdr_len'
+ if op and op.fixed_header:
+ if op.fixed_header != family.fixed_header:
+ if family.is_classic():
+ self.fixed_hdr_len = f"sizeof(struct {c_lower(fixed_hdr)})"
+ else:
+ raise Exception("Per-op fixed header not supported, yet")
+
+
# 'do' and 'dump' response parsing is identical
self.type_consistent = True
- if op_mode != 'do' and 'dump' in op and 'do' in op:
- if ('reply' in op['do']) != ('reply' in op["dump"]):
- self.type_consistent = False
- elif 'reply' in op['do'] and op["do"]["reply"] != op["dump"]["reply"]:
- self.type_consistent = False
+ self.type_oneside = False
+ if op_mode != 'do' and 'dump' in op:
+ if 'do' in op:
+ if ('reply' in op['do']) != ('reply' in op["dump"]):
+ self.type_consistent = False
+ elif 'reply' in op['do'] and op["do"]["reply"] != op["dump"]["reply"]:
+ self.type_consistent = False
+ else:
+ self.type_consistent = True
+ self.type_oneside = True
self.attr_set = attr_set
if not self.attr_set:
@@ -1035,27 +1615,42 @@ class RenderInfo:
self.struct = dict()
if op_mode == 'notify':
- op_mode = 'do'
+ op_mode = 'do' if 'do' in op else 'dump'
for op_dir in ['request', 'reply']:
- if op and op_dir in op[op_mode]:
+ if op:
+ type_list = []
+ if op_dir in op[op_mode]:
+ type_list = op[op_mode][op_dir]['attributes']
self.struct[op_dir] = Struct(family, self.attr_set,
- type_list=op[op_mode][op_dir]['attributes'])
+ fixed_header=fixed_hdr,
+ type_list=type_list)
if op_mode == 'event':
- self.struct['reply'] = Struct(family, self.attr_set, type_list=op['event']['attributes'])
+ self.struct['reply'] = Struct(family, self.attr_set,
+ fixed_header=fixed_hdr,
+ type_list=op['event']['attributes'])
+
+ def type_empty(self, key):
+ return len(self.struct[key].attr_list) == 0 and \
+ self.struct['request'].fixed_header is None
+
+ def needs_nlflags(self, direction):
+ return self.op_mode == 'do' and direction == 'request' and self.family.is_classic()
class CodeWriter:
- def __init__(self, nlib, out_file=None):
+ def __init__(self, nlib, out_file=None, overwrite=True):
self.nlib = nlib
+ self._overwrite = overwrite
self._nl = False
self._block_end = False
self._silent_block = False
self._ind = 0
+ self._ifdef_block = None
if out_file is None:
self._out = os.sys.stdout
else:
- self._out = tempfile.TemporaryFile('w+')
+ self._out = tempfile.NamedTemporaryFile('w+')
self._out_file = out_file
def __del__(self):
@@ -1064,6 +1659,11 @@ class CodeWriter:
def close_out_file(self):
if self._out == os.sys.stdout:
return
+ # Avoid modifying the file if contents didn't change
+ self._out.flush()
+ if not self._overwrite and os.path.isfile(self._out_file):
+ if filecmp.cmp(self._out.name, self._out_file, shallow=False):
+ return
with open(self._out_file, 'w+') as out_file:
self._out.seek(0)
shutil.copyfileobj(self._out, out_file)
@@ -1092,6 +1692,9 @@ class CodeWriter:
if self._silent_block:
ind += 1
self._silent_block = line.endswith(')') and CodeWriter._is_cond(line)
+ self._silent_block |= line.strip() == 'else'
+ if line[0] == '#':
+ ind = 0
if add_ind:
ind += add_ind
self._out.write('\t' * ind + line + '\n')
@@ -1186,9 +1789,9 @@ class CodeWriter:
def write_func(self, qual_ret, name, body, args=None, local_vars=None):
self.write_func_prot(qual_ret=qual_ret, name=name, args=args)
+ self.block_start()
self.write_func_lvar(local_vars=local_vars)
- self.block_start()
for line in body:
self.p(line)
self.block_end()
@@ -1215,11 +1818,24 @@ class CodeWriter:
for one in members:
line = '.' + one[0]
line += '\t' * ((longest - len(one[0]) - 1 + 7) // 8)
- line += '= ' + one[1] + ','
+ line += '= ' + str(one[1]) + ','
self.p(line)
+ def ifdef_block(self, config):
+ config_option = None
+ if config:
+ config_option = 'CONFIG_' + c_upper(config)
+ if self._ifdef_block == config_option:
+ return
+
+ if self._ifdef_block:
+ self.p('#endif /* ' + self._ifdef_block + ' */')
+ if config_option:
+ self.p('#ifdef ' + config_option)
+ self._ifdef_block = config_option
-scalars = {'u8', 'u16', 'u32', 'u64', 's32', 's64'}
+
+scalars = {'u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'uint', 'sint'}
direction_to_suffix = {
'reply': '_rsp',
@@ -1283,11 +1899,15 @@ def rdir(direction):
def op_prefix(ri, direction, deref=False):
suffix = f"_{ri.type_name}"
- if not ri.op_mode or ri.op_mode == 'do':
+ if not ri.op_mode:
+ pass
+ elif ri.op_mode == 'do':
suffix += f"{direction_to_suffix[direction]}"
else:
if direction == 'request':
- suffix += '_req_dump'
+ suffix += '_req'
+ if not ri.type_oneside:
+ suffix += '_dump'
else:
if ri.type_consistent:
if deref:
@@ -1298,7 +1918,7 @@ def op_prefix(ri, direction, deref=False):
suffix += '_rsp'
suffix += '_dump' if deref else '_list'
- return f"{ri.family['name']}{suffix}"
+ return f"{ri.family.c_name}{suffix}"
def type_name(ri, direction, deref=False):
@@ -1331,9 +1951,39 @@ def print_dump_prototype(ri):
print_prototype(ri, "request")
+def put_typol_submsg(cw, struct):
+ cw.block_start(line=f'const struct ynl_policy_attr {struct.render_name}_policy[] =')
+
+ i = 0
+ for name, arg in struct.member_list():
+ nest = ""
+ if arg.type == 'nest':
+ nest = f" .nest = &{arg.nested_render_name}_nest,"
+ cw.p('[%d] = { .type = YNL_PT_SUBMSG, .name = "%s",%s },' %
+ (i, name, nest))
+ i += 1
+
+ cw.block_end(line=';')
+ cw.nl()
+
+ cw.block_start(line=f'const struct ynl_policy_nest {struct.render_name}_nest =')
+ cw.p(f'.max_attr = {i - 1},')
+ cw.p(f'.table = {struct.render_name}_policy,')
+ cw.block_end(line=';')
+ cw.nl()
+
+
+def put_typol_fwd(cw, struct):
+ cw.p(f'extern const struct ynl_policy_nest {struct.render_name}_nest;')
+
+
def put_typol(cw, struct):
+ if struct.submsg:
+ put_typol_submsg(cw, struct)
+ return
+
type_max = struct.attr_set.max_name
- cw.block_start(line=f'struct ynl_policy_attr {struct.render_name}_policy[{type_max} + 1] =')
+ cw.block_start(line=f'const struct ynl_policy_attr {struct.render_name}_policy[{type_max} + 1] =')
for _, arg in struct.member_list():
arg.attr_typol(cw)
@@ -1341,7 +1991,7 @@ def put_typol(cw, struct):
cw.block_end(line=';')
cw.nl()
- cw.block_start(line=f'struct ynl_policy_nest {struct.render_name}_nest =')
+ cw.block_start(line=f'const struct ynl_policy_nest {struct.render_name}_nest =')
cw.p(f'.max_attr = {type_max},')
cw.p(f'.table = {struct.render_name}_policy,')
cw.block_end(line=';')
@@ -1350,13 +2000,13 @@ def put_typol(cw, struct):
def _put_enum_to_str_helper(cw, render_name, map_name, arg_name, enum=None):
args = [f'int {arg_name}']
- if enum and not ('enum-name' in enum and not enum['enum-name']):
- args = [f'enum {render_name} {arg_name}']
+ if enum:
+ args = [enum.user_type + ' ' + arg_name]
cw.write_func_prot('const char *', f'{render_name}_str', args)
cw.block_start()
if enum and enum.type == 'flags':
cw.p(f'{arg_name} = ffs({arg_name}) - 1;')
- cw.p(f'if ({arg_name} < 0 || {arg_name} >= (int)MNL_ARRAY_SIZE({map_name}))')
+ cw.p(f'if ({arg_name} < 0 || {arg_name} >= (int)YNL_ARRAY_SIZE({map_name}))')
cw.p('return NULL;')
cw.p(f'return {map_name}[{arg_name}];')
cw.block_end()
@@ -1364,14 +2014,20 @@ def _put_enum_to_str_helper(cw, render_name, map_name, arg_name, enum=None):
def put_op_name_fwd(family, cw):
- cw.write_func_prot('const char *', f'{family.name}_op_str', ['int op'], suffix=';')
+ cw.write_func_prot('const char *', f'{family.c_name}_op_str', ['int op'], suffix=';')
def put_op_name(family, cw):
- map_name = f'{family.name}_op_strmap'
+ map_name = f'{family.c_name}_op_strmap'
cw.block_start(line=f"static const char * const {map_name}[] =")
for op_name, op in family.msgs.items():
if op.rsp_value:
+ # Make sure we don't add duplicated entries, if multiple commands
+ # produce the same response in legacy families.
+ if family.rsp_by_value[op.rsp_value] != op:
+ cw.p(f'// skip "{op_name}", duplicate reply value')
+ continue
+
if op.req_value == op.rsp_value:
cw.p(f'[{op.enum_name}] = "{op_name}",')
else:
@@ -1379,13 +2035,11 @@ def put_op_name(family, cw):
cw.block_end(line=';')
cw.nl()
- _put_enum_to_str_helper(cw, family.name + '_op', map_name, 'op')
+ _put_enum_to_str_helper(cw, family.c_name + '_op', map_name, 'op')
def put_enum_to_str_fwd(family, cw, enum):
- args = [f'enum {enum.render_name} value']
- if 'enum-name' in enum and not enum['enum-name']:
- args = ['int value']
+ args = [enum.user_type + ' value']
cw.write_func_prot('const char *', f'{enum.render_name}_str', args, suffix=';')
@@ -1400,21 +2054,56 @@ def put_enum_to_str(family, cw, enum):
_put_enum_to_str_helper(cw, enum.render_name, map_name, 'value', enum=enum)
-def put_req_nested(ri, struct):
+def put_local_vars(struct):
+ local_vars = []
+ has_array = False
+ has_count = False
+ for _, arg in struct.member_list():
+ has_array |= arg.type == 'indexed-array'
+ has_count |= arg.presence_type() == 'count'
+ if has_array:
+ local_vars.append('struct nlattr *array;')
+ if has_count:
+ local_vars.append('unsigned int i;')
+ return local_vars
+
+
+def put_req_nested_prototype(ri, struct, suffix=';'):
func_args = ['struct nlmsghdr *nlh',
'unsigned int attr_type',
f'{struct.ptr_name}obj']
- ri.cw.write_func_prot('int', f'{struct.render_name}_put', func_args)
+ ri.cw.write_func_prot('int', f'{struct.render_name}_put', func_args,
+ suffix=suffix)
+
+
+def put_req_nested(ri, struct):
+ local_vars = []
+ init_lines = []
+
+ if struct.submsg is None:
+ local_vars.append('struct nlattr *nest;')
+ init_lines.append("nest = ynl_attr_nest_start(nlh, attr_type);")
+ if struct.fixed_header:
+ local_vars.append('void *hdr;')
+ struct_sz = f'sizeof({struct.fixed_header})'
+ init_lines.append(f"hdr = ynl_nlmsg_put_extra_header(nlh, {struct_sz});")
+ init_lines.append(f"memcpy(hdr, &obj->_hdr, {struct_sz});")
+
+ local_vars += put_local_vars(struct)
+
+ put_req_nested_prototype(ri, struct, suffix='')
ri.cw.block_start()
- ri.cw.write_func_lvar('struct nlattr *nest;')
+ ri.cw.write_func_lvar(local_vars)
- ri.cw.p("nest = mnl_attr_nest_start(nlh, attr_type);")
+ for line in init_lines:
+ ri.cw.p(line)
for _, arg in struct.member_list():
arg.attr_put(ri, "obj")
- ri.cw.p("mnl_attr_nest_end(nlh, nest);")
+ if struct.submsg is None:
+ ri.cw.p("ynl_attr_nest_end(nlh, nest);")
ri.cw.nl()
ri.cw.p('return 0;')
@@ -1423,31 +2112,56 @@ def put_req_nested(ri, struct):
def _multi_parse(ri, struct, init_lines, local_vars):
+ if struct.fixed_header:
+ local_vars += ['void *hdr;']
if struct.nested:
- iter_line = "mnl_attr_for_each_nested(attr, nested)"
+ if struct.fixed_header:
+ iter_line = f"ynl_attr_for_each_nested_off(attr, nested, sizeof({struct.fixed_header}))"
+ else:
+ iter_line = "ynl_attr_for_each_nested(attr, nested)"
else:
- iter_line = "mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr))"
+ iter_line = "ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len)"
+ if ri.op.fixed_header != ri.family.fixed_header:
+ if ri.family.is_classic():
+ iter_line = f"ynl_attr_for_each(attr, nlh, sizeof({struct.fixed_header}))"
+ else:
+ raise Exception("Per-op fixed header not supported, yet")
- array_nests = set()
+ indexed_arrays = set()
multi_attrs = set()
needs_parg = False
+ var_set = set()
for arg, aspec in struct.member_list():
- if aspec['type'] == 'array-nest':
- local_vars.append(f'const struct nlattr *attr_{aspec.c_name};')
- array_nests.add(arg)
+ if aspec['type'] == 'indexed-array' and 'sub-type' in aspec:
+ if aspec["sub-type"] in {'binary', 'nest'}:
+ local_vars.append(f'const struct nlattr *attr_{aspec.c_name} = NULL;')
+ indexed_arrays.add(arg)
+ elif aspec['sub-type'] in scalars:
+ local_vars.append(f'const struct nlattr *attr_{aspec.c_name} = NULL;')
+ indexed_arrays.add(arg)
+ else:
+ raise Exception(f'Not supported sub-type {aspec["sub-type"]}')
if 'multi-attr' in aspec:
multi_attrs.add(arg)
needs_parg |= 'nested-attributes' in aspec
- if array_nests or multi_attrs:
+ needs_parg |= 'sub-message' in aspec
+
+ try:
+ _, _, l_vars = aspec._attr_get(ri, '')
+ var_set |= set(l_vars) if l_vars else set()
+ except Exception:
+ pass # _attr_get() not implemented by simple types, ignore
+ local_vars += list(var_set)
+ if indexed_arrays or multi_attrs:
local_vars.append('int i;')
if needs_parg:
local_vars.append('struct ynl_parse_arg parg;')
init_lines.append('parg.ys = yarg->ys;')
- all_multi = array_nests | multi_attrs
+ all_multi = indexed_arrays | multi_attrs
- for anest in sorted(all_multi):
- local_vars.append(f"unsigned int n_{struct[anest].c_name} = 0;")
+ for arg in sorted(all_multi):
+ local_vars.append(f"unsigned int n_{struct[arg].c_name} = 0;")
ri.cw.block_start()
ri.cw.write_func_lvar(local_vars)
@@ -1459,14 +2173,22 @@ def _multi_parse(ri, struct, init_lines, local_vars):
for arg in struct.inherited:
ri.cw.p(f'dst->{arg} = {arg};')
- for anest in sorted(all_multi):
- aspec = struct[anest]
+ if struct.fixed_header:
+ if struct.nested:
+ ri.cw.p('hdr = ynl_attr_data(nested);')
+ elif ri.family.is_classic():
+ ri.cw.p('hdr = ynl_nlmsg_data(nlh);')
+ else:
+ ri.cw.p('hdr = ynl_nlmsg_data_offset(nlh, sizeof(struct genlmsghdr));')
+ ri.cw.p(f"memcpy(&dst->_hdr, hdr, sizeof({struct.fixed_header}));")
+ for arg in sorted(all_multi):
+ aspec = struct[arg]
ri.cw.p(f"if (dst->{aspec.c_name})")
ri.cw.p(f'return ynl_error_parse(yarg, "attribute already present ({struct.attr_set.name}.{aspec.name})");')
ri.cw.nl()
ri.cw.block_start(line=iter_line)
- ri.cw.p('unsigned int type = mnl_attr_get_type(attr);')
+ ri.cw.p('unsigned int type = ynl_attr_type(attr);')
ri.cw.nl()
first = True
@@ -1478,44 +2200,64 @@ def _multi_parse(ri, struct, init_lines, local_vars):
ri.cw.block_end()
ri.cw.nl()
- for anest in sorted(array_nests):
- aspec = struct[anest]
+ for arg in sorted(indexed_arrays):
+ aspec = struct[arg]
ri.cw.block_start(line=f"if (n_{aspec.c_name})")
- ri.cw.p(f"dst->{aspec.c_name} = calloc({aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
- ri.cw.p(f"dst->n_{aspec.c_name} = n_{aspec.c_name};")
+ ri.cw.p(f"dst->{aspec.c_name} = calloc(n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
+ ri.cw.p(f"dst->_count.{aspec.c_name} = n_{aspec.c_name};")
ri.cw.p('i = 0;')
- ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;")
- ri.cw.block_start(line=f"mnl_attr_for_each_nested(attr, attr_{aspec.c_name})")
- ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];")
- ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr, mnl_attr_get_type(attr)))")
- ri.cw.p('return MNL_CB_ERROR;')
+ if 'nested-attributes' in aspec:
+ ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;")
+ ri.cw.block_start(line=f"ynl_attr_for_each_nested(attr, attr_{aspec.c_name})")
+ if 'nested-attributes' in aspec:
+ ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];")
+ ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr, ynl_attr_type(attr)))")
+ ri.cw.p('return YNL_PARSE_CB_ERROR;')
+ elif aspec.sub_type in scalars:
+ ri.cw.p(f"dst->{aspec.c_name}[i] = ynl_attr_get_{aspec.sub_type}(attr);")
+ elif aspec.sub_type == 'binary' and 'exact-len' in aspec.checks:
+ # Length is validated by typol
+ ri.cw.p(f'memcpy(dst->{aspec.c_name}[i], ynl_attr_data(attr), {aspec.checks["exact-len"]});')
+ else:
+ raise Exception(f"Nest parsing type not supported in {aspec['name']}")
ri.cw.p('i++;')
ri.cw.block_end()
ri.cw.block_end()
ri.cw.nl()
- for anest in sorted(multi_attrs):
- aspec = struct[anest]
+ for arg in sorted(multi_attrs):
+ aspec = struct[arg]
ri.cw.block_start(line=f"if (n_{aspec.c_name})")
ri.cw.p(f"dst->{aspec.c_name} = calloc(n_{aspec.c_name}, sizeof(*dst->{aspec.c_name}));")
- ri.cw.p(f"dst->n_{aspec.c_name} = n_{aspec.c_name};")
+ ri.cw.p(f"dst->_count.{aspec.c_name} = n_{aspec.c_name};")
ri.cw.p('i = 0;')
if 'nested-attributes' in aspec:
ri.cw.p(f"parg.rsp_policy = &{aspec.nested_render_name}_nest;")
ri.cw.block_start(line=iter_line)
- ri.cw.block_start(line=f"if (mnl_attr_get_type(attr) == {aspec.enum_name})")
+ ri.cw.block_start(line=f"if (ynl_attr_type(attr) == {aspec.enum_name})")
if 'nested-attributes' in aspec:
ri.cw.p(f"parg.data = &dst->{aspec.c_name}[i];")
ri.cw.p(f"if ({aspec.nested_render_name}_parse(&parg, attr))")
- ri.cw.p('return MNL_CB_ERROR;')
- elif aspec['type'] in scalars:
- t = aspec['type']
- if t[0] == 's':
- t = 'u' + t[1:]
- ri.cw.p(f"dst->{aspec.c_name}[i] = mnl_attr_get_{t}(attr);")
+ ri.cw.p('return YNL_PARSE_CB_ERROR;')
+ elif aspec.type in scalars:
+ ri.cw.p(f"dst->{aspec.c_name}[i] = ynl_attr_get_{aspec.type}(attr);")
+ elif aspec.type == 'binary' and 'struct' in aspec:
+ ri.cw.p('size_t len = ynl_attr_data_len(attr);')
+ ri.cw.nl()
+ ri.cw.p(f'if (len > sizeof(dst->{aspec.c_name}[0]))')
+ ri.cw.p(f'len = sizeof(dst->{aspec.c_name}[0]);')
+ ri.cw.p(f"memcpy(&dst->{aspec.c_name}[i], ynl_attr_data(attr), len);")
+ elif aspec.type == 'string':
+ ri.cw.p('unsigned int len;')
+ ri.cw.nl()
+ ri.cw.p('len = strnlen(ynl_attr_get_str(attr), ynl_attr_data_len(attr));')
+ ri.cw.p(f'dst->{aspec.c_name}[i] = malloc(sizeof(struct ynl_string) + len + 1);')
+ ri.cw.p(f"dst->{aspec.c_name}[i]->len = len;")
+ ri.cw.p(f"memcpy(dst->{aspec.c_name}[i]->str, ynl_attr_get_str(attr), len);")
+ ri.cw.p(f"dst->{aspec.c_name}[i]->str[len] = 0;")
else:
- raise Exception('Nest parsing type not supported yet')
+ raise Exception(f'Nest parsing of type {aspec.type} not supported yet')
ri.cw.p('i++;')
ri.cw.block_end()
ri.cw.block_end()
@@ -1525,24 +2267,79 @@ def _multi_parse(ri, struct, init_lines, local_vars):
if struct.nested:
ri.cw.p('return 0;')
else:
- ri.cw.p('return MNL_CB_OK;')
+ ri.cw.p('return YNL_PARSE_CB_OK;')
ri.cw.block_end()
ri.cw.nl()
-def parse_rsp_nested(ri, struct):
+def parse_rsp_submsg(ri, struct):
+ parse_rsp_nested_prototype(ri, struct, suffix='')
+
+ var = 'dst'
+ local_vars = {'const struct nlattr *attr = nested;',
+ f'{struct.ptr_name}{var} = yarg->data;',
+ 'struct ynl_parse_arg parg;'}
+
+ for _, arg in struct.member_list():
+ _, _, l_vars = arg._attr_get(ri, var)
+ local_vars |= set(l_vars) if l_vars else set()
+
+ ri.cw.block_start()
+ ri.cw.write_func_lvar(list(local_vars))
+ ri.cw.p('parg.ys = yarg->ys;')
+ ri.cw.nl()
+
+ first = True
+ for name, arg in struct.member_list():
+ kw = 'if' if first else 'else if'
+ first = False
+
+ ri.cw.block_start(line=f'{kw} (!strcmp(sel, "{name}"))')
+ get_lines, init_lines, _ = arg._attr_get(ri, var)
+ for line in init_lines or []:
+ ri.cw.p(line)
+ for line in get_lines:
+ ri.cw.p(line)
+ if arg.presence_type() == 'present':
+ ri.cw.p(f"{var}->_present.{arg.c_name} = 1;")
+ ri.cw.block_end()
+ ri.cw.p('return 0;')
+ ri.cw.block_end()
+ ri.cw.nl()
+
+
+def parse_rsp_nested_prototype(ri, struct, suffix=';'):
func_args = ['struct ynl_parse_arg *yarg',
'const struct nlattr *nested']
+ for sel in struct.external_selectors():
+ func_args.append('const char *_sel_' + sel.name)
+ if struct.submsg:
+ func_args.insert(1, 'const char *sel')
for arg in struct.inherited:
func_args.append('__u32 ' + arg)
+ ri.cw.write_func_prot('int', f'{struct.render_name}_parse', func_args,
+ suffix=suffix)
+
+
+def parse_rsp_nested(ri, struct):
+ if struct.submsg:
+ return parse_rsp_submsg(ri, struct)
+
+ parse_rsp_nested_prototype(ri, struct, suffix='')
+
local_vars = ['const struct nlattr *attr;',
f'{struct.ptr_name}dst = yarg->data;']
init_lines = []
- ri.cw.write_func_prot('int', f'{struct.render_name}_parse', func_args)
-
- _multi_parse(ri, struct, init_lines, local_vars)
+ if struct.member_list():
+ _multi_parse(ri, struct, init_lines, local_vars)
+ else:
+ # Empty nest
+ ri.cw.block_start()
+ ri.cw.p('return 0;')
+ ri.cw.block_end()
+ ri.cw.nl()
def parse_rsp_msg(ri, deref=False):
@@ -1550,10 +2347,9 @@ def parse_rsp_msg(ri, deref=False):
return
func_args = ['const struct nlmsghdr *nlh',
- 'void *data']
+ 'struct ynl_parse_arg *yarg']
local_vars = [f'{type_name(ri, "reply", deref=deref)} *dst;',
- 'struct ynl_parse_arg *yarg = data;',
'const struct nlattr *attr;']
init_lines = ['dst = yarg->data;']
@@ -1564,7 +2360,7 @@ def parse_rsp_msg(ri, deref=False):
else:
# Empty reply
ri.cw.block_start()
- ri.cw.p('return MNL_CB_OK;')
+ ri.cw.p('return YNL_PARSE_CB_OK;')
ri.cw.block_end()
ri.cw.nl()
@@ -1573,30 +2369,46 @@ def print_req(ri):
ret_ok = '0'
ret_err = '-1'
direction = "request"
- local_vars = ['struct nlmsghdr *nlh;',
+ local_vars = ['struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };',
+ 'struct nlmsghdr *nlh;',
'int err;']
if 'reply' in ri.op[ri.op_mode]:
ret_ok = 'rsp'
ret_err = 'NULL'
- local_vars += [f'{type_name(ri, rdir(direction))} *rsp;',
- 'struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };']
+ local_vars += [f'{type_name(ri, rdir(direction))} *rsp;']
+
+ if ri.struct["request"].fixed_header:
+ local_vars += ['size_t hdr_len;',
+ 'void *hdr;']
+
+ local_vars += put_local_vars(ri.struct['request'])
print_prototype(ri, direction, terminate=False)
ri.cw.block_start()
ri.cw.write_func_lvar(local_vars)
- ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
+ if ri.family.is_classic():
+ ri.cw.p(f"nlh = ynl_msg_start_req(ys, {ri.op.enum_name}, req->_nlmsg_flags);")
+ else:
+ ri.cw.p(f"nlh = ynl_gemsg_start_req(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;")
+ ri.cw.p(f"ys->req_hdr_len = {ri.fixed_hdr_len};")
if 'reply' in ri.op[ri.op_mode]:
ri.cw.p(f"yrs.yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;")
ri.cw.nl()
+
+ if ri.struct['request'].fixed_header:
+ ri.cw.p("hdr_len = sizeof(req->_hdr);")
+ ri.cw.p("hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len);")
+ ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);")
+ ri.cw.nl()
+
for _, attr in ri.struct["request"].member_list():
attr.attr_put(ri, "req")
ri.cw.nl()
- parse_arg = "NULL"
if 'reply' in ri.op[ri.op_mode]:
ri.cw.p('rsp = calloc(1, sizeof(*rsp));')
ri.cw.p('yrs.yarg.data = rsp;')
@@ -1606,8 +2418,7 @@ def print_req(ri):
else:
ri.cw.p(f'yrs.rsp_cmd = {ri.op.rsp_value};')
ri.cw.nl()
- parse_arg = '&yrs'
- ri.cw.p(f"err = ynl_exec(ys, nlh, {parse_arg});")
+ ri.cw.p("err = ynl_exec(ys, nlh, &yrs);")
ri.cw.p('if (err < 0)')
if 'reply' in ri.op[ri.op_mode]:
ri.cw.p('goto err_free;')
@@ -1634,23 +2445,39 @@ def print_dump(ri):
'struct nlmsghdr *nlh;',
'int err;']
- for var in local_vars:
- ri.cw.p(f'{var}')
- ri.cw.nl()
+ if ri.struct['request'].fixed_header:
+ local_vars += ['size_t hdr_len;',
+ 'void *hdr;']
+
+ if 'request' in ri.op[ri.op_mode]:
+ local_vars += put_local_vars(ri.struct['request'])
- ri.cw.p('yds.ys = ys;')
+ ri.cw.write_func_lvar(local_vars)
+
+ ri.cw.p('yds.yarg.ys = ys;')
+ ri.cw.p(f"yds.yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;")
+ ri.cw.p("yds.yarg.data = NULL;")
ri.cw.p(f"yds.alloc_sz = sizeof({type_name(ri, rdir(direction))});")
ri.cw.p(f"yds.cb = {op_prefix(ri, 'reply', deref=True)}_parse;")
if ri.op.value is not None:
ri.cw.p(f'yds.rsp_cmd = {ri.op.enum_name};')
else:
ri.cw.p(f'yds.rsp_cmd = {ri.op.rsp_value};')
- ri.cw.p(f"yds.rsp_policy = &{ri.struct['reply'].render_name}_nest;")
ri.cw.nl()
- ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
+ if ri.family.is_classic():
+ ri.cw.p(f"nlh = ynl_msg_start_dump(ys, {ri.op.enum_name});")
+ else:
+ ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);")
+
+ if ri.struct['request'].fixed_header:
+ ri.cw.p("hdr_len = sizeof(req->_hdr);")
+ ri.cw.p("hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len);")
+ ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);")
+ ri.cw.nl()
if "request" in ri.op[ri.op_mode]:
ri.cw.p(f"ys->req_policy = &{ri.struct['request'].render_name}_nest;")
+ ri.cw.p(f"ys->req_hdr_len = {ri.fixed_hdr_len};")
ri.cw.nl()
for _, attr in ri.struct["request"].member_list():
attr.attr_put(ri, "req")
@@ -1679,11 +2506,22 @@ def free_arg_name(direction):
return 'obj'
-def print_alloc_wrapper(ri, direction):
+def print_alloc_wrapper(ri, direction, struct=None):
name = op_prefix(ri, direction)
- ri.cw.write_func_prot(f'static inline struct {name} *', f"{name}_alloc", [f"void"])
+ struct_name = name
+ if ri.type_name_conflict:
+ struct_name += '_'
+
+ args = ["void"]
+ cnt = "1"
+ if struct and struct.in_multi_val:
+ args = ["unsigned int n"]
+ cnt = "n"
+
+ ri.cw.write_func_prot(f'static inline struct {struct_name} *',
+ f"{name}_alloc", args)
ri.cw.block_start()
- ri.cw.p(f'return calloc(1, sizeof(struct {name}));')
+ ri.cw.p(f'return calloc({cnt}, sizeof(struct {struct_name}));')
ri.cw.block_end()
@@ -1696,28 +2534,45 @@ def print_free_prototype(ri, direction, suffix=';'):
ri.cw.write_func_prot('void', f"{name}_free", [f"struct {struct_name} *{arg}"], suffix=suffix)
+def print_nlflags_set(ri, direction):
+ name = op_prefix(ri, direction)
+ ri.cw.write_func_prot('static inline void', f"{name}_set_nlflags",
+ [f"struct {name} *req", "__u16 nl_flags"])
+ ri.cw.block_start()
+ ri.cw.p('req->_nlmsg_flags = nl_flags;')
+ ri.cw.block_end()
+ ri.cw.nl()
+
+
def _print_type(ri, direction, struct):
suffix = f'_{ri.type_name}{direction_to_suffix[direction]}'
if not direction and ri.type_name_conflict:
suffix += '_'
- if ri.op_mode == 'dump':
+ if ri.op_mode == 'dump' and not ri.type_oneside:
suffix += '_dump'
- ri.cw.block_start(line=f"struct {ri.family['name']}{suffix}")
+ ri.cw.block_start(line=f"struct {ri.family.c_name}{suffix}")
- meta_started = False
- for _, attr in struct.member_list():
- for type_filter in ['len', 'bit']:
+ if ri.needs_nlflags(direction):
+ ri.cw.p('__u16 _nlmsg_flags;')
+ ri.cw.nl()
+ if struct.fixed_header:
+ ri.cw.p(struct.fixed_header + ' _hdr;')
+ ri.cw.nl()
+
+ for type_filter in ['present', 'len', 'count']:
+ meta_started = False
+ for _, attr in struct.member_list():
line = attr.presence_member(ri.ku_space, type_filter)
if line:
if not meta_started:
- ri.cw.block_start(line=f"struct")
+ ri.cw.block_start(line="struct")
meta_started = True
ri.cw.p(line)
- if meta_started:
- ri.cw.block_end(line='_present;')
- ri.cw.nl()
+ if meta_started:
+ ri.cw.block_end(line=f'_{type_filter};')
+ ri.cw.nl()
for arg in struct.inherited:
ri.cw.p(f"__u32 {arg};")
@@ -1736,11 +2591,27 @@ def print_type(ri, direction):
def print_type_full(ri, struct):
_print_type(ri, "", struct)
+ if struct.request and struct.in_multi_val:
+ print_alloc_wrapper(ri, "", struct)
+ ri.cw.nl()
+ free_rsp_nested_prototype(ri)
+ ri.cw.nl()
+
+ # Name conflicts are too hard to deal with with the current code base,
+ # they are very rare so don't bother printing setters in that case.
+ if ri.ku_space == 'user' and not ri.type_name_conflict:
+ for _, attr in struct.member_list():
+ attr.setter(ri, ri.attr_set, "", var="obj")
+ ri.cw.nl()
+
def print_type_helpers(ri, direction, deref=False):
print_free_prototype(ri, direction)
ri.cw.nl()
+ if ri.needs_nlflags(direction):
+ print_nlflags_set(ri, direction)
+
if ri.ku_space == 'user' and direction == 'request':
for _, attr in ri.struct[direction].member_list():
attr.setter(ri, ri.attr_set, direction, deref=deref)
@@ -1748,6 +2619,8 @@ def print_type_helpers(ri, direction, deref=False):
def print_req_type_helpers(ri):
+ if ri.type_empty("request"):
+ return
print_alloc_wrapper(ri, "request")
print_type_helpers(ri, "request")
@@ -1769,6 +2642,8 @@ def print_parse_prototype(ri, direction, terminate=True):
def print_req_type(ri):
+ if ri.type_empty("request"):
+ return
print_type(ri, "request")
@@ -1797,7 +2672,7 @@ def print_wrapped_type(ri):
ri.cw.p('__u8 cmd;')
ri.cw.p('struct ynl_ntf_base_type *next;')
ri.cw.p(f"void (*free)({type_name(ri, 'reply')} *ntf);")
- ri.cw.p(f"{type_name(ri, 'reply', deref=True)} obj __attribute__ ((aligned (8)));")
+ ri.cw.p(f"{type_name(ri, 'reply', deref=True)} obj __attribute__((aligned(8)));")
ri.cw.block_end(line=';')
ri.cw.nl()
print_free_prototype(ri, 'reply')
@@ -1805,11 +2680,9 @@ def print_wrapped_type(ri):
def _free_type_members_iter(ri, struct):
- for _, attr in struct.member_list():
- if attr.free_needs_iter():
- ri.cw.p('unsigned int i;')
- ri.cw.nl()
- break
+ if struct.free_needs_iter():
+ ri.cw.p('unsigned int i;')
+ ri.cw.nl()
def _free_type_members(ri, var, struct, ref=''):
@@ -1830,6 +2703,10 @@ def _free_type(ri, direction, struct):
ri.cw.nl()
+def free_rsp_nested_prototype(ri):
+ print_free_prototype(ri, "")
+
+
def free_rsp_nested(ri, struct):
_free_type(ri, "", struct)
@@ -1854,7 +2731,7 @@ def print_dump_type_free(ri):
ri.cw.nl()
_free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.')
- ri.cw.p(f'free(rsp);')
+ ri.cw.p('free(rsp);')
ri.cw.block_end()
ri.cw.block_end()
ri.cw.nl()
@@ -1865,7 +2742,7 @@ def print_ntf_type_free(ri):
ri.cw.block_start()
_free_type_members_iter(ri, ri.struct['reply'])
_free_type_members(ri, 'rsp', ri.struct['reply'], ref='obj.')
- ri.cw.p(f'free(rsp);')
+ ri.cw.p('free(rsp);')
ri.cw.block_end()
ri.cw.nl()
@@ -1895,10 +2772,13 @@ def print_req_policy_fwd(cw, struct, ri=None, terminate=True):
def print_req_policy(cw, struct, ri=None):
+ if ri and ri.op:
+ cw.ifdef_block(ri.op.get('config-cond', None))
print_req_policy_fwd(cw, struct, ri=ri, terminate=False)
for _, arg in struct.member_list():
arg.attr_policy(cw)
cw.p("};")
+ cw.ifdef_block(None)
cw.nl()
@@ -1910,11 +2790,78 @@ def policy_should_be_static(family):
return family.kernel_policy == 'split' or kernel_can_gen_family_struct(family)
+def print_kernel_policy_ranges(family, cw):
+ first = True
+ for _, attr_set in family.attr_sets.items():
+ if attr_set.subset_of:
+ continue
+
+ for _, attr in attr_set.items():
+ if not attr.request:
+ continue
+ if 'full-range' not in attr.checks:
+ continue
+
+ if first:
+ cw.p('/* Integer value ranges */')
+ first = False
+
+ sign = '' if attr.type[0] == 'u' else '_signed'
+ suffix = 'ULL' if attr.type[0] == 'u' else 'LL'
+ cw.block_start(line=f'static const struct netlink_range_validation{sign} {c_lower(attr.enum_name)}_range =')
+ members = []
+ if 'min' in attr.checks:
+ members.append(('min', attr.get_limit_str('min', suffix=suffix)))
+ if 'max' in attr.checks:
+ members.append(('max', attr.get_limit_str('max', suffix=suffix)))
+ cw.write_struct_init(members)
+ cw.block_end(line=';')
+ cw.nl()
+
+
+def print_kernel_policy_sparse_enum_validates(family, cw):
+ first = True
+ for _, attr_set in family.attr_sets.items():
+ if attr_set.subset_of:
+ continue
+
+ for _, attr in attr_set.items():
+ if not attr.request:
+ continue
+ if not attr.enum_name:
+ continue
+ if 'sparse' not in attr.checks:
+ continue
+
+ if first:
+ cw.p('/* Sparse enums validation callbacks */')
+ first = False
+
+ cw.write_func_prot('static int', f'{c_lower(attr.enum_name)}_validate',
+ ['const struct nlattr *attr', 'struct netlink_ext_ack *extack'])
+ cw.block_start()
+ cw.block_start(line=f'switch (nla_get_{attr["type"]}(attr))')
+ enum = family.consts[attr['enum']]
+ first_entry = True
+ for entry in enum.entries.values():
+ if first_entry:
+ first_entry = False
+ else:
+ cw.p('fallthrough;')
+ cw.p(f'case {entry.c_name}:')
+ cw.p('return 0;')
+ cw.block_end()
+ cw.p('NL_SET_ERR_MSG_ATTR(extack, attr, "invalid enum value");')
+ cw.p('return -EINVAL;')
+ cw.block_end()
+ cw.nl()
+
+
def print_kernel_op_table_fwd(family, cw, terminate):
exported = not kernel_can_gen_family_struct(family)
if not terminate or exported:
- cw.p(f"/* Ops table for {family.name} */")
+ cw.p(f"/* Ops table for {family.ident_name} */")
pol_to_struct = {'global': 'genl_small_ops',
'per-op': 'genl_ops',
@@ -1934,7 +2881,7 @@ def print_kernel_op_table_fwd(family, cw, terminate):
cnt = len(family.ops)
qual = 'static const' if not exported else 'const'
- line = f"{qual} struct {struct_type} {family.name}_nl_ops[{cnt}]"
+ line = f"{qual} struct {struct_type} {family.c_name}_nl_ops[{cnt}]"
if terminate:
cw.p(f"extern {line};")
else:
@@ -1966,12 +2913,12 @@ def print_kernel_op_table_fwd(family, cw, terminate):
continue
if 'do' in op:
- name = c_lower(f"{family.name}-nl-{op_name}-doit")
+ name = c_lower(f"{family.fn_prefix}-{op_name}-doit")
cw.write_func_prot('int', name,
['struct sk_buff *skb', 'struct genl_info *info'], suffix=';')
if 'dump' in op:
- name = c_lower(f"{family.name}-nl-{op_name}-dumpit")
+ name = c_lower(f"{family.fn_prefix}-{op_name}-dumpit")
cw.write_func_prot('int', name,
['struct sk_buff *skb', 'struct netlink_callback *cb'], suffix=';')
cw.nl()
@@ -1988,6 +2935,7 @@ def print_kernel_op_table(family, cw):
if op.is_async:
continue
+ cw.ifdef_block(op.get('config-cond', None))
cw.block_start()
members = [('cmd', op.enum_name)]
if 'dont-validate' in op:
@@ -1996,13 +2944,13 @@ def print_kernel_op_table(family, cw):
for x in op['dont-validate']])), )
for op_mode in ['do', 'dump']:
if op_mode in op:
- name = c_lower(f"{family.name}-nl-{op_name}-{op_mode}it")
+ name = c_lower(f"{family.fn_prefix}-{op_name}-{op_mode}it")
members.append((op_mode + 'it', name))
if family.kernel_policy == 'per-op':
struct = Struct(family, op['attribute-set'],
type_list=op['do']['request']['attributes'])
- name = c_lower(f"{family.name}-{op_name}-nl-policy")
+ name = c_lower(f"{family.ident_name}-{op_name}-nl-policy")
members.append(('policy', name))
members.append(('maxattr', struct.attr_max_val.enum_name))
if 'flags' in op:
@@ -2018,6 +2966,7 @@ def print_kernel_op_table(family, cw):
if op.is_async or op_mode not in op:
continue
+ cw.ifdef_block(op.get('config-cond', None))
cw.block_start()
members = [('cmd', op.enum_name)]
if 'dont-validate' in op:
@@ -2033,7 +2982,7 @@ def print_kernel_op_table(family, cw):
members.append(('validate',
' | '.join([c_upper('genl-dont-validate-' + x)
for x in dont_validate])), )
- name = c_lower(f"{family.name}-nl-{op_name}-{op_mode}it")
+ name = c_lower(f"{family.fn_prefix}-{op_name}-{op_mode}it")
if 'pre' in op[op_mode]:
members.append((cb_names[op_mode]['pre'], c_lower(op[op_mode]['pre'])))
members.append((op_mode + 'it', name))
@@ -2044,15 +2993,16 @@ def print_kernel_op_table(family, cw):
type_list=op[op_mode]['request']['attributes'])
if op.dual_policy:
- name = c_lower(f"{family.name}-{op_name}-{op_mode}-nl-policy")
+ name = c_lower(f"{family.ident_name}-{op_name}-{op_mode}-nl-policy")
else:
- name = c_lower(f"{family.name}-{op_name}-nl-policy")
+ name = c_lower(f"{family.ident_name}-{op_name}-nl-policy")
members.append(('policy', name))
members.append(('maxattr', struct.attr_max_val.enum_name))
flags = (op['flags'] if 'flags' in op else []) + ['cmd-cap-' + op_mode]
members.append(('flags', ' | '.join([c_upper('genl-' + x) for x in flags])))
cw.write_struct_init(members)
cw.block_end(line=',')
+ cw.ifdef_block(None)
cw.block_end(line=';')
cw.nl()
@@ -2064,7 +3014,7 @@ def print_kernel_mcgrp_hdr(family, cw):
cw.block_start('enum')
for grp in family.mcgrps['list']:
- grp_id = c_upper(f"{family.name}-nlgrp-{grp['name']},")
+ grp_id = c_upper(f"{family.ident_name}-nlgrp-{grp['name']},")
cw.p(grp_id)
cw.block_end(';')
cw.nl()
@@ -2074,10 +3024,10 @@ def print_kernel_mcgrp_src(family, cw):
if not family.mcgrps['list']:
return
- cw.block_start('static const struct genl_multicast_group ' + family.name + '_nl_mcgrps[] =')
+ cw.block_start('static const struct genl_multicast_group ' + family.c_name + '_nl_mcgrps[] =')
for grp in family.mcgrps['list']:
name = grp['name']
- grp_id = c_upper(f"{family.name}-nlgrp-{name}")
+ grp_id = c_upper(f"{family.ident_name}-nlgrp-{name}")
cw.p('[' + grp_id + '] = { "' + name + '", },')
cw.block_end(';')
cw.nl()
@@ -2087,29 +3037,48 @@ def print_kernel_family_struct_hdr(family, cw):
if not kernel_can_gen_family_struct(family):
return
- cw.p(f"extern struct genl_family {family.name}_nl_family;")
+ cw.p(f"extern struct genl_family {family.c_name}_nl_family;")
cw.nl()
+ if 'sock-priv' in family.kernel_family:
+ cw.p(f'void {family.c_name}_nl_sock_priv_init({family.kernel_family["sock-priv"]} *priv);')
+ cw.p(f'void {family.c_name}_nl_sock_priv_destroy({family.kernel_family["sock-priv"]} *priv);')
+ cw.nl()
def print_kernel_family_struct_src(family, cw):
if not kernel_can_gen_family_struct(family):
return
- cw.block_start(f"struct genl_family {family.name}_nl_family __ro_after_init =")
+ if 'sock-priv' in family.kernel_family:
+ # Generate "trampolines" to make CFI happy
+ cw.write_func("static void", f"__{family.c_name}_nl_sock_priv_init",
+ [f"{family.c_name}_nl_sock_priv_init(priv);"],
+ ["void *priv"])
+ cw.nl()
+ cw.write_func("static void", f"__{family.c_name}_nl_sock_priv_destroy",
+ [f"{family.c_name}_nl_sock_priv_destroy(priv);"],
+ ["void *priv"])
+ cw.nl()
+
+ cw.block_start(f"struct genl_family {family.ident_name}_nl_family __ro_after_init =")
cw.p('.name\t\t= ' + family.fam_key + ',')
cw.p('.version\t= ' + family.ver_key + ',')
cw.p('.netnsok\t= true,')
cw.p('.parallel_ops\t= true,')
cw.p('.module\t\t= THIS_MODULE,')
if family.kernel_policy == 'per-op':
- cw.p(f'.ops\t\t= {family.name}_nl_ops,')
- cw.p(f'.n_ops\t\t= ARRAY_SIZE({family.name}_nl_ops),')
+ cw.p(f'.ops\t\t= {family.c_name}_nl_ops,')
+ cw.p(f'.n_ops\t\t= ARRAY_SIZE({family.c_name}_nl_ops),')
elif family.kernel_policy == 'split':
- cw.p(f'.split_ops\t= {family.name}_nl_ops,')
- cw.p(f'.n_split_ops\t= ARRAY_SIZE({family.name}_nl_ops),')
+ cw.p(f'.split_ops\t= {family.c_name}_nl_ops,')
+ cw.p(f'.n_split_ops\t= ARRAY_SIZE({family.c_name}_nl_ops),')
if family.mcgrps['list']:
- cw.p(f'.mcgrps\t\t= {family.name}_nl_mcgrps,')
- cw.p(f'.n_mcgrps\t= ARRAY_SIZE({family.name}_nl_mcgrps),')
+ cw.p(f'.mcgrps\t\t= {family.c_name}_nl_mcgrps,')
+ cw.p(f'.n_mcgrps\t= ARRAY_SIZE({family.c_name}_nl_mcgrps),')
+ if 'sock-priv' in family.kernel_family:
+ cw.p(f'.sock_priv_size\t= sizeof({family.kernel_family["sock-priv"]}),')
+ cw.p(f'.sock_priv_init\t= __{family.c_name}_nl_sock_priv_init,')
+ cw.p(f'.sock_priv_destroy = __{family.c_name}_nl_sock_priv_destroy,')
cw.block_end(';')
@@ -2119,12 +3088,94 @@ def uapi_enum_start(family, cw, obj, ckey='', enum_name='enum-name'):
if obj[enum_name]:
start_line = 'enum ' + c_lower(obj[enum_name])
elif ckey and ckey in obj:
- start_line = 'enum ' + family.name + '_' + c_lower(obj[ckey])
+ start_line = 'enum ' + family.c_name + '_' + c_lower(obj[ckey])
cw.block_start(line=start_line)
+def render_uapi_unified(family, cw, max_by_define, separate_ntf):
+ max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
+ cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
+ max_value = f"({cnt_name} - 1)"
+
+ uapi_enum_start(family, cw, family['operations'], 'enum-name')
+ val = 0
+ for op in family.msgs.values():
+ if separate_ntf and ('notify' in op or 'event' in op):
+ continue
+
+ suffix = ','
+ if op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(op.enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+
+def render_uapi_directional(family, cw, max_by_define):
+ max_name = f"{family.op_prefix}USER_MAX"
+ cnt_name = f"__{family.op_prefix}USER_CNT"
+ max_value = f"({cnt_name} - 1)"
+
+ cw.block_start(line='enum')
+ cw.p(c_upper(f'{family.name}_MSG_USER_NONE = 0,'))
+ val = 0
+ for op in family.msgs.values():
+ if 'do' in op and 'event' not in op:
+ suffix = ','
+ if op.value and op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(op.enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+ max_name = f"{family.op_prefix}KERNEL_MAX"
+ cnt_name = f"__{family.op_prefix}KERNEL_CNT"
+ max_value = f"({cnt_name} - 1)"
+
+ cw.block_start(line='enum')
+ cw.p(c_upper(f'{family.name}_MSG_KERNEL_NONE = 0,'))
+ val = 0
+ for op in family.msgs.values():
+ if ('do' in op and 'reply' in op['do']) or 'notify' in op or 'event' in op:
+ enum_name = op.enum_name
+ if 'event' not in op and 'notify' not in op:
+ enum_name = f'{enum_name}_REPLY'
+
+ suffix = ','
+ if op.value and op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+
def render_uapi(family, cw):
- hdr_prot = f"_UAPI_LINUX_{family.name.upper()}_H"
+ hdr_prot = f"_UAPI_LINUX_{c_upper(family.uapi_header_name)}_H"
+ hdr_prot = hdr_prot.replace('/', '_')
cw.p('#ifndef ' + hdr_prot)
cw.p('#define ' + hdr_prot)
cw.nl()
@@ -2136,6 +3187,9 @@ def render_uapi(family, cw):
defines = []
for const in family['definitions']:
+ if const.get('header'):
+ continue
+
if const['type'] != 'const':
cw.writes_defines(defines)
defines = []
@@ -2145,12 +3199,19 @@ def render_uapi(family, cw):
if const['type'] == 'enum' or const['type'] == 'flags':
enum = family.consts[const['name']]
+ if enum.header:
+ continue
+
if enum.has_doc():
- cw.p('/**')
- doc = ''
- if 'doc' in enum:
- doc = ' - ' + enum['doc']
- cw.write_doc_line(enum.enum_name + doc)
+ if enum.has_entry_doc():
+ cw.p('/**')
+ doc = ''
+ if 'doc' in enum:
+ doc = ' - ' + enum['doc']
+ cw.write_doc_line(enum.enum_name + doc)
+ else:
+ cw.p('/*')
+ cw.write_doc_line(enum['doc'], indent=False)
for entry in enum.entries.values():
if entry.has_doc():
doc = '@' + entry.c_name + ': ' + entry['doc']
@@ -2158,7 +3219,7 @@ def render_uapi(family, cw):
cw.p(' */')
uapi_enum_start(family, cw, const, 'name')
- name_pfx = const.get('name-prefix', f"{family.name}-{const['name']}-")
+ name_pfx = const.get('name-prefix', f"{family.ident_name}-{const['name']}-")
for entry in enum.entries.values():
suffix = ','
if entry.value_change:
@@ -2173,14 +3234,18 @@ def render_uapi(family, cw):
max_val = f' = {enum.get_mask()},'
cw.p(max_name + max_val)
else:
+ cnt_name = enum.enum_cnt_name
max_name = c_upper(name_pfx + 'max')
- cw.p('__' + max_name + ',')
- cw.p(max_name + ' = (__' + max_name + ' - 1)')
+ if not cnt_name:
+ cnt_name = '__' + name_pfx + 'max'
+ cw.p(c_upper(cnt_name) + ',')
+ cw.p(max_name + ' = (' + c_upper(cnt_name) + ' - 1)')
cw.block_end(line=';')
cw.nl()
elif const['type'] == 'const':
+ name_pfx = const.get('name-prefix', f"{family.ident_name}-")
defines.append([c_upper(family.get('c-define-name',
- f"{family.name}-{const['name']}")),
+ f"{name_pfx}{const['name']}")),
const['value']])
if defines:
@@ -2193,8 +3258,7 @@ def render_uapi(family, cw):
if attr_set.subset_of:
continue
- cnt_name = c_upper(family.get('attr-cnt-name', f"__{attr_set.name_prefix}MAX"))
- max_value = f"({cnt_name} - 1)"
+ max_value = f"({attr_set.cnt_name} - 1)"
val = 0
uapi_enum_start(family, cw, attr_set.yaml, 'enum-name')
@@ -2205,8 +3269,9 @@ def render_uapi(family, cw):
val = attr.value
val += 1
cw.p(attr.enum_name + suffix)
- cw.nl()
- cw.p(cnt_name + ('' if max_by_define else ','))
+ if attr_set.items():
+ cw.nl()
+ cw.p(attr_set.cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{attr_set.max_name} = {max_value}")
cw.block_end(line=';')
@@ -2217,30 +3282,12 @@ def render_uapi(family, cw):
# Commands
separate_ntf = 'async-prefix' in family['operations']
- max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
- cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
- max_value = f"({cnt_name} - 1)"
-
- uapi_enum_start(family, cw, family['operations'], 'enum-name')
- val = 0
- for op in family.msgs.values():
- if separate_ntf and ('notify' in op or 'event' in op):
- continue
-
- suffix = ','
- if op.value != val:
- suffix = f" = {op.value},"
- val = op.value
- cw.p(op.enum_name + suffix)
- val += 1
- cw.nl()
- cw.p(cnt_name + ('' if max_by_define else ','))
- if not max_by_define:
- cw.p(f"{max_name} = {max_value}")
- cw.block_end(line=';')
- if max_by_define:
- cw.p(f"#define {max_name} {max_value}")
- cw.nl()
+ if family.msg_id_model == 'unified':
+ render_uapi_unified(family, cw, max_by_define, separate_ntf)
+ elif family.msg_id_model == 'directional':
+ render_uapi_directional(family, cw, max_by_define)
+ else:
+ raise Exception(f'Unsupported message enum-model {family.msg_id_model}')
if separate_ntf:
uapi_enum_start(family, cw, family['operations'], enum_name='async-enum')
@@ -2259,7 +3306,7 @@ def render_uapi(family, cw):
defines = []
for grp in family.mcgrps['list']:
name = grp['name']
- defines.append([c_upper(grp.get('c-define-name', f"{family.name}-mcgrp-{name}")),
+ defines.append([c_upper(grp.get('c-define-name', f"{family.ident_name}-mcgrp-{name}")),
f'{name}'])
cw.nl()
if defines:
@@ -2270,7 +3317,11 @@ def render_uapi(family, cw):
def _render_user_ntf_entry(ri, op):
- ri.cw.block_start(line=f"[{op.enum_name}] = ")
+ if not ri.family.is_classic():
+ ri.cw.block_start(line=f"[{op.enum_name}] = ")
+ else:
+ crud_op = ri.family.req_by_value[op.rsp_value]
+ ri.cw.block_start(line=f"[{crud_op.enum_name}] = ")
ri.cw.p(f".alloc_sz\t= sizeof({type_name(ri, 'event')}),")
ri.cw.p(f".cb\t\t= {op_prefix(ri, 'reply', deref=True)}_parse,")
ri.cw.p(f".policy\t\t= &{ri.struct['reply'].render_name}_nest,")
@@ -2285,7 +3336,7 @@ def render_user_family(family, cw, prototype):
return
if family.ntfs:
- cw.block_start(line=f"static const struct ynl_ntf_info {family['name']}_ntf_info[] = ")
+ cw.block_start(line=f"static const struct ynl_ntf_info {family.c_name}_ntf_info[] = ")
for ntf_op_name, ntf_op in family.ntfs.items():
if 'notify' in ntf_op:
op = family.ops[ntf_op['notify']]
@@ -2304,13 +3355,33 @@ def render_user_family(family, cw, prototype):
cw.nl()
cw.block_start(f'{symbol} = ')
- cw.p(f'.name\t\t= "{family.name}",')
+ cw.p(f'.name\t\t= "{family.c_name}",')
+ if family.is_classic():
+ cw.p('.is_classic\t= true,')
+ cw.p(f'.classic_id\t= {family.get("protonum")},')
+ if family.is_classic():
+ if family.fixed_header:
+ cw.p(f'.hdr_len\t= sizeof(struct {c_lower(family.fixed_header)}),')
+ elif family.fixed_header:
+ cw.p(f'.hdr_len\t= sizeof(struct genlmsghdr) + sizeof(struct {c_lower(family.fixed_header)}),')
+ else:
+ cw.p('.hdr_len\t= sizeof(struct genlmsghdr),')
if family.ntfs:
- cw.p(f".ntf_info\t= {family['name']}_ntf_info,")
- cw.p(f".ntf_info_size\t= MNL_ARRAY_SIZE({family['name']}_ntf_info),")
+ cw.p(f".ntf_info\t= {family.c_name}_ntf_info,")
+ cw.p(f".ntf_info_size\t= YNL_ARRAY_SIZE({family.c_name}_ntf_info),")
cw.block_end(line=';')
+def family_contains_bitfield32(family):
+ for _, attr_set in family.attr_sets.items():
+ if attr_set.subset_of:
+ continue
+ for _, attr in attr_set.items():
+ if attr.type == "bitfield32":
+ return True
+ return False
+
+
def find_kernel_root(full_path):
sub_path = ''
while True:
@@ -2323,13 +3394,17 @@ def find_kernel_root(full_path):
def main():
parser = argparse.ArgumentParser(description='Netlink simple parsing generator')
- parser.add_argument('--mode', dest='mode', type=str, required=True)
+ parser.add_argument('--mode', dest='mode', type=str, required=True,
+ choices=('user', 'kernel', 'uapi'))
parser.add_argument('--spec', dest='spec', type=str, required=True)
parser.add_argument('--header', dest='header', action='store_true', default=None)
parser.add_argument('--source', dest='header', action='store_false')
parser.add_argument('--user-header', nargs='+', default=[])
+ parser.add_argument('--cmp-out', action='store_true', default=None,
+ help='Do not overwrite the output file if the new output is identical to the old')
parser.add_argument('--exclude-op', action='append', default=[])
parser.add_argument('-o', dest='out_file', type=str, default=None)
+ parser.add_argument('--function-prefix', dest='fn_prefix', type=str)
args = parser.parse_args()
if args.header is None:
@@ -2338,7 +3413,7 @@ def main():
exclude_ops = [re.compile(expr) for expr in args.exclude_op]
try:
- parsed = Family(args.spec, exclude_ops)
+ parsed = Family(args.spec, exclude_ops, args.fn_prefix)
if parsed.license != '((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)':
print('Spec license:', parsed.license)
print('License must be: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)')
@@ -2348,14 +3423,7 @@ def main():
os.sys.exit(1)
return
- supported_models = ['unified']
- if args.mode in ['user', 'kernel']:
- supported_models += ['directional']
- if parsed.msg_id_model not in supported_models:
- print(f'Message enum-model {parsed.msg_id_model} not supported for {args.mode} generation')
- os.sys.exit(1)
-
- cw = CodeWriter(BaseNlLib(), args.out_file)
+ cw = CodeWriter(BaseNlLib(), args.out_file, overwrite=(not args.cmp_out))
_, spec_kernel = find_kernel_root(args.spec)
if args.mode == 'uapi' or args.header:
@@ -2365,51 +3433,68 @@ def main():
cw.p("/* Do not edit directly, auto-generated from: */")
cw.p(f"/*\t{spec_kernel} */")
cw.p(f"/* YNL-GEN {args.mode} {'header' if args.header else 'source'} */")
- if args.exclude_op or args.user_header:
+ if args.exclude_op or args.user_header or args.fn_prefix:
line = ''
- line += ' --user-header '.join([''] + args.user_header)
- line += ' --exclude-op '.join([''] + args.exclude_op)
+ if args.user_header:
+ line += ' --user-header '.join([''] + args.user_header)
+ if args.exclude_op:
+ line += ' --exclude-op '.join([''] + args.exclude_op)
+ if args.fn_prefix:
+ line += f' --function-prefix {args.fn_prefix}'
cw.p(f'/* YNL-ARG{line} */')
+ cw.p('/* To regenerate run: tools/net/ynl/ynl-regen.sh */')
cw.nl()
if args.mode == 'uapi':
render_uapi(parsed, cw)
return
- hdr_prot = f"_LINUX_{parsed.name.upper()}_GEN_H"
+ hdr_prot = f"_LINUX_{parsed.c_name.upper()}_GEN_H"
if args.header:
cw.p('#ifndef ' + hdr_prot)
cw.p('#define ' + hdr_prot)
cw.nl()
+ if args.out_file:
+ hdr_file = os.path.basename(args.out_file[:-2]) + ".h"
+ else:
+ hdr_file = "generated_header_file.h"
+
if args.mode == 'kernel':
cw.p('#include <net/netlink.h>')
cw.p('#include <net/genetlink.h>')
cw.nl()
if not args.header:
if args.out_file:
- cw.p(f'#include "{os.path.basename(args.out_file[:-2])}.h"')
+ cw.p(f'#include "{hdr_file}"')
cw.nl()
headers = ['uapi/' + parsed.uapi_header]
+ headers += parsed.kernel_family.get('headers', [])
else:
cw.p('#include <stdlib.h>')
cw.p('#include <string.h>')
if args.header:
cw.p('#include <linux/types.h>')
+ if family_contains_bitfield32(parsed):
+ cw.p('#include <linux/netlink.h>')
else:
- cw.p(f'#include "{parsed.name}-user.h"')
+ cw.p(f'#include "{hdr_file}"')
cw.p('#include "ynl.h"')
- headers = [parsed.uapi_header]
- for definition in parsed['definitions']:
+ headers = []
+ for definition in parsed['definitions'] + parsed['attribute-sets']:
if 'header' in definition:
headers.append(definition['header'])
+ if args.mode == 'user':
+ headers.append(parsed.uapi_header)
+ seen_header = []
for one in headers:
- cw.p(f"#include <{one}>")
+ if one not in seen_header:
+ cw.p(f"#include <{one}>")
+ seen_header.append(one)
cw.nl()
if args.mode == "user":
if not args.header:
- cw.p("#include <libmnl/libmnl.h>")
cw.p("#include <linux/genetlink.h>")
cw.nl()
for one in args.user_header:
@@ -2449,6 +3534,9 @@ def main():
print_kernel_mcgrp_hdr(parsed, cw)
print_kernel_family_struct_hdr(parsed, cw)
else:
+ print_kernel_policy_ranges(parsed, cw)
+ print_kernel_policy_sparse_enum_validates(parsed, cw)
+
for _, struct in sorted(parsed.pure_nested_structs.items()):
if struct.request:
cw.p('/* Common nested types */')
@@ -2511,10 +3599,9 @@ def main():
if 'dump' in op:
cw.p(f"/* {op.enum_name} - dump */")
ri = RenderInfo(cw, parsed, args.mode, op, 'dump')
- if 'request' in op['dump']:
- print_req_type(ri)
- print_req_type_helpers(ri)
- if not ri.type_consistent:
+ print_req_type(ri)
+ print_req_type_helpers(ri)
+ if not ri.type_consistent or ri.type_oneside:
print_rsp_type(ri)
print_wrapped_type(ri)
print_dump_prototype(ri)
@@ -2544,15 +3631,30 @@ def main():
put_enum_to_str(parsed, cw, const)
cw.nl()
+ has_recursive_nests = False
cw.p('/* Policies */')
- for name in parsed.pure_nested_structs:
- struct = Struct(parsed, name)
+ for struct in parsed.pure_nested_structs.values():
+ if struct.recursive:
+ put_typol_fwd(cw, struct)
+ has_recursive_nests = True
+ if has_recursive_nests:
+ cw.nl()
+ for struct in parsed.pure_nested_structs.values():
put_typol(cw, struct)
for name in parsed.root_sets:
struct = Struct(parsed, name)
put_typol(cw, struct)
cw.p('/* Common nested types */')
+ if has_recursive_nests:
+ for attr_set, struct in parsed.pure_nested_structs.items():
+ ri = RenderInfo(cw, parsed, args.mode, "", "", attr_set)
+ free_rsp_nested_prototype(ri)
+ if struct.request:
+ put_req_nested_prototype(ri, struct)
+ if struct.reply:
+ parse_rsp_nested_prototype(ri, struct)
+ cw.nl()
for attr_set, struct in parsed.pure_nested_structs.items():
ri = RenderInfo(cw, parsed, args.mode, "", "", attr_set)
@@ -2576,8 +3678,9 @@ def main():
if 'dump' in op:
cw.p(f"/* {op.enum_name} - dump */")
ri = RenderInfo(cw, parsed, args.mode, op, "dump")
- if not ri.type_consistent:
+ if not ri.type_consistent or ri.type_oneside:
parse_rsp_msg(ri, deref=True)
+ print_req_free(ri)
print_dump_type_free(ri)
print_dump(ri)
cw.nl()
diff --git a/tools/net/ynl/pyynl/ynl_gen_rst.py b/tools/net/ynl/pyynl/ynl_gen_rst.py
new file mode 100755
index 000000000000..90ae19aac89d
--- /dev/null
+++ b/tools/net/ynl/pyynl/ynl_gen_rst.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8; mode: python -*-
+
+"""
+ Script to auto generate the documentation for Netlink specifications.
+
+ :copyright: Copyright (C) 2023 Breno Leitao <leitao@debian.org>
+ :license: GPL Version 2, June 1991 see linux/COPYING for details.
+
+ This script performs extensive parsing to the Linux kernel's netlink YAML
+ spec files, in an effort to avoid needing to heavily mark up the original
+ YAML file. It uses the library code from scripts/lib.
+"""
+
+import os.path
+import pathlib
+import sys
+import argparse
+import logging
+
+sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix())
+from lib import YnlDocGenerator # pylint: disable=C0413
+
+def parse_arguments() -> argparse.Namespace:
+ """Parse arguments from user"""
+ parser = argparse.ArgumentParser(description="Netlink RST generator")
+
+ parser.add_argument("-v", "--verbose", action="store_true")
+ parser.add_argument("-o", "--output", help="Output file name")
+
+ # Index and input are mutually exclusive
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument("-i", "--input", help="YAML file name")
+
+ args = parser.parse_args()
+
+ if args.verbose:
+ logging.basicConfig(level=logging.DEBUG)
+
+ if args.input and not os.path.isfile(args.input):
+ logging.warning("%s is not a valid file.", args.input)
+ sys.exit(-1)
+
+ if not args.output:
+ logging.error("No output file specified.")
+ sys.exit(-1)
+
+ if os.path.isfile(args.output):
+ logging.debug("%s already exists. Overwriting it.", args.output)
+
+ return args
+
+
+def write_to_rstfile(content: str, filename: str) -> None:
+ """Write the generated content into an RST file"""
+ logging.debug("Saving RST file to %s", filename)
+
+ with open(filename, "w", encoding="utf-8") as rst_file:
+ rst_file.write(content)
+
+
+def main() -> None:
+ """Main function that reads the YAML files and generates the RST files"""
+
+ args = parse_arguments()
+
+ parser = YnlDocGenerator()
+
+ if args.input:
+ logging.debug("Parsing %s", args.input)
+ try:
+ content = parser.parse_yaml_file(os.path.join(args.input))
+ except Exception as exception:
+ logging.warning("Failed to parse %s.", args.input)
+ logging.warning(exception)
+ sys.exit(-1)
+
+ write_to_rstfile(content, args.output)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/net/ynl/samples/.gitignore b/tools/net/ynl/samples/.gitignore
index 2aae60c4829f..05087ee323ba 100644
--- a/tools/net/ynl/samples/.gitignore
+++ b/tools/net/ynl/samples/.gitignore
@@ -1,3 +1,10 @@
ethtool
devlink
netdev
+ovs
+page-pool
+rt-addr
+rt-link
+rt-route
+tc
+tc-filter-add
diff --git a/tools/net/ynl/samples/Makefile b/tools/net/ynl/samples/Makefile
index f2db8bb78309..d76cbd41cbb1 100644
--- a/tools/net/ynl/samples/Makefile
+++ b/tools/net/ynl/samples/Makefile
@@ -3,13 +3,13 @@
include ../Makefile.deps
CC=gcc
-CFLAGS=-std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow \
+CFLAGS += -std=gnu11 -O2 -W -Wall -Wextra -Wno-unused-parameter -Wshadow \
-I../lib/ -I../generated/ -idirafter $(UAPI_PATH)
ifeq ("$(DEBUG)","1")
CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
endif
-LDLIBS=-lmnl ../lib/ynl.a ../generated/protos.a
+LDLIBS=../lib/ynl.a ../generated/protos.a
SRCS=$(wildcard *.c)
BINS=$(patsubst %.c,%,${SRCS})
@@ -18,13 +18,19 @@ include $(wildcard *.d)
all: $(BINS)
-$(BINS): ../lib/ynl.a ../generated/protos.a
+CFLAGS_page-pool=$(CFLAGS_netdev)
+CFLAGS_tc-filter-add:=$(CFLAGS_tc)
+
+$(BINS): ../lib/ynl.a ../generated/protos.a $(SRCS)
+ @echo -e '\tCC sample $@'
+ @$(COMPILE.c) $(CFLAGS_$@) $@.c -o $@.o
+ @$(LINK.c) $@.o -o $@ $(LDLIBS)
clean:
rm -f *.o *.d *~
-hardclean: clean
+distclean: clean
rm -f $(BINS)
-.PHONY: all clean
+.PHONY: all clean distclean
.DEFAULT_GOAL=all
diff --git a/tools/net/ynl/samples/devlink.c b/tools/net/ynl/samples/devlink.c
index d2611d7ebab4..ac9dfb01f280 100644
--- a/tools/net/ynl/samples/devlink.c
+++ b/tools/net/ynl/samples/devlink.c
@@ -22,6 +22,7 @@ int main(int argc, char **argv)
ynl_dump_foreach(devs, d) {
struct devlink_info_get_req *info_req;
struct devlink_info_get_rsp *info_rsp;
+ unsigned i;
printf("%s/%s:\n", d->bus_name, d->dev_name);
@@ -34,11 +35,11 @@ int main(int argc, char **argv)
if (!info_rsp)
goto err_free_devs;
- if (info_rsp->_present.info_driver_name_len)
+ if (info_rsp->_len.info_driver_name)
printf(" driver: %s\n", info_rsp->info_driver_name);
- if (info_rsp->n_info_version_running)
+ if (info_rsp->_count.info_version_running)
printf(" running fw:\n");
- for (unsigned i = 0; i < info_rsp->n_info_version_running; i++)
+ for (i = 0; i < info_rsp->_count.info_version_running; i++)
printf(" %s: %s\n",
info_rsp->info_version_running[i].info_version_name,
info_rsp->info_version_running[i].info_version_value);
diff --git a/tools/net/ynl/samples/netdev.c b/tools/net/ynl/samples/netdev.c
index 06433400dddd..22609d44c89a 100644
--- a/tools/net/ynl/samples/netdev.c
+++ b/tools/net/ynl/samples/netdev.c
@@ -32,12 +32,24 @@ static void netdev_print_device(struct netdev_dev_get_rsp *d, unsigned int op)
if (!d->_present.xdp_features)
return;
- printf("%llx:", d->xdp_features);
- for (int i = 0; d->xdp_features > 1U << i; i++) {
+ printf("xdp-features (%llx):", d->xdp_features);
+ for (int i = 0; d->xdp_features >= 1U << i; i++) {
if (d->xdp_features & (1U << i))
printf(" %s", netdev_xdp_act_str(1 << i));
}
+ printf(" xdp-rx-metadata-features (%llx):", d->xdp_rx_metadata_features);
+ for (int i = 0; d->xdp_rx_metadata_features >= 1U << i; i++) {
+ if (d->xdp_rx_metadata_features & (1U << i))
+ printf(" %s", netdev_xdp_rx_metadata_str(1 << i));
+ }
+
+ printf(" xsk-features (%llx):", d->xsk_features);
+ for (int i = 0; d->xsk_features >= 1U << i; i++) {
+ if (d->xsk_features & (1U << i))
+ printf(" %s", netdev_xsk_flags_str(1 << i));
+ }
+
printf(" xdp-zc-max-segs=%u", d->xdp_zc_max_segs);
name = netdev_op_str(op);
@@ -67,7 +79,10 @@ int main(int argc, char **argv)
goto err_close;
printf("Select ifc ($ifindex; or 0 = dump; or -2 ntf check): ");
- scanf("%d", &ifindex);
+ if (scanf("%d", &ifindex) != 1) {
+ fprintf(stderr, "Error: unable to parse input\n");
+ goto err_destroy;
+ }
if (ifindex > 0) {
struct netdev_dev_get_req *req;
@@ -88,6 +103,8 @@ int main(int argc, char **argv)
if (!devs)
goto err_close;
+ if (ynl_dump_empty(devs))
+ fprintf(stderr, "Error: no devices reported\n");
ynl_dump_foreach(devs, d)
netdev_print_device(d, 0);
netdev_dev_get_list_free(devs);
@@ -105,6 +122,7 @@ int main(int argc, char **argv)
err_close:
fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_destroy:
ynl_sock_destroy(ys);
return 2;
}
diff --git a/tools/net/ynl/samples/ovs.c b/tools/net/ynl/samples/ovs.c
new file mode 100644
index 000000000000..3e975c003d77
--- /dev/null
+++ b/tools/net/ynl/samples/ovs.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include "ovs_datapath-user.h"
+
+int main(int argc, char **argv)
+{
+ struct ynl_sock *ys;
+ int err;
+
+ ys = ynl_sock_create(&ynl_ovs_datapath_family, NULL);
+ if (!ys)
+ return 1;
+
+ if (argc > 1) {
+ struct ovs_datapath_new_req *req;
+
+ req = ovs_datapath_new_req_alloc();
+ if (!req)
+ goto err_close;
+
+ ovs_datapath_new_req_set_upcall_pid(req, 1);
+ ovs_datapath_new_req_set_name(req, argv[1]);
+
+ err = ovs_datapath_new(ys, req);
+ ovs_datapath_new_req_free(req);
+ if (err)
+ goto err_close;
+ } else {
+ struct ovs_datapath_get_req_dump *req;
+ struct ovs_datapath_get_list *dps;
+
+ printf("Dump:\n");
+ req = ovs_datapath_get_req_dump_alloc();
+
+ dps = ovs_datapath_get_dump(ys, req);
+ ovs_datapath_get_req_dump_free(req);
+ if (!dps)
+ goto err_close;
+
+ ynl_dump_foreach(dps, dp) {
+ printf(" %s(%d): pid:%u cache:%u\n",
+ dp->name, dp->_hdr.dp_ifindex,
+ dp->upcall_pid, dp->masks_cache_size);
+ }
+ ovs_datapath_get_list_free(dps);
+ }
+
+ ynl_sock_destroy(ys);
+
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL (%d): %s\n", ys->err.code, ys->err.msg);
+ ynl_sock_destroy(ys);
+ return 2;
+}
diff --git a/tools/net/ynl/samples/rt-addr.c b/tools/net/ynl/samples/rt-addr.c
new file mode 100644
index 000000000000..2edde5c36b18
--- /dev/null
+++ b/tools/net/ynl/samples/rt-addr.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "rt-addr-user.h"
+
+static void rt_addr_print(struct rt_addr_getaddr_rsp *a)
+{
+ char ifname[IF_NAMESIZE];
+ char addr_str[64];
+ const char *addr;
+ const char *name;
+
+ name = if_indextoname(a->_hdr.ifa_index, ifname);
+ if (name)
+ printf("%16s: ", name);
+
+ switch (a->_len.address) {
+ case 4:
+ addr = inet_ntop(AF_INET, a->address,
+ addr_str, sizeof(addr_str));
+ break;
+ case 16:
+ addr = inet_ntop(AF_INET6, a->address,
+ addr_str, sizeof(addr_str));
+ break;
+ default:
+ addr = NULL;
+ break;
+ }
+ if (addr)
+ printf("%s", addr);
+ else
+ printf("[%d]", a->_len.address);
+
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct rt_addr_getaddr_list *rsp;
+ struct rt_addr_getaddr_req *req;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+
+ ys = ynl_sock_create(&ynl_rt_addr_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ req = rt_addr_getaddr_req_alloc();
+ if (!req)
+ goto err_destroy;
+
+ rsp = rt_addr_getaddr_dump(ys, req);
+ rt_addr_getaddr_req_free(req);
+ if (!rsp)
+ goto err_close;
+
+ if (ynl_dump_empty(rsp))
+ fprintf(stderr, "Error: no addresses reported\n");
+ ynl_dump_foreach(rsp, addr)
+ rt_addr_print(addr);
+ rt_addr_getaddr_list_free(rsp);
+
+ ynl_sock_destroy(ys);
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_destroy:
+ ynl_sock_destroy(ys);
+ return 2;
+}
diff --git a/tools/net/ynl/samples/rt-link.c b/tools/net/ynl/samples/rt-link.c
new file mode 100644
index 000000000000..acdd4b4a0f74
--- /dev/null
+++ b/tools/net/ynl/samples/rt-link.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "rt-link-user.h"
+
+static void rt_link_print(struct rt_link_getlink_rsp *r)
+{
+ unsigned int i;
+
+ printf("%3d: ", r->_hdr.ifi_index);
+
+ if (r->_len.ifname)
+ printf("%16s: ", r->ifname);
+
+ if (r->_present.mtu)
+ printf("mtu %5d ", r->mtu);
+
+ if (r->linkinfo._len.kind)
+ printf("kind %-8s ", r->linkinfo.kind);
+ else
+ printf(" %8s ", "");
+
+ if (r->prop_list._count.alt_ifname) {
+ printf("altname ");
+ for (i = 0; i < r->prop_list._count.alt_ifname; i++)
+ printf("%s ", r->prop_list.alt_ifname[i]->str);
+ printf(" ");
+ }
+
+ if (r->linkinfo._present.data && r->linkinfo.data._present.netkit) {
+ struct rt_link_linkinfo_netkit_attrs *netkit;
+ const char *name;
+
+ netkit = &r->linkinfo.data.netkit;
+ printf("primary %d ", netkit->primary);
+
+ name = NULL;
+ if (netkit->_present.policy)
+ name = rt_link_netkit_policy_str(netkit->policy);
+ if (name)
+ printf("policy %s ", name);
+ }
+
+ printf("\n");
+}
+
+static int rt_link_create_netkit(struct ynl_sock *ys)
+{
+ struct rt_link_getlink_ntf *ntf_gl;
+ struct rt_link_newlink_req *req;
+ struct ynl_ntf_base_type *ntf;
+ int ret;
+
+ req = rt_link_newlink_req_alloc();
+ if (!req) {
+ fprintf(stderr, "Can't alloc req\n");
+ return -1;
+ }
+
+ /* rtnetlink doesn't provide info about the created object.
+ * It expects us to set the ECHO flag and the dig the info out
+ * of the notifications...
+ */
+ rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
+
+ rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
+
+ /* Test error messages */
+ rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, 10);
+ ret = rt_link_newlink(ys, req);
+ if (ret) {
+ printf("Testing error message for policy being bad:\n\t%s\n", ys->err.msg);
+ } else {
+ fprintf(stderr, "Warning: unexpected success creating netkit with bad attrs\n");
+ goto created;
+ }
+
+ rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, NETKIT_DROP);
+
+ ret = rt_link_newlink(ys, req);
+created:
+ rt_link_newlink_req_free(req);
+ if (ret) {
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+ return -1;
+ }
+
+ if (!ynl_has_ntf(ys)) {
+ fprintf(stderr,
+ "Warning: interface created but received no notification, won't delete the interface\n");
+ return 0;
+ }
+
+ ntf = ynl_ntf_dequeue(ys);
+ if (ntf->cmd != RTM_NEWLINK) {
+ fprintf(stderr,
+ "Warning: unexpected notification type, won't delete the interface\n");
+ return 0;
+ }
+ ntf_gl = (void *)ntf;
+ ret = ntf_gl->obj._hdr.ifi_index;
+ ynl_ntf_free(ntf);
+
+ return ret;
+}
+
+static void rt_link_del(struct ynl_sock *ys, int ifindex)
+{
+ struct rt_link_dellink_req *req;
+
+ req = rt_link_dellink_req_alloc();
+ if (!req) {
+ fprintf(stderr, "Can't alloc req\n");
+ return;
+ }
+
+ req->_hdr.ifi_index = ifindex;
+ if (rt_link_dellink(ys, req))
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+ else
+ fprintf(stderr,
+ "Trying to delete a Netkit interface (ifindex %d)\n",
+ ifindex);
+
+ rt_link_dellink_req_free(req);
+}
+
+int main(int argc, char **argv)
+{
+ struct rt_link_getlink_req_dump *req;
+ struct rt_link_getlink_list *rsp;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ int created = 0;
+
+ ys = ynl_sock_create(&ynl_rt_link_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ if (argc > 1) {
+ fprintf(stderr, "Trying to create a Netkit interface\n");
+ created = rt_link_create_netkit(ys);
+ if (created < 0)
+ goto err_destroy;
+ }
+
+ req = rt_link_getlink_req_dump_alloc();
+ if (!req)
+ goto err_del_ifc;
+
+ rsp = rt_link_getlink_dump(ys, req);
+ rt_link_getlink_req_dump_free(req);
+ if (!rsp)
+ goto err_close;
+
+ if (ynl_dump_empty(rsp))
+ fprintf(stderr, "Error: no links reported\n");
+ ynl_dump_foreach(rsp, link)
+ rt_link_print(link);
+ rt_link_getlink_list_free(rsp);
+
+ if (created)
+ rt_link_del(ys, created);
+
+ ynl_sock_destroy(ys);
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_del_ifc:
+ if (created)
+ rt_link_del(ys, created);
+err_destroy:
+ ynl_sock_destroy(ys);
+ return 2;
+}
diff --git a/tools/net/ynl/samples/rt-route.c b/tools/net/ynl/samples/rt-route.c
new file mode 100644
index 000000000000..7427104a96df
--- /dev/null
+++ b/tools/net/ynl/samples/rt-route.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "rt-route-user.h"
+
+static void rt_route_print(struct rt_route_getroute_rsp *r)
+{
+ char ifname[IF_NAMESIZE];
+ char route_str[64];
+ const char *route;
+ const char *name;
+
+ /* Ignore local */
+ if (r->_hdr.rtm_table == RT_TABLE_LOCAL)
+ return;
+
+ if (r->_present.oif) {
+ name = if_indextoname(r->oif, ifname);
+ if (name)
+ printf("oif: %-16s ", name);
+ }
+
+ if (r->_len.dst) {
+ route = inet_ntop(r->_hdr.rtm_family, r->dst,
+ route_str, sizeof(route_str));
+ printf("dst: %s/%d", route, r->_hdr.rtm_dst_len);
+ }
+
+ if (r->_len.gateway) {
+ route = inet_ntop(r->_hdr.rtm_family, r->gateway,
+ route_str, sizeof(route_str));
+ printf("gateway: %s ", route);
+ }
+
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct rt_route_getroute_req_dump *req;
+ struct rt_route_getroute_list *rsp;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+
+ ys = ynl_sock_create(&ynl_rt_route_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ req = rt_route_getroute_req_dump_alloc();
+ if (!req)
+ goto err_destroy;
+
+ rsp = rt_route_getroute_dump(ys, req);
+ rt_route_getroute_req_dump_free(req);
+ if (!rsp)
+ goto err_close;
+
+ if (ynl_dump_empty(rsp))
+ fprintf(stderr, "Error: no routeesses reported\n");
+ ynl_dump_foreach(rsp, route)
+ rt_route_print(route);
+ rt_route_getroute_list_free(rsp);
+
+ ynl_sock_destroy(ys);
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_destroy:
+ ynl_sock_destroy(ys);
+ return 2;
+}
diff --git a/tools/net/ynl/samples/tc-filter-add.c b/tools/net/ynl/samples/tc-filter-add.c
new file mode 100644
index 000000000000..97871e9e9edc
--- /dev/null
+++ b/tools/net/ynl/samples/tc-filter-add.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <linux/pkt_sched.h>
+#include <linux/tc_act/tc_vlan.h>
+#include <linux/tc_act/tc_gact.h>
+#include <linux/if_ether.h>
+#include <net/if.h>
+
+#include <ynl.h>
+
+#include "tc-user.h"
+
+#define TC_HANDLE (0xFFFF << 16)
+
+const char *vlan_act_name(struct tc_vlan *p)
+{
+ switch (p->v_action) {
+ case TCA_VLAN_ACT_POP:
+ return "pop";
+ case TCA_VLAN_ACT_PUSH:
+ return "push";
+ case TCA_VLAN_ACT_MODIFY:
+ return "modify";
+ default:
+ break;
+ }
+
+ return "not supported";
+}
+
+const char *gact_act_name(struct tc_gact *p)
+{
+ switch (p->action) {
+ case TC_ACT_SHOT:
+ return "drop";
+ case TC_ACT_OK:
+ return "ok";
+ case TC_ACT_PIPE:
+ return "pipe";
+ default:
+ break;
+ }
+
+ return "not supported";
+}
+
+static void print_vlan(struct tc_act_vlan_attrs *vlan)
+{
+ printf("%s ", vlan_act_name(vlan->parms));
+ if (vlan->_present.push_vlan_id)
+ printf("id %u ", vlan->push_vlan_id);
+ if (vlan->_present.push_vlan_protocol)
+ printf("protocol %#x ", ntohs(vlan->push_vlan_protocol));
+ if (vlan->_present.push_vlan_priority)
+ printf("priority %u ", vlan->push_vlan_priority);
+}
+
+static void print_gact(struct tc_act_gact_attrs *gact)
+{
+ struct tc_gact *p = gact->parms;
+
+ printf("%s ", gact_act_name(p));
+}
+
+static void flower_print(struct tc_flower_attrs *flower, const char *kind)
+{
+ struct tc_act_attrs *a;
+ unsigned int i;
+
+ printf("%s:\n", kind);
+
+ if (flower->_present.key_vlan_id)
+ printf(" vlan_id: %u\n", flower->key_vlan_id);
+ if (flower->_present.key_vlan_prio)
+ printf(" vlan_prio: %u\n", flower->key_vlan_prio);
+ if (flower->_present.key_num_of_vlans)
+ printf(" num_of_vlans: %u\n", flower->key_num_of_vlans);
+
+ for (i = 0; i < flower->_count.act; i++) {
+ a = &flower->act[i];
+ printf("action order: %i %s ", i + 1, a->kind);
+ if (a->options._present.vlan)
+ print_vlan(&a->options.vlan);
+ else if (a->options._present.gact)
+ print_gact(&a->options.gact);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+static void tc_filter_print(struct tc_gettfilter_rsp *f)
+{
+ struct tc_options_msg *opt = &f->options;
+
+ if (opt->_present.flower)
+ flower_print(&opt->flower, f->kind);
+ else if (f->_len.kind)
+ printf("%s pref %u proto: %#x\n", f->kind,
+ (f->_hdr.tcm_info >> 16),
+ ntohs(TC_H_MIN(f->_hdr.tcm_info)));
+}
+
+static int tc_filter_add(struct ynl_sock *ys, int ifi)
+{
+ struct tc_newtfilter_req *req;
+ struct tc_act_attrs *acts;
+ struct tc_vlan p = {
+ .action = TC_ACT_PIPE,
+ .v_action = TCA_VLAN_ACT_PUSH
+ };
+ __u16 flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
+ int ret;
+
+ req = tc_newtfilter_req_alloc();
+ if (!req) {
+ fprintf(stderr, "tc_newtfilter_req_alloc failed\n");
+ return -1;
+ }
+ memset(req, 0, sizeof(*req));
+
+ acts = tc_act_attrs_alloc(3);
+ if (!acts) {
+ fprintf(stderr, "tc_act_attrs_alloc\n");
+ tc_newtfilter_req_free(req);
+ return -1;
+ }
+ memset(acts, 0, sizeof(*acts) * 3);
+
+ req->_hdr.tcm_ifindex = ifi;
+ req->_hdr.tcm_parent = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
+ req->_hdr.tcm_info = TC_H_MAKE(1 << 16, htons(ETH_P_8021Q));
+ req->chain = 0;
+
+ tc_newtfilter_req_set_nlflags(req, flags);
+ tc_newtfilter_req_set_kind(req, "flower");
+ tc_newtfilter_req_set_options_flower_key_vlan_id(req, 100);
+ tc_newtfilter_req_set_options_flower_key_vlan_prio(req, 5);
+ tc_newtfilter_req_set_options_flower_key_num_of_vlans(req, 3);
+
+ __tc_newtfilter_req_set_options_flower_act(req, acts, 3);
+
+ /* Skip action at index 0 because in TC, the action array
+ * index starts at 1, with each index defining the action's
+ * order. In contrast, in YNL indexed arrays start at index 0.
+ */
+ tc_act_attrs_set_kind(&acts[1], "vlan");
+ tc_act_attrs_set_options_vlan_parms(&acts[1], &p, sizeof(p));
+ tc_act_attrs_set_options_vlan_push_vlan_id(&acts[1], 200);
+ tc_act_attrs_set_kind(&acts[2], "vlan");
+ tc_act_attrs_set_options_vlan_parms(&acts[2], &p, sizeof(p));
+ tc_act_attrs_set_options_vlan_push_vlan_id(&acts[2], 300);
+
+ tc_newtfilter_req_set_options_flower_flags(req, 0);
+ tc_newtfilter_req_set_options_flower_key_eth_type(req, htons(0x8100));
+
+ ret = tc_newtfilter(ys, req);
+ if (ret)
+ fprintf(stderr, "tc_newtfilter: %s\n", ys->err.msg);
+
+ tc_newtfilter_req_free(req);
+
+ return ret;
+}
+
+static int tc_filter_show(struct ynl_sock *ys, int ifi)
+{
+ struct tc_gettfilter_req_dump *req;
+ struct tc_gettfilter_list *rsp;
+
+ req = tc_gettfilter_req_dump_alloc();
+ if (!req) {
+ fprintf(stderr, "tc_gettfilter_req_dump_alloc failed\n");
+ return -1;
+ }
+ memset(req, 0, sizeof(*req));
+
+ req->_hdr.tcm_ifindex = ifi;
+ req->_hdr.tcm_parent = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
+ req->_present.chain = 1;
+ req->chain = 0;
+
+ rsp = tc_gettfilter_dump(ys, req);
+ tc_gettfilter_req_dump_free(req);
+ if (!rsp) {
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+ return -1;
+ }
+
+ if (ynl_dump_empty(rsp))
+ fprintf(stderr, "Error: no filters reported\n");
+ else
+ ynl_dump_foreach(rsp, flt) tc_filter_print(flt);
+
+ tc_gettfilter_list_free(rsp);
+
+ return 0;
+}
+
+static int tc_filter_del(struct ynl_sock *ys, int ifi)
+{
+ struct tc_deltfilter_req *req;
+ __u16 flags = NLM_F_REQUEST;
+ int ret;
+
+ req = tc_deltfilter_req_alloc();
+ if (!req) {
+ fprintf(stderr, "tc_deltfilter_req_alloc failed\n");
+ return -1;
+ }
+ memset(req, 0, sizeof(*req));
+
+ req->_hdr.tcm_ifindex = ifi;
+ req->_hdr.tcm_parent = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
+ req->_hdr.tcm_info = TC_H_MAKE(1 << 16, htons(ETH_P_8021Q));
+ tc_deltfilter_req_set_nlflags(req, flags);
+
+ ret = tc_deltfilter(ys, req);
+ if (ret)
+ fprintf(stderr, "tc_deltfilter failed: %s\n", ys->err.msg);
+
+ tc_deltfilter_req_free(req);
+
+ return ret;
+}
+
+static int tc_clsact_add(struct ynl_sock *ys, int ifi)
+{
+ struct tc_newqdisc_req *req;
+ __u16 flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE;
+ int ret;
+
+ req = tc_newqdisc_req_alloc();
+ if (!req) {
+ fprintf(stderr, "tc_newqdisc_req_alloc failed\n");
+ return -1;
+ }
+ memset(req, 0, sizeof(*req));
+
+ req->_hdr.tcm_ifindex = ifi;
+ req->_hdr.tcm_parent = TC_H_CLSACT;
+ req->_hdr.tcm_handle = TC_HANDLE;
+ tc_newqdisc_req_set_nlflags(req, flags);
+ tc_newqdisc_req_set_kind(req, "clsact");
+
+ ret = tc_newqdisc(ys, req);
+ if (ret)
+ fprintf(stderr, "tc_newqdisc failed: %s\n", ys->err.msg);
+
+ tc_newqdisc_req_free(req);
+
+ return ret;
+}
+
+static int tc_clsact_del(struct ynl_sock *ys, int ifi)
+{
+ struct tc_delqdisc_req *req;
+ __u16 flags = NLM_F_REQUEST;
+ int ret;
+
+ req = tc_delqdisc_req_alloc();
+ if (!req) {
+ fprintf(stderr, "tc_delqdisc_req_alloc failed\n");
+ return -1;
+ }
+ memset(req, 0, sizeof(*req));
+
+ req->_hdr.tcm_ifindex = ifi;
+ req->_hdr.tcm_parent = TC_H_CLSACT;
+ req->_hdr.tcm_handle = TC_HANDLE;
+ tc_delqdisc_req_set_nlflags(req, flags);
+
+ ret = tc_delqdisc(ys, req);
+ if (ret)
+ fprintf(stderr, "tc_delqdisc failed: %s\n", ys->err.msg);
+
+ tc_delqdisc_req_free(req);
+
+ return ret;
+}
+
+static int tc_filter_config(struct ynl_sock *ys, int ifi)
+{
+ int ret = 0;
+
+ if (tc_filter_add(ys, ifi))
+ return -1;
+
+ ret = tc_filter_show(ys, ifi);
+
+ if (tc_filter_del(ys, ifi))
+ return -1;
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ int ifi, ret = 0;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <interface_name>\n", argv[0]);
+ return 1;
+ }
+ ifi = if_nametoindex(argv[1]);
+ if (!ifi) {
+ perror("if_nametoindex");
+ return 1;
+ }
+
+ ys = ynl_sock_create(&ynl_tc_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ if (tc_clsact_add(ys, ifi)) {
+ ret = 2;
+ goto err_destroy;
+ }
+
+ if (tc_filter_config(ys, ifi))
+ ret = 3;
+
+ if (tc_clsact_del(ys, ifi))
+ ret = 4;
+
+err_destroy:
+ ynl_sock_destroy(ys);
+ return ret;
+}
diff --git a/tools/net/ynl/samples/tc.c b/tools/net/ynl/samples/tc.c
new file mode 100644
index 000000000000..0bfff0fdd792
--- /dev/null
+++ b/tools/net/ynl/samples/tc.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include <net/if.h>
+
+#include "tc-user.h"
+
+static void tc_qdisc_print(struct tc_getqdisc_rsp *q)
+{
+ char ifname[IF_NAMESIZE];
+ const char *name;
+
+ name = if_indextoname(q->_hdr.tcm_ifindex, ifname);
+ if (name)
+ printf("%16s: ", name);
+
+ if (q->_len.kind) {
+ printf("%s ", q->kind);
+
+ if (q->options._present.fq_codel) {
+ struct tc_fq_codel_attrs *fq_codel;
+ struct tc_fq_codel_xstats *stats;
+
+ fq_codel = &q->options.fq_codel;
+ stats = q->stats2.app.fq_codel;
+
+ if (fq_codel->_present.limit)
+ printf("limit: %dp ", fq_codel->limit);
+ if (fq_codel->_present.target)
+ printf("target: %dms ",
+ (fq_codel->target + 500) / 1000);
+ if (q->stats2.app._len.fq_codel)
+ printf("new_flow_cnt: %d ",
+ stats->qdisc_stats.new_flow_count);
+ }
+ }
+
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ struct tc_getqdisc_req_dump *req;
+ struct tc_getqdisc_list *rsp;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+
+ ys = ynl_sock_create(&ynl_tc_family, &yerr);
+ if (!ys) {
+ fprintf(stderr, "YNL: %s\n", yerr.msg);
+ return 1;
+ }
+
+ req = tc_getqdisc_req_dump_alloc();
+ if (!req)
+ goto err_destroy;
+
+ rsp = tc_getqdisc_dump(ys, req);
+ tc_getqdisc_req_dump_free(req);
+ if (!rsp)
+ goto err_close;
+
+ if (ynl_dump_empty(rsp))
+ fprintf(stderr, "Error: no addresses reported\n");
+ ynl_dump_foreach(rsp, qdisc)
+ tc_qdisc_print(qdisc);
+ tc_getqdisc_list_free(rsp);
+
+ ynl_sock_destroy(ys);
+ return 0;
+
+err_close:
+ fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_destroy:
+ ynl_sock_destroy(ys);
+ return 2;
+}
diff --git a/tools/net/ynl/tests/Makefile b/tools/net/ynl/tests/Makefile
new file mode 100644
index 000000000000..c1df2e001255
--- /dev/null
+++ b/tools/net/ynl/tests/Makefile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for YNL tests
+
+TESTS := \
+ test_ynl_cli.sh \
+ test_ynl_ethtool.sh \
+# end of TESTS
+
+all: $(TESTS)
+
+run_tests:
+ @for test in $(TESTS); do \
+ ./$$test; \
+ done
+
+install: $(TESTS)
+ @mkdir -p $(DESTDIR)/usr/bin
+ @mkdir -p $(DESTDIR)/usr/share/kselftest
+ @cp ../../../testing/selftests/kselftest/ktap_helpers.sh $(DESTDIR)/usr/share/kselftest/
+ @for test in $(TESTS); do \
+ name=$$(basename $$test .sh); \
+ sed -e 's|^ynl=.*|ynl="ynl"|' \
+ -e 's|^ynl_ethtool=.*|ynl_ethtool="ynl-ethtool"|' \
+ -e 's|KSELFTEST_KTAP_HELPERS=.*|KSELFTEST_KTAP_HELPERS="/usr/share/kselftest/ktap_helpers.sh"|' \
+ $$test > $(DESTDIR)/usr/bin/$$name; \
+ chmod +x $(DESTDIR)/usr/bin/$$name; \
+ done
+
+clean distclean:
+ @# Nothing to clean
+
+.PHONY: all install clean run_tests
diff --git a/tools/net/ynl/tests/config b/tools/net/ynl/tests/config
new file mode 100644
index 000000000000..339f1309c03f
--- /dev/null
+++ b/tools/net/ynl/tests/config
@@ -0,0 +1,6 @@
+CONFIG_DUMMY=m
+CONFIG_INET_DIAG=y
+CONFIG_IPV6=y
+CONFIG_NET_NS=y
+CONFIG_NETDEVSIM=m
+CONFIG_VETH=m
diff --git a/tools/net/ynl/tests/test_ynl_cli.sh b/tools/net/ynl/tests/test_ynl_cli.sh
new file mode 100755
index 000000000000..7c0722a08117
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_cli.sh
@@ -0,0 +1,327 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Test YNL CLI functionality
+
+# Load KTAP test helpers
+KSELFTEST_KTAP_HELPERS="$(dirname "$(realpath "$0")")/../../../testing/selftests/kselftest/ktap_helpers.sh"
+# shellcheck source=../../../testing/selftests/kselftest/ktap_helpers.sh
+source "$KSELFTEST_KTAP_HELPERS"
+
+# Default ynl path for direct execution, can be overridden by make install
+ynl="../pyynl/cli.py"
+
+readonly NSIM_ID="1338"
+readonly NSIM_DEV_NAME="nsim${NSIM_ID}"
+readonly VETH_A="veth_a"
+readonly VETH_B="veth_b"
+
+testns="ynl-$(mktemp -u XXXXXX)"
+TESTS_NO=0
+
+# Test listing available families
+cli_list_families()
+{
+ if $ynl --list-families &>/dev/null; then
+ ktap_test_pass "YNL CLI list families"
+ else
+ ktap_test_fail "YNL CLI list families"
+ fi
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test netdev family operations (dev-get, queue-get)
+cli_netdev_ops()
+{
+ local dev_output
+ local ifindex
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+
+ dev_output=$(ip netns exec "$testns" $ynl --family netdev \
+ --do dev-get --json "{\"ifindex\": $ifindex}" 2>/dev/null)
+
+ if ! echo "$dev_output" | grep -q "ifindex"; then
+ ktap_test_fail "YNL CLI netdev operations (netdev dev-get output missing ifindex)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl --family netdev \
+ --dump queue-get --json "{\"ifindex\": $ifindex}" &>/dev/null; then
+ ktap_test_fail "YNL CLI netdev operations (failed to get netdev queue info)"
+ return
+ fi
+
+ ktap_test_pass "YNL CLI netdev operations"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test ethtool family operations (rings-get, linkinfo-get)
+cli_ethtool_ops()
+{
+ local rings_output
+ local linkinfo_output
+
+ rings_output=$(ip netns exec "$testns" $ynl --family ethtool \
+ --do rings-get --json "{\"header\": {\"dev-name\": \"$NSIM_DEV_NAME\"}}" 2>/dev/null)
+
+ if ! echo "$rings_output" | grep -q "header"; then
+ ktap_test_fail "YNL CLI ethtool operations (ethtool rings-get output missing header)"
+ return
+ fi
+
+ linkinfo_output=$(ip netns exec "$testns" $ynl --family ethtool \
+ --do linkinfo-get --json "{\"header\": {\"dev-name\": \"$VETH_A\"}}" 2>/dev/null)
+
+ if ! echo "$linkinfo_output" | grep -q "header"; then
+ ktap_test_fail "YNL CLI ethtool operations (ethtool linkinfo-get output missing header)"
+ return
+ fi
+
+ ktap_test_pass "YNL CLI ethtool operations"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test rt-route family operations
+cli_rt_route_ops()
+{
+ local ifindex
+
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-route"; then
+ ktap_test_skip "YNL CLI rt-route operations (rt-route family not available)"
+ return
+ fi
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+
+ # Add route: 192.0.2.0/24 dev $dev scope link
+ if ! ip netns exec "$testns" $ynl --family rt-route --do newroute --create \
+ --json "{\"dst\": \"192.0.2.0\", \"oif\": $ifindex, \"rtm-dst-len\": 24, \"rtm-family\": 2, \"rtm-scope\": 253, \"rtm-type\": 1, \"rtm-protocol\": 3, \"rtm-table\": 254}" &>/dev/null; then
+ ktap_test_fail "YNL CLI rt-route operations (failed to add route)"
+ return
+ fi
+
+ local route_output
+ route_output=$(ip netns exec "$testns" $ynl --family rt-route --dump getroute 2>/dev/null)
+ if echo "$route_output" | grep -q "192.0.2.0"; then
+ ktap_test_pass "YNL CLI rt-route operations"
+ else
+ ktap_test_fail "YNL CLI rt-route operations (failed to verify route)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-route --do delroute \
+ --json "{\"dst\": \"192.0.2.0\", \"oif\": $ifindex, \"rtm-dst-len\": 24, \"rtm-family\": 2, \"rtm-scope\": 253, \"rtm-type\": 1, \"rtm-protocol\": 3, \"rtm-table\": 254}" &>/dev/null
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test rt-addr family operations
+cli_rt_addr_ops()
+{
+ local ifindex
+
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-addr"; then
+ ktap_test_skip "YNL CLI rt-addr operations (rt-addr family not available)"
+ return
+ fi
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+
+ if ! ip netns exec "$testns" $ynl --family rt-addr --do newaddr \
+ --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null; then
+ ktap_test_fail "YNL CLI rt-addr operations (failed to add address)"
+ return
+ fi
+
+ local addr_output
+ addr_output=$(ip netns exec "$testns" $ynl --family rt-addr --dump getaddr 2>/dev/null)
+ if echo "$addr_output" | grep -q "192.0.2.100"; then
+ ktap_test_pass "YNL CLI rt-addr operations"
+ else
+ ktap_test_fail "YNL CLI rt-addr operations (failed to verify address)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-addr --do deladdr \
+ --json "{\"ifa-index\": $ifindex, \"local\": \"192.0.2.100\", \"ifa-prefixlen\": 24, \"ifa-family\": 2}" &>/dev/null
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test rt-link family operations
+cli_rt_link_ops()
+{
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-link"; then
+ ktap_test_skip "YNL CLI rt-link operations (rt-link family not available)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl --family rt-link --do newlink --create \
+ --json "{\"ifname\": \"dummy0\", \"linkinfo\": {\"kind\": \"dummy\"}}" &>/dev/null; then
+ ktap_test_fail "YNL CLI rt-link operations (failed to add link)"
+ return
+ fi
+
+ local link_output
+ link_output=$(ip netns exec "$testns" $ynl --family rt-link --dump getlink 2>/dev/null)
+ if echo "$link_output" | grep -q "$NSIM_DEV_NAME" && echo "$link_output" | grep -q "dummy0"; then
+ ktap_test_pass "YNL CLI rt-link operations"
+ else
+ ktap_test_fail "YNL CLI rt-link operations (failed to verify link)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-link --do dellink \
+ --json "{\"ifname\": \"dummy0\"}" &>/dev/null
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test rt-neigh family operations
+cli_rt_neigh_ops()
+{
+ local ifindex
+
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-neigh"; then
+ ktap_test_skip "YNL CLI rt-neigh operations (rt-neigh family not available)"
+ return
+ fi
+
+ ifindex=$(ip netns exec "$testns" cat /sys/class/net/"$NSIM_DEV_NAME"/ifindex 2>/dev/null)
+
+ # Add neighbor: 192.0.2.1 dev nsim1338 lladdr 11:22:33:44:55:66 PERMANENT
+ if ! ip netns exec "$testns" $ynl --family rt-neigh --do newneigh --create \
+ --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2, \"ndm-state\": 128}" &>/dev/null; then
+ ktap_test_fail "YNL CLI rt-neigh operations (failed to add neighbor)"
+ fi
+
+ local neigh_output
+ neigh_output=$(ip netns exec "$testns" $ynl --family rt-neigh --dump getneigh 2>/dev/null)
+ if echo "$neigh_output" | grep -q "192.0.2.1"; then
+ ktap_test_pass "YNL CLI rt-neigh operations"
+ else
+ ktap_test_fail "YNL CLI rt-neigh operations (failed to verify neighbor)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-neigh --do delneigh \
+ --json "{\"ndm-ifindex\": $ifindex, \"dst\": \"192.0.2.1\", \"lladdr\": \"11:22:33:44:55:66\", \"ndm-family\": 2}" &>/dev/null
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test rt-rule family operations
+cli_rt_rule_ops()
+{
+ if ! $ynl --list-families 2>/dev/null | grep -q "rt-rule"; then
+ ktap_test_skip "YNL CLI rt-rule operations (rt-rule family not available)"
+ return
+ fi
+
+ # Add rule: from 192.0.2.0/24 lookup 100 none
+ if ! ip netns exec "$testns" $ynl --family rt-rule --do newrule \
+ --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null; then
+ ktap_test_fail "YNL CLI rt-rule operations (failed to add rule)"
+ return
+ fi
+
+ local rule_output
+ rule_output=$(ip netns exec "$testns" $ynl --family rt-rule --dump getrule 2>/dev/null)
+ if echo "$rule_output" | grep -q "192.0.2.0"; then
+ ktap_test_pass "YNL CLI rt-rule operations"
+ else
+ ktap_test_fail "YNL CLI rt-rule operations (failed to verify rule)"
+ fi
+
+ ip netns exec "$testns" $ynl --family rt-rule --do delrule \
+ --json "{\"family\": 2, \"src-len\": 24, \"src\": \"192.0.2.0\", \"table\": 100}" &>/dev/null
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+# Test nlctrl family operations
+cli_nlctrl_ops()
+{
+ local family_output
+
+ if ! family_output=$($ynl --family nlctrl \
+ --do getfamily --json "{\"family-name\": \"netdev\"}" 2>/dev/null); then
+ ktap_test_fail "YNL CLI nlctrl getfamily (failed to get nlctrl family info)"
+ return
+ fi
+
+ if ! echo "$family_output" | grep -q "family-name"; then
+ ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-name)"
+ return
+ fi
+
+ if ! echo "$family_output" | grep -q "family-id"; then
+ ktap_test_fail "YNL CLI nlctrl getfamily (nlctrl getfamily output missing family-id)"
+ return
+ fi
+
+ ktap_test_pass "YNL CLI nlctrl getfamily"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+setup()
+{
+ modprobe netdevsim &> /dev/null
+ if ! [ -f /sys/bus/netdevsim/new_device ]; then
+ ktap_skip_all "netdevsim module not available"
+ exit "$KSFT_SKIP"
+ fi
+
+ if ! ip netns add "$testns" 2>/dev/null; then
+ ktap_skip_all "failed to create test namespace"
+ exit "$KSFT_SKIP"
+ fi
+
+ echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || {
+ ktap_skip_all "failed to create netdevsim device"
+ exit "$KSFT_SKIP"
+ }
+
+ local dev
+ dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1)
+ if [[ -z "$dev" ]]; then
+ ktap_skip_all "failed to find netdevsim device"
+ exit "$KSFT_SKIP"
+ fi
+
+ ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || {
+ ktap_skip_all "failed to rename netdevsim device"
+ exit "$KSFT_SKIP"
+ }
+
+ ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null
+
+ if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then
+ ktap_skip_all "failed to create veth pair"
+ exit "$KSFT_SKIP"
+ fi
+
+ ip -n "$testns" link set "$VETH_A" up 2>/dev/null
+ ip -n "$testns" link set "$VETH_B" up 2>/dev/null
+}
+
+cleanup()
+{
+ ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true
+ ip netns del "$testns" 2>/dev/null || true
+}
+
+# Check if ynl command is available
+if ! command -v $ynl &>/dev/null && [[ ! -x $ynl ]]; then
+ ktap_skip_all "ynl command not found: $ynl"
+ exit "$KSFT_SKIP"
+fi
+
+trap cleanup EXIT
+
+ktap_print_header
+setup
+ktap_set_plan "${TESTS_NO}"
+
+cli_list_families
+cli_netdev_ops
+cli_ethtool_ops
+cli_rt_route_ops
+cli_rt_addr_ops
+cli_rt_link_ops
+cli_rt_neigh_ops
+cli_rt_rule_ops
+cli_nlctrl_ops
+
+ktap_finished
diff --git a/tools/net/ynl/tests/test_ynl_ethtool.sh b/tools/net/ynl/tests/test_ynl_ethtool.sh
new file mode 100755
index 000000000000..b826269017f4
--- /dev/null
+++ b/tools/net/ynl/tests/test_ynl_ethtool.sh
@@ -0,0 +1,222 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Test YNL ethtool functionality
+
+# Load KTAP test helpers
+KSELFTEST_KTAP_HELPERS="$(dirname "$(realpath "$0")")/../../../testing/selftests/kselftest/ktap_helpers.sh"
+# shellcheck source=../../../testing/selftests/kselftest/ktap_helpers.sh
+source "$KSELFTEST_KTAP_HELPERS"
+
+# Default ynl-ethtool path for direct execution, can be overridden by make install
+ynl_ethtool="../pyynl/ethtool.py"
+
+readonly NSIM_ID="1337"
+readonly NSIM_DEV_NAME="nsim${NSIM_ID}"
+readonly VETH_A="veth_a"
+readonly VETH_B="veth_b"
+
+testns="ynl-ethtool-$(mktemp -u XXXXXX)"
+TESTS_NO=0
+
+# Uses veth device as netdevsim doesn't support basic ethtool device info
+ethtool_device_info()
+{
+ local info_output
+
+ info_output=$(ip netns exec "$testns" $ynl_ethtool "$VETH_A" 2>/dev/null)
+
+ if ! echo "$info_output" | grep -q "Settings for"; then
+ ktap_test_fail "YNL ethtool device info (device info output missing expected content)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool device info"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_statistics()
+{
+ local stats_output
+
+ stats_output=$(ip netns exec "$testns" $ynl_ethtool --statistics "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$stats_output" | grep -q -E "(NIC statistics|packets|bytes)"; then
+ ktap_test_fail "YNL ethtool statistics (statistics output missing expected content)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool statistics"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_ring_params()
+{
+ local ring_output
+
+ ring_output=$(ip netns exec "$testns" $ynl_ethtool --show-ring "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$ring_output" | grep -q -E "(Ring parameters|RX|TX)"; then
+ ktap_test_fail "YNL ethtool ring parameters (ring parameters output missing expected content)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-ring "$NSIM_DEV_NAME" rx 64 2>/dev/null; then
+ ktap_test_fail "YNL ethtool ring parameters (set-ring command failed unexpectedly)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool ring parameters (show/set)"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_coalesce_params()
+{
+ if ! ip netns exec "$testns" $ynl_ethtool --show-coalesce "$NSIM_DEV_NAME" &>/dev/null; then
+ ktap_test_fail "YNL ethtool coalesce parameters (failed to get coalesce parameters)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-coalesce "$NSIM_DEV_NAME" rx-usecs 50 2>/dev/null; then
+ ktap_test_fail "YNL ethtool coalesce parameters (set-coalesce command failed unexpectedly)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool coalesce parameters (show/set)"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_pause_params()
+{
+ if ! ip netns exec "$testns" $ynl_ethtool --show-pause "$NSIM_DEV_NAME" &>/dev/null; then
+ ktap_test_fail "YNL ethtool pause parameters (failed to get pause parameters)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-pause "$NSIM_DEV_NAME" tx 1 rx 1 2>/dev/null; then
+ ktap_test_fail "YNL ethtool pause parameters (set-pause command failed unexpectedly)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool pause parameters (show/set)"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_features_info()
+{
+ local features_output
+
+ features_output=$(ip netns exec "$testns" $ynl_ethtool --show-features "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$features_output" | grep -q -E "(Features|offload)"; then
+ ktap_test_fail "YNL ethtool features info (features output missing expected content)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool features info (show/set)"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_channels_info()
+{
+ local channels_output
+
+ channels_output=$(ip netns exec "$testns" $ynl_ethtool --show-channels "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$channels_output" | grep -q -E "(Channel|Combined|RX|TX)"; then
+ ktap_test_fail "YNL ethtool channels info (channels output missing expected content)"
+ return
+ fi
+
+ if ! ip netns exec "$testns" $ynl_ethtool --set-channels "$NSIM_DEV_NAME" combined-count 1 2>/dev/null; then
+ ktap_test_fail "YNL ethtool channels info (set-channels command failed unexpectedly)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool channels info (show/set)"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+ethtool_time_stamping()
+{
+ local ts_output
+
+ ts_output=$(ip netns exec "$testns" $ynl_ethtool --show-time-stamping "$NSIM_DEV_NAME" 2>/dev/null)
+
+ if ! echo "$ts_output" | grep -q -E "(Time stamping|timestamping|SOF_TIMESTAMPING)"; then
+ ktap_test_fail "YNL ethtool time stamping (time stamping output missing expected content)"
+ return
+ fi
+
+ ktap_test_pass "YNL ethtool time stamping"
+}
+TESTS_NO=$((TESTS_NO + 1))
+
+setup()
+{
+ modprobe netdevsim &> /dev/null
+ if ! [ -f /sys/bus/netdevsim/new_device ]; then
+ ktap_skip_all "netdevsim module not available"
+ exit "$KSFT_SKIP"
+ fi
+
+ if ! ip netns add "$testns" 2>/dev/null; then
+ ktap_skip_all "failed to create test namespace"
+ exit "$KSFT_SKIP"
+ fi
+
+ echo "$NSIM_ID 1" | ip netns exec "$testns" tee /sys/bus/netdevsim/new_device >/dev/null 2>&1 || {
+ ktap_skip_all "failed to create netdevsim device"
+ exit "$KSFT_SKIP"
+ }
+
+ local dev
+ dev=$(ip netns exec "$testns" ls /sys/bus/netdevsim/devices/netdevsim$NSIM_ID/net 2>/dev/null | head -1)
+ if [[ -z "$dev" ]]; then
+ ktap_skip_all "failed to find netdevsim device"
+ exit "$KSFT_SKIP"
+ fi
+
+ ip -netns "$testns" link set dev "$dev" name "$NSIM_DEV_NAME" 2>/dev/null || {
+ ktap_skip_all "failed to rename netdevsim device"
+ exit "$KSFT_SKIP"
+ }
+
+ ip -netns "$testns" link set dev "$NSIM_DEV_NAME" up 2>/dev/null
+
+ if ! ip -n "$testns" link add "$VETH_A" type veth peer name "$VETH_B" 2>/dev/null; then
+ ktap_skip_all "failed to create veth pair"
+ exit "$KSFT_SKIP"
+ fi
+
+ ip -n "$testns" link set "$VETH_A" up 2>/dev/null
+ ip -n "$testns" link set "$VETH_B" up 2>/dev/null
+}
+
+cleanup()
+{
+ ip netns exec "$testns" bash -c "echo $NSIM_ID > /sys/bus/netdevsim/del_device" 2>/dev/null || true
+ ip netns del "$testns" 2>/dev/null || true
+}
+
+# Check if ynl-ethtool command is available
+if ! command -v $ynl_ethtool &>/dev/null && [[ ! -x $ynl_ethtool ]]; then
+ ktap_skip_all "ynl-ethtool command not found: $ynl_ethtool"
+ exit "$KSFT_SKIP"
+fi
+
+trap cleanup EXIT
+
+ktap_print_header
+setup
+ktap_set_plan "${TESTS_NO}"
+
+ethtool_device_info
+ethtool_statistics
+ethtool_ring_params
+ethtool_coalesce_params
+ethtool_pause_params
+ethtool_features_info
+ethtool_channels_info
+ethtool_time_stamping
+
+ktap_finished
diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh
index bdba24066cf1..81b4ecd89100 100755
--- a/tools/net/ynl/ynl-regen.sh
+++ b/tools/net/ynl/ynl-regen.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-TOOL=$(dirname $(realpath $0))/ynl-gen-c.py
+TOOL=$(dirname $(realpath $0))/pyynl/ynl_gen_c.py
force=
search=
@@ -30,8 +30,8 @@ for f in $files; do
fi
echo -e "\tGEN ${params[2]}\t$f"
- $TOOL --mode ${params[2]} --${params[3]} --spec $KDIR/${params[0]} \
- $args -o $f
+ $TOOL --cmp-out --mode ${params[2]} --${params[3]} \
+ --spec $KDIR/${params[0]} $args -o $f
done
popd >>/dev/null
diff --git a/tools/net/ynl/ynltool/.gitignore b/tools/net/ynl/ynltool/.gitignore
new file mode 100644
index 000000000000..690d399c921a
--- /dev/null
+++ b/tools/net/ynl/ynltool/.gitignore
@@ -0,0 +1,2 @@
+ynltool
+*.d
diff --git a/tools/net/ynl/ynltool/Makefile b/tools/net/ynl/ynltool/Makefile
new file mode 100644
index 000000000000..f5b1de32daa5
--- /dev/null
+++ b/tools/net/ynl/ynltool/Makefile
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+include ../Makefile.deps
+
+INSTALL ?= install
+prefix ?= /usr
+
+CC := gcc
+CFLAGS := -Wall -Wextra -Werror -O2
+ifeq ("$(DEBUG)","1")
+ CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
+endif
+CFLAGS += -I../lib -I../generated -I../../../include/uapi/
+
+SRC_VERSION := \
+ $(shell make --no-print-directory -sC ../../../.. kernelversion || \
+ echo "unknown")
+
+CFLAGS += -DSRC_VERSION='"$(SRC_VERSION)"'
+
+SRCS := $(wildcard *.c)
+OBJS := $(patsubst %.c,$(OUTPUT)%.o,$(SRCS))
+
+YNLTOOL := $(OUTPUT)ynltool
+
+include $(wildcard *.d)
+
+all: $(YNLTOOL)
+
+Q = @
+
+$(YNLTOOL): ../libynl.a $(OBJS)
+ $(Q)echo -e "\tLINK $@"
+ $(Q)$(CC) $(CFLAGS) -o $@ $(OBJS) ../libynl.a -lm
+
+%.o: %.c ../libynl.a
+ $(Q)echo -e "\tCC $@"
+ $(Q)$(COMPILE.c) -MMD -c -o $@ $<
+
+../libynl.a:
+ $(Q)$(MAKE) -C ../
+
+clean:
+ rm -f *.o *.d *~
+
+distclean: clean
+ rm -f $(YNLTOOL)
+
+bindir ?= /usr/bin
+
+install: $(YNLTOOL)
+ $(INSTALL) -m 0755 $(YNLTOOL) $(DESTDIR)$(bindir)/$(YNLTOOL)
+
+.PHONY: all clean distclean
+.DEFAULT_GOAL=all
diff --git a/tools/net/ynl/ynltool/json_writer.c b/tools/net/ynl/ynltool/json_writer.c
new file mode 100644
index 000000000000..c8685e592cd3
--- /dev/null
+++ b/tools/net/ynl/ynltool/json_writer.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
+/*
+ * Simple streaming JSON writer
+ *
+ * This takes care of the annoying bits of JSON syntax like the commas
+ * after elements
+ *
+ * Authors: Stephen Hemminger <stephen@networkplumber.org>
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include "json_writer.h"
+
+struct json_writer {
+ FILE *out;
+ unsigned depth;
+ bool pretty;
+ char sep;
+};
+
+static void jsonw_indent(json_writer_t *self)
+{
+ unsigned i;
+ for (i = 0; i < self->depth; ++i)
+ fputs(" ", self->out);
+}
+
+static void jsonw_eol(json_writer_t *self)
+{
+ if (!self->pretty)
+ return;
+
+ putc('\n', self->out);
+ jsonw_indent(self);
+}
+
+static void jsonw_eor(json_writer_t *self)
+{
+ if (self->sep != '\0')
+ putc(self->sep, self->out);
+ self->sep = ',';
+}
+
+static void jsonw_puts(json_writer_t *self, const char *str)
+{
+ putc('"', self->out);
+ for (; *str; ++str)
+ switch (*str) {
+ case '\t':
+ fputs("\\t", self->out);
+ break;
+ case '\n':
+ fputs("\\n", self->out);
+ break;
+ case '\r':
+ fputs("\\r", self->out);
+ break;
+ case '\f':
+ fputs("\\f", self->out);
+ break;
+ case '\b':
+ fputs("\\b", self->out);
+ break;
+ case '\\':
+ fputs("\\\\", self->out);
+ break;
+ case '"':
+ fputs("\\\"", self->out);
+ break;
+ default:
+ putc(*str, self->out);
+ }
+ putc('"', self->out);
+}
+
+json_writer_t *jsonw_new(FILE *f)
+{
+ json_writer_t *self = malloc(sizeof(*self));
+ if (self) {
+ self->out = f;
+ self->depth = 0;
+ self->pretty = false;
+ self->sep = '\0';
+ }
+ return self;
+}
+
+void jsonw_destroy(json_writer_t **self_p)
+{
+ json_writer_t *self = *self_p;
+
+ assert(self->depth == 0);
+ fputs("\n", self->out);
+ fflush(self->out);
+ free(self);
+ *self_p = NULL;
+}
+
+void jsonw_pretty(json_writer_t *self, bool on)
+{
+ self->pretty = on;
+}
+
+void jsonw_reset(json_writer_t *self)
+{
+ assert(self->depth == 0);
+ self->sep = '\0';
+}
+
+static void jsonw_begin(json_writer_t *self, int c)
+{
+ jsonw_eor(self);
+ putc(c, self->out);
+ ++self->depth;
+ self->sep = '\0';
+}
+
+static void jsonw_end(json_writer_t *self, int c)
+{
+ assert(self->depth > 0);
+
+ --self->depth;
+ if (self->sep != '\0')
+ jsonw_eol(self);
+ putc(c, self->out);
+ self->sep = ',';
+}
+
+void jsonw_name(json_writer_t *self, const char *name)
+{
+ jsonw_eor(self);
+ jsonw_eol(self);
+ self->sep = '\0';
+ jsonw_puts(self, name);
+ putc(':', self->out);
+ if (self->pretty)
+ putc(' ', self->out);
+}
+
+void jsonw_vprintf_enquote(json_writer_t *self, const char *fmt, va_list ap)
+{
+ jsonw_eor(self);
+ putc('"', self->out);
+ vfprintf(self->out, fmt, ap);
+ putc('"', self->out);
+}
+
+void jsonw_printf(json_writer_t *self, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ jsonw_eor(self);
+ vfprintf(self->out, fmt, ap);
+ va_end(ap);
+}
+
+void jsonw_start_object(json_writer_t *self)
+{
+ jsonw_begin(self, '{');
+}
+
+void jsonw_end_object(json_writer_t *self)
+{
+ jsonw_end(self, '}');
+}
+
+void jsonw_start_array(json_writer_t *self)
+{
+ jsonw_begin(self, '[');
+}
+
+void jsonw_end_array(json_writer_t *self)
+{
+ jsonw_end(self, ']');
+}
+
+void jsonw_string(json_writer_t *self, const char *value)
+{
+ jsonw_eor(self);
+ jsonw_puts(self, value);
+}
+
+void jsonw_bool(json_writer_t *self, bool val)
+{
+ jsonw_printf(self, "%s", val ? "true" : "false");
+}
+
+void jsonw_null(json_writer_t *self)
+{
+ jsonw_printf(self, "null");
+}
+
+void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num)
+{
+ jsonw_printf(self, fmt, num);
+}
+
+void jsonw_float(json_writer_t *self, double num)
+{
+ jsonw_printf(self, "%g", num);
+}
+
+void jsonw_hu(json_writer_t *self, unsigned short num)
+{
+ jsonw_printf(self, "%hu", num);
+}
+
+void jsonw_uint(json_writer_t *self, uint64_t num)
+{
+ jsonw_printf(self, "%"PRIu64, num);
+}
+
+void jsonw_lluint(json_writer_t *self, unsigned long long int num)
+{
+ jsonw_printf(self, "%llu", num);
+}
+
+void jsonw_int(json_writer_t *self, int64_t num)
+{
+ jsonw_printf(self, "%"PRId64, num);
+}
+
+void jsonw_string_field(json_writer_t *self, const char *prop, const char *val)
+{
+ jsonw_name(self, prop);
+ jsonw_string(self, val);
+}
+
+void jsonw_bool_field(json_writer_t *self, const char *prop, bool val)
+{
+ jsonw_name(self, prop);
+ jsonw_bool(self, val);
+}
+
+void jsonw_float_field(json_writer_t *self, const char *prop, double val)
+{
+ jsonw_name(self, prop);
+ jsonw_float(self, val);
+}
+
+void jsonw_float_field_fmt(json_writer_t *self,
+ const char *prop,
+ const char *fmt,
+ double val)
+{
+ jsonw_name(self, prop);
+ jsonw_float_fmt(self, fmt, val);
+}
+
+void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num)
+{
+ jsonw_name(self, prop);
+ jsonw_uint(self, num);
+}
+
+void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num)
+{
+ jsonw_name(self, prop);
+ jsonw_hu(self, num);
+}
+
+void jsonw_lluint_field(json_writer_t *self,
+ const char *prop,
+ unsigned long long int num)
+{
+ jsonw_name(self, prop);
+ jsonw_lluint(self, num);
+}
+
+void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num)
+{
+ jsonw_name(self, prop);
+ jsonw_int(self, num);
+}
+
+void jsonw_null_field(json_writer_t *self, const char *prop)
+{
+ jsonw_name(self, prop);
+ jsonw_null(self);
+}
diff --git a/tools/net/ynl/ynltool/json_writer.h b/tools/net/ynl/ynltool/json_writer.h
new file mode 100644
index 000000000000..0f1e63c88f6a
--- /dev/null
+++ b/tools/net/ynl/ynltool/json_writer.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Simple streaming JSON writer
+ *
+ * This takes care of the annoying bits of JSON syntax like the commas
+ * after elements
+ *
+ * Authors: Stephen Hemminger <stephen@networkplumber.org>
+ */
+
+#ifndef _JSON_WRITER_H_
+#define _JSON_WRITER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/* Opaque class structure */
+typedef struct json_writer json_writer_t;
+
+/* Create a new JSON stream */
+json_writer_t *jsonw_new(FILE *f);
+/* End output to JSON stream */
+void jsonw_destroy(json_writer_t **self_p);
+
+/* Cause output to have pretty whitespace */
+void jsonw_pretty(json_writer_t *self, bool on);
+
+/* Reset separator to create new JSON */
+void jsonw_reset(json_writer_t *self);
+
+/* Add property name */
+void jsonw_name(json_writer_t *self, const char *name);
+
+/* Add value */
+void __attribute__((format(printf, 2, 0))) jsonw_vprintf_enquote(json_writer_t *self,
+ const char *fmt,
+ va_list ap);
+void __attribute__((format(printf, 2, 3))) jsonw_printf(json_writer_t *self,
+ const char *fmt, ...);
+void jsonw_string(json_writer_t *self, const char *value);
+void jsonw_bool(json_writer_t *self, bool value);
+void jsonw_float(json_writer_t *self, double number);
+void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num);
+void jsonw_uint(json_writer_t *self, uint64_t number);
+void jsonw_hu(json_writer_t *self, unsigned short number);
+void jsonw_int(json_writer_t *self, int64_t number);
+void jsonw_null(json_writer_t *self);
+void jsonw_lluint(json_writer_t *self, unsigned long long int num);
+
+/* Useful Combinations of name and value */
+void jsonw_string_field(json_writer_t *self, const char *prop, const char *val);
+void jsonw_bool_field(json_writer_t *self, const char *prop, bool value);
+void jsonw_float_field(json_writer_t *self, const char *prop, double num);
+void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num);
+void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num);
+void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num);
+void jsonw_null_field(json_writer_t *self, const char *prop);
+void jsonw_lluint_field(json_writer_t *self, const char *prop,
+ unsigned long long int num);
+void jsonw_float_field_fmt(json_writer_t *self, const char *prop,
+ const char *fmt, double val);
+
+/* Collections */
+void jsonw_start_object(json_writer_t *self);
+void jsonw_end_object(json_writer_t *self);
+
+void jsonw_start_array(json_writer_t *self);
+void jsonw_end_array(json_writer_t *self);
+
+/* Override default exception handling */
+typedef void (jsonw_err_handler_fn)(const char *);
+
+#endif /* _JSON_WRITER_H_ */
diff --git a/tools/net/ynl/ynltool/main.c b/tools/net/ynl/ynltool/main.c
new file mode 100644
index 000000000000..5d0f428eed0a
--- /dev/null
+++ b/tools/net/ynl/ynltool/main.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
+/* Copyright Meta Platforms, Inc. and affiliates */
+
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "main.h"
+
+const char *bin_name;
+static int last_argc;
+static char **last_argv;
+static int (*last_do_help)(int argc, char **argv);
+json_writer_t *json_wtr;
+bool pretty_output;
+bool json_output;
+
+static void __attribute__((noreturn)) clean_and_exit(int i)
+{
+ if (json_output)
+ jsonw_destroy(&json_wtr);
+
+ exit(i);
+}
+
+void usage(void)
+{
+ last_do_help(last_argc - 1, last_argv + 1);
+
+ clean_and_exit(-1);
+}
+
+static int do_help(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)))
+{
+ if (json_output) {
+ jsonw_null(json_wtr);
+ return 0;
+ }
+
+ fprintf(stderr,
+ "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n"
+ " %s version\n"
+ "\n"
+ " OBJECT := { page-pool | qstats }\n"
+ " " HELP_SPEC_OPTIONS "\n"
+ "",
+ bin_name, bin_name);
+
+ return 0;
+}
+
+static int do_version(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)))
+{
+ if (json_output) {
+ jsonw_start_object(json_wtr);
+ jsonw_name(json_wtr, "version");
+ jsonw_printf(json_wtr, SRC_VERSION);
+ jsonw_end_object(json_wtr);
+ } else {
+ printf("%s " SRC_VERSION "\n", bin_name);
+ }
+ return 0;
+}
+
+static const struct cmd commands[] = {
+ { "help", do_help },
+ { "page-pool", do_page_pool },
+ { "qstats", do_qstats },
+ { "version", do_version },
+ { 0 }
+};
+
+int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int (*help)(int argc, char **argv))
+{
+ unsigned int i;
+
+ last_argc = argc;
+ last_argv = argv;
+ last_do_help = help;
+
+ if (argc < 1 && cmds[0].func)
+ return cmds[0].func(argc, argv);
+
+ for (i = 0; cmds[i].cmd; i++) {
+ if (is_prefix(*argv, cmds[i].cmd)) {
+ if (!cmds[i].func) {
+ p_err("command '%s' is not available", cmds[i].cmd);
+ return -1;
+ }
+ return cmds[i].func(argc - 1, argv + 1);
+ }
+ }
+
+ help(argc - 1, argv + 1);
+
+ return -1;
+}
+
+bool is_prefix(const char *pfx, const char *str)
+{
+ if (!pfx)
+ return false;
+ if (strlen(str) < strlen(pfx))
+ return false;
+
+ return !memcmp(str, pfx, strlen(pfx));
+}
+
+/* Last argument MUST be NULL pointer */
+int detect_common_prefix(const char *arg, ...)
+{
+ unsigned int count = 0;
+ const char *ref;
+ char msg[256];
+ va_list ap;
+
+ snprintf(msg, sizeof(msg), "ambiguous prefix: '%s' could be '", arg);
+ va_start(ap, arg);
+ while ((ref = va_arg(ap, const char *))) {
+ if (!is_prefix(arg, ref))
+ continue;
+ count++;
+ if (count > 1)
+ strncat(msg, "' or '", sizeof(msg) - strlen(msg) - 1);
+ strncat(msg, ref, sizeof(msg) - strlen(msg) - 1);
+ }
+ va_end(ap);
+ strncat(msg, "'", sizeof(msg) - strlen(msg) - 1);
+
+ if (count >= 2) {
+ p_err("%s", msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+void p_err(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (json_output) {
+ jsonw_start_object(json_wtr);
+ jsonw_name(json_wtr, "error");
+ jsonw_vprintf_enquote(json_wtr, fmt, ap);
+ jsonw_end_object(json_wtr);
+ } else {
+ fprintf(stderr, "Error: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ }
+ va_end(ap);
+}
+
+void p_info(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (json_output)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+int main(int argc, char **argv)
+{
+ static const struct option options[] = {
+ { "json", no_argument, NULL, 'j' },
+ { "help", no_argument, NULL, 'h' },
+ { "pretty", no_argument, NULL, 'p' },
+ { "version", no_argument, NULL, 'V' },
+ { 0 }
+ };
+ bool version_requested = false;
+ int opt, ret;
+
+ setlinebuf(stdout);
+
+ last_do_help = do_help;
+ pretty_output = false;
+ json_output = false;
+ bin_name = "ynltool";
+
+ opterr = 0;
+ while ((opt = getopt_long(argc, argv, "Vhjp",
+ options, NULL)) >= 0) {
+ switch (opt) {
+ case 'V':
+ version_requested = true;
+ break;
+ case 'h':
+ return do_help(argc, argv);
+ case 'p':
+ pretty_output = true;
+ /* fall through */
+ case 'j':
+ if (!json_output) {
+ json_wtr = jsonw_new(stdout);
+ if (!json_wtr) {
+ p_err("failed to create JSON writer");
+ return -1;
+ }
+ json_output = true;
+ }
+ jsonw_pretty(json_wtr, pretty_output);
+ break;
+ default:
+ p_err("unrecognized option '%s'", argv[optind - 1]);
+ if (json_output)
+ clean_and_exit(-1);
+ else
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 0)
+ usage();
+
+ if (version_requested)
+ ret = do_version(argc, argv);
+ else
+ ret = cmd_select(commands, argc, argv, do_help);
+
+ if (json_output)
+ jsonw_destroy(&json_wtr);
+
+ return ret;
+}
diff --git a/tools/net/ynl/ynltool/main.h b/tools/net/ynl/ynltool/main.h
new file mode 100644
index 000000000000..c7039f9ac55a
--- /dev/null
+++ b/tools/net/ynl/ynltool/main.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
+/* Copyright Meta Platforms, Inc. and affiliates */
+
+#ifndef __YNLTOOL_H
+#define __YNLTOOL_H
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "json_writer.h"
+
+#define NEXT_ARG() ({ argc--; argv++; if (argc < 0) usage(); })
+#define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); })
+#define BAD_ARG() ({ p_err("what is '%s'?", *argv); -1; })
+#define GET_ARG() ({ argc--; *argv++; })
+#define REQ_ARGS(cnt) \
+ ({ \
+ int _cnt = (cnt); \
+ bool _res; \
+ \
+ if (argc < _cnt) { \
+ p_err("'%s' needs at least %d arguments, %d found", \
+ argv[-1], _cnt, argc); \
+ _res = false; \
+ } else { \
+ _res = true; \
+ } \
+ _res; \
+ })
+
+#define HELP_SPEC_OPTIONS \
+ "OPTIONS := { {-j|--json} [{-p|--pretty}] }"
+
+extern const char *bin_name;
+
+extern json_writer_t *json_wtr;
+extern bool json_output;
+extern bool pretty_output;
+
+void __attribute__((format(printf, 1, 2))) p_err(const char *fmt, ...);
+void __attribute__((format(printf, 1, 2))) p_info(const char *fmt, ...);
+
+bool is_prefix(const char *pfx, const char *str);
+int detect_common_prefix(const char *arg, ...);
+void usage(void) __attribute__((noreturn));
+
+struct cmd {
+ const char *cmd;
+ int (*func)(int argc, char **argv);
+};
+
+int cmd_select(const struct cmd *cmds, int argc, char **argv,
+ int (*help)(int argc, char **argv));
+
+/* subcommands */
+int do_page_pool(int argc, char **argv);
+int do_qstats(int argc, char **argv);
+
+#endif /* __YNLTOOL_H */
diff --git a/tools/net/ynl/ynltool/page-pool.c b/tools/net/ynl/ynltool/page-pool.c
new file mode 100644
index 000000000000..4b24492abab7
--- /dev/null
+++ b/tools/net/ynl/ynltool/page-pool.c
@@ -0,0 +1,461 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <net/if.h>
+
+#include <ynl.h>
+#include "netdev-user.h"
+
+#include "main.h"
+
+struct pp_stat {
+ unsigned int ifc;
+
+ struct {
+ unsigned int cnt;
+ size_t refs, bytes;
+ } live[2];
+
+ size_t alloc_slow, alloc_fast, recycle_ring, recycle_cache;
+};
+
+struct pp_stats_array {
+ unsigned int i, max;
+ struct pp_stat *s;
+};
+
+static struct pp_stat *find_ifc(struct pp_stats_array *a, unsigned int ifindex)
+{
+ unsigned int i;
+
+ for (i = 0; i < a->i; i++) {
+ if (a->s[i].ifc == ifindex)
+ return &a->s[i];
+ }
+
+ a->i++;
+ if (a->i == a->max) {
+ a->max *= 2;
+ a->s = reallocarray(a->s, a->max, sizeof(*a->s));
+ }
+ a->s[i].ifc = ifindex;
+ return &a->s[i];
+}
+
+static void count_pool(struct pp_stat *s, unsigned int l,
+ struct netdev_page_pool_get_rsp *pp)
+{
+ s->live[l].cnt++;
+ if (pp->_present.inflight)
+ s->live[l].refs += pp->inflight;
+ if (pp->_present.inflight_mem)
+ s->live[l].bytes += pp->inflight_mem;
+}
+
+/* We don't know how many pages are sitting in cache and ring
+ * so we will under-count the recycling rate a bit.
+ */
+static void print_json_recycling_stats(struct pp_stat *s)
+{
+ double recycle;
+
+ if (s->alloc_fast + s->alloc_slow) {
+ recycle = (double)(s->recycle_ring + s->recycle_cache) /
+ (s->alloc_fast + s->alloc_slow) * 100;
+ jsonw_float_field(json_wtr, "recycling_pct", recycle);
+ }
+
+ jsonw_name(json_wtr, "alloc");
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "slow", s->alloc_slow);
+ jsonw_uint_field(json_wtr, "fast", s->alloc_fast);
+ jsonw_end_object(json_wtr);
+
+ jsonw_name(json_wtr, "recycle");
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "ring", s->recycle_ring);
+ jsonw_uint_field(json_wtr, "cache", s->recycle_cache);
+ jsonw_end_object(json_wtr);
+}
+
+static void print_plain_recycling_stats(struct pp_stat *s)
+{
+ double recycle;
+
+ if (s->alloc_fast + s->alloc_slow) {
+ recycle = (double)(s->recycle_ring + s->recycle_cache) /
+ (s->alloc_fast + s->alloc_slow) * 100;
+ printf("recycling: %.1lf%% (alloc: %zu:%zu recycle: %zu:%zu)",
+ recycle, s->alloc_slow, s->alloc_fast,
+ s->recycle_ring, s->recycle_cache);
+ }
+}
+
+static void print_json_stats(struct pp_stats_array *a)
+{
+ jsonw_start_array(json_wtr);
+
+ for (unsigned int i = 0; i < a->i; i++) {
+ char ifname[IF_NAMESIZE];
+ struct pp_stat *s = &a->s[i];
+ const char *name;
+
+ jsonw_start_object(json_wtr);
+
+ if (!s->ifc) {
+ jsonw_string_field(json_wtr, "ifname", "<orphan>");
+ jsonw_uint_field(json_wtr, "ifindex", 0);
+ } else {
+ name = if_indextoname(s->ifc, ifname);
+ if (name)
+ jsonw_string_field(json_wtr, "ifname", name);
+ jsonw_uint_field(json_wtr, "ifindex", s->ifc);
+ }
+
+ jsonw_uint_field(json_wtr, "page_pools", s->live[1].cnt);
+ jsonw_uint_field(json_wtr, "zombies", s->live[0].cnt);
+
+ jsonw_name(json_wtr, "live");
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "refs", s->live[1].refs);
+ jsonw_uint_field(json_wtr, "bytes", s->live[1].bytes);
+ jsonw_end_object(json_wtr);
+
+ jsonw_name(json_wtr, "zombie");
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "refs", s->live[0].refs);
+ jsonw_uint_field(json_wtr, "bytes", s->live[0].bytes);
+ jsonw_end_object(json_wtr);
+
+ if (s->alloc_fast || s->alloc_slow)
+ print_json_recycling_stats(s);
+
+ jsonw_end_object(json_wtr);
+ }
+
+ jsonw_end_array(json_wtr);
+}
+
+static void print_plain_stats(struct pp_stats_array *a)
+{
+ for (unsigned int i = 0; i < a->i; i++) {
+ char ifname[IF_NAMESIZE];
+ struct pp_stat *s = &a->s[i];
+ const char *name;
+
+ if (!s->ifc) {
+ printf("<orphan>\t");
+ } else {
+ name = if_indextoname(s->ifc, ifname);
+ if (name)
+ printf("%8s", name);
+ printf("[%u]\t", s->ifc);
+ }
+
+ printf("page pools: %u (zombies: %u)\n",
+ s->live[1].cnt, s->live[0].cnt);
+ printf("\t\trefs: %zu bytes: %zu (refs: %zu bytes: %zu)\n",
+ s->live[1].refs, s->live[1].bytes,
+ s->live[0].refs, s->live[0].bytes);
+
+ if (s->alloc_fast || s->alloc_slow) {
+ printf("\t\t");
+ print_plain_recycling_stats(s);
+ printf("\n");
+ }
+ }
+}
+
+static bool
+find_pool_stat_in_list(struct netdev_page_pool_stats_get_list *pp_stats,
+ __u64 pool_id, struct pp_stat *pstat)
+{
+ ynl_dump_foreach(pp_stats, pp) {
+ if (!pp->_present.info || !pp->info._present.id)
+ continue;
+ if (pp->info.id != pool_id)
+ continue;
+
+ memset(pstat, 0, sizeof(*pstat));
+ if (pp->_present.alloc_fast)
+ pstat->alloc_fast = pp->alloc_fast;
+ if (pp->_present.alloc_refill)
+ pstat->alloc_fast += pp->alloc_refill;
+ if (pp->_present.alloc_slow)
+ pstat->alloc_slow = pp->alloc_slow;
+ if (pp->_present.recycle_ring)
+ pstat->recycle_ring = pp->recycle_ring;
+ if (pp->_present.recycle_cached)
+ pstat->recycle_cache = pp->recycle_cached;
+ return true;
+ }
+ return false;
+}
+
+static void
+print_json_pool_list(struct netdev_page_pool_get_list *pools,
+ struct netdev_page_pool_stats_get_list *pp_stats,
+ bool zombies_only)
+{
+ jsonw_start_array(json_wtr);
+
+ ynl_dump_foreach(pools, pp) {
+ char ifname[IF_NAMESIZE];
+ struct pp_stat pstat;
+ const char *name;
+
+ if (zombies_only && !pp->_present.detach_time)
+ continue;
+
+ jsonw_start_object(json_wtr);
+
+ jsonw_uint_field(json_wtr, "id", pp->id);
+
+ if (pp->_present.ifindex) {
+ name = if_indextoname(pp->ifindex, ifname);
+ if (name)
+ jsonw_string_field(json_wtr, "ifname", name);
+ jsonw_uint_field(json_wtr, "ifindex", pp->ifindex);
+ }
+
+ if (pp->_present.napi_id)
+ jsonw_uint_field(json_wtr, "napi_id", pp->napi_id);
+
+ if (pp->_present.inflight)
+ jsonw_uint_field(json_wtr, "refs", pp->inflight);
+
+ if (pp->_present.inflight_mem)
+ jsonw_uint_field(json_wtr, "bytes", pp->inflight_mem);
+
+ if (pp->_present.detach_time)
+ jsonw_uint_field(json_wtr, "detach_time", pp->detach_time);
+
+ if (pp->_present.dmabuf)
+ jsonw_uint_field(json_wtr, "dmabuf", pp->dmabuf);
+
+ if (find_pool_stat_in_list(pp_stats, pp->id, &pstat) &&
+ (pstat.alloc_fast || pstat.alloc_slow))
+ print_json_recycling_stats(&pstat);
+
+ jsonw_end_object(json_wtr);
+ }
+
+ jsonw_end_array(json_wtr);
+}
+
+static void
+print_plain_pool_list(struct netdev_page_pool_get_list *pools,
+ struct netdev_page_pool_stats_get_list *pp_stats,
+ bool zombies_only)
+{
+ ynl_dump_foreach(pools, pp) {
+ char ifname[IF_NAMESIZE];
+ struct pp_stat pstat;
+ const char *name;
+
+ if (zombies_only && !pp->_present.detach_time)
+ continue;
+
+ printf("pool id: %llu", pp->id);
+
+ if (pp->_present.ifindex) {
+ name = if_indextoname(pp->ifindex, ifname);
+ if (name)
+ printf(" dev: %s", name);
+ printf("[%u]", pp->ifindex);
+ }
+
+ if (pp->_present.napi_id)
+ printf(" napi: %llu", pp->napi_id);
+
+ printf("\n");
+
+ if (pp->_present.inflight || pp->_present.inflight_mem) {
+ printf(" inflight:");
+ if (pp->_present.inflight)
+ printf(" %llu pages", pp->inflight);
+ if (pp->_present.inflight_mem)
+ printf(" %llu bytes", pp->inflight_mem);
+ printf("\n");
+ }
+
+ if (pp->_present.detach_time)
+ printf(" detached: %llu\n", pp->detach_time);
+
+ if (pp->_present.dmabuf)
+ printf(" dmabuf: %u\n", pp->dmabuf);
+
+ if (find_pool_stat_in_list(pp_stats, pp->id, &pstat) &&
+ (pstat.alloc_fast || pstat.alloc_slow)) {
+ printf(" ");
+ print_plain_recycling_stats(&pstat);
+ printf("\n");
+ }
+ }
+}
+
+static void aggregate_device_stats(struct pp_stats_array *a,
+ struct netdev_page_pool_get_list *pools,
+ struct netdev_page_pool_stats_get_list *pp_stats)
+{
+ ynl_dump_foreach(pools, pp) {
+ struct pp_stat *s = find_ifc(a, pp->ifindex);
+
+ count_pool(s, 1, pp);
+ if (pp->_present.detach_time)
+ count_pool(s, 0, pp);
+ }
+
+ ynl_dump_foreach(pp_stats, pp) {
+ struct pp_stat *s = find_ifc(a, pp->info.ifindex);
+
+ if (pp->_present.alloc_fast)
+ s->alloc_fast += pp->alloc_fast;
+ if (pp->_present.alloc_refill)
+ s->alloc_fast += pp->alloc_refill;
+ if (pp->_present.alloc_slow)
+ s->alloc_slow += pp->alloc_slow;
+ if (pp->_present.recycle_ring)
+ s->recycle_ring += pp->recycle_ring;
+ if (pp->_present.recycle_cached)
+ s->recycle_cache += pp->recycle_cached;
+ }
+}
+
+static int do_stats(int argc, char **argv)
+{
+ struct netdev_page_pool_stats_get_list *pp_stats;
+ struct netdev_page_pool_get_list *pools;
+ enum {
+ GROUP_BY_DEVICE,
+ GROUP_BY_POOL,
+ } group_by = GROUP_BY_DEVICE;
+ bool zombies_only = false;
+ struct pp_stats_array a = {};
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ int ret = 0;
+
+ /* Parse options */
+ while (argc > 0) {
+ if (is_prefix(*argv, "group-by")) {
+ NEXT_ARG();
+
+ if (!REQ_ARGS(1))
+ return -1;
+
+ if (is_prefix(*argv, "device")) {
+ group_by = GROUP_BY_DEVICE;
+ } else if (is_prefix(*argv, "pp") ||
+ is_prefix(*argv, "page-pool") ||
+ is_prefix(*argv, "none")) {
+ group_by = GROUP_BY_POOL;
+ } else {
+ p_err("invalid group-by value '%s'", *argv);
+ return -1;
+ }
+ NEXT_ARG();
+ } else if (is_prefix(*argv, "zombies")) {
+ zombies_only = true;
+ group_by = GROUP_BY_POOL;
+ NEXT_ARG();
+ } else {
+ p_err("unknown option '%s'", *argv);
+ return -1;
+ }
+ }
+
+ ys = ynl_sock_create(&ynl_netdev_family, &yerr);
+ if (!ys) {
+ p_err("YNL: %s", yerr.msg);
+ return -1;
+ }
+
+ pools = netdev_page_pool_get_dump(ys);
+ if (!pools) {
+ p_err("failed to get page pools: %s", ys->err.msg);
+ ret = -1;
+ goto exit_close;
+ }
+
+ pp_stats = netdev_page_pool_stats_get_dump(ys);
+ if (!pp_stats) {
+ p_err("failed to get page pool stats: %s", ys->err.msg);
+ ret = -1;
+ goto exit_free_pp_list;
+ }
+
+ /* If grouping by pool, print individual pools */
+ if (group_by == GROUP_BY_POOL) {
+ if (json_output)
+ print_json_pool_list(pools, pp_stats, zombies_only);
+ else
+ print_plain_pool_list(pools, pp_stats, zombies_only);
+ } else {
+ /* Aggregated stats mode (group-by device) */
+ a.max = 64;
+ a.s = calloc(a.max, sizeof(*a.s));
+ if (!a.s) {
+ p_err("failed to allocate stats array");
+ ret = -1;
+ goto exit_free_stats_list;
+ }
+
+ aggregate_device_stats(&a, pools, pp_stats);
+
+ if (json_output)
+ print_json_stats(&a);
+ else
+ print_plain_stats(&a);
+
+ free(a.s);
+ }
+
+exit_free_stats_list:
+ netdev_page_pool_stats_get_list_free(pp_stats);
+exit_free_pp_list:
+ netdev_page_pool_get_list_free(pools);
+exit_close:
+ ynl_sock_destroy(ys);
+ return ret;
+}
+
+static int do_help(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)))
+{
+ if (json_output) {
+ jsonw_null(json_wtr);
+ return 0;
+ }
+
+ fprintf(stderr,
+ "Usage: %s page-pool { COMMAND | help }\n"
+ " %s page-pool stats [ OPTIONS ]\n"
+ "\n"
+ " OPTIONS := { group-by { device | page-pool | none } | zombies }\n"
+ "\n"
+ " stats - Display page pool statistics\n"
+ " stats group-by device - Group statistics by network device (default)\n"
+ " stats group-by page-pool | pp | none\n"
+ " - Show individual page pool details (no grouping)\n"
+ " stats zombies - Show only zombie page pools (detached but with\n"
+ " pages in flight). Implies group-by page-pool.\n"
+ "",
+ bin_name, bin_name);
+
+ return 0;
+}
+
+static const struct cmd page_pool_cmds[] = {
+ { "help", do_help },
+ { "stats", do_stats },
+ { 0 }
+};
+
+int do_page_pool(int argc, char **argv)
+{
+ return cmd_select(page_pool_cmds, argc, argv, do_help);
+}
diff --git a/tools/net/ynl/ynltool/qstats.c b/tools/net/ynl/ynltool/qstats.c
new file mode 100644
index 000000000000..31fb45709ffa
--- /dev/null
+++ b/tools/net/ynl/ynltool/qstats.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <net/if.h>
+#include <math.h>
+
+#include <ynl.h>
+#include "netdev-user.h"
+
+#include "main.h"
+
+static enum netdev_qstats_scope scope; /* default - device */
+
+struct queue_balance {
+ unsigned int ifindex;
+ enum netdev_queue_type type;
+ unsigned int queue_count;
+ __u64 *rx_packets;
+ __u64 *rx_bytes;
+ __u64 *tx_packets;
+ __u64 *tx_bytes;
+};
+
+static void print_json_qstats(struct netdev_qstats_get_list *qstats)
+{
+ jsonw_start_array(json_wtr);
+
+ ynl_dump_foreach(qstats, qs) {
+ char ifname[IF_NAMESIZE];
+ const char *name;
+
+ jsonw_start_object(json_wtr);
+
+ name = if_indextoname(qs->ifindex, ifname);
+ if (name)
+ jsonw_string_field(json_wtr, "ifname", name);
+ jsonw_uint_field(json_wtr, "ifindex", qs->ifindex);
+
+ if (qs->_present.queue_type)
+ jsonw_string_field(json_wtr, "queue-type",
+ netdev_queue_type_str(qs->queue_type));
+ if (qs->_present.queue_id)
+ jsonw_uint_field(json_wtr, "queue-id", qs->queue_id);
+
+ if (qs->_present.rx_packets || qs->_present.rx_bytes ||
+ qs->_present.rx_alloc_fail || qs->_present.rx_hw_drops ||
+ qs->_present.rx_csum_complete || qs->_present.rx_hw_gro_packets) {
+ jsonw_name(json_wtr, "rx");
+ jsonw_start_object(json_wtr);
+ if (qs->_present.rx_packets)
+ jsonw_uint_field(json_wtr, "packets", qs->rx_packets);
+ if (qs->_present.rx_bytes)
+ jsonw_uint_field(json_wtr, "bytes", qs->rx_bytes);
+ if (qs->_present.rx_alloc_fail)
+ jsonw_uint_field(json_wtr, "alloc-fail", qs->rx_alloc_fail);
+ if (qs->_present.rx_hw_drops)
+ jsonw_uint_field(json_wtr, "hw-drops", qs->rx_hw_drops);
+ if (qs->_present.rx_hw_drop_overruns)
+ jsonw_uint_field(json_wtr, "hw-drop-overruns", qs->rx_hw_drop_overruns);
+ if (qs->_present.rx_hw_drop_ratelimits)
+ jsonw_uint_field(json_wtr, "hw-drop-ratelimits", qs->rx_hw_drop_ratelimits);
+ if (qs->_present.rx_csum_complete)
+ jsonw_uint_field(json_wtr, "csum-complete", qs->rx_csum_complete);
+ if (qs->_present.rx_csum_unnecessary)
+ jsonw_uint_field(json_wtr, "csum-unnecessary", qs->rx_csum_unnecessary);
+ if (qs->_present.rx_csum_none)
+ jsonw_uint_field(json_wtr, "csum-none", qs->rx_csum_none);
+ if (qs->_present.rx_csum_bad)
+ jsonw_uint_field(json_wtr, "csum-bad", qs->rx_csum_bad);
+ if (qs->_present.rx_hw_gro_packets)
+ jsonw_uint_field(json_wtr, "hw-gro-packets", qs->rx_hw_gro_packets);
+ if (qs->_present.rx_hw_gro_bytes)
+ jsonw_uint_field(json_wtr, "hw-gro-bytes", qs->rx_hw_gro_bytes);
+ if (qs->_present.rx_hw_gro_wire_packets)
+ jsonw_uint_field(json_wtr, "hw-gro-wire-packets", qs->rx_hw_gro_wire_packets);
+ if (qs->_present.rx_hw_gro_wire_bytes)
+ jsonw_uint_field(json_wtr, "hw-gro-wire-bytes", qs->rx_hw_gro_wire_bytes);
+ jsonw_end_object(json_wtr);
+ }
+
+ if (qs->_present.tx_packets || qs->_present.tx_bytes ||
+ qs->_present.tx_hw_drops || qs->_present.tx_csum_none ||
+ qs->_present.tx_hw_gso_packets) {
+ jsonw_name(json_wtr, "tx");
+ jsonw_start_object(json_wtr);
+ if (qs->_present.tx_packets)
+ jsonw_uint_field(json_wtr, "packets", qs->tx_packets);
+ if (qs->_present.tx_bytes)
+ jsonw_uint_field(json_wtr, "bytes", qs->tx_bytes);
+ if (qs->_present.tx_hw_drops)
+ jsonw_uint_field(json_wtr, "hw-drops", qs->tx_hw_drops);
+ if (qs->_present.tx_hw_drop_errors)
+ jsonw_uint_field(json_wtr, "hw-drop-errors", qs->tx_hw_drop_errors);
+ if (qs->_present.tx_hw_drop_ratelimits)
+ jsonw_uint_field(json_wtr, "hw-drop-ratelimits", qs->tx_hw_drop_ratelimits);
+ if (qs->_present.tx_csum_none)
+ jsonw_uint_field(json_wtr, "csum-none", qs->tx_csum_none);
+ if (qs->_present.tx_needs_csum)
+ jsonw_uint_field(json_wtr, "needs-csum", qs->tx_needs_csum);
+ if (qs->_present.tx_hw_gso_packets)
+ jsonw_uint_field(json_wtr, "hw-gso-packets", qs->tx_hw_gso_packets);
+ if (qs->_present.tx_hw_gso_bytes)
+ jsonw_uint_field(json_wtr, "hw-gso-bytes", qs->tx_hw_gso_bytes);
+ if (qs->_present.tx_hw_gso_wire_packets)
+ jsonw_uint_field(json_wtr, "hw-gso-wire-packets", qs->tx_hw_gso_wire_packets);
+ if (qs->_present.tx_hw_gso_wire_bytes)
+ jsonw_uint_field(json_wtr, "hw-gso-wire-bytes", qs->tx_hw_gso_wire_bytes);
+ if (qs->_present.tx_stop)
+ jsonw_uint_field(json_wtr, "stop", qs->tx_stop);
+ if (qs->_present.tx_wake)
+ jsonw_uint_field(json_wtr, "wake", qs->tx_wake);
+ jsonw_end_object(json_wtr);
+ }
+
+ jsonw_end_object(json_wtr);
+ }
+
+ jsonw_end_array(json_wtr);
+}
+
+static void print_one(bool present, const char *name, unsigned long long val,
+ int *line)
+{
+ if (!present)
+ return;
+
+ if (!*line) {
+ printf(" ");
+ ++(*line);
+ }
+
+ /* Don't waste space on tx- and rx- prefix, its implied by queue type */
+ if (scope == NETDEV_QSTATS_SCOPE_QUEUE &&
+ (name[0] == 'r' || name[0] == 't') &&
+ name[1] == 'x' && name[2] == '-')
+ name += 3;
+
+ printf(" %15s: %15llu", name, val);
+
+ if (++(*line) == 3) {
+ printf("\n");
+ *line = 0;
+ }
+}
+
+static void print_plain_qstats(struct netdev_qstats_get_list *qstats)
+{
+ ynl_dump_foreach(qstats, qs) {
+ char ifname[IF_NAMESIZE];
+ const char *name;
+ int n;
+
+ name = if_indextoname(qs->ifindex, ifname);
+ if (name)
+ printf("%s", name);
+ else
+ printf("ifindex:%u", qs->ifindex);
+
+ if (qs->_present.queue_type && qs->_present.queue_id)
+ printf("\t%s-%-3u",
+ netdev_queue_type_str(qs->queue_type),
+ qs->queue_id);
+ else
+ printf("\t ");
+
+ n = 1;
+
+ /* Basic counters */
+ print_one(qs->_present.rx_packets, "rx-packets", qs->rx_packets, &n);
+ print_one(qs->_present.rx_bytes, "rx-bytes", qs->rx_bytes, &n);
+ print_one(qs->_present.tx_packets, "tx-packets", qs->tx_packets, &n);
+ print_one(qs->_present.tx_bytes, "tx-bytes", qs->tx_bytes, &n);
+
+ /* RX error/drop counters */
+ print_one(qs->_present.rx_alloc_fail, "rx-alloc-fail",
+ qs->rx_alloc_fail, &n);
+ print_one(qs->_present.rx_hw_drops, "rx-hw-drops",
+ qs->rx_hw_drops, &n);
+ print_one(qs->_present.rx_hw_drop_overruns, "rx-hw-drop-overruns",
+ qs->rx_hw_drop_overruns, &n);
+ print_one(qs->_present.rx_hw_drop_ratelimits, "rx-hw-drop-ratelimits",
+ qs->rx_hw_drop_ratelimits, &n);
+
+ /* RX checksum counters */
+ print_one(qs->_present.rx_csum_complete, "rx-csum-complete",
+ qs->rx_csum_complete, &n);
+ print_one(qs->_present.rx_csum_unnecessary, "rx-csum-unnecessary",
+ qs->rx_csum_unnecessary, &n);
+ print_one(qs->_present.rx_csum_none, "rx-csum-none",
+ qs->rx_csum_none, &n);
+ print_one(qs->_present.rx_csum_bad, "rx-csum-bad",
+ qs->rx_csum_bad, &n);
+
+ /* RX GRO counters */
+ print_one(qs->_present.rx_hw_gro_packets, "rx-hw-gro-packets",
+ qs->rx_hw_gro_packets, &n);
+ print_one(qs->_present.rx_hw_gro_bytes, "rx-hw-gro-bytes",
+ qs->rx_hw_gro_bytes, &n);
+ print_one(qs->_present.rx_hw_gro_wire_packets, "rx-hw-gro-wire-packets",
+ qs->rx_hw_gro_wire_packets, &n);
+ print_one(qs->_present.rx_hw_gro_wire_bytes, "rx-hw-gro-wire-bytes",
+ qs->rx_hw_gro_wire_bytes, &n);
+
+ /* TX error/drop counters */
+ print_one(qs->_present.tx_hw_drops, "tx-hw-drops",
+ qs->tx_hw_drops, &n);
+ print_one(qs->_present.tx_hw_drop_errors, "tx-hw-drop-errors",
+ qs->tx_hw_drop_errors, &n);
+ print_one(qs->_present.tx_hw_drop_ratelimits, "tx-hw-drop-ratelimits",
+ qs->tx_hw_drop_ratelimits, &n);
+
+ /* TX checksum counters */
+ print_one(qs->_present.tx_csum_none, "tx-csum-none",
+ qs->tx_csum_none, &n);
+ print_one(qs->_present.tx_needs_csum, "tx-needs-csum",
+ qs->tx_needs_csum, &n);
+
+ /* TX GSO counters */
+ print_one(qs->_present.tx_hw_gso_packets, "tx-hw-gso-packets",
+ qs->tx_hw_gso_packets, &n);
+ print_one(qs->_present.tx_hw_gso_bytes, "tx-hw-gso-bytes",
+ qs->tx_hw_gso_bytes, &n);
+ print_one(qs->_present.tx_hw_gso_wire_packets, "tx-hw-gso-wire-packets",
+ qs->tx_hw_gso_wire_packets, &n);
+ print_one(qs->_present.tx_hw_gso_wire_bytes, "tx-hw-gso-wire-bytes",
+ qs->tx_hw_gso_wire_bytes, &n);
+
+ /* TX queue control */
+ print_one(qs->_present.tx_stop, "tx-stop", qs->tx_stop, &n);
+ print_one(qs->_present.tx_wake, "tx-wake", qs->tx_wake, &n);
+
+ if (n)
+ printf("\n");
+ }
+}
+
+static int do_show(int argc, char **argv)
+{
+ struct netdev_qstats_get_list *qstats;
+ struct netdev_qstats_get_req *req;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ int ret = 0;
+
+ /* Parse options */
+ while (argc > 0) {
+ if (is_prefix(*argv, "scope") || is_prefix(*argv, "group-by")) {
+ NEXT_ARG();
+
+ if (!REQ_ARGS(1))
+ return -1;
+
+ if (is_prefix(*argv, "queue")) {
+ scope = NETDEV_QSTATS_SCOPE_QUEUE;
+ } else if (is_prefix(*argv, "device")) {
+ scope = 0;
+ } else {
+ p_err("invalid scope value '%s'", *argv);
+ return -1;
+ }
+ NEXT_ARG();
+ } else {
+ p_err("unknown option '%s'", *argv);
+ return -1;
+ }
+ }
+
+ ys = ynl_sock_create(&ynl_netdev_family, &yerr);
+ if (!ys) {
+ p_err("YNL: %s", yerr.msg);
+ return -1;
+ }
+
+ req = netdev_qstats_get_req_alloc();
+ if (!req) {
+ p_err("failed to allocate qstats request");
+ ret = -1;
+ goto exit_close;
+ }
+
+ if (scope)
+ netdev_qstats_get_req_set_scope(req, scope);
+
+ qstats = netdev_qstats_get_dump(ys, req);
+ netdev_qstats_get_req_free(req);
+ if (!qstats) {
+ p_err("failed to get queue stats: %s", ys->err.msg);
+ ret = -1;
+ goto exit_close;
+ }
+
+ /* Print the stats as returned by the kernel */
+ if (json_output)
+ print_json_qstats(qstats);
+ else
+ print_plain_qstats(qstats);
+
+ netdev_qstats_get_list_free(qstats);
+exit_close:
+ ynl_sock_destroy(ys);
+ return ret;
+}
+
+static void compute_stats(__u64 *values, unsigned int count,
+ double *mean, double *stddev, __u64 *min, __u64 *max)
+{
+ double sum = 0.0, variance = 0.0;
+ unsigned int i;
+
+ *min = ~0ULL;
+ *max = 0;
+
+ if (count == 0) {
+ *mean = 0;
+ *stddev = 0;
+ *min = 0;
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ sum += values[i];
+ if (values[i] < *min)
+ *min = values[i];
+ if (values[i] > *max)
+ *max = values[i];
+ }
+
+ *mean = sum / count;
+
+ if (count > 1) {
+ for (i = 0; i < count; i++) {
+ double diff = values[i] - *mean;
+
+ variance += diff * diff;
+ }
+ *stddev = sqrt(variance / (count - 1));
+ } else {
+ *stddev = 0;
+ }
+}
+
+static void print_balance_stats(const char *name, enum netdev_queue_type type,
+ __u64 *values, unsigned int count)
+{
+ double mean, stddev, cv, ns;
+ __u64 min, max;
+
+ if ((name[0] == 'r' && type != NETDEV_QUEUE_TYPE_RX) ||
+ (name[0] == 't' && type != NETDEV_QUEUE_TYPE_TX))
+ return;
+
+ compute_stats(values, count, &mean, &stddev, &min, &max);
+
+ cv = mean > 0 ? (stddev / mean) * 100.0 : 0.0;
+ ns = min + max > 0 ? (double)2 * (max - min) / (max + min) * 100 : 0.0;
+
+ printf(" %-12s: cv=%.1f%% ns=%.1f%% stddev=%.0f\n",
+ name, cv, ns, stddev);
+ printf(" %-12s min=%llu max=%llu mean=%.0f\n",
+ "", min, max, mean);
+}
+
+static void
+print_balance_stats_json(const char *name, enum netdev_queue_type type,
+ __u64 *values, unsigned int count)
+{
+ double mean, stddev, cv, ns;
+ __u64 min, max;
+
+ if ((name[0] == 'r' && type != NETDEV_QUEUE_TYPE_RX) ||
+ (name[0] == 't' && type != NETDEV_QUEUE_TYPE_TX))
+ return;
+
+ compute_stats(values, count, &mean, &stddev, &min, &max);
+
+ cv = mean > 0 ? (stddev / mean) * 100.0 : 0.0;
+ ns = min + max > 0 ? (double)2 * (max - min) / (max + min) * 100 : 0.0;
+
+ jsonw_name(json_wtr, name);
+ jsonw_start_object(json_wtr);
+ jsonw_uint_field(json_wtr, "queue-count", count);
+ jsonw_uint_field(json_wtr, "min", min);
+ jsonw_uint_field(json_wtr, "max", max);
+ jsonw_float_field(json_wtr, "mean", mean);
+ jsonw_float_field(json_wtr, "stddev", stddev);
+ jsonw_float_field(json_wtr, "coefficient-of-variation", cv);
+ jsonw_float_field(json_wtr, "normalized-spread", ns);
+ jsonw_end_object(json_wtr);
+}
+
+static int cmp_ifindex_type(const void *a, const void *b)
+{
+ const struct netdev_qstats_get_rsp *qa = a;
+ const struct netdev_qstats_get_rsp *qb = b;
+
+ if (qa->ifindex != qb->ifindex)
+ return qa->ifindex - qb->ifindex;
+ if (qa->queue_type != qb->queue_type)
+ return qa->queue_type - qb->queue_type;
+ return qa->queue_id - qb->queue_id;
+}
+
+static int do_balance(int argc, char **argv __attribute__((unused)))
+{
+ struct netdev_qstats_get_list *qstats;
+ struct netdev_qstats_get_req *req;
+ struct netdev_qstats_get_rsp **sorted;
+ struct ynl_error yerr;
+ struct ynl_sock *ys;
+ unsigned int count = 0;
+ unsigned int i, j;
+ int ret = 0;
+
+ if (argc > 0) {
+ p_err("balance command takes no arguments");
+ return -1;
+ }
+
+ ys = ynl_sock_create(&ynl_netdev_family, &yerr);
+ if (!ys) {
+ p_err("YNL: %s", yerr.msg);
+ return -1;
+ }
+
+ req = netdev_qstats_get_req_alloc();
+ if (!req) {
+ p_err("failed to allocate qstats request");
+ ret = -1;
+ goto exit_close;
+ }
+
+ /* Always use queue scope for balance analysis */
+ netdev_qstats_get_req_set_scope(req, NETDEV_QSTATS_SCOPE_QUEUE);
+
+ qstats = netdev_qstats_get_dump(ys, req);
+ netdev_qstats_get_req_free(req);
+ if (!qstats) {
+ p_err("failed to get queue stats: %s", ys->err.msg);
+ ret = -1;
+ goto exit_close;
+ }
+
+ /* Count and sort queues */
+ ynl_dump_foreach(qstats, qs)
+ count++;
+
+ if (count == 0) {
+ if (json_output)
+ jsonw_start_array(json_wtr);
+ else
+ printf("No queue statistics available\n");
+ goto exit_free_qstats;
+ }
+
+ sorted = calloc(count, sizeof(*sorted));
+ if (!sorted) {
+ p_err("failed to allocate sorted array");
+ ret = -1;
+ goto exit_free_qstats;
+ }
+
+ i = 0;
+ ynl_dump_foreach(qstats, qs)
+ sorted[i++] = qs;
+
+ qsort(sorted, count, sizeof(*sorted), cmp_ifindex_type);
+
+ if (json_output)
+ jsonw_start_array(json_wtr);
+
+ /* Process each device/queue-type combination */
+ i = 0;
+ while (i < count) {
+ __u64 *rx_packets, *rx_bytes, *tx_packets, *tx_bytes;
+ enum netdev_queue_type type = sorted[i]->queue_type;
+ unsigned int ifindex = sorted[i]->ifindex;
+ unsigned int queue_count = 0;
+ char ifname[IF_NAMESIZE];
+ const char *name;
+
+ /* Count queues for this device/type */
+ for (j = i; j < count && sorted[j]->ifindex == ifindex &&
+ sorted[j]->queue_type == type; j++)
+ queue_count++;
+
+ /* Skip if no packets/bytes (inactive queues) */
+ if (!sorted[i]->_present.rx_packets &&
+ !sorted[i]->_present.rx_bytes &&
+ !sorted[i]->_present.tx_packets &&
+ !sorted[i]->_present.tx_bytes)
+ goto next_ifc;
+
+ /* Allocate arrays for statistics */
+ rx_packets = calloc(queue_count, sizeof(*rx_packets));
+ rx_bytes = calloc(queue_count, sizeof(*rx_bytes));
+ tx_packets = calloc(queue_count, sizeof(*tx_packets));
+ tx_bytes = calloc(queue_count, sizeof(*tx_bytes));
+
+ if (!rx_packets || !rx_bytes || !tx_packets || !tx_bytes) {
+ p_err("failed to allocate statistics arrays");
+ free(rx_packets);
+ free(rx_bytes);
+ free(tx_packets);
+ free(tx_bytes);
+ ret = -1;
+ goto exit_free_sorted;
+ }
+
+ /* Collect statistics */
+ for (j = 0; j < queue_count; j++) {
+ rx_packets[j] = sorted[i + j]->_present.rx_packets ?
+ sorted[i + j]->rx_packets : 0;
+ rx_bytes[j] = sorted[i + j]->_present.rx_bytes ?
+ sorted[i + j]->rx_bytes : 0;
+ tx_packets[j] = sorted[i + j]->_present.tx_packets ?
+ sorted[i + j]->tx_packets : 0;
+ tx_bytes[j] = sorted[i + j]->_present.tx_bytes ?
+ sorted[i + j]->tx_bytes : 0;
+ }
+
+ name = if_indextoname(ifindex, ifname);
+
+ if (json_output) {
+ jsonw_start_object(json_wtr);
+ if (name)
+ jsonw_string_field(json_wtr, "ifname", name);
+ jsonw_uint_field(json_wtr, "ifindex", ifindex);
+ jsonw_string_field(json_wtr, "queue-type",
+ netdev_queue_type_str(type));
+
+ print_balance_stats_json("rx-packets", type,
+ rx_packets, queue_count);
+ print_balance_stats_json("rx-bytes", type,
+ rx_bytes, queue_count);
+ print_balance_stats_json("tx-packets", type,
+ tx_packets, queue_count);
+ print_balance_stats_json("tx-bytes", type,
+ tx_bytes, queue_count);
+
+ jsonw_end_object(json_wtr);
+ } else {
+ if (name)
+ printf("%s", name);
+ else
+ printf("ifindex:%u", ifindex);
+ printf(" %s %d queues:\n",
+ netdev_queue_type_str(type), queue_count);
+
+ print_balance_stats("rx-packets", type,
+ rx_packets, queue_count);
+ print_balance_stats("rx-bytes", type,
+ rx_bytes, queue_count);
+ print_balance_stats("tx-packets", type,
+ tx_packets, queue_count);
+ print_balance_stats("tx-bytes", type,
+ tx_bytes, queue_count);
+ printf("\n");
+ }
+
+ free(rx_packets);
+ free(rx_bytes);
+ free(tx_packets);
+ free(tx_bytes);
+
+next_ifc:
+ i += queue_count;
+ }
+
+ if (json_output)
+ jsonw_end_array(json_wtr);
+
+exit_free_sorted:
+ free(sorted);
+exit_free_qstats:
+ netdev_qstats_get_list_free(qstats);
+exit_close:
+ ynl_sock_destroy(ys);
+ return ret;
+}
+
+static int do_help(int argc __attribute__((unused)),
+ char **argv __attribute__((unused)))
+{
+ if (json_output) {
+ jsonw_null(json_wtr);
+ return 0;
+ }
+
+ fprintf(stderr,
+ "Usage: %s qstats { COMMAND | help }\n"
+ " %s qstats [ show ] [ OPTIONS ]\n"
+ " %s qstats balance\n"
+ "\n"
+ " OPTIONS := { scope queue | group-by { device | queue } }\n"
+ "\n"
+ " show - Display queue statistics (default)\n"
+ " Statistics are aggregated for the entire device.\n"
+ " show scope queue - Display per-queue statistics\n"
+ " show group-by device - Display device-aggregated statistics (default)\n"
+ " show group-by queue - Display per-queue statistics\n"
+ " balance - Analyze traffic distribution balance.\n"
+ "",
+ bin_name, bin_name, bin_name);
+
+ return 0;
+}
+
+static const struct cmd qstats_cmds[] = {
+ { "show", do_show },
+ { "balance", do_balance },
+ { "help", do_help },
+ { 0 }
+};
+
+int do_qstats(int argc, char **argv)
+{
+ return cmd_select(qstats_cmds, argc, argv, do_help);
+}