iproute2/ip/iplink_can.c
<<
>>
Prefs
   1/*
   2 * iplink_can.c CAN device support
   3 *
   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.
   8 *
   9 * Authors:     Wolfgang Grandegger <wg@grandegger.com>
  10 */
  11
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15
  16#include <linux/can/netlink.h>
  17
  18#include "rt_names.h"
  19#include "utils.h"
  20#include "ip_common.h"
  21
  22static void print_usage(FILE *f)
  23{
  24        fprintf(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"
  28                "\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"
  31                "\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"
  40                "\t[ cc-len8-dlc { on | off } ]\n"
  41                "\n"
  42                "\t[ restart-ms TIME-MS ]\n"
  43                "\t[ restart ]\n"
  44                "\n"
  45                "\t[ termination { 0..65535 } ]\n"
  46                "\n"
  47                "\tWhere: BITRATE       := { 1..1000000 }\n"
  48                "\t       SAMPLE-POINT  := { 0.000..0.999 }\n"
  49                "\t       TQ            := { NUMBER }\n"
  50                "\t       PROP-SEG      := { 1..8 }\n"
  51                "\t       PHASE-SEG1    := { 1..8 }\n"
  52                "\t       PHASE-SEG2    := { 1..8 }\n"
  53                "\t       SJW           := { 1..4 }\n"
  54                "\t       RESTART-MS    := { 0 | NUMBER }\n"
  55                );
  56}
  57
  58static void usage(void)
  59{
  60        print_usage(stderr);
  61}
  62
  63static int get_float(float *val, const char *arg)
  64{
  65        float res;
  66        char *ptr;
  67
  68        if (!arg || !*arg)
  69                return -1;
  70        res = strtof(arg, &ptr);
  71        if (!ptr || ptr == arg || *ptr)
  72                return -1;
  73        *val = res;
  74        return 0;
  75}
  76
  77static void set_ctrlmode(char *name, char *arg,
  78                         struct can_ctrlmode *cm, __u32 flags)
  79{
  80        if (strcmp(arg, "on") == 0) {
  81                cm->flags |= flags;
  82        } else if (strcmp(arg, "off") != 0) {
  83                fprintf(stderr,
  84                        "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n",
  85                        name, arg);
  86                exit(-1);
  87        }
  88        cm->mask |= flags;
  89}
  90
  91static void print_ctrlmode(FILE *f, __u32 cm)
  92{
  93        open_json_array(PRINT_ANY, is_json_context() ? "ctrlmode" : "<");
  94#define _PF(cmflag, cmname)                                             \
  95        if (cm & cmflag) {                                              \
  96                cm &= ~cmflag;                                          \
  97                print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \
  98        }
  99        _PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
 100        _PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
 101        _PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING");
 102        _PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT");
 103        _PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING");
 104        _PF(CAN_CTRLMODE_FD, "FD");
 105        _PF(CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO");
 106        _PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
 107        _PF(CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC");
 108#undef _PF
 109        if (cm)
 110                print_hex(PRINT_ANY, NULL, "%x", cm);
 111        close_json_array(PRINT_ANY, "> ");
 112}
 113
 114static int can_parse_opt(struct link_util *lu, int argc, char **argv,
 115                         struct nlmsghdr *n)
 116{
 117        struct can_bittiming bt = {}, dbt = {};
 118        struct can_ctrlmode cm = {0, 0};
 119
 120        while (argc > 0) {
 121                if (matches(*argv, "bitrate") == 0) {
 122                        NEXT_ARG();
 123                        if (get_u32(&bt.bitrate, *argv, 0))
 124                                invarg("invalid \"bitrate\" value\n", *argv);
 125                } else if (matches(*argv, "sample-point") == 0) {
 126                        float sp;
 127
 128                        NEXT_ARG();
 129                        if (get_float(&sp, *argv))
 130                                invarg("invalid \"sample-point\" value\n",
 131                                       *argv);
 132                        bt.sample_point = (__u32)(sp * 1000);
 133                } else if (matches(*argv, "tq") == 0) {
 134                        NEXT_ARG();
 135                        if (get_u32(&bt.tq, *argv, 0))
 136                                invarg("invalid \"tq\" value\n", *argv);
 137                } else if (matches(*argv, "prop-seg") == 0) {
 138                        NEXT_ARG();
 139                        if (get_u32(&bt.prop_seg, *argv, 0))
 140                                invarg("invalid \"prop-seg\" value\n", *argv);
 141                } else if (matches(*argv, "phase-seg1") == 0) {
 142                        NEXT_ARG();
 143                        if (get_u32(&bt.phase_seg1, *argv, 0))
 144                                invarg("invalid \"phase-seg1\" value\n", *argv);
 145                } else if (matches(*argv, "phase-seg2") == 0) {
 146                        NEXT_ARG();
 147                        if (get_u32(&bt.phase_seg2, *argv, 0))
 148                                invarg("invalid \"phase-seg2\" value\n", *argv);
 149                } else if (matches(*argv, "sjw") == 0) {
 150                        NEXT_ARG();
 151                        if (get_u32(&bt.sjw, *argv, 0))
 152                                invarg("invalid \"sjw\" value\n", *argv);
 153                } else if (matches(*argv, "dbitrate") == 0) {
 154                        NEXT_ARG();
 155                        if (get_u32(&dbt.bitrate, *argv, 0))
 156                                invarg("invalid \"dbitrate\" value\n", *argv);
 157                } else if (matches(*argv, "dsample-point") == 0) {
 158                        float sp;
 159
 160                        NEXT_ARG();
 161                        if (get_float(&sp, *argv))
 162                                invarg("invalid \"dsample-point\" value\n", *argv);
 163                        dbt.sample_point = (__u32)(sp * 1000);
 164                } else if (matches(*argv, "dtq") == 0) {
 165                        NEXT_ARG();
 166                        if (get_u32(&dbt.tq, *argv, 0))
 167                                invarg("invalid \"dtq\" value\n", *argv);
 168                } else if (matches(*argv, "dprop-seg") == 0) {
 169                        NEXT_ARG();
 170                        if (get_u32(&dbt.prop_seg, *argv, 0))
 171                                invarg("invalid \"dprop-seg\" value\n", *argv);
 172                } else if (matches(*argv, "dphase-seg1") == 0) {
 173                        NEXT_ARG();
 174                        if (get_u32(&dbt.phase_seg1, *argv, 0))
 175                                invarg("invalid \"dphase-seg1\" value\n", *argv);
 176                } else if (matches(*argv, "dphase-seg2") == 0) {
 177                        NEXT_ARG();
 178                        if (get_u32(&dbt.phase_seg2, *argv, 0))
 179                                invarg("invalid \"dphase-seg2\" value\n", *argv);
 180                } else if (matches(*argv, "dsjw") == 0) {
 181                        NEXT_ARG();
 182                        if (get_u32(&dbt.sjw, *argv, 0))
 183                                invarg("invalid \"dsjw\" value\n", *argv);
 184                } else if (matches(*argv, "loopback") == 0) {
 185                        NEXT_ARG();
 186                        set_ctrlmode("loopback", *argv, &cm,
 187                                     CAN_CTRLMODE_LOOPBACK);
 188                } else if (matches(*argv, "listen-only") == 0) {
 189                        NEXT_ARG();
 190                        set_ctrlmode("listen-only", *argv, &cm,
 191                                     CAN_CTRLMODE_LISTENONLY);
 192                } else if (matches(*argv, "triple-sampling") == 0) {
 193                        NEXT_ARG();
 194                        set_ctrlmode("triple-sampling", *argv, &cm,
 195                                     CAN_CTRLMODE_3_SAMPLES);
 196                } else if (matches(*argv, "one-shot") == 0) {
 197                        NEXT_ARG();
 198                        set_ctrlmode("one-shot", *argv, &cm,
 199                                     CAN_CTRLMODE_ONE_SHOT);
 200                } else if (matches(*argv, "berr-reporting") == 0) {
 201                        NEXT_ARG();
 202                        set_ctrlmode("berr-reporting", *argv, &cm,
 203                                     CAN_CTRLMODE_BERR_REPORTING);
 204                } else if (matches(*argv, "fd") == 0) {
 205                        NEXT_ARG();
 206                        set_ctrlmode("fd", *argv, &cm,
 207                                     CAN_CTRLMODE_FD);
 208                } else if (matches(*argv, "fd-non-iso") == 0) {
 209                        NEXT_ARG();
 210                        set_ctrlmode("fd-non-iso", *argv, &cm,
 211                                     CAN_CTRLMODE_FD_NON_ISO);
 212                } else if (matches(*argv, "presume-ack") == 0) {
 213                        NEXT_ARG();
 214                        set_ctrlmode("presume-ack", *argv, &cm,
 215                                     CAN_CTRLMODE_PRESUME_ACK);
 216                } else if (matches(*argv, "cc-len8-dlc") == 0) {
 217                        NEXT_ARG();
 218                        set_ctrlmode("cc-len8-dlc", *argv, &cm,
 219                                     CAN_CTRLMODE_CC_LEN8_DLC);
 220                } else if (matches(*argv, "restart") == 0) {
 221                        __u32 val = 1;
 222
 223                        addattr32(n, 1024, IFLA_CAN_RESTART, val);
 224                } else if (matches(*argv, "restart-ms") == 0) {
 225                        __u32 val;
 226
 227                        NEXT_ARG();
 228                        if (get_u32(&val, *argv, 0))
 229                                invarg("invalid \"restart-ms\" value\n", *argv);
 230                        addattr32(n, 1024, IFLA_CAN_RESTART_MS, val);
 231                } else if (matches(*argv, "termination") == 0) {
 232                        __u16 val;
 233
 234                        NEXT_ARG();
 235                        if (get_u16(&val, *argv, 0))
 236                                invarg("invalid \"termination\" value\n",
 237                                       *argv);
 238                        addattr16(n, 1024, IFLA_CAN_TERMINATION, val);
 239                } else if (matches(*argv, "help") == 0) {
 240                        usage();
 241                        return -1;
 242                } else {
 243                        fprintf(stderr, "can: unknown option \"%s\"\n", *argv);
 244                        usage();
 245                        return -1;
 246                }
 247                argc--, argv++;
 248        }
 249
 250        if (bt.bitrate || bt.tq)
 251                addattr_l(n, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
 252        if (dbt.bitrate || dbt.tq)
 253                addattr_l(n, 1024, IFLA_CAN_DATA_BITTIMING, &dbt, sizeof(dbt));
 254        if (cm.mask)
 255                addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
 256
 257        return 0;
 258}
 259
 260static const char *can_state_names[CAN_STATE_MAX] = {
 261        [CAN_STATE_ERROR_ACTIVE] = "ERROR-ACTIVE",
 262        [CAN_STATE_ERROR_WARNING] = "ERROR-WARNING",
 263        [CAN_STATE_ERROR_PASSIVE] = "ERROR-PASSIVE",
 264        [CAN_STATE_BUS_OFF] = "BUS-OFF",
 265        [CAN_STATE_STOPPED] = "STOPPED",
 266        [CAN_STATE_SLEEPING] = "SLEEPING"
 267};
 268
 269static void can_print_json_timing_min_max(const char *attr, int min, int max)
 270{
 271        open_json_object(attr);
 272        print_int(PRINT_JSON, "min", NULL, min);
 273        print_int(PRINT_JSON, "max", NULL, max);
 274        close_json_object();
 275}
 276
 277static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 278{
 279        if (!tb)
 280                return;
 281
 282        if (tb[IFLA_CAN_CTRLMODE]) {
 283                struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);
 284
 285                if (cm->flags)
 286                        print_ctrlmode(f, cm->flags);
 287        }
 288
 289        if (tb[IFLA_CAN_STATE]) {
 290                uint32_t state = rta_getattr_u32(tb[IFLA_CAN_STATE]);
 291
 292                print_string(PRINT_ANY, "state", "state %s ", state < CAN_STATE_MAX ?
 293                        can_state_names[state] : "UNKNOWN");
 294        }
 295
 296        if (tb[IFLA_CAN_BERR_COUNTER]) {
 297                struct can_berr_counter *bc =
 298                        RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
 299
 300                if (is_json_context()) {
 301                        open_json_object("berr_counter");
 302                        print_int(PRINT_JSON, "tx", NULL, bc->txerr);
 303                        print_int(PRINT_JSON, "rx", NULL, bc->rxerr);
 304                        close_json_object();
 305                } else {
 306                        fprintf(f, "(berr-counter tx %d rx %d) ",
 307                                bc->txerr, bc->rxerr);
 308                }
 309        }
 310
 311        if (tb[IFLA_CAN_RESTART_MS]) {
 312                __u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
 313
 314                print_int(PRINT_ANY,
 315                          "restart_ms",
 316                          "restart-ms %d ",
 317                          *restart_ms);
 318        }
 319
 320        /* bittiming is irrelevant if fixed bitrate is defined */
 321        if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
 322                struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
 323
 324                if (is_json_context()) {
 325                        json_writer_t *jw;
 326
 327                        open_json_object("bittiming");
 328                        print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
 329                        jw = get_json_writer();
 330                        jsonw_name(jw, "sample_point");
 331                        jsonw_printf(jw, "%.3f",
 332                                     (float) bt->sample_point / 1000);
 333                        print_int(PRINT_ANY, "tq", NULL, bt->tq);
 334                        print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg);
 335                        print_int(PRINT_ANY, "phase_seg1",
 336                                  NULL, bt->phase_seg1);
 337                        print_int(PRINT_ANY, "phase_seg2",
 338                                  NULL, bt->phase_seg2);
 339                        print_int(PRINT_ANY, "sjw", NULL, bt->sjw);
 340                        close_json_object();
 341                } else {
 342                        fprintf(f, "\n    bitrate %d sample-point %.3f ",
 343                                bt->bitrate, (float) bt->sample_point / 1000.);
 344                        fprintf(f,
 345                                "\n       tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d",
 346                                bt->tq, bt->prop_seg,
 347                                bt->phase_seg1, bt->phase_seg2,
 348                                bt->sjw);
 349                }
 350        }
 351
 352        /* bittiming const is irrelevant if fixed bitrate is defined */
 353        if (tb[IFLA_CAN_BITTIMING_CONST] && !tb[IFLA_CAN_BITRATE_CONST]) {
 354                struct can_bittiming_const *btc =
 355                        RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]);
 356
 357                if (is_json_context()) {
 358                        open_json_object("bittiming_const");
 359                        print_string(PRINT_JSON, "name", NULL, btc->name);
 360                        can_print_json_timing_min_max("tseg1",
 361                                                      btc->tseg1_min,
 362                                                      btc->tseg1_max);
 363                        can_print_json_timing_min_max("tseg2",
 364                                                      btc->tseg2_min,
 365                                                      btc->tseg2_max);
 366                        can_print_json_timing_min_max("sjw", 1, btc->sjw_max);
 367                        can_print_json_timing_min_max("brp",
 368                                                      btc->brp_min,
 369                                                      btc->brp_max);
 370                        print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc);
 371                        close_json_object();
 372                } else {
 373                        fprintf(f, "\n    %s: tseg1 %d..%d tseg2 %d..%d "
 374                                "sjw 1..%d brp %d..%d brp-inc %d",
 375                                btc->name, btc->tseg1_min, btc->tseg1_max,
 376                                btc->tseg2_min, btc->tseg2_max, btc->sjw_max,
 377                                btc->brp_min, btc->brp_max, btc->brp_inc);
 378                }
 379        }
 380
 381        if (tb[IFLA_CAN_BITRATE_CONST]) {
 382                __u32 *bitrate_const = RTA_DATA(tb[IFLA_CAN_BITRATE_CONST]);
 383                int bitrate_cnt = RTA_PAYLOAD(tb[IFLA_CAN_BITRATE_CONST]) /
 384                        sizeof(*bitrate_const);
 385                int i;
 386                __u32 bitrate = 0;
 387
 388                if (tb[IFLA_CAN_BITTIMING]) {
 389                        struct can_bittiming *bt =
 390                                RTA_DATA(tb[IFLA_CAN_BITTIMING]);
 391                        bitrate = bt->bitrate;
 392                }
 393
 394                if (is_json_context()) {
 395                        print_uint(PRINT_JSON,
 396                                   "bittiming_bitrate",
 397                                   NULL, bitrate);
 398                        open_json_array(PRINT_JSON, "bitrate_const");
 399                        for (i = 0; i < bitrate_cnt; ++i)
 400                                print_uint(PRINT_JSON, NULL, NULL,
 401                                           bitrate_const[i]);
 402                        close_json_array(PRINT_JSON, NULL);
 403                } else {
 404                        fprintf(f, "\n    bitrate %u", bitrate);
 405                        fprintf(f, "\n       [");
 406
 407                        for (i = 0; i < bitrate_cnt - 1; ++i) {
 408                                /* This will keep lines below 80 signs */
 409                                if (!(i % 6) && i)
 410                                        fprintf(f, "\n        ");
 411
 412                                fprintf(f, "%8u, ", bitrate_const[i]);
 413                        }
 414
 415                        if (!(i % 6) && i)
 416                                fprintf(f, "\n        ");
 417                        fprintf(f, "%8u ]", bitrate_const[i]);
 418                }
 419        }
 420
 421        /* data bittiming is irrelevant if fixed bitrate is defined */
 422        if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
 423                struct can_bittiming *dbt =
 424                        RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
 425
 426                if (is_json_context()) {
 427                        json_writer_t *jw;
 428
 429                        open_json_object("data_bittiming");
 430                        print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
 431                        jw = get_json_writer();
 432                        jsonw_name(jw, "sample_point");
 433                        jsonw_printf(jw, "%.3f",
 434                                     (float) dbt->sample_point / 1000.);
 435                        print_int(PRINT_JSON, "tq", NULL, dbt->tq);
 436                        print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg);
 437                        print_int(PRINT_JSON, "phase_seg1",
 438                                  NULL, dbt->phase_seg1);
 439                        print_int(PRINT_JSON, "phase_seg2",
 440                                  NULL, dbt->phase_seg2);
 441                        print_int(PRINT_JSON, "sjw", NULL, dbt->sjw);
 442                        close_json_object();
 443                } else {
 444                        fprintf(f, "\n    dbitrate %d dsample-point %.3f ",
 445                                dbt->bitrate,
 446                                (float) dbt->sample_point / 1000.);
 447                        fprintf(f, "\n    dtq %d dprop-seg %d dphase-seg1 %d "
 448                                "dphase-seg2 %d dsjw %d",
 449                                dbt->tq, dbt->prop_seg, dbt->phase_seg1,
 450                                dbt->phase_seg2, dbt->sjw);
 451                }
 452        }
 453
 454        /* data bittiming const is irrelevant if fixed bitrate is defined */
 455        if (tb[IFLA_CAN_DATA_BITTIMING_CONST] &&
 456            !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
 457                struct can_bittiming_const *dbtc =
 458                        RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]);
 459
 460                if (is_json_context()) {
 461                        open_json_object("data_bittiming_const");
 462                        print_string(PRINT_JSON, "name", NULL, dbtc->name);
 463                        can_print_json_timing_min_max("tseg1",
 464                                                      dbtc->tseg1_min,
 465                                                      dbtc->tseg1_max);
 466                        can_print_json_timing_min_max("tseg2",
 467                                                      dbtc->tseg2_min,
 468                                                      dbtc->tseg2_max);
 469                        can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max);
 470                        can_print_json_timing_min_max("brp",
 471                                                      dbtc->brp_min,
 472                                                      dbtc->brp_max);
 473
 474                        print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
 475                        close_json_object();
 476                } else {
 477                        fprintf(f, "\n    %s: dtseg1 %d..%d dtseg2 %d..%d "
 478                                "dsjw 1..%d dbrp %d..%d dbrp-inc %d",
 479                                dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
 480                                dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
 481                                dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
 482                }
 483        }
 484
 485        if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
 486                __u32 *dbitrate_const =
 487                        RTA_DATA(tb[IFLA_CAN_DATA_BITRATE_CONST]);
 488                int dbitrate_cnt =
 489                        RTA_PAYLOAD(tb[IFLA_CAN_DATA_BITRATE_CONST]) /
 490                        sizeof(*dbitrate_const);
 491                int i;
 492                __u32 dbitrate = 0;
 493
 494                if (tb[IFLA_CAN_DATA_BITTIMING]) {
 495                        struct can_bittiming *dbt =
 496                                RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
 497                        dbitrate = dbt->bitrate;
 498                }
 499
 500                if (is_json_context()) {
 501                        print_uint(PRINT_JSON, "data_bittiming_bitrate",
 502                                   NULL, dbitrate);
 503                        open_json_array(PRINT_JSON, "data_bitrate_const");
 504                        for (i = 0; i < dbitrate_cnt; ++i)
 505                                print_uint(PRINT_JSON, NULL, NULL,
 506                                           dbitrate_const[i]);
 507                        close_json_array(PRINT_JSON, NULL);
 508                } else {
 509                        fprintf(f, "\n    dbitrate %u", dbitrate);
 510                        fprintf(f, "\n       [");
 511
 512                        for (i = 0; i < dbitrate_cnt - 1; ++i) {
 513                                /* This will keep lines below 80 signs */
 514                                if (!(i % 6) && i)
 515                                        fprintf(f, "\n        ");
 516
 517                                fprintf(f, "%8u, ", dbitrate_const[i]);
 518                        }
 519
 520                        if (!(i % 6) && i)
 521                                fprintf(f, "\n        ");
 522                        fprintf(f, "%8u ]", dbitrate_const[i]);
 523                }
 524        }
 525
 526        if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
 527                __u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]);
 528                __u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]);
 529                int trm_cnt = RTA_PAYLOAD(tb[IFLA_CAN_TERMINATION_CONST]) /
 530                        sizeof(*trm_const);
 531                int i;
 532
 533                if (is_json_context()) {
 534                        print_hu(PRINT_JSON, "termination", NULL, *trm);
 535                        open_json_array(PRINT_JSON, "termination_const");
 536                        for (i = 0; i < trm_cnt; ++i)
 537                                print_hu(PRINT_JSON, NULL, NULL, trm_const[i]);
 538                        close_json_array(PRINT_JSON, NULL);
 539                } else {
 540                        fprintf(f, "\n    termination %hu [ ", *trm);
 541
 542                        for (i = 0; i < trm_cnt - 1; ++i)
 543                                fprintf(f, "%hu, ", trm_const[i]);
 544
 545                        fprintf(f, "%hu ]", trm_const[i]);
 546                }
 547        }
 548
 549        if (tb[IFLA_CAN_CLOCK]) {
 550                struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
 551
 552                print_int(PRINT_ANY,
 553                          "clock",
 554                          "\n     clock %d ",
 555                          clock->freq);
 556        }
 557
 558}
 559
 560static void can_print_xstats(struct link_util *lu,
 561                             FILE *f, struct rtattr *xstats)
 562{
 563        struct can_device_stats *stats;
 564
 565        if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
 566                stats = RTA_DATA(xstats);
 567
 568                if (is_json_context()) {
 569                        print_int(PRINT_JSON, "restarts",
 570                                  NULL, stats->restarts);
 571                        print_int(PRINT_JSON, "bus_error",
 572                                  NULL, stats->bus_error);
 573                        print_int(PRINT_JSON, "arbitration_lost",
 574                                  NULL, stats->arbitration_lost);
 575                        print_int(PRINT_JSON, "error_warning",
 576                                  NULL, stats->error_warning);
 577                        print_int(PRINT_JSON, "error_passive",
 578                                  NULL, stats->error_passive);
 579                        print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off);
 580                } else {
 581                        fprintf(f, "\n    re-started bus-errors arbit-lost "
 582                                "error-warn error-pass bus-off");
 583                        fprintf(f, "\n    %-10d %-10d %-10d %-10d %-10d %-10d",
 584                                stats->restarts, stats->bus_error,
 585                                stats->arbitration_lost, stats->error_warning,
 586                                stats->error_passive, stats->bus_off);
 587                }
 588        }
 589}
 590
 591static void can_print_help(struct link_util *lu, int argc, char **argv,
 592                           FILE *f)
 593{
 594        print_usage(f);
 595}
 596
 597struct link_util can_link_util = {
 598        .id             = "can",
 599        .maxattr        = IFLA_CAN_MAX,
 600        .parse_opt      = can_parse_opt,
 601        .print_opt      = can_print_opt,
 602        .print_xstats   = can_print_xstats,
 603        .print_help     = can_print_help,
 604};
 605