isotpsend: add support for transmission without flow control

Usually the ISO 15765-2 protocol is a point-to-point protocol to transfer
segmented PDUs to a dedicated receiver. This receiver sends a flow control
message to specify protocol options and timings (e.g. block size / STmin).

The so called functional addressing communication allows a 1:N
communication but is limited to a single frame length.

The new CAN_ISOTP_CF_BROADCAST flag introduced in Linux 5.19 allows an
unconfirmed 1:N communication with PDU lengths that would not fit into a
single frame. This feature is not covered by the ISO 15765-2 standard.

The isotpsend tool gets a new option '-C' to enable this unconfirmed 1:N
communication by setting the CAN_ISOTP_CF_BROADCAST flag.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
pull/365/head
Oliver Hartkopp 2022-05-13 20:00:45 +02:00
parent d320a4a871
commit 6e7f845a68
2 changed files with 30 additions and 17 deletions

View File

@ -124,18 +124,19 @@ struct can_isotp_ll_options {
/* flags for isotp behaviour */ /* flags for isotp behaviour */
#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */ #define CAN_ISOTP_LISTEN_MODE 0x0001 /* listen only (do not send FC) */
#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */ #define CAN_ISOTP_EXTEND_ADDR 0x0002 /* enable extended addressing */
#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */ #define CAN_ISOTP_TX_PADDING 0x0004 /* enable CAN frame padding tx path */
#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */ #define CAN_ISOTP_RX_PADDING 0x0008 /* enable CAN frame padding rx path */
#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */ #define CAN_ISOTP_CHK_PAD_LEN 0x0010 /* check received CAN frame padding */
#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */ #define CAN_ISOTP_CHK_PAD_DATA 0x0020 /* check received CAN frame padding */
#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */ #define CAN_ISOTP_HALF_DUPLEX 0x0040 /* half duplex error state handling */
#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */ #define CAN_ISOTP_FORCE_TXSTMIN 0x0080 /* ignore stmin from received FC */
#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */ #define CAN_ISOTP_FORCE_RXSTMIN 0x0100 /* ignore CFs depending on rx stmin */
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */ #define CAN_ISOTP_RX_EXT_ADDR 0x0200 /* different rx extended addressing */
#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */ #define CAN_ISOTP_WAIT_TX_DONE 0x0400 /* wait for tx completion */
#define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */ #define CAN_ISOTP_SF_BROADCAST 0x0800 /* 1-to-N functional addressing */
#define CAN_ISOTP_CF_BROADCAST 0x1000 /* 1-to-N transmission w/o FC */
/* protocol machine default values */ /* protocol machine default values */

View File

@ -75,7 +75,8 @@ void print_usage(char *prg)
fprintf(stderr, " -l <num> (send num PDUs - use 'i' for infinite loop)\n"); fprintf(stderr, " -l <num> (send num PDUs - use 'i' for infinite loop)\n");
fprintf(stderr, " -g <usecs> (wait given usecs before sending a PDU)\n"); fprintf(stderr, " -g <usecs> (wait given usecs before sending a PDU)\n");
fprintf(stderr, " -b (block until the PDU transmission is completed)\n"); fprintf(stderr, " -b (block until the PDU transmission is completed)\n");
fprintf(stderr, " -S (SF broadcast mode for functional addressing)\n"); fprintf(stderr, " -S (SF broadcast mode - for functional addressing)\n");
fprintf(stderr, " -C (CF broadcast mode - no wait for flow controls)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n"); fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n"); fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n"); fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n");
@ -101,7 +102,7 @@ int main(int argc, char **argv)
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID; addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSL:?")) != -1) { while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
switch (opt) { switch (opt) {
case 's': case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16); addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
@ -211,6 +212,10 @@ int main(int argc, char **argv)
opts.flags |= CAN_ISOTP_SF_BROADCAST; opts.flags |= CAN_ISOTP_SF_BROADCAST;
break; break;
case 'C':
opts.flags |= CAN_ISOTP_CF_BROADCAST;
break;
case 'L': case 'L':
if (sscanf(optarg, "%hhu:%hhu:%hhu", if (sscanf(optarg, "%hhu:%hhu:%hhu",
&llopts.mtu, &llopts.mtu,
@ -235,20 +240,27 @@ int main(int argc, char **argv)
} }
} }
#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
if ((argc - optind != 1) || if ((argc - optind != 1) ||
(addr.can_addr.tp.tx_id == NO_CAN_ID) || (addr.can_addr.tp.tx_id == NO_CAN_ID) ||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
((addr.can_addr.tp.rx_id == NO_CAN_ID) && ((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
(!(opts.flags & CAN_ISOTP_SF_BROADCAST)))) { (!(opts.flags & BC_FLAGS)))) {
print_usage(basename(argv[0])); print_usage(basename(argv[0]));
exit(1); exit(1);
} }
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) { if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
perror("socket"); perror("socket");
exit(1); exit(1);
} }
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)); if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
perror("sockopt");
exit(1);
}
if (llopts.tx_dl) { if (llopts.tx_dl) {
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) { if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {