All of lore.kernel.org
 help / color / mirror / Atom feed
* How to send a CAN message while in a kernel module?
@ 2020-03-21 14:50 Robert Barrows
  2020-03-21 16:46 ` Oliver Hartkopp
  0 siblings, 1 reply; 9+ messages in thread
From: Robert Barrows @ 2020-03-21 14:50 UTC (permalink / raw)
  To: linux-can

I have attempted to write a kernel module that sends a message via CAN but I am
having trouble understanding which level of the socket api I should be using,
and where there may be some documentation or examples of how to use it?

I am on a much older embedded 2.6.31 imx arm kernel, and eventually I
would like to
send this message from within a high res timer triggered ISR.

This is my code, which is hobbled together from internet examples, and kernel
oops is during sock_sendmsg, for now I am just trying to get it do run as part
of the init of the module:

int SendCanTime(struct timespec *tsCurrentTime) {
  int s;
  struct sockaddr_can addr;
  struct can_frame frame;
  struct socket *sock;
  int thetime = tsCurrentTime->tv_sec;
  mm_segment_t oldfs;

  oldfs = get_fs();
  set_fs(KERNEL_DS);

  printk("cantime.ko: Socket 10\n");
  if ((s = sock_create(PF_CAN, SOCK_RAW, CAN_RAW, &sock)) < 0) {
    printk("cantime.ko: Socket failure\n");
    return 1;
  }

  printk("cantime.ko: Socket 20\n");
  memset(&addr, 0, sizeof(addr));
  addr.can_family = PF_CAN;
  addr.can_ifindex = 2; // This is bad how do I dynamically find it?

  printk("cantime.ko: Socket 30");
  if (sock->ops->bind(sock, (struct sockaddr *)&addr, sizeof(struct
sockaddr) ) < 0) {
    printk("cantime.ko: Bind failure\n");
    return 1;
  }

  printk("cantime.ko: Socket 40\n");
  frame.can_id = 0x00050F93 | CAN_EFF_FLAG;
  frame.can_dlc = 6;
  frame.data[0] = 0x00;
  frame.data[1] = 0x02;

  memcpy(frame.data+2, &thetime, sizeof(int));

  printk("cantime.ko: Socket 50\n");
  if (sock_sendmsg(sock,(struct msghdr*)&frame,sizeof(struct
can_frame)) !=  sizeof(struct can_frame)) {
    printk("cantime.ko: Write failure");
    return 1;
  }

  sock_release(sock);
  set_fs(oldfs);

  return 0;

}

Output:
cantime.ko: Socket 10
cantime.ko: Socket 20
cantime.ko: Socket 30cantime.ko: Socket 40
cantime.ko: Socket 50
Unable to handle kernel paging request at virtual address 80050f93
pgd = d14c8000
[80050f93] *pgd=00000000
Internal error: Oops: 1 [#1] PREEMPT
Modules linked in: cantime(+) g_ether arcotg_udc
CPU: 0    Not tainted  (2.6.31-imx-09.12.00 #1)
PC is at raw_sendmsg+0x20/0x138
LR is at sock_sendmsg+0xa0/0xc4
pc : [<c02fe83c>]    lr : [<c0283c30>]    psr: a0000013
sp : d67fddc8  ip : c04246c4  fp : 00000000
r10: 0000bb38  r9 : d67fc000  r8 : 00000010
r7 : d67fded0  r6 : d679fe00  r5 : 00000000  r4 : 00000000
r3 : 00000010  r2 : 80050f93  r1 : d0d194e0  r0 : d67fdde8
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 0005317f  Table: 914c8000  DAC: 00000017
Process insmod (pid: 13116, stack limit = 0xd67fc270)
Stack: (0xd67fddc8 to 0xd67fe000)
ddc0:                   d67fc000 000699b8 00000000 00000000 d67fded0 00000000
dde0: c0044fe4 c0283c30 c031b2a8 d785c4cc 00000000 00000001 ffffffff 00000000
de00: 00000000 00000000 00000000 00000000 d785c340 d67fde20 00000000 00000000
de20: 00002a89 d785c340 c00793d0 d67fde2c d67fde2c c031b278 00000000 00000016
de40: d67fde78 c0398293 d679ff38 d6aaa800 00000034 60000013 00000000 c0044fe4
de60: d6aaa800 0000bb38 00000000 c02feb94 00000000 d0d194e0 d6aaa800 d679fe00
de80: d6aaa800 00000010 d0d194e0 00000000 00000000 d67fded0 00000002 bf000000
dea0: 00000000 c0044fe4 d67fc000 0000bb38 00000000 c031ab78 00000000 d67fdee0
dec0: 00000002 bf000000 00000000 bf01837c 80050f93 bf019506 00000200 bf010000
dee0: 0000001d 00000002 00000000 00000000 00000000 d0d194e0 bf019528 00000000
df00: bf01877b bf0185e8 bf01877b c040e5d0 00000000 00000000 00000000 00000000
df20: 00000000 00000000 bf0188a0 00000000 00000000 00000000 00000000 00000000
df40: 00000000 00000000 00000000 0000003c 00000000 bf0193ac bf0184cc c004432c
df60: 00001e66 bf0193ac 00000000 000c9058 c0044fe4 00000000 bf0193ac 00000000
df80: 000c9058 c008d974 d6bcf6c0 d1477a60 be926ca4 00001e66 be926e67 00000002
dfa0: 00000080 c0044e60 00001e66 be926e67 000c9058 00001e66 000c9008 000c86b8
dfc0: 00001e66 be926e67 00000002 00000080 00000002 0000d33c 0000bb38 00000000
dfe0: be926ca0 be926c90 0001f87c 4001a8d0 20000010 000c9058 00000000 00000000
[<c02fe83c>] (raw_sendmsg+0x20/0x138) from [<c0283c30>] (sock_sendmsg+0xa0/0xc4)
[<c0283c30>] (sock_sendmsg+0xa0/0xc4) from [<bf01837c>]
(SendCanTime+0x10c/0x180 [cantime])
[<bf01837c>] (SendCanTime+0x10c/0x180 [cantime]) from [<bf0185e8>]
(cantime_init+0x11c/0x180 [cantime])
[<bf0185e8>] (cantime_init+0x11c/0x180 [cantime]) from [<c004432c>]
(do_one_initcall+0x5c/0x1c4)
[<c004432c>] (do_one_initcall+0x5c/0x1c4) from [<c008d974>]
(sys_init_module+0xc0/0x1d8)
[<c008d974>] (sys_init_module+0xc0/0x1d8) from [<c0044e60>]
(ret_fast_syscall+0x0/0x2c)
Code: e3520000 e1a08003 e591601c 0a000004 (e1d230b0)
---[ end trace 8599b84226905be0 ]---

I also have the user space code that works perfectly that I was trying to model
my kernel module code after:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

int main(int argc, char **argv)
{
  int s;
  struct sockaddr_can addr;
  struct ifreq ifr;
  struct can_frame frame;

  if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    perror("Socket");
    return 1;
  }

  strcpy(ifr.ifr_name, "can0" );
  ioctl(s, SIOCGIFINDEX, &ifr);

  memset(&addr, 0, sizeof(addr));
  addr.can_family = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;
  printf("if index = %x\n", addr.can_ifindex);

  if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror("Bind");
    return 1;
  }

  frame.can_id = 0x00050F93 | CAN_EFF_FLAG;
  frame.can_dlc = 6;
  frame.data[0] = 0x00;
  frame.data[1] = 0x02;

  int thetime = (int)time(NULL);
  memcpy(frame.data+2, &thetime, sizeof(int));

  if (write(s, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame)) {
    perror("Write");
    return 1;
  }

  if (close(s) < 0) {
    perror("Close");
    return 1;
  }

  return 0;
}


                                                                               ^

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-21 14:50 How to send a CAN message while in a kernel module? Robert Barrows
@ 2020-03-21 16:46 ` Oliver Hartkopp
  2020-03-21 19:15   ` Robert Barrows
  0 siblings, 1 reply; 9+ messages in thread
From: Oliver Hartkopp @ 2020-03-21 16:46 UTC (permalink / raw)
  To: Robert Barrows, linux-can

Hi Robert,

On 21/03/2020 15.50, Robert Barrows wrote:
> I have attempted to write a kernel module that sends a message via CAN but I am
> having trouble understanding which level of the socket api I should be using,
> and where there may be some documentation or examples of how to use it?
> 
> I am on a much older embedded 2.6.31 imx arm kernel, and eventually I
> would like to
> send this message from within a high res timer triggered ISR.

You can probably use the CAN_BCM sockets for your use-case which uses 
high-res timers too - even in the 2.6.31 kernel. But I'll come to that 
later ...

> This is my code, which is hobbled together from internet examples, and kernel
> oops is during sock_sendmsg, for now I am just trying to get it do run as part
> of the init of the module:
> 
> int SendCanTime(struct timespec *tsCurrentTime) {
>    int s;
>    struct sockaddr_can addr;
>    struct can_frame frame;
>    struct socket *sock;
>    int thetime = tsCurrentTime->tv_sec;
>    mm_segment_t oldfs;
> 
>    oldfs = get_fs();
>    set_fs(KERNEL_DS);
> 
>    printk("cantime.ko: Socket 10\n");
>    if ((s = sock_create(PF_CAN, SOCK_RAW, CAN_RAW, &sock)) < 0) {
>      printk("cantime.ko: Socket failure\n");
>      return 1;
>    }

Argh - No!

You don't use sockets from INSIDE the kernel.
If you want to send CAN frames from inside the kernel you should use the 
can_send() function from af_can.c

> 
>    printk("cantime.ko: Socket 20\n");
>    memset(&addr, 0, sizeof(addr));
>    addr.can_family = PF_CAN;
>    addr.can_ifindex = 2; // This is bad how do I dynamically find it?
> 
>    printk("cantime.ko: Socket 30");
>    if (sock->ops->bind(sock, (struct sockaddr *)&addr, sizeof(struct
> sockaddr) ) < 0) {
>      printk("cantime.ko: Bind failure\n");
>      return 1;
>    }
> 
>    printk("cantime.ko: Socket 40\n");
>    frame.can_id = 0x00050F93 | CAN_EFF_FLAG;
>    frame.can_dlc = 6;
>    frame.data[0] = 0x00;
>    frame.data[1] = 0x02;
> 
>    memcpy(frame.data+2, &thetime, sizeof(int));

Is your requirement to send "some content" in a very defined time slot 
OR do you need to send the time as content?

> 
>    printk("cantime.ko: Socket 50\n");
>    if (sock_sendmsg(sock,(struct msghdr*)&frame,sizeof(struct
> can_frame)) !=  sizeof(struct can_frame)) {
>      printk("cantime.ko: Write failure");
>      return 1;
>    }
> 
>    sock_release(sock);
>    set_fs(oldfs);
> 
>    return 0;
> 
> }
> 
> Output:
> cantime.ko: Socket 10
> cantime.ko: Socket 20
> cantime.ko: Socket 30cantime.ko: Socket 40
> cantime.ko: Socket 50
> Unable to handle kernel paging request at virtual address 80050f93
> pgd = d14c8000
> [80050f93] *pgd=00000000
> Internal error: Oops: 1 [#1] PREEMPT
> Modules linked in: cantime(+) g_ether arcotg_udc

Funny thing :-)

> I also have the user space code that works perfectly that I was trying to model
> my kernel module code after:

Ok - but we need to check your use-case.

Sending CAN frames in a very precise (hrtimer) manner can be done with 
the broadcast manager (aka CAN_BCM) sockets.

See:
https://elixir.bootlin.com/linux/latest/source/Documentation/networking/can.rst#L677

1. You can send fixed CAN frames and also a sequence of up to 256 
(different) CAN frames at a precisely defined time with a CAN_BCM TX job.

2. You can generate the timestamp in user space and send it via CAN_RAW 
socket.

3. You write your own kernel module o_O :)

Regards,
Oliver

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-21 16:46 ` Oliver Hartkopp
@ 2020-03-21 19:15   ` Robert Barrows
  2020-03-21 20:51     ` Oliver Hartkopp
  0 siblings, 1 reply; 9+ messages in thread
