[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250814164413.1258893-1-sdf@fomichev.me>
Date: Thu, 14 Aug 2025 09:44:13 -0700
From: Stanislav Fomichev <sdf@...ichev.me>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com,
donald.hunter@...il.com,
horms@...nel.org,
jstancek@...hat.com,
sdf@...ichev.me,
jacob.e.keller@...el.com,
linux-kernel@...r.kernel.org
Subject: [PATCH net-next] tools: ynl: make ynl.c more c++ friendly
Compiling ynl.c in a C++ code base requires invoking C compiler and
using extern "C" for the headers. To make it easier, we can add
small changes to the ynl.c file to make it palatable to the native
C++ compiler. The changes are:
- avoid using void* pointer arithmetic, use char* instead
- avoid implicit void* type casts, add c-style explicit casts
- avoid implicit int->enum type casts, add c-style explicit casts
- avoid anonymous structs (for type casts)
- namespacify cpp version, this should let us compile both ynl.c
as c and ynl.c as cpp in the same binary (YNL_CPP can be used
to enable/disable namespacing)
Also add test_cpp rule to make sure ynl.c won't break C++ in the future.
Signed-off-by: Stanislav Fomichev <sdf@...ichev.me>
---
tools/net/ynl/lib/Makefile | 5 +++-
tools/net/ynl/lib/ynl-priv.h | 11 ++++++-
tools/net/ynl/lib/ynl.c | 58 +++++++++++++++++++++---------------
tools/net/ynl/lib/ynl.h | 19 +++++++++---
4 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/tools/net/ynl/lib/Makefile b/tools/net/ynl/lib/Makefile
index 4b2b98704ff9..94f8dc4a31d1 100644
--- a/tools/net/ynl/lib/Makefile
+++ b/tools/net/ynl/lib/Makefile
@@ -11,7 +11,7 @@ OBJS=$(patsubst %.c,%.o,${SRCS})
include $(wildcard *.d)
-all: ynl.a
+all: ynl.a test_cpp
ynl.a: $(OBJS)
@echo -e "\tAR $@"
@@ -23,6 +23,9 @@ ynl.a: $(OBJS)
distclean: clean
rm -f *.a
+test_cpp: ynl.c
+ $(COMPILE.cpp) -DYNL_CPP -o ynl.cc.o $<
+
%.o: %.c
$(COMPILE.c) -MMD -c -o $@ $<
diff --git a/tools/net/ynl/lib/ynl-priv.h b/tools/net/ynl/lib/ynl-priv.h
index 824777d7e05e..1dbb14e760e6 100644
--- a/tools/net/ynl/lib/ynl-priv.h
+++ b/tools/net/ynl/lib/ynl-priv.h
@@ -6,6 +6,10 @@
#include <stddef.h>
#include <linux/types.h>
+#if defined(__cplusplus) && defined(YNL_CPP)
+namespace ynl_cpp {
+#endif
+
struct ynl_parse_arg;
/*
@@ -224,7 +228,7 @@ static inline void *ynl_attr_data_end(const struct nlattr *attr)
#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))
+ (attr) = ynl_attr_next((char *)start + len, attr))
static inline struct nlattr *
ynl_attr_if_good(const void *end, struct nlattr *attr)
@@ -467,4 +471,9 @@ ynl_attr_put_sint(struct nlmsghdr *nlh, __u16 type, __s64 data)
else
ynl_attr_put_s64(nlh, type, data);
}
+
+#if defined(__cplusplus) && defined(YNL_CPP)
+} // namespace ynl_cpp
+#endif
+
#endif
diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c
index 2a169c3c0797..9155b4d5b9f9 100644
--- a/tools/net/ynl/lib/ynl.c
+++ b/tools/net/ynl/lib/ynl.c
@@ -11,6 +11,10 @@
#include "ynl.h"
+#if defined(__cplusplus) && defined(YNL_CPP)
+namespace ynl_cpp {
+#endif
+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*arr))
#define __yerr_msg(yse, _msg...) \
@@ -23,13 +27,13 @@
} \
})
-#define __yerr_code(yse, _code...) \
- ({ \
- struct ynl_error *_yse = (yse); \
- \
- if (_yse) { \
- _yse->code = _code; \
- } \
+#define __yerr_code(yse, _code...) \
+ ({ \
+ struct ynl_error *_yse = (yse); \
+ \
+ if (_yse) { \
+ _yse->code = (enum ynl_error_code)_code; \
+ } \
})
#define __yerr(yse, _code, _msg...) \
@@ -149,7 +153,7 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
return n;
}
- data_len = end - start;
+ data_len = (char *)end - (char *)start;
ynl_attr_for_each_payload(start, data_len, attr) {
astart_off = (char *)attr - (char *)start;
@@ -192,7 +196,7 @@ ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
off -= sizeof(struct nlattr);
start = ynl_attr_data(attr);
- end = start + ynl_attr_data_len(attr);
+ end = (char *)start + ynl_attr_data_len(attr);
return n + ynl_err_walk(ys, start, end, off, next_pol,
&str[n], str_sz - n, nest_pol);
@@ -325,12 +329,12 @@ ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
static int
ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
+ const struct nlmsgerr *err = (struct nlmsgerr *)ynl_nlmsg_data(nlh);
unsigned int hlen;
int code;
code = err->error >= 0 ? err->error : -err->error;
- yarg->ys->err.code = code;
+ yarg->ys->err.code = (enum ynl_error_code)code;
errno = code;
hlen = sizeof(*err);
@@ -348,7 +352,7 @@ static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
err = *(int *)NLMSG_DATA(nlh);
if (err < 0) {
- yarg->ys->err.code = -err;
+ yarg->ys->err.code = (enum ynl_error_code)-err;
errno = -err;
ynl_ext_ack_check(yarg->ys, nlh, sizeof(int));
@@ -366,7 +370,7 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
unsigned int type, len;
unsigned char *data;
- data = ynl_attr_data(attr);
+ data = (unsigned char *)ynl_attr_data(attr);
len = ynl_attr_data_len(attr);
type = ynl_attr_type(attr);
if (type > yarg->rsp_policy->max_attr) {
@@ -463,7 +467,7 @@ int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
static void ynl_err_reset(struct ynl_sock *ys)
{
- ys->err.code = 0;
+ ys->err.code = YNL_ERROR_NONE;
ys->err.attr_offs = 0;
ys->err.msg[0] = 0;
}
@@ -643,8 +647,8 @@ ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
if (!ys->n_mcast_groups)
return 0;
- ys->mcast_groups = calloc(ys->n_mcast_groups,
- sizeof(*ys->mcast_groups));
+ ys->mcast_groups = (struct ynl_sock_mcast *)calloc(
+ ys->n_mcast_groups, sizeof(*ys->mcast_groups));
if (!ys->mcast_groups)
return YNL_PARSE_CB_ERROR;
@@ -741,7 +745,8 @@ ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
int sock_type;
int one = 1;
- ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE);
+ ys = (struct ynl_sock *)malloc(sizeof(*ys) +
+ 2 * YNL_SOCKET_BUFFER_SIZE);
if (!ys)
return NULL;
memset(ys, 0, sizeof(*ys));
@@ -878,7 +883,7 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
} else {
struct genlmsghdr *gehdr;
- gehdr = ynl_nlmsg_data(nlh);
+ gehdr = (struct genlmsghdr *)ynl_nlmsg_data(nlh);
cmd = gehdr->cmd;
}
@@ -888,7 +893,7 @@ static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
if (!info->cb)
return YNL_PARSE_CB_ERROR;
- rsp = calloc(1, info->alloc_sz);
+ rsp = (struct ynl_ntf_base_type *)calloc(1, info->alloc_sz);
rsp->free = info->free;
yarg.data = rsp->data;
yarg.rsp_policy = info->policy;
@@ -933,7 +938,8 @@ int ynl_ntf_check(struct ynl_sock *ys)
/* YNL specific helpers used by the auto-generated code */
-struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123);
+struct ynl_dump_list_type *YNL_LIST_END =
+ (struct ynl_dump_list_type *)(void *)(0xb4d123);
void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd)
{
@@ -962,7 +968,7 @@ ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
return -1;
}
- gehdr = ynl_nlmsg_data(nlh);
+ gehdr = (struct genlmsghdr *)ynl_nlmsg_data(nlh);
if (gehdr->cmd != rsp_cmd)
return ynl_ntf_parse(ys, nlh);
}
@@ -973,7 +979,7 @@ ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
static
int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
{
- struct ynl_req_state *yrs = (void *)yarg;
+ struct ynl_req_state *yrs = (struct ynl_req_state *)yarg;
int ret;
ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd);
@@ -1006,7 +1012,7 @@ int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
static int
ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
{
- struct ynl_dump_state *ds = (void *)data;
+ struct ynl_dump_state *ds = (struct ynl_dump_state *)data;
struct ynl_dump_list_type *obj;
struct ynl_parse_arg yarg = {};
int ret;
@@ -1015,7 +1021,7 @@ ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
if (ret)
return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
- obj = calloc(1, ds->alloc_sz);
+ obj = (struct ynl_dump_list_type *)calloc(1, ds->alloc_sz);
if (!obj)
return YNL_PARSE_CB_ERROR;
@@ -1066,3 +1072,7 @@ int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
yds->first = ynl_dump_end(yds);
return -1;
}
+
+#if defined(__cplusplus) && defined(YNL_CPP)
+} // namespace ynl_cpp
+#endif
diff --git a/tools/net/ynl/lib/ynl.h b/tools/net/ynl/lib/ynl.h
index db7c0591a63f..47a8652f056f 100644
--- a/tools/net/ynl/lib/ynl.h
+++ b/tools/net/ynl/lib/ynl.h
@@ -9,6 +9,10 @@
#include "ynl-priv.h"
+#if defined(__cplusplus) && defined(YNL_CPP)
+namespace ynl_cpp {
+#endif
+
enum ynl_error_code {
YNL_ERROR_NONE = 0,
__YNL_ERRNO_END = 4096,
@@ -56,6 +60,11 @@ struct ynl_family {
unsigned int ntf_info_size;
};
+struct ynl_sock_mcast {
+ unsigned int id;
+ char name[GENL_NAMSIZ];
+};
+
/**
* struct ynl_sock - YNL wrapped netlink socket
* @err: YNL error descriptor, cleared on every request.
@@ -71,10 +80,7 @@ struct ynl_sock {
__u16 family_id;
unsigned int n_mcast_groups;
- struct {
- unsigned int id;
- char name[GENL_NAMSIZ];
- } *mcast_groups;
+ struct ynl_sock_mcast *mcast_groups;
struct ynl_ntf_base_type *ntf_first;
struct ynl_ntf_base_type **ntf_last_next;
@@ -140,4 +146,9 @@ 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);
+
+#if defined(__cplusplus) && defined(YNL_CPP)
+} // namespace ynl_cpp
+#endif
+
#endif
--
2.50.1
Powered by blists - more mailing lists