Commit Graph

31 Commits

Author SHA1 Message Date
Chuck Lever
573954a996 xdrgen: Remove program_stat_to_errno() call sites
Refactor: Translating an on-the-wire value to a local host errno is
architecturally a job for the proc function, not the XDR decoder.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-18 20:23:07 -05:00
Chuck Lever
903a7d37d9 xdrgen: Update the files included in client-side source code
In particular, client-side source code needs the definition of
"struct rpc_procinfo" and does not want header files that pull
in "struct svc_rqst". Otherwise, the source does not compile.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-18 20:23:06 -05:00
Chuck Lever
82c2a36179 xdrgen: Remove check for "nfs_ok" in C templates
Obviously, "nfs_ok" is defined only for NFS protocols. Other XDR
protocols won't know "nfs_ok" from Adam.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-18 20:23:06 -05:00
Chuck Lever
07decac0ac xdrgen: Remove tracepoint call site
This tracepoint was a "note to self" and is not operational. It is
added only to client-side code, which so far we haven't needed. It
will cause immediate breakage once we start generating client code,
though, so remove it now.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-18 20:23:06 -05:00
Chuck Lever
a32442f6ca xdrgen: Add a utility for extracting XDR from RFCs
For convenience, copy the XDR extraction script from RFC

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-18 20:22:59 -05:00
Chuck Lever
ac159338d5 xdrgen: emit maxsize macros
Add "definitions" subcommand logic to emit maxsize macros in
generated code.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:06 -05:00
Chuck Lever
e9e1e7e75a xdrgen: Add generator code for XDR width macros
Introduce logic in the code generators to emit maxsize (XDR
width) definitions. In C, these are pre-processor macros.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:05 -05:00
Chuck Lever
ce5a75d993 xdrgen: XDR width for union types
Not yet complete.

The tool doesn't do any math yet. Thus, even though the maximum XDR
width of a union is the width of the union enumerator plus the width
of its largest arm, we're using the sum of all the elements of the
union for the moment.

This means that buffer size requirements are overestimated, and that
the generated maxsize macro cannot yet be used for determining data
element alignment in the XDR buffer.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:05 -05:00
Chuck Lever
447dc1efeb xdrgen: XDR width for pointer types
The XDR width of a pointer type is the sum of the widths of each of
the struct's fields, except for the last field. The width of the
implicit boolean "value follows" field is added as well.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:05 -05:00
Chuck Lever
f4bc1e996a xdrgen: XDR width for struct types
The XDR width of a struct type is the sum of the widths of each of
the struct's fields.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:04 -05:00
Chuck Lever
2852c92ba1 xdrgen: XDR width for typedef
The XDR width of a typedef is the same as the width of the base type.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:04 -05:00
Chuck Lever
dc6fa83b6a xdrgen: XDR width for optional_data type
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:04 -05:00
Chuck Lever
2db8940e6c xdrgen: XDR width for variable-length array
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:03 -05:00
Chuck Lever
59b01b9636 xdrgen: XDR width for fixed-length array
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:03 -05:00
Chuck Lever
da298d0113 xdrgen: XDR width for a string
A string works like a variable-length opaque. See Section 4.11 of
RFC 4506.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:03 -05:00
Chuck Lever
b0b85ef754 xdrgen: XDR width for variable-length opaque
The byte size of a variable-length opaque is conveyed in an unsigned
integer. If there is a specified maximum size, that is included in
the type's widths list.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:02 -05:00
Chuck Lever
16c98ce04a xdrgen: XDR width for fixed-length opaque
The XDR width for a fixed-length opaque is the byte size of the
opaque rounded up to the next XDR_UNIT, divided by XDR_UNIT.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:02 -05:00
Chuck Lever
3f890755c8 xdrgen: XDR widths for enum types
RFC 4506 says that an XDR enum is represented as a signed integer
on the wire; thus its width is 1 XDR_UNIT.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:02 -05:00
Chuck Lever
631c2925ba xdrgen: Keep track of on-the-wire data type widths
The generic parts of the RPC layer need to know the widths (in
XDR_UNIT increments) of the XDR data types defined for each
protocol.

