forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
- Loading branch information
1 parent
45bb63e
commit 4b132aa
Showing
153 changed files
with
4,196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (c) 2024 Oracle and/or its affiliates. | ||
* | ||
* This header defines XDR data type primitives specified in | ||
* Section 4 of RFC 4506, used by RPC programs implemented | ||
* in the Linux kernel. | ||
*/ | ||
|
||
#ifndef _SUNRPC_XDRGEN__BUILTINS_H_ | ||
#define _SUNRPC_XDRGEN__BUILTINS_H_ | ||
|
||
#include <linux/sunrpc/xdr.h> | ||
|
||
static inline bool | ||
xdrgen_decode_void(struct xdr_stream *xdr) | ||
{ | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_void(struct xdr_stream *xdr) | ||
{ | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_bool(struct xdr_stream *xdr, bool *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = (*p != xdr_zero); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_bool(struct xdr_stream *xdr, bool val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*p = val ? xdr_one : xdr_zero; | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_int(struct xdr_stream *xdr, s32 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = be32_to_cpup(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_int(struct xdr_stream *xdr, s32 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*p = cpu_to_be32(val); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_unsigned_int(struct xdr_stream *xdr, u32 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = be32_to_cpup(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_unsigned_int(struct xdr_stream *xdr, u32 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*p = cpu_to_be32(val); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_long(struct xdr_stream *xdr, s32 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = be32_to_cpup(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_long(struct xdr_stream *xdr, s32 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*p = cpu_to_be32(val); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_unsigned_long(struct xdr_stream *xdr, u32 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = be32_to_cpup(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_unsigned_long(struct xdr_stream *xdr, u32 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*p = cpu_to_be32(val); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_hyper(struct xdr_stream *xdr, s64 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = get_unaligned_be64(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_hyper(struct xdr_stream *xdr, s64 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
put_unaligned_be64(val, p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_unsigned_hyper(struct xdr_stream *xdr, u64 *ptr) | ||
{ | ||
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
*ptr = get_unaligned_be64(p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_unsigned_hyper(struct xdr_stream *xdr, u64 val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
put_unaligned_be64(val, p); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_string(struct xdr_stream *xdr, string *ptr, u32 maxlen) | ||
{ | ||
__be32 *p; | ||
u32 len; | ||
|
||
if (unlikely(xdr_stream_decode_u32(xdr, &len) != XDR_UNIT)) | ||
return false; | ||
if (unlikely(maxlen && len > maxlen)) | ||
return false; | ||
if (len != 0) { | ||
p = xdr_inline_decode(xdr, len); | ||
if (unlikely(!p)) | ||
return false; | ||
ptr->data = (unsigned char *)p; | ||
} | ||
ptr->len = len; | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_string(struct xdr_stream *xdr, string val, u32 maxlen) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len)); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
xdr_encode_opaque(p, val.data, val.len); | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_decode_opaque(struct xdr_stream *xdr, opaque *ptr, u32 maxlen) | ||
{ | ||
__be32 *p; | ||
u32 len; | ||
|
||
if (unlikely(xdr_stream_decode_u32(xdr, &len) != XDR_UNIT)) | ||
return false; | ||
if (unlikely(maxlen && len > maxlen)) | ||
return false; | ||
if (len != 0) { | ||
p = xdr_inline_decode(xdr, len); | ||
if (unlikely(!p)) | ||
return false; | ||
ptr->data = (u8 *)p; | ||
} | ||
ptr->len = len; | ||
return true; | ||
} | ||
|
||
static inline bool | ||
xdrgen_encode_opaque(struct xdr_stream *xdr, opaque val) | ||
{ | ||
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len)); | ||
|
||
if (unlikely(!p)) | ||
return false; | ||
xdr_encode_opaque(p, val.data, val.len); | ||
return true; | ||
} | ||
|
||
#endif /* _SUNRPC_XDRGEN__BUILTINS_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
/* | ||
* Copyright (c) 2024 Oracle and/or its affiliates. | ||
* | ||
* This header defines XDR data type primitives specified in | ||
* Section 4 of RFC 4506, used by RPC programs implemented | ||
* in the Linux kernel. | ||
*/ | ||
|
||
#ifndef _SUNRPC_XDRGEN__DEFS_H_ | ||
#define _SUNRPC_XDRGEN__DEFS_H_ | ||
|
||
#define TRUE (true) | ||
#define FALSE (false) | ||
|
||
typedef struct { | ||
u32 len; | ||
unsigned char *data; | ||
} string; | ||
|
||
typedef struct { | ||
u32 len; | ||
u8 *data; | ||
} opaque; | ||
|
||
#endif /* _SUNRPC_XDRGEN__DEFS_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
__pycache__ | ||
generators/__pycache__ |
Oops, something went wrong.