From: Robert Barrows @ 2020-03-21 19:15 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

> You don't use sockets from INSIDE the kernel.
> If you want to send CAN frames from inside the kernel you should use the
> can_send() function from af_can.c
Great to know! I Will look at that right away, any example(s) you could point
me towards?

> Is your requirement to send "some content" in a very defined time slot
> OR do you need to send the time as content?
Use case:
I need to send the epoch seconds as close to the zeroth of the second
as possible, there are some legacy cards that use this packet to set their
clocks, and I am attempting a solution to improve their accuracy without
modifying their firmware.
Hence I have a kernel module that can run a function with sub 10uS accuracy,
the function of choice would spit out a CAN packet with the epoch seconds in
it.

> Sending CAN frames in a very precise (hrtimer) manner can be done with
> the broadcast manager (aka CAN_BCM) sockets.
>
> See:
> https://elixir.bootlin.com/linux/latest/source/Documentation/networking/can.rst#L677
>
> 1. You can send fixed CAN frames and also a sequence of up to 256
> (different) CAN frames at a precisely defined time with a CAN_BCM TX job.

struct timeval ival1, ival2;    /* count and subsequent interval */
Unfortunately, this doesn't look like it fits my use case, would have been nice
to do from user space though.  This looks like it can send out evenly spaced
packets. And I need to send one packet at a precise clock time.

