I wrote a C program like below to test my can port send speed:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/can.h>
#include <linux/can/raw.h>
void send_candata(unsigned int len, unsigned char *buf)
{
int s;
struct sockaddr_can addr;
struct ifreq ifr;
struct can_frame frame;
const char *ifname = "can0";
memset(&addr, 0, sizeof(addr));
memset(&frame, 0, sizeof(frame));
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
return;
strcpy(ifr.ifr_name, ifname);
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex(ifr.ifr_name);
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(s);
return;
}
frame.can_id = 0x123;
frame.can_dlc = len;
memcpy(&frame.data[0], buf, 8);
resend:
if (write(s, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame))
goto resend;
close(s);
}
int main(int argc, char *argv[])
{
unsigned int cont = 0;
unsigned int time = 0;
unsigned int total = 0;
unsigned char buf1[8];
unsigned char buf2[8];
unsigned char buf3[8];
unsigned char buf4[8];
unsigned char buf5[8];
unsigned char buf6[8];
unsigned char buf7[8];
unsigned char buf8[8];
unsigned char buf9[8];
memset(buf1, 0x11, 8);
memset(buf2, 0x22, 8);
memset(buf3, 0x33, 8);
memset(buf4, 0x44, 8);
memset(buf5, 0x55, 8);
memset(buf6, 0x66, 8);
memset(buf7, 0x77, 8);
memset(buf8, 0x88, 8);
memset(buf9, 0x99, 8);
if (argc < 4) {
printf("please input delay time and total test times you want\r\n");
printf(" usage: \r\n");
printf(" ./testcan 200 1000\r\n");
return 0;
}
time = atoi(argv[1]);
printf("delay: %dus\r\n", time);
total = atoi(argv[2]);
printf("total time: %d * 9 = %d\n", total, total * 9);
while (1) {
cont++;
usleep(time);
send_candata(8, buf1);
usleep(time);
send_candata(8, buf2);
usleep(time);
send_candata(8, buf3);
usleep(time);
send_candata(8, buf4);
usleep(time);
send_candata(8, buf5);
usleep(time);
send_candata(8, buf6);
usleep(time);
send_candata(8, buf7);
usleep(time);
send_candata(8, buf8);
usleep(time);
send_candata(8, buf9);
if (cont >= total)
break;
}
return 0;
}
I use this program to test my can port driver, but when I send about 1600000 frames (it depends how much DDR space in my system), Linux kernel crashed, this program used out of memory, log like below:
[ 293.703838] [<ffffffff800049ba>] dump_backtrace+0x1c/0x24
[ 293.709259] [<ffffffff80c60a90>] dump_stack_lvl+0x40/0x58
[ 293.714665] [<ffffffff80c60abc>] dump_stack+0x14/0x1c
[ 293.719721] [<ffffffff80c5f748>] dump_header+0x46/0x256
[ 293.724955] [<ffffffff800eef3a>] oom_kill_process+0x386/0x388
[ 293.730708] [<ffffffff800ef6f0>] out_of_memory+0x1a4/0x3ae
[ 293.736201] [<ffffffff8012810c>] __alloc_pages+0xa74/0xb60
[ 293.741695] [<ffffffff80139db0>] new_slab+0x382/0x394
[ 293.746751] [<ffffffff8013c694>] ___slab_alloc.constprop.0+0x4c6/0x598
[ 293.753288] [<ffffffff8013c792>] __slab_alloc.constprop.0+0x2c/0x3e
[ 293.759563] [<ffffffff8013c868>] __kmalloc_track_caller+0xc4/0x216
[ 293.765751] [<ffffffff80a13ee8>] __alloc_skb+0x7a/0x1b4
[ 293.770986] [<ffffffff80a18950>] alloc_skb_with_frags+0x48/0x160
[ 293.776997] [<ffffffff80a0deba>] sock_alloc_send_pskb+0x19a/0x1b2
[ 293.783095] [<ffffffff80a0dee6>] sock_alloc_send_skb+0x14/0x1c
[ 293.788935] [<ffffffff80b68c3e>] raw_sendmsg+0x86/0x224
[ 293.794168] [<ffffffff80a09e98>] sock_write_iter+0x94/0xe8
[ 293.799663] [<ffffffff80145742>] new_sync_write+0xee/0x14c
[ 293.805158] [<ffffffff80146f2c>] vfs_write+0x1aa/0x23e
[ 293.810303] [<ffffffff80147138>] ksys_write+0x9c/0xc6
[ 293.815358] [<ffffffff80147170>] sys_write+0xe/0x16
[ 293.820243] [<ffffffff800030f6>] ret_from_syscall+0x0/0x2
[ 293.825662] Mem-Info:
[ 293.827942] active_anon:35 inactive_anon:840 isolated_anon:0
[ 293.827942] active_file:45 inactive_file:110 isolated_file:0
[ 293.827942] unevictable:0 dirty:0 writeback:0
[ 293.827942] slab_reclaimable:3861 slab_unreclaimable:715005
[ 293.827942] mapped:102 shmem:69 pagetables:130 bounce:0
[ 293.827942] kernel_misc_reclaimable:0
[ 293.827942] free:264660 free_pcp:32 free_cma:261384
I use Linux kernel v5.15 as my test kernel version, This problem also exsits on Linux kernel v4.19. Do anyone who knows where is the problem in my program? I copied this code from cansend
open source.
Is it possible because I create and close socket too many times? and It's not the socket correct usage?