candump: support new raw socket option to join the given CAN filters
The CAN_RAW socket can set multiple CAN identifier specific filters that lead to multiple filters in the af_can.c filter processing. These filters are indenpendent from each other which leads to logical OR'ed filters when applied. This socket option joines the given CAN filters in the way that only CAN frames are passed to user space that matched *all* given CAN filters. The semantic for the applied filters is therefore changed to a logical AND. This is useful especially when the filterset is a combination of filters where the CAN_INV_FILTER flag is set in order to notch single CAN IDs or CAN ID ranges from the incoming traffic. Example: candump can0,100~7FF,200~7FF,400~7FF (logical OR'ed filters) candump can0,100~7FF,200~7FF,400~7FF,J (logical AND'ed filters) Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>pull/1/head
parent
0eb1e3db2e
commit
1a2467ed29
|
|
@ -131,6 +131,7 @@ void print_usage(char *prg)
|
||||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||||
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
||||||
|
fprintf(stderr, " [j|J] (join the given CAN filters - logical AND semantic)\n");
|
||||||
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
fprintf(stderr, "\nCAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
||||||
fprintf(stderr, "When can_id and can_mask are both 8 digits, they are assumed to be 29 bit EFF.\n");
|
fprintf(stderr, "When can_id and can_mask are both 8 digits, they are assumed to be 29 bit EFF.\n");
|
||||||
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n");
|
fprintf(stderr, "Without any given filter all data frames are received ('0:0' default filter).\n");
|
||||||
|
|
@ -218,6 +219,7 @@ int main(int argc, char **argv)
|
||||||
int rcvbuf_size = 0;
|
int rcvbuf_size = 0;
|
||||||
int opt, ret;
|
int opt, ret;
|
||||||
int currmax, numfilter;
|
int currmax, numfilter;
|
||||||
|
int join_filter;
|
||||||
char *ptr, *nptr;
|
char *ptr, *nptr;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
|
char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
|
||||||
|
|
@ -467,6 +469,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
numfilter = 0;
|
numfilter = 0;
|
||||||
err_mask = 0;
|
err_mask = 0;
|
||||||
|
join_filter = 0;
|
||||||
|
|
||||||
while (nptr) {
|
while (nptr) {
|
||||||
|
|
||||||
|
|
@ -484,6 +487,8 @@ int main(int argc, char **argv)
|
||||||
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
||||||
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
|
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
|
||||||
numfilter++;
|
numfilter++;
|
||||||
|
} else if (*ptr == 'j' || *ptr == 'J') {
|
||||||
|
join_filter = 1;
|
||||||
} else if (sscanf(ptr, "#%x", &err_mask) != 1) {
|
} else if (sscanf(ptr, "#%x", &err_mask) != 1) {
|
||||||
fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr);
|
fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -498,6 +503,10 @@ int main(int argc, char **argv)
|
||||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||||
rfilter, numfilter * sizeof(struct can_filter));
|
rfilter, numfilter * sizeof(struct can_filter));
|
||||||
|
|
||||||
|
if (join_filter)
|
||||||
|
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS,
|
||||||
|
&join_filter, sizeof(join_filter));
|
||||||
|
|
||||||
free(rfilter);
|
free(rfilter);
|
||||||
|
|
||||||
} /* if (nptr) */
|
} /* if (nptr) */
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ enum {
|
||||||
CAN_RAW_LOOPBACK, /* local loopback (default:on) */
|
CAN_RAW_LOOPBACK, /* local loopback (default:on) */
|
||||||
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
|
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
|
||||||
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
|
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
|
||||||
|
CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue