net_ratelimit 在非阻塞模式下创建多个 TCP 连接时内核日志中的消息
net_ratelimit message in kernel log when creating multiple TCP connection in NONBLOCKING mode
我有一个 C 程序试图轮询网络中的设备,如果设备可用,它会尝试从中读取值。但是,当不存在任何设备时,应用程序的 运行ning 会在内核日志中创建以下消息。此外,除了以下消息之外,日志中没有其他 warning/alert 消息。 (即使在使用 net.core.message_cost=0
禁用速率限制后)
net_ratelimit: xx callbacks supressed
与此同时,另一个通过网络广播消息的应用程序在返回 EINVAL
的发送系统调用中开始失败。一旦我停止轮询 TCP
客户端,UDP Broadcast
应用程序 运行 就可以了。
我所在的系统 运行 这是一个基于 RAMFS
的系统 运行ning 3.14 系列内核 与 RT_PREEMPT
已应用补丁。我编写了一个示例应用程序,当我在后台启动 5 个进程时,它模拟了与我的原始应用程序相同的行为。 (请注意,触发它的进程超过 4 个)。下面是示例客户端代码。
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
int sfd;
void openProtocol(const char *hostname) {
int sfd = socket(PF_INET, SOCK_STREAM, 0);
CHK_ERR(sfd, "socket");
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = PF_INET;
address.sin_addr.s_addr = inet_addr(hostname);
address.sin_port = htons(502);
int opt = 1;
int result = ioctl(sfd, FIONBIO, &opt);
if (result == -1) {
close(sfd);
CHK_ERR(result, "ioctl");
}
result = connect(sfd, (struct sockaddr*)&address, sizeof(address));
if (result == -1 && errno != EINPROGRESS) {
close(sfd);
CHK_ERR(result, "connect");
}
fd_set fdlist;
FD_ZERO(&fdlist);
struct timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
result = select(sfd + 1, NULL, &fdlist, NULL, &tm);
if (result == 0) {
printf ("TCP/IP connection error!\n");
close(sfd);
}
if (result == -1) {
close(sfd);
CHK_ERR(result, "select");
}
}
int main(int argc, char *argv[])
{
char *base_addr = "192.168.1.";
unsigned short startAddr = 21;
if ( argc < 3) {
fprintf (stderr, "Please provide number of IP and wait period\n");
exit(EXIT_FAILURE);
}
unsigned int no_of_ip;
if (sscanf (argv[1], "%u", (unsigned int*)&no_of_ip) != 1 ) {
fprintf (stderr, "Scan of number of device failed\n");
exit(EXIT_FAILURE);
}
unsigned int wait_period;
if (sscanf (argv[2], "%u", (unsigned int*)&wait_period) != 1) {
fprintf (stderr, "Scan of wait period failed\n");
exit(EXIT_FAILURE);
}
char full_addr[100];
char last_part[10];
while (1) {
for (int i = startAddr; i < (startAddr + no_of_ip); i++) {
memset(&full_addr[0], 0, sizeof(full_addr));
memset(&last_part[0], 0, sizeof(last_part));
strncat (full_addr, base_addr, sizeof(full_addr));
snprintf (last_part, sizeof(last_part), "%u", i);
strncat (full_addr, last_part, sizeof(full_addr));
openProtocol(full_addr);
usleep(wait_period * 1000);
}
}
return 0;
}
应用程序将输入作为设备数量和等待时间。我通过 shell 脚本 运行 5 个上述应用程序的实例,其中 128
作为设备编号 和 5
作为等待时间(5 毫秒).
现在我的问题。
为什么我在 运行 运行此应用程序(5
个实例 时收到 net_ratelimit
消息。我尝试通过将 net.core.message_cost
设置为 0
来禁用 net_ratelimit
,但是除了 net_ratelimit
消息之外,我在内核日志中找不到任何内容。
为什么不相关的应用程序(UDP broadcast
客户端)在尝试发送广播时收到 EINVAL
。这也只有在我的轮询应用程序 运行s 时才会发生。杀死轮询应用广播客户端returns正常。
PS:我找不到更好的标题行,如果有人有更好的标题行请suggest/edit ;-)。
将内核升级到4.1系列后,我可以看到消息的原因。真正的根本原因在消息
下面
neighbour: arp_cache: neighbour table overflow
然后我注意到我正在向 ARP 缓存中添加超过 1024(默认限制)的条目。修复此问题后,回调抑制消息的问题停止。我猜这是 3.14 系列中的一个错误,它没有提供 call back supressed
消息的实际原因。
我有一个 C 程序试图轮询网络中的设备,如果设备可用,它会尝试从中读取值。但是,当不存在任何设备时,应用程序的 运行ning 会在内核日志中创建以下消息。此外,除了以下消息之外,日志中没有其他 warning/alert 消息。 (即使在使用 net.core.message_cost=0
禁用速率限制后)
net_ratelimit: xx callbacks supressed
与此同时,另一个通过网络广播消息的应用程序在返回 EINVAL
的发送系统调用中开始失败。一旦我停止轮询 TCP
客户端,UDP Broadcast
应用程序 运行 就可以了。
我所在的系统 运行 这是一个基于 RAMFS
的系统 运行ning 3.14 系列内核 与 RT_PREEMPT
已应用补丁。我编写了一个示例应用程序,当我在后台启动 5 个进程时,它模拟了与我的原始应用程序相同的行为。 (请注意,触发它的进程超过 4 个)。下面是示例客户端代码。
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
int sfd;
void openProtocol(const char *hostname) {
int sfd = socket(PF_INET, SOCK_STREAM, 0);
CHK_ERR(sfd, "socket");
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = PF_INET;
address.sin_addr.s_addr = inet_addr(hostname);
address.sin_port = htons(502);
int opt = 1;
int result = ioctl(sfd, FIONBIO, &opt);
if (result == -1) {
close(sfd);
CHK_ERR(result, "ioctl");
}
result = connect(sfd, (struct sockaddr*)&address, sizeof(address));
if (result == -1 && errno != EINPROGRESS) {
close(sfd);
CHK_ERR(result, "connect");
}
fd_set fdlist;
FD_ZERO(&fdlist);
struct timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
result = select(sfd + 1, NULL, &fdlist, NULL, &tm);
if (result == 0) {
printf ("TCP/IP connection error!\n");
close(sfd);
}
if (result == -1) {
close(sfd);
CHK_ERR(result, "select");
}
}
int main(int argc, char *argv[])
{
char *base_addr = "192.168.1.";
unsigned short startAddr = 21;
if ( argc < 3) {
fprintf (stderr, "Please provide number of IP and wait period\n");
exit(EXIT_FAILURE);
}
unsigned int no_of_ip;
if (sscanf (argv[1], "%u", (unsigned int*)&no_of_ip) != 1 ) {
fprintf (stderr, "Scan of number of device failed\n");
exit(EXIT_FAILURE);
}
unsigned int wait_period;
if (sscanf (argv[2], "%u", (unsigned int*)&wait_period) != 1) {
fprintf (stderr, "Scan of wait period failed\n");
exit(EXIT_FAILURE);
}
char full_addr[100];
char last_part[10];
while (1) {
for (int i = startAddr; i < (startAddr + no_of_ip); i++) {
memset(&full_addr[0], 0, sizeof(full_addr));
memset(&last_part[0], 0, sizeof(last_part));
strncat (full_addr, base_addr, sizeof(full_addr));
snprintf (last_part, sizeof(last_part), "%u", i);
strncat (full_addr, last_part, sizeof(full_addr));
openProtocol(full_addr);
usleep(wait_period * 1000);
}
}
return 0;
}
应用程序将输入作为设备数量和等待时间。我通过 shell 脚本 运行 5 个上述应用程序的实例,其中 128
作为设备编号 和 5
作为等待时间(5 毫秒).
现在我的问题。
为什么我在 运行 运行此应用程序(
5
个实例 时收到net_ratelimit
消息。我尝试通过将net.core.message_cost
设置为0
来禁用net_ratelimit
,但是除了net_ratelimit
消息之外,我在内核日志中找不到任何内容。为什么不相关的应用程序(
UDP broadcast
客户端)在尝试发送广播时收到EINVAL
。这也只有在我的轮询应用程序 运行s 时才会发生。杀死轮询应用广播客户端returns正常。
PS:我找不到更好的标题行,如果有人有更好的标题行请suggest/edit ;-)。
将内核升级到4.1系列后,我可以看到消息的原因。真正的根本原因在消息
下面neighbour: arp_cache: neighbour table overflow
然后我注意到我正在向 ARP 缓存中添加超过 1024(默认限制)的条目。修复此问题后,回调抑制消息的问题停止。我猜这是 3.14 系列中的一个错误,它没有提供 call back supressed
消息的实际原因。