I just programming a ROS node where I'm trying to set up filters on a CAN Socket. I would like to get the messages with CAN_Id 0x6A0 to 0x6A4
as well as the CAN_Id 0x0CF02980
.
I'm using the socket can from linux. Here an extract of my code :
#include <linux/can.h>
#include <linux/can/raw.h>
can_filter m_rfilter[2];
// Open can socket
struct ifreq ifr = {};
struct sockaddr_can addr = {};
if ((g_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
{
perror("Socket");
}
strcpy(static_cast<char*>(ifr.ifr_name), "can0");
ioctl(g_socket, SIOCGIFINDEX, &ifr);
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(g_socket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0)
{
perror("Bind");
}
m_rfilter[0].can_id = 0x6A0;
m_rfilter[0].can_mask = 0xFF8; //I already tried 0x958
m_rfilter[1].can_id = 0x0CF02980;
m_rfilter[1].can_mask = 0xFFFFFFFF;
// Set the CAN filters to receive only the desired CAN IDs
setsockopt(g_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &m_rfilter, 2);`
I tried my algo using a recorded camdump containing the expected messages and some others on a virtual machine (virtual CAN):
can0 784 \[8\] B0 84 25 00 00 00 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 6A0 \[8\] F9 18 6A 50 89 67 40 0D
can0 784 \[8\] B0 84 25 00 00 00 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 780 \[8\] 00 00 00 00 98 21 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 780 \[8\] 00 00 00 00 98 21 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 784 \[8\] B0 84 25 00 00 00 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 784 \[8\] B0 84 25 00 00 00 00 00
can0 0CF02980 \[8\] 00 00 78 00 00 82 00 00
can0 780 \[8\] 00 00 00 00 98 21 00 00
can0 6A0 \[8\] F9 18 6A 50 89 68 4C 86
I expected to only receive the filtered Id but I get all of them. I also tried to set the filters to where I expected to discard every incoming CAN message. But also here I get all of them!!!
It really seems, the filtering doesn't work at all!!! Did somebody already implement some CAN filtering on Linux and encounter these problems? According the Linux Doc, it should work as implemented...
Many Thanks in advance for your help
Many thanks for all your answers. I finally find out my mistakes.
CanFilterId = 0x6A0; // 6A* (e.g. 6A0, 6A1, 6A2, 6A3..)
MaskCanId =0x95E; // 6A0 - 6A7
CanFilterId = 0x8cf02980 | CAN_EFF_FLAG;
MaskCanId = (CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK);