Thanks to @Hasturkun
AFAICT, CAN messages would be prioritized based on their message ID (and that seems to be up to the specific driver/hw by default). I did find a couple of relevant links about setting up a queue discipline, though, rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf and forum.opencyphal.org/t/queue-disciplines-and-linux-socketcan/… . The default qdisc pfifo_fast supports 3 priority bands (which you can apparently get at with SO_PRIORITY on a per socket basis for a raw socket).
This is exactly the mechanism to do this.
The only confusion i had was that:
Some where was mentioned the priority is 0 to 7. 0 means best and 7 means lowest. This is not the priority meant to put in SO_PRIORITY. There is a Priority map:
$ tc qdisc show dev can1
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
So according to this map it is read like this:
SO_PRIO | qdisc PRIO
0 | 1
1 | 2
2 | 2
3 | 2
4 | 1
5 | 2
6 | 0
7 | 0
8 | 1
.. | 1
13 | 1
So this is how i configured my can Interface:
sudo ip link set can1 type can bitrate 125000
sudo ip link set up can1
Here is an example code that worked to illustrate that the high_fd is prioretised over the low_fd:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
static const unsigned char dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
8, 12, 16, 20, 24, 32, 48, 64};
/* get data length from raw data length code (DLC) */
unsigned char can_fd_dlc2len(unsigned char dlc)
{
return dlc2len[dlc & 0x0F];
}
static const unsigned char len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
9, 9, 9, 9, /* 9 - 12 */
10, 10, 10, 10, /* 13 - 16 */
11, 11, 11, 11, /* 17 - 20 */
12, 12, 12, 12, /* 21 - 24 */
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
/* map the sanitized data length to an appropriate data length code */
unsigned char can_fd_len2dlc(unsigned char len)
{
if (len > 64)
return 0xF;
return len2dlc[len];
}
int main(int argc, char **argv)
{
int mtuSize = CAN_MTU;
int low_fd, high_fd;
struct sockaddr_can low_addr, high_addr;
struct ifreq ifr = {
.ifr_name = "can1",
.ifr_ifindex = if_nametoindex(ifr.ifr_name)
};
struct can_frame frame = {
.can_id = 0x80,
.len = 4,
.len8_dlc = 4,
.data = {0xba, 0xd0, 0x00, 0x00}
};
if (!ifr.ifr_ifindex) {
perror("wrong ifr_ifindex");
return 1;
}
/* open socket */
if ((low_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("can't create low_fd");
return 1;
}
/* open socket high prio */
if ((high_fd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("can't create high_fd");
return 1;
}
memset(&low_addr, 0, sizeof(low_addr));
low_addr.can_family = AF_CAN;
low_addr.can_ifindex = ifr.ifr_ifindex;
memset(&high_addr, 0, sizeof(high_addr));
high_addr.can_family = AF_CAN;
high_addr.can_ifindex = ifr.ifr_ifindex;
frame.len = can_fd_dlc2len(can_fd_len2dlc(frame.len));
/* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage. */
setsockopt(low_fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (bind(low_fd, (struct sockaddr *)&low_addr, sizeof(low_addr)) < 0) {
perror("error binding low_fd");
return 1;
}
setsockopt(high_fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
if (bind(high_fd, (struct sockaddr *)&high_addr, sizeof(high_addr)) < 0) {
perror("error binding high_fd");
return 1;
}
/* set priorities */
int low_prio = 2;
setsockopt(low_fd, SOL_SOCKET, SO_PRIORITY, &low_prio, sizeof(low_prio));
int high_prio = 0;
setsockopt(high_fd, SOL_SOCKET, SO_PRIORITY, &high_prio, sizeof(high_prio));
for(int i=0;i<24;i++) {
/* send frame */
//printf("Packet: %d\r\n", i);
if (write(low_fd, &frame, sizeof(frame)) != CAN_MTU) {
perror("low write error packet");
printf("Error on packet: %d\r\n", i);
return -2;
} else {
frame.data[2]++;
}
usleep(10);
}
frame.can_id = 0x33;
frame.data[3] = 0x33;
if (write(high_fd, &frame, sizeof(frame)) != CAN_MTU) {
perror("high write error");
}
close(low_fd);
close(high_fd);
return 0;
}
This is the output on the Bus when prio_low is 2 => 2 and prio_high is 0 => 1
CAN6: 18137.742 <- sff 080 (4) ba d0 00 00
CAN6: 1.717 <- sff 080 (4) ba d0 01 00
CAN6: 1.720 <- sff 080 (4) ba d0 02 00
CAN6: 1.739 <- sff 080 (4) ba d0 03 00
CAN6: 1.718 <- sff 080 (4) ba d0 04 00
CAN6: 1.720 <- sff 080 (4) ba d0 05 00
CAN6: 1.738 <- sff 080 (4) ba d0 06 00
CAN6: 1.720 <- sff 080 (4) ba d0 07 00
CAN6: 1.741 <- sff 080 (4) ba d0 08 00
CAN6: 1.701 <- sff 080 (4) ba d0 09 00
CAN6: 1.720 <- sff 080 (4) ba d0 0a 00
CAN6: 1.698 <- sff 080 (4) ba d0 0b 00
CAN6: 1.739 <- sff 080 (4) ba d0 0c 00
CAN6: 1.699 <- sff 080 (4) ba d0 0d 00
CAN6: 1.718 <- sff 080 (4) ba d0 0e 00
CAN6: 1.678 <- sff 033 (4) ba d0 18 33 <-- Prioritised
CAN6: 1.699 <- sff 080 (4) ba d0 0f 00
CAN6: 1.739 <- sff 080 (4) ba d0 10 00
CAN6: 1.699 <- sff 080 (4) ba d0 11 00
CAN6: 1.739 <- sff 080 (4) ba d0 12 00
CAN6: 1.720 <- sff 080 (4) ba d0 13 00
CAN6: 1.739 <- sff 080 (4) ba d0 14 00
CAN6: 1.718 <- sff 080 (4) ba d0 15 00
CAN6: 1.718 <- sff 080 (4) ba d0 16 00
CAN6: 1.699 <- sff 080 (4) ba d0 17 00
This is the output if prio low is 7 => 0 and prio high is 0 => 1:
CAN6: 1027753.429 <- sff 080 (4) ba d0 00 00
CAN6: 1.718 <- sff 080 (4) ba d0 01 00
CAN6: 1.720 <- sff 080 (4) ba d0 02 00
CAN6: 1.741 <- sff 080 (4) ba d0 03 00
CAN6: 1.720 <- sff 080 (4) ba d0 04 00
CAN6: 1.722 <- sff 080 (4) ba d0 05 00
CAN6: 1.742 <- sff 080 (4) ba d0 06 00
CAN6: 1.722 <- sff 080 (4) ba d0 07 00
CAN6: 1.742 <- sff 080 (4) ba d0 08 00
CAN6: 1.701 <- sff 080 (4) ba d0 09 00
CAN6: 1.720 <- sff 080 (4) ba d0 0a 00
CAN6: 1.701 <- sff 080 (4) ba d0 0b 00
CAN6: 1.741 <- sff 080 (4) ba d0 0c 00
CAN6: 1.701 <- sff 080 (4) ba d0 0d 00
CAN6: 1.723 <- sff 080 (4) ba d0 0e 00
CAN6: 1.699 <- sff 080 (4) ba d0 0f 00
CAN6: 1.739 <- sff 080 (4) ba d0 10 00
CAN6: 1.698 <- sff 080 (4) ba d0 11 00
CAN6: 1.739 <- sff 080 (4) ba d0 12 00
CAN6: 1.720 <- sff 080 (4) ba d0 13 00
CAN6: 1.742 <- sff 080 (4) ba d0 14 00
CAN6: 1.720 <- sff 080 (4) ba d0 15 00
CAN6: 1.722 <- sff 080 (4) ba d0 16 00
CAN6: 1.699 <- sff 080 (4) ba d0 17 00
CAN6: 47.819 <- sff 033 (4) ba d0 18 33 <-- Not Prioritised