Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netlink: add tracepoint at NL_SET_ERR_MSG

Often userspace won't request the extack information, or they don't log it
because of log level or so, and even when they do, sometimes it's not
enough to know exactly what caused the error.

Netlink extack is the standard way of reporting erros with descriptive
error messages. With a trace point on it, we then can know exactly where
the error happened, regardless of userspace app. Also, we can even see if
the err msg was overwritten.

The wrapper do_trace_netlink_extack() is because trace points shouldn't be
called from .h files, as trace points are not that small, and the function
call to do_trace_netlink_extack() on the macros is not protected by
tracepoint_enabled() because the macros are called from modules, and this
would require exporting some trace structs. As this is error path, it's
better to export just the wrapper instead.

v2: removed leftover tracepoint declaration

Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/4546b63e67b2989789d146498b13cc09e1fdc543.1612403190.git.marcelo.leitner@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Marcelo Ricardo Leitner and committed by
Jakub Kicinski
7e3ce05e e93fac3b

+43
+6
include/linux/netlink.h
··· 11 11 12 12 struct net; 13 13 14 + void do_trace_netlink_extack(const char *msg); 15 + 14 16 static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb) 15 17 { 16 18 return (struct nlmsghdr *)skb->data; ··· 92 90 static const char __msg[] = msg; \ 93 91 struct netlink_ext_ack *__extack = (extack); \ 94 92 \ 93 + do_trace_netlink_extack(__msg); \ 94 + \ 95 95 if (__extack) \ 96 96 __extack->_msg = __msg; \ 97 97 } while (0) ··· 113 109 #define NL_SET_ERR_MSG_ATTR_POL(extack, attr, pol, msg) do { \ 114 110 static const char __msg[] = msg; \ 115 111 struct netlink_ext_ack *__extack = (extack); \ 112 + \ 113 + do_trace_netlink_extack(__msg); \ 116 114 \ 117 115 if (__extack) { \ 118 116 __extack->_msg = __msg; \
+29
include/trace/events/netlink.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM netlink 3 + 4 + #if !defined(_TRACE_NETLINK_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_NETLINK_H 6 + 7 + #include <linux/tracepoint.h> 8 + 9 + TRACE_EVENT(netlink_extack, 10 + 11 + TP_PROTO(const char *msg), 12 + 13 + TP_ARGS(msg), 14 + 15 + TP_STRUCT__entry( 16 + __string( msg, msg ) 17 + ), 18 + 19 + TP_fast_assign( 20 + __assign_str(msg, msg); 21 + ), 22 + 23 + TP_printk("msg=%s", __get_str(msg)) 24 + ); 25 + 26 + #endif /* _TRACE_NETLINK_H */ 27 + 28 + /* This part must be outside protection */ 29 + #include <trace/define_trace.h>
+8
net/netlink/af_netlink.c
··· 67 67 #include <net/sock.h> 68 68 #include <net/scm.h> 69 69 #include <net/netlink.h> 70 + #define CREATE_TRACE_POINTS 71 + #include <trace/events/netlink.h> 70 72 71 73 #include "af_netlink.h" 72 74 ··· 148 146 149 147 150 148 static const struct rhashtable_params netlink_rhashtable_params; 149 + 150 + void do_trace_netlink_extack(const char *msg) 151 + { 152 + trace_netlink_extack(msg); 153 + } 154 + EXPORT_SYMBOL(do_trace_netlink_extack); 151 155 152 156 static inline u32 netlink_group_mask(u32 group) 153 157 {