Skip to content

Commit

Permalink
Merge branch 'netcons-add-udp-send-fail-statistics-to-netconsole'
Browse files Browse the repository at this point in the history
Maksym Kutsevol says:

====================
netcons: Add udp send fail statistics to netconsole

Enhance observability of netconsole. Packet sends can fail.
Start tracking at least two failure possibilities: ENOMEM and
NET_XMIT_DROP for every target. Stats are exposed via an additional
attribute in CONFIGFS.

The exposed statistics allows easier debugging of cases when netconsole
messages were not seen by receivers, eliminating the guesswork if the
sender thinks that messages in question were sent out.

Stats are not reset on enable/disable/change remote ip/etc, they
belong to the netcons target itself.
====================

Link: https://patch.msgid.link/20241202-netcons-add-udp-send-fail-statistics-to-netconsole-v5-0-70e82239f922@kutsevol.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Dec 5, 2024
2 parents a9ab02e + 36de47b commit a108177
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 9 deletions.
5 changes: 3 additions & 2 deletions Documentation/networking/netconsole.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ To remove a target::

The interface exposes these parameters of a netconsole target to userspace:

============== ================================= ============
=============== ================================= ============
enabled Is this target currently enabled? (read-write)
extended Extended mode enabled (read-write)
release Prepend kernel release to message (read-write)
Expand All @@ -135,7 +135,8 @@ The interface exposes these parameters of a netconsole target to userspace:
remote_ip Remote agent's IP address (read-write)
local_mac Local interface's MAC address (read-only)
remote_mac Remote agent's MAC address (read-write)
============== ================================= ============
transmit_errors Number of packet send errors (read-only)
=============== ================================= ============

The "enabled" attribute is also used to control whether the parameters of
a target can be updated or not -- you can modify the parameters of only
Expand Down
60 changes: 57 additions & 3 deletions drivers/net/netconsole.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/inet.h>
#include <linux/configfs.h>
#include <linux/etherdevice.h>
#include <linux/u64_stats_sync.h>
#include <linux/utsname.h>
#include <linux/rtnetlink.h>

Expand Down Expand Up @@ -90,13 +91,20 @@ static DEFINE_MUTEX(target_cleanup_list_lock);
*/
static struct console netconsole_ext;

struct netconsole_target_stats {
u64_stats_t xmit_drop_count;
u64_stats_t enomem_count;
struct u64_stats_sync syncp;
};

