Restrict kernel udp bad checksum failure alarm information

Problem description

The dmesg information of a certain system has the following contents printed frequently, which flushes out other relevant information and needs to be limited.

UDP: bad checksum. From 10.66.245.93:61525 to 255.255.255.255:137 ulen 58

Related code

File name in kernel source tree:

net/ipv4/udp.c 

Relevant source code:

csum_error:
        /*
         * RFC1122: OK.  Discards the bad packet silently (as far as
         * the network is concerned, anyway) as per 4.1.3.4 (MUST).
         */
        net_dbg_ratelimited("UDP%s: bad checksum. From %pI4:%u to %pI4:%u ulen %d\n",
                            proto == IPPROTO_UDPLITE ? "Lite" : "",
                            &saddr, ntohs(uh->source), &daddr, ntohs(uh->dest),
                            ulen);

The function of this part is that the kernel fails to check the checksum of the message, discards the message and prints a warning. The reason for the problem may be that there is a problem with the network link, resulting in wrong packets.

Functionally speaking, this is an abnormal alarm. It is obviously unreasonable to close it directly, but the system always prints this information. In addition, dmesg uses a ring buffer, and some useful kernel print information will be flushed by this information. Therefore, it needs to be processed.

How to restrict printing?

As can be seen from the source code above, the kernel calls net_ dbg_ The ratelimited function prints the alarm information. Net_ dbg_ The ratelimited function itself has the function of speed limit, but this speed limit obviously does not meet our requirements. If we can increase the speed limit, we may be able to solve our problem.

From net_ dbg_ Implementation of ratelimited function

linux-5.x kernel code, net_ dbg_ The implementation code of ratelimited function is as follows:

#if defined(CONFIG_DYNAMIC_DEBUG) || \
	(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define net_dbg_ratelimited(fmt, ...)					\
do {									\
	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);			\
	if (DYNAMIC_DEBUG_BRANCH(descriptor) &&				\
	    net_ratelimit())						\
		__dynamic_pr_debug(&descriptor, pr_fmt(fmt),		\
		                   ##__VA_ARGS__);			\
} while (0)
#elif defined(DEBUG)
#define net_dbg_ratelimited(fmt, ...)				\
	net_ratelimited_function(pr_debug, fmt, ##__VA_ARGS__)
#else
#define net_dbg_ratelimited(fmt, ...)				\
	do {							\
		if (0)						\
			no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \
	} while (0)
#endif

Config is enabled in our system_ DYNAMIC_ Debug kernel configuration. Only the first case needs to be considered here. According to the code, the problem can be reduced to net_ In the ratelimit function.

net_ The source code of ratelimit function is as follows:

DEFINE_RATELIMIT_STATE(net_ratelimit_state, 5 * HZ, 10);
/*
 * All net warning printk()s should be guarded by this function.
 */
int net_ratelimit(void)
{
        return __ratelimit(&net_ratelimit_state);
}
EXPORT_SYMBOL(net_ratelimit);

net_ratelimit_state is the configurable interface exported from the kernel to the user state. It is in net_core_table ctl_table is defined as follows:

        {
                .procname       = "message_cost",
                .data           = &net_ratelimit_state.interval,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
        {
                .procname       = "message_burst",
                .data           = &net_ratelimit_state.burst,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },

We can modify net core. message_ Cost and net core. message_ Burst to complete the speed limit function.

Two ways to realize speed limit

Net has been described above_ dbg_ The main implementation of ratelimited. According to the kernel code, the speed limit can be configured in the following two ways:

  1. Use sysctl -w to set

    The relevant items are as follows:

    [root] #$ sysctl -a  | grep net.core.message 
    net.core.message_burst = 10
    net.core.message_cost = 5
    
  2. Set through proc fs

    Relevant documents are as follows:

    /proc/sys/net/core/message_burst
    /proc/sys/net/core/message_cost
    

Keywords: network

Added by jil on Tue, 01 Feb 2022 12:52:44 +0200