Can port cause Linux kernel crash?

80 views Asked by At

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?

0

There are 0 answers