> 2. You can generate the timestamp in user space and send it via CAN_RAW
> socket.

This also wont work due to the use case.

> 3. You write your own kernel module o_O :)

Here we are :)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-21 19:15   ` Robert Barrows
@ 2020-03-21 20:51     ` Oliver Hartkopp
  2020-03-22 18:03       ` Robert Barrows
  0 siblings, 1 reply; 9+ messages in thread
From: Oliver Hartkopp @ 2020-03-21 20:51 UTC (permalink / raw)
  To: Robert Barrows; +Cc: linux-can

On 21/03/2020 20.15, Robert Barrows wrote:
>> You don't use sockets from INSIDE the kernel.
>> If you want to send CAN frames from inside the kernel you should use the
>> can_send() function from af_can.c
> Great to know! I Will look at that right away, any example(s) you could point
> me towards?
> 

You mainly need to look at raw_sendmsg() from linux/net/can/raw.c

Create a skb and set can_skb_reserve() and the other stuff and finally 
put your CAN frame content into the skb->data and invoke can_send().

You will at least need

#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/skb.h>

Of course you don't have a sk reference as you don't have a socket in place.

So you maybe should check the content of alloc_can_skb() from 
linux/drivers/net/can/dev.c and use netdev_alloc_skb() or alloc_skb() 
instead of sock_alloc_send_skb() which needs sk to take care of socket 
specific memory quotas.

If you are unsure just post the code for a review.

Best,
Oliver

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-21 20:51     ` Oliver Hartkopp
@ 2020-03-22 18:03       ` Robert Barrows
  2020-03-22 18:47         ` Oliver Hartkopp
  2020-03-22 18:55         ` Oliver Hartkopp
  0 siblings, 2 replies; 9+ messages in thread
From: Robert Barrows @ 2020-03-22 18:03 UTC (permalink / raw)
  To: Oliver Hartkopp; +Cc: linux-can

Thank you for all the direction Oliver,  I think I am on the correct path,
but now have can_send returning with a "-1" (ERESTART). I used raw_sendmsg
as a template for this and cut out (hopefully) unneeded code, but I am
concerned I cut out something I needed.  Would you mind taking another look?

Thanks.

int SendCanTime(struct timespec *tsCurrentTime) {

  struct sk_buff *skb;
  struct can_frame *frame = kmalloc(sizeof (struct can_frame), GFP_KERNEL);
  struct net_device *dev;
  int err = 0;
  int thetime = tsCurrentTime->tv_sec;

  // Set up can frame
  frame->can_id = 0x00050F93 | CAN_EFF_FLAG;
  frame->can_dlc = 6;
  frame->data[0] = 0x00;
  frame->data[1] = 0x02;
  memcpy(frame->data+2, &thetime, sizeof(int));

  // Find the netdevice named can0
  read_lock(&dev_base_lock);
  dev = first_net_device(&init_net);
  while (!strcmp(dev->name, "can0")) {
    printk(KERN_INFO "found [%s]\n", dev->name);
    dev = next_net_device(dev);
  }
  read_unlock(&dev_base_lock);

  if (!dev)
    return -ENXIO;

  // Create skb
  skb = alloc_can_skb(dev, &frame);
  if (!skb)
    goto put_dev;

  skb->dev = dev;

  err = can_send(skb, 0);

  dev_put(dev);

  if (err)
    goto send_failed;

  return 0;

//kfree_skb(skb);
put_dev:
  dev_put(dev);
send_failed:
  return err;

}
                                                                               ^

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-22 18:03       ` Robert Barrows
@ 2020-03-22 18:47         ` Oliver Hartkopp
       [not found]           ` <CAOHJ0jTksLTcRuvx8xarRdcCA4oKKggi1pYQy725Lf-Zav6xGw@mail.gmail.com>
  2020-03-22 18:55         ` Oliver Hartkopp
  1 sibling, 1 reply; 9+ messages in thread
From: Oliver Hartkopp @ 2020-03-22 18:47 UTC (permalink / raw)
  To: Robert Barrows; +Cc: linux-can



On 22/03/2020 19.03, Robert Barrows wrote:
> Thank you for all the direction Oliver,  I think I am on the correct path,
> but now have can_send returning with a "-1" (ERESTART). I used raw_sendmsg
> as a template for this and cut out (hopefully) unneeded code, but I am
> concerned I cut out something I needed.  Would you mind taking another look?

I would recommend to test your code with a virtual CAN (vcan0) first.

You should bring the system into the state that you can run

cangen vcan0

in one terminal and

candump vcan0

in another terminal and see some data there.

And then let your kernel module send on vcan0.

Running on a real CAN interface can have (wiring/termination) issue you 
would not like to debug when developing a kernel module ;-)

There's a problem with your code too:


> 
> Thanks.
> 
> int SendCanTime(struct timespec *tsCurrentTime) {
> 
>    struct sk_buff *skb;
>    struct can_frame *frame = kmalloc(sizeof (struct can_frame), GFP_KERNEL);

This creates a memory leak ...

Just use a static buffer:

struct can_frame frame;
struct can_frame *cf = &frame;


>    struct net_device *dev;
>    int err = 0;
>    int thetime = tsCurrentTime->tv_sec;
> 
>    // Set up can frame
>    frame->can_id = 0x00050F93 | CAN_EFF_FLAG;

cf->can_id = 0x00050F93 | CAN_EFF_FLAG;

>    frame->can_dlc = 6;

dito ...

>    frame->data[0] = 0x00;
>    frame->data[1] = 0x02;
>    memcpy(frame->data+2, &thetime, sizeof(int));
> 
>    // Find the netdevice named can0
>    read_lock(&dev_base_lock);
>    dev = first_net_device(&init_net);
>    while (!strcmp(dev->name, "can0")) {
>      printk(KERN_INFO "found [%s]\n", dev->name);
>      dev = next_net_device(dev);
>    }
>    read_unlock(&dev_base_lock);
> 
>    if (!dev)
>      return -ENXIO;
> 
>    // Create skb
>    skb = alloc_can_skb(dev, &frame);

skb = alloc_can_skb(dev, &cf);

I hope I made the pointer stuff correctly :-)

>    if (!skb)
>      goto put_dev;
> 
>    skb->dev = dev;
> 
>    err = can_send(skb, 0);
> 
>    dev_put(dev);
> 
>    if (err)
>      goto send_failed;
> 
>    return 0;
> 
> //kfree_skb(skb);
> put_dev:
>    dev_put(dev);
> send_failed:
>    return err;
> 
> }
>                                                                                 ^
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-22 18:03       ` Robert Barrows
  2020-03-22 18:47         ` Oliver Hartkopp
@ 2020-03-22 18:55         ` Oliver Hartkopp
  2020-03-24  2:55           ` Robert Barrows
  1 sibling, 1 reply; 9+ messages in thread
From: Oliver Hartkopp @ 2020-03-22 18:55 UTC (permalink / raw)
  To: Robert Barrows; +Cc: linux-can



On 22/03/2020 19.03, Robert Barrows wrote:
> Thank you for all the direction Oliver,  I think I am on the correct path,
> but now have can_send returning with a "-1" (ERESTART). I used raw_sendmsg
> as a template for this and cut out (hopefully) unneeded code, but I am
> concerned I cut out something I needed.  Would you mind taking another look?
> 
> Thanks.
> 
> int SendCanTime(struct timespec *tsCurrentTime) {
> 
>    struct sk_buff *skb;
>    struct can_frame *frame = kmalloc(sizeof (struct can_frame), GFP_KERNEL);
>    struct net_device *dev;
>    int err = 0;
>    int thetime = tsCurrentTime->tv_sec;
> 
>    // Set up can frame
>    frame->can_id = 0x00050F93 | CAN_EFF_FLAG;
>    frame->can_dlc = 6;
>    frame->data[0] = 0x00;
>    frame->data[1] = 0x02;
>    memcpy(frame->data+2, &thetime, sizeof(int));
> 
>    // Find the netdevice named can0
>    read_lock(&dev_base_lock);
>    dev = first_net_device(&init_net);
>    while (!strcmp(dev->name, "can0")) {
>      printk(KERN_INFO "found [%s]\n", dev->name);
>      dev = next_net_device(dev);
>    }
>    read_unlock(&dev_base_lock);

What does this return when you don't have can0 in the system??

You should use
  __dev_get_by_name()
here.
https://elixir.bootlin.com/linux/latest/source/net/core/dev.c#L762

And check for success :-)


> 
>    if (!dev)
>      return -ENXIO;
> 
>    // Create skb
>    skb = alloc_can_skb(dev, &frame);
>    if (!skb)
>      goto put_dev;
> 
>    skb->dev = dev;
> 
>    err = can_send(skb, 0);
> 
>    dev_put(dev);
> 
>    if (err)
>      goto send_failed;
> 
>    return 0;
> 
> //kfree_skb(skb);
> put_dev:
>    dev_put(dev);
> send_failed:
>    return err;
> 
> }
>                                                                                 ^
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
  2020-03-22 18:55         ` Oliver Hartkopp
