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()) {
319 open_json_object("bittiming");
320 print_int(PRINT_ANY
, "bitrate", NULL
, bt
->bitrate
);
321 jsonw_float_field_fmt(get_json_writer(),
322 "sample_point", "%.3f",
323 (float) bt
->sample_point
/ 1000.);
324 print_int(PRINT_ANY
, "tq", NULL
, bt
->tq
);
325 print_int(PRINT_ANY
, "prop_seg", NULL
, bt
->prop_seg
);
326 print_int(PRINT_ANY
, "phase_seg1",
327 NULL
, bt
->phase_seg1
);
328 print_int(PRINT_ANY
, "phase_seg2",
329 NULL
, bt
->phase_seg2
);
330 print_int(PRINT_ANY
, "sjw", NULL
, bt
->sjw
);
333 fprintf(f
, "\n bitrate %d sample-point %.3f ",
334 bt
->bitrate
, (float) bt
->sample_point
/ 1000.);
336 "\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
337 bt
->tq
, bt
->prop_seg
,
338 bt
->phase_seg1
, bt
->phase_seg2
,
343 /* bittiming const is irrelevant if fixed bitrate is defined */
344 if (tb
[IFLA_CAN_BITTIMING_CONST
] && !tb
[IFLA_CAN_BITRATE_CONST
]) {
345 struct can_bittiming_const
*btc
=
346 RTA_DATA(tb
[IFLA_CAN_BITTIMING_CONST
]);
348 if (is_json_context()) {
349 open_json_object("bittiming_const");
350 print_string(PRINT_JSON
, "name", NULL
, btc
->name
);
351 can_print_json_timing_min_max("tseg1",
354 can_print_json_timing_min_max("tseg2",
357 can_print_json_timing_min_max("sjw", 1, btc
->sjw_max
);
358 can_print_json_timing_min_max("brp",
361 print_int(PRINT_JSON
, "brp_inc", NULL
, btc
->brp_inc
);
364 fprintf(f
, "\n %s: tseg1 %d..%d tseg2 %d..%d "
365 "sjw 1..%d brp %d..%d brp-inc %d",
366 btc
->name
, btc
->tseg1_min
, btc
->tseg1_max
,
367 btc
->tseg2_min
, btc
->tseg2_max
, btc
->sjw_max
,
368 btc
->brp_min
, btc
->brp_max
, btc
->brp_inc
);
372 if (tb
[IFLA_CAN_BITRATE_CONST
]) {
373 __u32
*bitrate_const
= RTA_DATA(tb
[IFLA_CAN_BITRATE_CONST
]);
374 int bitrate_cnt
= RTA_PAYLOAD(tb
[IFLA_CAN_BITRATE_CONST
]) /
375 sizeof(*bitrate_const
);
379 if (tb
[IFLA_CAN_BITTIMING
]) {
380 struct can_bittiming
*bt
=
381 RTA_DATA(tb
[IFLA_CAN_BITTIMING
]);
382 bitrate
= bt
->bitrate
;
385 if (is_json_context()) {
386 print_uint(PRINT_JSON
,
389 open_json_array(PRINT_JSON
, "bitrate_const");
390 for (i
= 0; i
< bitrate_cnt
; ++i
)
391 print_uint(PRINT_JSON
, NULL
, NULL
,
393 close_json_array(PRINT_JSON
, NULL
);
395 fprintf(f
, "\n bitrate %u", bitrate
);
398 for (i
= 0; i
< bitrate_cnt
- 1; ++i
) {
399 /* This will keep lines below 80 signs */
403 fprintf(f
, "%8u, ", bitrate_const
[i
]);
408 fprintf(f
, "%8u ]", bitrate_const
[i
]);
412 /* data bittiming is irrelevant if fixed bitrate is defined */
413 if (tb
[IFLA_CAN_DATA_BITTIMING
] && !tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
414 struct can_bittiming
*dbt
=
415 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING
]);
417 if (is_json_context()) {
418 open_json_object("data_bittiming");
419 print_int(PRINT_JSON
, "bitrate", NULL
, dbt
->bitrate
);
420 jsonw_float_field_fmt(get_json_writer(),
423 (float) dbt
->sample_point
/ 1000.);
424 print_int(PRINT_JSON
, "tq", NULL
, dbt
->tq
);
425 print_int(PRINT_JSON
, "prop_seg", NULL
, dbt
->prop_seg
);
426 print_int(PRINT_JSON
, "phase_seg1",
427 NULL
, dbt
->phase_seg1
);
428 print_int(PRINT_JSON
, "phase_seg2",
429 NULL
, dbt
->phase_seg2
);
430 print_int(PRINT_JSON
, "sjw", NULL
, dbt
->sjw
);
433 fprintf(f
, "\n dbitrate %d dsample-point %.3f ",
435 (float) dbt
->sample_point
/ 1000.);
436 fprintf(f
, "\n dtq %d dprop-seg %d dphase-seg1 %d "
437 "dphase-seg2 %d dsjw %d",
438 dbt
->tq
, dbt
->prop_seg
, dbt
->phase_seg1
,
439 dbt
->phase_seg2
, dbt
->sjw
);
443 /* data bittiming const is irrelevant if fixed bitrate is defined */
444 if (tb
[IFLA_CAN_DATA_BITTIMING_CONST
] &&
445 !tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
446 struct can_bittiming_const
*dbtc
=
447 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING_CONST
]);
449 if (is_json_context()) {
450 open_json_object("data_bittiming_const");
451 print_string(PRINT_JSON
, "name", NULL
, dbtc
->name
);
452 can_print_json_timing_min_max("tseg1",
455 can_print_json_timing_min_max("tseg2",
458 can_print_json_timing_min_max("sjw", 1, dbtc
->sjw_max
);
459 can_print_json_timing_min_max("brp",
463 print_int(PRINT_JSON
, "brp_inc", NULL
, dbtc
->brp_inc
);
466 fprintf(f
, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
467 "dsjw 1..%d dbrp %d..%d dbrp-inc %d",
468 dbtc
->name
, dbtc
->tseg1_min
, dbtc
->tseg1_max
,
469 dbtc
->tseg2_min
, dbtc
->tseg2_max
, dbtc
->sjw_max
,
470 dbtc
->brp_min
, dbtc
->brp_max
, dbtc
->brp_inc
);
474 if (tb
[IFLA_CAN_DATA_BITRATE_CONST
]) {
475 __u32
*dbitrate_const
=
476 RTA_DATA(tb
[IFLA_CAN_DATA_BITRATE_CONST
]);
478 RTA_PAYLOAD(tb
[IFLA_CAN_DATA_BITRATE_CONST
]) /
479 sizeof(*dbitrate_const
);
483 if (tb
[IFLA_CAN_DATA_BITTIMING
]) {
484 struct can_bittiming
*dbt
=
485 RTA_DATA(tb
[IFLA_CAN_DATA_BITTIMING
]);
486 dbitrate
= dbt
->bitrate
;
489 if (is_json_context()) {
490 print_uint(PRINT_JSON
, "data_bittiming_bitrate",
492 open_json_array(PRINT_JSON
, "data_bitrate_const");
493 for (i
= 0; i
< dbitrate_cnt
; ++i
)
494 print_uint(PRINT_JSON
, NULL
, NULL
,
496 close_json_array(PRINT_JSON
, NULL
);
498 fprintf(f
, "\n dbitrate %u", dbitrate
);
501 for (i
= 0; i
< dbitrate_cnt
- 1; ++i
) {
502 /* This will keep lines below 80 signs */
506 fprintf(f
, "%8u, ", dbitrate_const
[i
]);
511 fprintf(f
, "%8u ]", dbitrate_const
[i
]);
515 if (tb
[IFLA_CAN_TERMINATION_CONST
] && tb
[IFLA_CAN_TERMINATION
]) {
516 __u16
*trm
= RTA_DATA(tb
[IFLA_CAN_TERMINATION
]);
517 __u16
*trm_const
= RTA_DATA(tb
[IFLA_CAN_TERMINATION_CONST
]);
518 int trm_cnt
= RTA_PAYLOAD(tb
[IFLA_CAN_TERMINATION_CONST
]) /
522 if (is_json_context()) {
523 print_hu(PRINT_JSON
, "termination", NULL
, *trm
);
524 open_json_array(PRINT_JSON
, "termination_const");
525 for (i
= 0; i
< trm_cnt
; ++i
)
526 print_hu(PRINT_JSON
, NULL
, NULL
, trm_const
[i
]);
527 close_json_array(PRINT_JSON
, NULL
);
529 fprintf(f
, "\n termination %hu [ ", *trm
);
531 for (i
= 0; i
< trm_cnt
- 1; ++i
)
532 fprintf(f
, "%hu, ", trm_const
[i
]);
534 fprintf(f
, "%hu ]", trm_const
[i
]);
538 if (tb
[IFLA_CAN_CLOCK
]) {
539 struct can_clock
*clock
= RTA_DATA(tb
[IFLA_CAN_CLOCK
]);
549 static void can_print_xstats(struct link_util
*lu
,
550 FILE *f
, struct rtattr
*xstats
)
552 struct can_device_stats
*stats
;
554 if (xstats
&& RTA_PAYLOAD(xstats
) == sizeof(*stats
)) {
555 stats
= RTA_DATA(xstats
);
557 if (is_json_context()) {
558 print_int(PRINT_JSON
, "restarts",
559 NULL
, stats
->restarts
);
560 print_int(PRINT_JSON
, "bus_error",
561 NULL
, stats
->bus_error
);
562 print_int(PRINT_JSON
, "arbitration_lost",
563 NULL
, stats
->arbitration_lost
);
564 print_int(PRINT_JSON
, "error_warning",
565 NULL
, stats
->error_warning
);
566 print_int(PRINT_JSON
, "error_passive",
567 NULL
, stats
->error_passive
);
568 print_int(PRINT_JSON
, "bus_off", NULL
, stats
->bus_off
);
570 fprintf(f
, "\n re-started bus-errors arbit-lost "
571 "error-warn error-pass bus-off");
572 fprintf(f
, "\n %-10d %-10d %-10d %-10d %-10d %-10d",
573 stats
->restarts
, stats
->bus_error
,
574 stats
->arbitration_lost
, stats
->error_warning
,
575 stats
->error_passive
, stats
->bus_off
);
580 static void can_print_help(struct link_util
*lu
, int argc
, char **argv
,
586 struct link_util can_link_util
= {
588 .maxattr
= IFLA_CAN_MAX
,
589 .parse_opt
= can_parse_opt
,
590 .print_opt
= can_print_opt
,
591 .print_xstats
= can_print_xstats
,
592 .print_help
= can_print_help
,