As a first step, add dictionaries to keep track of the symbolic and
actual maximum XDR width of XDR types.

This makes it straightforward to look up the width of a type by its
name. The built-in dictionaries are pre-loaded with the widths of
the built-in XDR types as defined in RFC 4506.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:01 -05:00
Chuck Lever
189f55d93d xdrgen: Track constant values
In order to compute the numeric on-the-wire width of XDR types,
xdrgen needs to keep track of the numeric value of constants that
are defined in the input specification so it can perform
calculations with those values.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:01 -05:00
Chuck Lever
1acd13cbc7 xdrgen: Refactor transformer arms
Clean up: Add a __post_init__ function to the data classes that
need to update the "structs" and "pass_by_reference" sets.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:00 -05:00
Chuck Lever
b376d519bd xdrgen: Implement big-endian enums
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:00 -05:00
Chuck Lever
6e853dcd2d xdrgen: Rename "enum yada" types as just "yada"
This simplifies the generated C code and makes way for supporting
big-endian XDR enums.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:42:00 -05:00
Chuck Lever
c060f8168b xdrgen: Rename enum's declaration Jinja2 template
"close.j2" is a confusing name.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:41:59 -05:00
Chuck Lever
041962d5c6 xdrgen: Rename "variable-length strings"
I misread RFC 4506. The built-in data type is called simply
"string", as there is no fixed-length variety.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:41:59 -05:00
Chuck Lever
5383ccd0cc xdrgen: Clean up type_specifier
Clean up: Make both arms of the type_specifier AST transformer
match. No behavior change is expected.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:41:59 -05:00
Chuck Lever
d86fca3aff xdrgen: Exit status should be zero on success
To use xdrgen in Makefiles, it needs to exit with a zero status if
the compilation worked. Otherwise the make command fails with an
error.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-11-11 13:41:58 -05:00
Chuck Lever
509abfc7a0 xdrgen: Prevent reordering of encoder and decoder functions
I noticed that "xdrgen source" reorders the procedure encoder and
decoder functions every time it is run. I would prefer that the
generated code be more deterministic: it enables a reader to better
see exactly what has changed between runs of the tool.

The problem is that Python sets are not ordered. I use a Python set
to ensure that, when multiple procedures use a particular argument or
result type, the encoder/decoder for that type is emitted only once.

Sets aren't ordered, but I can use Python dictionaries for this
purpose to ensure the procedure functions are always emitted in the
same order if the .x file does not change.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-09-20 19:31:41 -04:00
Chuck Lever
fed8a17c61 xdrgen: typedefs should use the built-in string and opaque functions
'typedef opaque yada<XYZ>' should use xdrgen's built-in opaque
encoder and decoder, to enable better compiler optimization.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-09-20 19:31:40 -04:00
Chuck Lever
663ad8b1df xdrgen: Fix return code checking in built-in XDR decoders
xdr_stream_encode_u32() returns XDR_UNIT on success.
xdr_stream_decode_u32() returns zero or -EMSGSIZE, but never
XDR_UNIT.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-09-20 19:31:39 -04:00
Chuck Lever
4b132aacb0 tools: Add xdrgen
Add a Python-based tool for translating XDR specifications into XDR
encoder and decoder functions written in the Linux kernel's C coding
style. The generator attempts to match the usual C coding style of
the Linux kernel's SunRPC consumers.

This approach is similar to the netlink code generator in
tools/net/ynl .

The maintainability benefits of machine-generated XDR code include:

- Stronger type checking
- Reduces the number of bugs introduced by human error
- Makes the XDR code easier to audit and analyze
- Enables rapid prototyping of new RPC-based protocols
- Hardens the layering between protocol logic and marshaling
- Makes it easier to add observability on demand
- Unit tests might be built for both the tool and (automatically)
  for the generated code

In addition, converting the XDR layer to use memory-safe languages
such as Rust will be easier if much of the code can be converted
automatically.

Tested-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
2024-09-20 19:31:39 -04:00