2 * iplink_can.c CAN device support
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Wolfgang Grandegger <wg@grandegger.com>
16 #include <linux/can/netlink.h>
20 #include "ip_common.h"
22 static void print_usage(FILE *f
)
25 "Usage: ip link set DEVICE type can\n"
26 "\t[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |\n"
27 "\t[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1\n \t phase-seg2 PHASE-SEG2 [ sjw SJW ] ]\n"
29 "\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n"
30 "\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n"
32 "\t[ loopback { on | off } ]\n"
33 "\t[ listen-only { on | off } ]\n"
34 "\t[ triple-sampling { on | off } ]\n"
35 "\t[ one-shot { on | off } ]\n"
36 "\t[ berr-reporting { on | off } ]\n"
37 "\t[ fd { on | off } ]\n"
38 "\t[ fd-non-iso { on | off } ]\n"
39 "\t[ presume-ack { on | off } ]\n"
41 "\t[ restart-ms TIME-MS ]\n"
44 "\t[ termination { 0..65535 } ]\n"
46 "\tWhere: BITRATE := { 1..1000000 }\n"
47 "\t SAMPLE-POINT := { 0.000..0.999 }\n"
48 "\t TQ := { NUMBER }\n"
49 "\t PROP-SEG := { 1..8 }\n"
50 "\t PHASE-SEG1 := { 1..8 }\n"
51 "\t PHASE-SEG2 := { 1..8 }\n"
52 "\t SJW := { 1..4 }\n"
53 "\t RESTART-MS := { 0 | NUMBER }\n"
57 static void usage(void)
62 static int get_float(float *val
, const char *arg
)
69 res
= strtof(arg
, &ptr
);
70 if (!ptr
|| ptr
== arg
|| *ptr
)
76 static void set_ctrlmode(char *name
, char *arg
,
77 struct can_ctrlmode
*cm
, __u32 flags
)
79 if (strcmp(arg
, "on") == 0) {
81 } else if (strcmp(arg
, "off") != 0) {
83 "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
90 static void print_ctrlmode(FILE *f
, __u32 cm
)
92 open_json_array(PRINT_ANY
, is_json_context() ? "ctrlmode" : "<");
93 #define _PF(cmflag, cmname) \
96 print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \
98 _PF(CAN_CTRLMODE_LOOPBACK
, "LOOPBACK");
99 _PF(CAN_CTRLMODE_LISTENONLY
, "LISTEN-ONLY");
100 _PF(CAN_CTRLMODE_3_SAMPLES
, "TRIPLE-SAMPLING");
101 _PF(CAN_CTRLMODE_ONE_SHOT
, "ONE-SHOT");
102 _PF(CAN_CTRLMODE_BERR_REPORTING
, "BERR-REPORTING");
103 _PF(CAN_CTRLMODE_FD
, "FD");
104 _PF(CAN_CTRLMODE_FD_NON_ISO
, "FD-NON-ISO");
105 _PF(CAN_CTRLMODE_PRESUME_ACK
, "PRESUME-ACK");
108 print_hex(PRINT_ANY
, NULL
, "%x", cm
);
109 close_json_array(PRINT_ANY
, "> ");
112 static int can_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
115 struct can_bittiming bt
= {}, dbt
= {};
116 struct can_ctrlmode cm
= {0, 0};
119 if (matches(*argv
, "bitrate") == 0) {
121 if (get_u32(&bt
.bitrate
, *argv
, 0))
122 invarg("invalid \"bitrate\" value\n", *argv
);
123 } else if (matches(*argv
, "sample-point") == 0) {
127 if (get_float(&sp
, *argv
))
128 invarg("invalid \"sample-point\" value\n",
130 bt
.sample_point
= (__u32
)(sp
* 1000);
131 } else if (matches(*argv
, "tq") == 0) {
133 if (get_u32(&bt
.tq
, *argv
, 0))
134 invarg("invalid \"tq\" value\n", *argv
);
135 } else if (matches(*argv
, "prop-seg") == 0) {
137 if (get_u32(&bt
.prop_seg
, *argv
, 0))
138 invarg("invalid \"prop-seg\" value\n", *argv
);
139 } else if (matches(*argv
, "phase-seg1") == 0) {
141 if (get_u32(&bt
.phase_seg1
, *argv
, 0))
142 invarg("invalid \"phase-seg1\" value\n", *argv
);
143 } else if (matches(*argv
, "phase-seg2") == 0) {
145 if (get_u32(&bt
.phase_seg2
, *argv
, 0))
146 invarg("invalid \"phase-seg2\" value\n", *argv
);
147 } else if (matches(*argv
, "sjw") == 0) {
149 if (get_u32(&bt
.sjw
, *argv
, 0))
150 invarg("invalid \"sjw\" value\n", *argv
);
151 } else if (matches(*argv
, "dbitrate") == 0) {
153 if (get_u32(&dbt
.bitrate
, *argv
, 0))
154 invarg("invalid \"dbitrate\" value\n", *argv
);
155 } else if (matches(*argv
, "dsample-point") == 0) {
159 if (get_float(&sp
, *argv
))
160 invarg("invalid \"dsample-point\" value\n", *argv
);
161 dbt
.sample_point
= (__u32
)(sp
* 1000);
162 } else if (matches(*argv
, "dtq") == 0) {
164 if (get_u32(&dbt
.tq
, *argv
, 0))
165 invarg("invalid \"dtq\" value\n", *argv
);
166 } else if (matches(*argv
, "dprop-seg") == 0) {
168 if (get_u32(&dbt
.prop_seg
, *argv
, 0))
169 invarg("invalid \"dprop-seg\" value\n", *argv
);
170 } else if (matches(*argv
, "dphase-seg1") == 0) {
172 if (get_u32(&dbt
.phase_seg1
, *argv
, 0))
173 invarg("invalid \"dphase-seg1\" value\n", *argv
);
174 } else if (matches(*argv
, "dphase-seg2") == 0) {
176 if (get_u32(&dbt
.phase_seg2
, *argv
, 0))
177 invarg("invalid \"dphase-seg2\" value\n", *argv
);
178 } else if (matches(*argv
, "dsjw") == 0) {
180 if (get_u32(&dbt
.sjw
, *argv
, 0))
181 invarg("invalid \"dsjw\" value\n", *argv
);
182 } else if (matches(*argv
, "loopback") == 0) {
184 set_ctrlmode("loopback", *argv
, &cm
,
185 CAN_CTRLMODE_LOOPBACK
);
186 } else if (matches(*argv
, "listen-only") == 0) {
188 set_ctrlmode("listen-only", *argv
, &cm
,
189 CAN_CTRLMODE_LISTENONLY
);
190 } else if (matches(*argv
, "triple-sampling") == 0) {
192 set_ctrlmode("triple-sampling", *argv
, &cm
,
193 CAN_CTRLMODE_3_SAMPLES
);
194 } else if (matches(*argv
, "one-shot") == 0) {
196 set_ctrlmode("one-shot", *argv
, &cm
,
197 CAN_CTRLMODE_ONE_SHOT
);
198 } else if (matches(*argv
, "berr-reporting") == 0) {
200 set_ctrlmode("berr-reporting", *argv
, &cm
,
201 CAN_CTRLMODE_BERR_REPORTING
);
202 } else if (matches(*argv
, "fd") == 0) {
204 set_ctrlmode("fd", *argv
, &cm
,
206 } else if (matches(*argv
, "fd-non-iso") == 0) {
208 set_ctrlmode("fd-non-iso", *argv
, &cm
,
209 CAN_CTRLMODE_FD_NON_ISO
);
210 } else if (matches(*argv
, "presume-ack") == 0) {
212 set_ctrlmode("presume-ack", *argv
, &cm
,
213 CAN_CTRLMODE_PRESUME_ACK
);
214 } else if (matches(*argv
, "restart") == 0) {
217 addattr32(n
, 1024, IFLA_CAN_RESTART
, val
);
218 } else if (matches(*argv
, "restart-ms") == 0) {
222 if (get_u32(&val
, *argv
, 0))
223 invarg("invalid \"restart-ms\" value\n", *argv
);
224 addattr32(n
, 1024, IFLA_CAN_RESTART_MS
, val
);
225 } else if (matches(*argv
, "termination") == 0) {
229 if (get_u16(&val
, *argv
, 0))
230 invarg("invalid \"termination\" value\n",
232 addattr16(n
, 1024, IFLA_CAN_TERMINATION
, val
);
233 } else if (matches(*argv
, "help") == 0) {
237 fprintf(stderr
, "can: unknown option \"%s\"\n", *argv
);
244 if (bt
.bitrate
|| bt
.tq
)
245 addattr_l(n
, 1024, IFLA_CAN_BITTIMING
, &bt
, sizeof(bt
));
246 if (dbt
.bitrate
|| dbt
.tq
)
247 addattr_l(n
, 1024, IFLA_CAN_DATA_BITTIMING
, &dbt
, sizeof(dbt
));
249 addattr_l(n
, 1024, IFLA_CAN_CTRLMODE
, &cm
, sizeof(cm
));
254 static const char *can_state_names
[CAN_STATE_MAX
] = {
255 [CAN_STATE_ERROR_ACTIVE
] = "ERROR-ACTIVE",
256 [CAN_STATE_ERROR_WARNING
] = "ERROR-WARNING",
257 [CAN_STATE_ERROR_PASSIVE
] = "ERROR-PASSIVE",
258 [CAN_STATE_BUS_OFF
] = "BUS-OFF",
259 [CAN_STATE_STOPPED
] = "STOPPED",
260 [CAN_STATE_SLEEPING
] = "SLEEPING"
263 static void can_print_json_timing_min_max(const char *attr
, int min
, int max
)
265 open_json_object(attr
);
266 print_int(PRINT_JSON
, "min", NULL
, min
);
267 print_int(PRINT_JSON
, "max", NULL
, max
);
271 static void can_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
276 if (tb
[IFLA_CAN_CTRLMODE
]) {
277 struct can_ctrlmode
*cm
= RTA_DATA(tb
[IFLA_CAN_CTRLMODE
]);
280 print_ctrlmode(f
, cm
->flags
);
283 if (tb
[IFLA_CAN_STATE
]) {
284 uint32_t state
= rta_getattr_u32(tb
[IFLA_CAN_STATE
]);
286 fprintf(f
, "state %s ", state
< CAN_STATE_MAX
?
287 can_state_names
[state
] : "UNKNOWN");
290 if (tb
[IFLA_CAN_BERR_COUNTER
]) {
291 struct can_berr_counter
*bc
=
292 RTA_DATA(tb
[IFLA_CAN_BERR_COUNTER
]);
294 if (is_json_context()) {
295 open_json_object("berr_counter");
296 print_int(PRINT_JSON
, "tx", NULL
, bc
->txerr
);
297 print_int(PRINT_JSON
, "rx", NULL
, bc
->rxerr
);
300 fprintf(f
, "(berr-counter tx %d rx %d) ",
301 bc
->txerr
, bc
->rxerr
);
305 if (tb
[IFLA_CAN_RESTART_MS
]) {
306 __u32
*restart_ms
= RTA_DATA(tb
[IFLA_CAN_RESTART_MS
]);
314 /* bittiming is irrelevant if fixed bitrate is defined */
315 if (tb
[IFLA_CAN_BITTIMING
] && !tb
[IFLA_CAN_BITRATE_CONST
]) {
316 struct can_bittiming
*bt
= RTA_DATA(tb
[IFLA_CAN_BITTIMING
]);
318 if (is_json_context()) {
321 open_json_object("bittiming");
322 print_int(PRINT_ANY
, "bitrate", NULL
, bt
->bitrate
);
323 jw
= get_json_writer();
324 jsonw_name(jw
, "sample_point");
325 jsonw_printf(jw
, "%.3f",
326 (float) bt
->sample_point
/ 1000);
327 print_int(PRINT_ANY
, "tq", NULL
, bt
->tq
);
328 print_int(PRINT_ANY
, "prop_seg", NULL
, bt
->prop_seg
);
329 print_int(PRINT_ANY
, "phase_seg1",
330 NULL
, bt
->phase_seg1
);
331 print_int(PRINT_ANY
, "phase_seg2",
332 NULL
, bt
->phase_seg2
);
333 print_int(PRINT_ANY
, "sjw", NULL
, bt
->sjw
);
336 fprintf(f
, "\n bitrate %d sample-point %.3f ",
337 bt
->bitrate
, (float) bt
->sample_point
/ 1000.);
339 "\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
340 bt
->tq
, bt
->prop_seg
,
341 bt
->phase_seg1
, bt
->phase_seg2
,
346 /* bittiming const is irrelevant if fixed bitrate is defined */
347 if (tb
[IFLA_CAN_BITTIMING_CONST
] && !tb
[IFLA_CAN_BITRATE_CONST
]) {
348 struct can_bittiming_const
*btc
=
349 RTA_DATA(tb
[IFLA_CAN_BITTIMING_CONST
]);
351 if (is_json_context()) {
352 open_json_object("bittiming_const");
353 print_string(PRINT_JSON
, "name", NULL
, btc
->name
);
354 can_print_json_timing_min_max("tseg1",
357 can_print_json_timing_min_max("tseg2",
360 can_print_json_timing_min_max("sjw", 1, btc
->sjw_max
);
361 can_print_json_timing_min_max("brp",
364 print_int(PRINT_JSON
, "brp_inc", NULL
, btc
->brp_inc
);
367 fprintf(f
, "\n %s: tseg1 %d..%d tseg2 %d..%d "
368 "sjw 1..%d brp %d..%d brp-inc %d",
369 btc
->name
, btc
->tseg1_min
, btc
->tseg1_max
,
370 btc
->tseg2_min
, btc
->tseg2_max
, btc
->sjw_max
,
371 btc
->brp_min
, btc
->brp_max
, btc
->brp_inc
);
375 if (tb
[IFLA_CAN_BITRATE_CONST
]) {
376 __u32
*bitrate_const
= RTA_DATA(tb
[IFLA_CAN_BITRATE_CONST
]);
377 int bitrate_cnt
= RTA_PAYLOAD(tb
[IFLA_CAN_BITRATE_CONST
]) /
378 sizeof(*bitrate_const
);
382 if (tb
[IFLA_CAN_BITTIMING
]) {
383 struct can_bittiming
*bt
=
384 RTA_DATA(tb
[IFLA_CAN_BITTIMING
]);
385 bitrate
= bt
->bitrate
;
388 if (is_json_context()) {
389 print_uint(PRINT_JSON
,
392 open_json_array(PRINT_JSON
, "bitrate_const");
393 for (i
= 0; i
< bitrate_cnt
; ++i
)
394 print_uint(PRINT_JSON
, NULL
, NULL
,
396 close_json_array(PRINT_JSON
, NULL
);
398 fprintf(f
, "\n bitrate %u", bitrate
);
401 for (i
= 0; i
< bitrate_cnt
- 1; ++i
) {
402 /* This will keep lines below 80 signs */
406 fprintf(f
, "%8u, ", bitrate_const
[i
]);
411 fprintf(f
, "%8u ]", bitrate_const
[i
]);
415 /* data bittiming is irrelevant if fixed bitrate is defined */
416 if (tb
[IFLA_CAN_DATA_BITTIMING
] && !tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
417 struct can_bittiming
*dbt
=
418 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING
]);
420 if (is_json_context()) {
423 open_json_object("data_bittiming");
424 print_int(PRINT_JSON
, "bitrate", NULL
, dbt
->bitrate
);
425 jw
= get_json_writer();
426 jsonw_name(jw
, "sample_point");
427 jsonw_printf(jw
, "%.3f",
428 (float) dbt
->sample_point
/ 1000.);
429 print_int(PRINT_JSON
, "tq", NULL
, dbt
->tq
);
430 print_int(PRINT_JSON
, "prop_seg", NULL
, dbt
->prop_seg
);
431 print_int(PRINT_JSON
, "phase_seg1",
432 NULL
, dbt
->phase_seg1
);
433 print_int(PRINT_JSON
, "phase_seg2",
434 NULL
, dbt
->phase_seg2
);
435 print_int(PRINT_JSON
, "sjw", NULL
, dbt
->sjw
);
438 fprintf(f
, "\n dbitrate %d dsample-point %.3f ",
440 (float) dbt
->sample_point
/ 1000.);
441 fprintf(f
, "\n dtq %d dprop-seg %d dphase-seg1 %d "
442 "dphase-seg2 %d dsjw %d",
443 dbt
->tq
, dbt
->prop_seg
, dbt
->phase_seg1
,
444 dbt
->phase_seg2
, dbt
->sjw
);
448 /* data bittiming const is irrelevant if fixed bitrate is defined */
449 if (tb
[IFLA_CAN_DATA_BITTIMING_CONST
] &&
450 !tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
451 struct can_bittiming_const
*dbtc
=
452 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING_CONST
]);
454 if (is_json_context()) {
455 open_json_object("data_bittiming_const");
456 print_string(PRINT_JSON
, "name", NULL
, dbtc
->name
);
457 can_print_json_timing_min_max("tseg1",
460 can_print_json_timing_min_max("tseg2",
463 can_print_json_timing_min_max("sjw", 1, dbtc
->sjw_max
);
464 can_print_json_timing_min_max("brp",
468 print_int(PRINT_JSON
, "brp_inc", NULL
, dbtc
->brp_inc
);
471 fprintf(f
, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
472 "dsjw 1..%d dbrp %d..%d dbrp-inc %d",
473 dbtc
->name
, dbtc
->tseg1_min
, dbtc
->tseg1_max
,
474 dbtc
->tseg2_min
, dbtc
->tseg2_max
, dbtc
->sjw_max
,
475 dbtc
->brp_min
, dbtc
->brp_max
, dbtc
->brp_inc
);
479 if (tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
480 __u32
*dbitrate_const
=
481 RTA_DATA(tb
[IFLA_CAN_DATA_BITRATE_CONST
]);
483 RTA_PAYLOAD(tb
[IFLA_CAN_DATA_BITRATE_CONST
]) /
484 sizeof(*dbitrate_const
);
488 if (tb
[IFLA_CAN_DATA_BITTIMING
]) {
489 struct can_bittiming
*dbt
=
490 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING
]);
491 dbitrate
= dbt
->bitrate
;
494 if (is_json_context()) {
495 print_uint(PRINT_JSON
, "data_bittiming_bitrate",
497 open_json_array(PRINT_JSON
, "data_bitrate_const");
498 for (i
= 0; i
< dbitrate_cnt
; ++i
)
499 print_uint(PRINT_JSON
, NULL
, NULL
,
501 close_json_array(PRINT_JSON
, NULL
);
503 fprintf(f
, "\n dbitrate %u", dbitrate
);
506 for (i
= 0; i
< dbitrate_cnt
- 1; ++i
) {
507 /* This will keep lines below 80 signs */
511 fprintf(f
, "%8u, ", dbitrate_const
[i
]);
516 fprintf(f
, "%8u ]", dbitrate_const
[i
]);
520 if (tb
[IFLA_CAN_TERMINATION_CONST
] && tb
[IFLA_CAN_TERMINATION
]) {
521 __u16
*trm
= RTA_DATA(tb
[IFLA_CAN_TERMINATION
]);
522 __u16
*trm_const
= RTA_DATA(tb
[IFLA_CAN_TERMINATION_CONST
]);
523 int trm_cnt
= RTA_PAYLOAD(tb
[IFLA_CAN_TERMINATION_CONST
]) /
527 if (is_json_context()) {
528 print_hu(PRINT_JSON
, "termination", NULL
, *trm
);
529 open_json_array(PRINT_JSON
, "termination_const");
530 for (i
= 0; i
< trm_cnt
; ++i
)
531 print_hu(PRINT_JSON
, NULL
, NULL
, trm_const
[i
]);
532 close_json_array(PRINT_JSON
, NULL
);
534 fprintf(f
, "\n termination %hu [ ", *trm
);
536 for (i
= 0; i
< trm_cnt
- 1; ++i
)
537 fprintf(f
, "%hu, ", trm_const
[i
]);
539 fprintf(f
, "%hu ]", trm_const
[i
]);
543 if (tb
[IFLA_CAN_CLOCK
]) {
544 struct can_clock
*clock
= RTA_DATA(tb
[IFLA_CAN_CLOCK
]);
554 static void can_print_xstats(struct link_util
*lu
,
555 FILE *f
, struct rtattr
*xstats
)
557 struct can_device_stats
*stats
;
559 if (xstats
&& RTA_PAYLOAD(xstats
) == sizeof(*stats
)) {
560 stats
= RTA_DATA(xstats
);
562 if (is_json_context()) {
563 print_int(PRINT_JSON
, "restarts",
564 NULL
, stats
->restarts
);
565 print_int(PRINT_JSON
, "bus_error",
566 NULL
, stats
->bus_error
);
567 print_int(PRINT_JSON
, "arbitration_lost",
568 NULL
, stats
->arbitration_lost
);
569 print_int(PRINT_JSON
, "error_warning",
570 NULL
, stats
->error_warning
);
571 print_int(PRINT_JSON
, "error_passive",
572 NULL
, stats
->error_passive
);
573 print_int(PRINT_JSON
, "bus_off", NULL
, stats
->bus_off
);
575 fprintf(f
, "\n re-started bus-errors arbit-lost "
576 "error-warn error-pass bus-off");
577 fprintf(f
, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
578 stats
->restarts
, stats
->bus_error
,
579 stats
->arbitration_lost
, stats
->error_warning
,
580 stats
->error_passive
, stats
->bus_off
);
585 static void can_print_help(struct link_util
*lu
, int argc
, char **argv
,
591 struct link_util can_link_util
= {
593 .maxattr
= IFLA_CAN_MAX
,
594 .parse_opt
= can_parse_opt
,
595 .print_opt
= can_print_opt
,
596 .print_xstats
= can_print_xstats
,
597 .print_help
= can_print_help
,