@ 2020-03-24  2:55           ` Robert Barrows
  0 siblings, 0 replies; 9+ messages in thread
From: Robert Barrows @ 2020-03-24  2:55 UTC (permalink / raw)
  To: linux-can

Thank you for all the help it seems I have everything working and am able to
hit sub 20uS accuracy.  Is there any concern with my HR timer ISR interrupting
a currently pending CAN message that is only partially done, thus sending my
packet in "the middle" of another one?  Or is each packet in the can driver
sent as an atomic event?

If you are curious, here were my initial results:

 (1584977760.000001)  can0  00050F93   [6]  00 02 5F D7 78 5E
 (1584977761.999995)  can0  00050F93   [6]  00 02 61 D7 78 5E
 (1584977763.999993)  can0  00050F93   [6]  00 02 63 D7 78 5E
 (1584977766.000002)  can0  00050F93   [6]  00 02 65 D7 78 5E
 (1584977767.999996)  can0  00050F93   [6]  00 02 67 D7 78 5E
 (1584977769.999999)  can0  00050F93   [6]  00 02 69 D7 78 5E
 (1584977772.000002)  can0  00050F93   [6]  00 02 6B D7 78 5E
 (1584977774.000001)  can0  00050F93   [6]  00 02 6D D7 78 5E
 (1584977776.000000)  can0  00050F93   [6]  00 02 6F D7 78 5E
 (1584977778.000000)  can0  00050F93   [6]  00 02 71 D7 78 5E
 (1584977779.999997)  can0  00050F93   [6]  00 02 73 D7 78 5E
 (1584977781.999999)  can0  00050F93   [6]  00 02 75 D7 78 5E
 (1584977783.999996)  can0  00050F93   [6]  00 02 77 D7 78 5E
 (1584977786.000022)  can0  00050F93   [6]  00 02 79 D7 78 5E
 (1584977788.000000)  can0  00050F93   [6]  00 02 7B D7 78 5E

And my current functioning code:

int SendCanTime(struct timespec *tsCurrentTime) {

  struct can_frame frame;
  struct can_frame *cf = &frame;
  struct sk_buff *skb;
  int thetime = tsCurrentTime->tv_sec;
  struct net_device *dev;
  int err;

  // Find the netdevice named can0
  dev = __dev_get_by_name(&init_net,"can0");
  if (!dev)
    return -ENXIO;

  // Create skb
  skb = alloc_can_skb(dev, &cf);
  if (!skb) {
    dev_put(dev);
    return 1;
  }

  skb->dev = dev;

  // Set up can frame
  cf->can_id = 0x00050F93 | CAN_EFF_FLAG;
  cf->can_dlc = 6;
  cf->data[0] = 0x00;
  cf->data[1] = 0x02;
  memcpy(cf->data+2, &thetime, sizeof(int));

  err = can_send(skb, 1);

  if(err) {
    dev_put(skb->dev);


    return 1;
  }
  return 0;
}

                                                                               ^

                                                                               ^


On Sun, Mar 22, 2020 at 1:55 PM Oliver Hartkopp <socketcan@hartkopp.net> wrote:
>
>
>
> On 22/03/2020 19.03, Robert Barrows wrote:
> > Thank you for all the direction Oliver,  I think I am on the correct path,
> > but now have can_send returning with a "-1" (ERESTART). I used raw_sendmsg
> > as a template for this and cut out (hopefully) unneeded code, but I am
> > concerned I cut out something I needed.  Would you mind taking another look?
> >
> > Thanks.
> >
> > int SendCanTime(struct timespec *tsCurrentTime) {
> >
> >    struct sk_buff *skb;
> >    struct can_frame *frame = kmalloc(sizeof (struct can_frame), GFP_KERNEL);
> >    struct net_device *dev;
> >    int err = 0;
> >    int thetime = tsCurrentTime->tv_sec;
> >
> >    // Set up can frame
> >    frame->can_id = 0x00050F93 | CAN_EFF_FLAG;
> >    frame->can_dlc = 6;
> >    frame->data[0] = 0x00;
> >    frame->data[1] = 0x02;
> >    memcpy(frame->data+2, &thetime, sizeof(int));
> >
> >    // Find the netdevice named can0
> >    read_lock(&dev_base_lock);
> >    dev = first_net_device(&init_net);
> >    while (!strcmp(dev->name, "can0")) {
> >      printk(KERN_INFO "found [%s]\n", dev->name);
> >      dev = next_net_device(dev);
> >    }
> >    read_unlock(&dev_base_lock);
>
> What does this return when you don't have can0 in the system??
>
> You should use
>   __dev_get_by_name()
> here.
> https://elixir.bootlin.com/linux/latest/source/net/core/dev.c#L762
>
> And check for success :-)
>
>
> >
> >    if (!dev)
> >      return -ENXIO;
> >
> >    // Create skb
> >    skb = alloc_can_skb(dev, &frame);
> >    if (!skb)
> >      goto put_dev;
> >
> >    skb->dev = dev;
> >
> >    err = can_send(skb, 0);
> >
> >    dev_put(dev);
> >
> >    if (err)
> >      goto send_failed;
> >
> >    return 0;
> >
> > //kfree_skb(skb);
> > put_dev:
> >    dev_put(dev);
> > send_failed:
> >    return err;
> >
> > }
> >                                                                                 ^
> >

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How to send a CAN message while in a kernel module?
       [not found]               ` <CAOHJ0jQmfUMW2tE_xQvm8RmH-KBzGZ=rxG--kCJ0_yabE3FbYA@mail.gmail.com>
