SocketCAN:过滤具有某些CAN ID的帧不起作用

时间:2019-05-29 08:09:45

标签: c can-bus socketcan

我正在尝试按此处所述过滤具有特定ID的CAN帧:https://landlock.io/linux-doc/landlock-v8/networking/can.html#raw-protocol-sockets-with-can-filters-sock-raw

部分代码:

struct can_filter rfilter[4];

if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    fprintf(stderr, "Error while opening socket.\n");
    exit(EXIT_FAILURE);
}
rfilter[0].can_id   = 0x0D6 | CAN_INV_FILTER;
rfilter[0].can_mask = CAN_SFF_MASK;
rfilter[1].can_id   = 0x0D8 | CAN_INV_FILTER;
rfilter[1].can_mask = CAN_SFF_MASK;
rfilter[2].can_id   = 0x0E4 | CAN_INV_FILTER;
rfilter[2].can_mask = CAN_SFF_MASK;
rfilter[3].can_id   = 0x77F | CAN_INV_FILTER;
rfilter[3].can_mask = CAN_SFF_MASK;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

如果我仅使用四个过滤器之一,并注释掉其他三个过滤器,则该过滤器将按预期工作。如果我全部使用四个过滤器,则根本无法使用。在那种情况下,我仍然可以通过CANbus接口接收所有信息。

所以,我的猜测是我的过滤器以某种方式相互抵消了!要过滤CAN ID 0x0D6、0x0D8、0x0E4和0x77F,我需要更改什么?

2 个答案:

答案 0 :(得分:1)

您首先需要提供CAN过滤器:

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

附加一个整数值,以通过setsockopt()启用CAN_RAW_JOIN_FILTERS

int join_filter = 1;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &join_filter, sizeof(join_filter));

顺便说一句。如果为CAN_RAW_JOIN_FILTERS提供了CAN过滤器以将它们设置为setsockopt(),则这是一个意外的长度,应生成-EINVAL作为返回码。

请参阅转储代码: https://github.com/linux-can/can-utils/commit/1a2467ed29302149d4d1253888ac1f1dfcc11d3f

是的,Linux 4.4支持CAN_RAW_JOIN_FILTERS:-)

答案 1 :(得分:0)

像您一样使用CAN_INV_FILTER时,您指定“除ID_x之外的所有内容”。

使用CAN_RAW_FILTER时,它将检查是否存在允许接收的ID通过的规则。就您而言,您的规则相互矛盾,这就是为什么没有过滤任何内容的原因。

来自documentation

  

4.1.6 RAW套接字选项CAN_RAW_JOIN_FILTERS

     

CAN_RAW套接字可以设置多个CAN标识符特定的过滤器   在af_can.c过滤器处理中导致多个过滤器。   这些过滤器相互独立,导致   应用时进行逻辑“或”过滤器(请参见4.1.1)。

     

此套接字选项以仅   将CAN帧传递给与给定CAN all 匹配的用户空间   过滤器。因此更改了所应用过滤器的语义   到逻辑AND。

     

这在过滤器集是以下各项的组合时特别有用   设置CAN_INV_FILTER标志以进行陷波的过滤器   单个CAN ID或CAN ID范围从传入流量开始。

要获得预期的行为,您应该替换:

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

作者:

setsockopt(s, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &rfilter, sizeof(rfilter));

注意:您的Linux内核可能不支持CAN_RAW_JOIN_FILTERS选项