/**
* struct netconsole_target - Represents a configured netconsole target.
* @list: Links this target into the target_list.
* @group: Links us into the configfs subsystem hierarchy.
* @userdata_group: Links to the userdata configfs hierarchy
* @userdata_complete: Cached, formatted string of append
* @userdata_length: String length of userdata_complete
* @stats: Packet send stats for the target. Used for debugging.
* @enabled: On / off knob to enable / disable target.
* Visible from userspace (read-write).
* We maintain a strict 1:1 correspondence between this and
Expand Down Expand Up @@ -124,6 +132,7 @@ struct netconsole_target {
char userdata_complete[MAX_USERDATA_ENTRY_LENGTH * MAX_USERDATA_ITEMS];
size_t userdata_length;
#endif
struct netconsole_target_stats stats;
bool enabled;
bool extended;
bool release;
Expand Down Expand Up @@ -262,6 +271,7 @@ static void netconsole_process_cleanups_core(void)
* | remote_ip
* | local_mac
* | remote_mac
* | transmit_errors
* | userdata/
* | <key>/
* | value
Expand Down Expand Up @@ -371,6 +381,21 @@ static ssize_t remote_mac_show(struct config_item *item, char *buf)
return sysfs_emit(buf, "%pM\n", to_target(item)->np.remote_mac);
}

static ssize_t transmit_errors_show(struct config_item *item, char *buf)
{
struct netconsole_target *nt = to_target(item);
u64 xmit_drop_count, enomem_count;
unsigned int start;

do {
start = u64_stats_fetch_begin(&nt->stats.syncp);
xmit_drop_count = u64_stats_read(&nt->stats.xmit_drop_count);
enomem_count = u64_stats_read(&nt->stats.enomem_count);
} while (u64_stats_fetch_retry(&nt->stats.syncp, start));

return sysfs_emit(buf, "%llu\n", xmit_drop_count + enomem_count);
}

/*
* This one is special -- targets created through the configfs interface
* are not enabled (and the corresponding netpoll activated) by default.
Expand Down Expand Up @@ -842,6 +867,7 @@ CONFIGFS_ATTR(, remote_ip);
CONFIGFS_ATTR_RO(, local_mac);
CONFIGFS_ATTR(, remote_mac);
CONFIGFS_ATTR(, release);
CONFIGFS_ATTR_RO(, transmit_errors);

static struct configfs_attribute *netconsole_target_attrs[] = {
&attr_enabled,
Expand All @@ -854,6 +880,7 @@ static struct configfs_attribute *netconsole_target_attrs[] = {
&attr_remote_ip,
&attr_local_mac,
&attr_remote_mac,
&attr_transmit_errors,
NULL,
};

Expand Down Expand Up @@ -1058,6 +1085,33 @@ static struct notifier_block netconsole_netdev_notifier = {
.notifier_call = netconsole_netdev_event,
};

/**
* send_udp - Wrapper for netpoll_send_udp that counts errors
* @nt: target to send message to
* @msg: message to send
* @len: length of message
*
* Calls netpoll_send_udp and classifies the return value. If an error
* occurred it increments statistics in nt->stats accordingly.
* Only calls netpoll_send_udp if CONFIG_NETCONSOLE_DYNAMIC is disabled.
*/
static void send_udp(struct netconsole_target *nt, const char *msg, int len)
{
int result = netpoll_send_udp(&nt->np, msg, len);

if (IS_ENABLED(CONFIG_NETCONSOLE_DYNAMIC)) {
if (result == NET_XMIT_DROP) {
u64_stats_update_begin(&nt->stats.syncp);
u64_stats_inc(&nt->stats.xmit_drop_count);
u64_stats_update_end(&nt->stats.syncp);
} else if (result == -ENOMEM) {
u64_stats_update_begin(&nt->stats.syncp);
u64_stats_inc(&nt->stats.enomem_count);
u64_stats_update_end(&nt->stats.syncp);
}
}
}

static void send_msg_no_fragmentation(struct netconsole_target *nt,
const char *msg,
int msg_len,
Expand Down Expand Up @@ -1085,7 +1139,7 @@ static void send_msg_no_fragmentation(struct netconsole_target *nt,
MAX_PRINT_CHUNK - msg_len,
"%s", userdata);

netpoll_send_udp(&nt->np, buf, msg_len);
send_udp(nt, buf, msg_len);
}

static void append_release(char *buf)
Expand Down Expand Up @@ -1178,7 +1232,7 @@ static void send_fragmented_body(struct netconsole_target *nt, char *buf,
this_offset += this_chunk;
}

netpoll_send_udp(&nt->np, buf, this_header + this_offset);
send_udp(nt, buf, this_header + this_offset);
offset += this_offset;
}
}
Expand Down Expand Up @@ -1288,7 +1342,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
tmp = msg;
for (left = len; left;) {
frag = min(left, MAX_PRINT_CHUNK);
netpoll_send_udp(&nt->np, tmp, frag);
send_udp(nt, tmp, frag);
tmp += frag;
left -= frag;
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/netpoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static inline void netpoll_poll_disable(struct net_device *dev) { return; }
static inline void netpoll_poll_enable(struct net_device *dev) { return; }
#endif

void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
int netpoll_send_udp(struct netpoll *np, const char *msg, int len);
void netpoll_print_options(struct netpoll *np);
int netpoll_parse_options(struct netpoll *np, char *opt);
int __netpoll_setup(struct netpoll *np, struct net_device *ndev);
Expand Down
6 changes: 3 additions & 3 deletions net/core/netpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
}
EXPORT_SYMBOL(netpoll_send_skb);

void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, ip_len, udp_len;
struct sk_buff *skb;
Expand All @@ -414,7 +414,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
skb = find_skb(np, total_len + np->dev->needed_tailroom,
total_len - len);
if (!skb)
return;
return -ENOMEM;

skb_copy_to_linear_data(skb, msg, len);
skb_put(skb, len);
Expand Down Expand Up @@ -490,7 +490,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)

skb->dev = np->dev;

netpoll_send_skb(np, skb);
return (int)netpoll_send_skb(np, skb);
}
EXPORT_SYMBOL(netpoll_send_udp);

Expand Down

0 comments on commit a108177

Please sign in to comment.