@ 2020-03-24  7:20                 ` Oliver Hartkopp
  0 siblings, 0 replies; 9+ messages in thread
From: Oliver Hartkopp @ 2020-03-24  7:20 UTC (permalink / raw)
  To: Robert Barrows; +Cc: linux-can



On 23/03/2020 22.37, Robert Barrows wrote:
>> The CAN controller gets the frame from a FIFO (netdev tx queue) which
>> has a length of 10 elements by default.
> Any way I can force my way to the head of the queue?  I see
> skb->priority but I thought that was for TCP packets.

Yes.

>> But when you generate additional traffic (e.g. with cangen) you might
>> get some jitter.
>> Is this relevant on your box / use-case?
> It is possible there could be a lot of packets flying around and I would
> like to keep my jitter <100uS. Any tips?

Please take a look into slide 41 - 45 of this PDF:
https://wiki.automotivelinux.org/_media/agl-distro/agl2017-socketcan-print.pdf

The academic report about this can be found here
http://rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf

You still have to cope with the txqueue length of 10 so you probably 
need to create a setup that drains the tx queue before your 
jitter/time-sensitive CAN frame is enqueued.

Another option would be to implement multiple tx queues on CAN drivers - 
but that has not been focused AFAIK.

Best,
Oliver

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-03-24  7:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-21 14:50 How to send a CAN message while in a kernel module? Robert Barrows
2020-03-21 16:46 ` Oliver Hartkopp
2020-03-21 19:15   ` Robert Barrows
2020-03-21 20:51     ` Oliver Hartkopp
2020-03-22 18:03       ` Robert Barrows
2020-03-22 18:47         ` Oliver Hartkopp
     [not found]           ` <CAOHJ0jTksLTcRuvx8xarRdcCA4oKKggi1pYQy725Lf-Zav6xGw@mail.gmail.com>
     [not found]             ` <a8ebf3b8-3a7e-596d-7b83-5ce772d093a8@hartkopp.net>
     [not found]               ` <CAOHJ0jQmfUMW2tE_xQvm8RmH-KBzGZ=rxG--kCJ0_yabE3FbYA@mail.gmail.com>
2020-03-24  7:20                 ` Oliver Hartkopp
2020-03-22 18:55         ` Oliver Hartkopp
2020-03-24  2:55           ` Robert Barrows

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.