SocketCAN: фильтрация кадров с определенными идентификаторами CAN не работает - PullRequest
1 голос
/ 29 мая 2019

Я пытаюсь отфильтровать кадры 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 идентификаторы 0x0D6, 0x0D8, 0x0E4 и 0x77F?

1 Ответ

0 голосов
/ 29 мая 2019

При использовании CAN_INV_FILTER, как и вы, вы указываете «все проходит, кроме ID_x».

При использовании CAN_RAW_FILTER он проверит, существует ли правило, которое пропускает полученный идентификатор.В вашем случае ваши правила противоречат друг другу, поэтому ничего не фильтруется.

Из документации :

4.1.6 Опция сокета RAW CAN_RAW_JOIN_FILTERS

Сокет CAN_RAW может устанавливать несколько специфичных для идентификатора CAN фильтров, которые приводят к нескольким фильтрам при обработке фильтра af_can.c.Эти фильтры не зависят друг от друга, что приводит к применению фильтров логического ИЛИ при применении (см. 4.1.1).

Эта опция сокета объединяет данные фильтры CAN таким образом, что только кадры CAN передаются в пространство пользователя.что соответствует всем данным фильтрам CAN.Таким образом, семантика для примененных фильтров изменяется на логическое И.

Это особенно полезно, когда набор фильтров представляет собой комбинацию фильтров, в которых установлен флаг 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));

Примечание: возможно, чтоОпция CAN_RAW_JOIN_FILTERS не поддерживается вашим ядром Linux

...