This patch adds handling for new CAN netlink interface introduced in 4.11 kernel: - IFLA_CAN_TERMINATION, - IFLA_CAN_TERMINATION_CONST, - IFLA_CAN_BITRATE_CONST, - IFLA_CAN_DATA_BITRATE_CONST
Output example: $ip -d link show can0 6: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0 bitrate 80000 [ 20000, 33333, 50000, 80000, 83333, 100000, 125000, 150000, 175000, 200000, 225000, 250000, 275000, 300000, 500000, 625000, 800000, 1000000 ] termination 0 [ 0, 120 ] clock 0numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 Signed-off-by: Remigiusz Kołłątaj <remigiusz.kolla...@mobica.com> --- ip/iplink_can.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 20d4d37d..5df56b2b 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -41,6 +41,8 @@ static void print_usage(FILE *f) "\t[ restart-ms TIME-MS ]\n" "\t[ restart ]\n" "\n" + "\t[ termination { 0..65535 } ]\n" + "\n" "\tWhere: BITRATE := { 1..1000000 }\n" "\t SAMPLE-POINT := { 0.000..0.999 }\n" "\t TQ := { NUMBER }\n" @@ -220,6 +222,14 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, if (get_u32(&val, *argv, 0)) invarg("invalid \"restart-ms\" value\n", *argv); addattr32(n, 1024, IFLA_CAN_RESTART_MS, val); + } else if (matches(*argv, "termination") == 0) { + __u16 val; + + NEXT_ARG(); + if (get_u16(&val, *argv, 0)) + invarg("invalid \"termination\" value\n", + *argv); + addattr16(n, 1024, IFLA_CAN_TERMINATION, val); } else if (matches(*argv, "help") == 0) { usage(); return -1; @@ -282,7 +292,8 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) fprintf(f, "restart-ms %d ", *restart_ms); } - if (tb[IFLA_CAN_BITTIMING]) { + /* bittiming is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) { struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]); fprintf(f, "\n bitrate %d sample-point %.3f ", @@ -292,7 +303,8 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) bt->sjw); } - if (tb[IFLA_CAN_BITTIMING_CONST]) { + /* bittiming const is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_BITTIMING_CONST] && !tb[IFLA_CAN_BITRATE_CONST]) { struct can_bittiming_const *btc = RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]); @@ -303,7 +315,37 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) btc->brp_min, btc->brp_max, btc->brp_inc); } - if (tb[IFLA_CAN_DATA_BITTIMING]) { + if (tb[IFLA_CAN_BITRATE_CONST]) { + __u32 *bitrate_const = RTA_DATA(tb[IFLA_CAN_BITRATE_CONST]); + int bitrate_cnt = RTA_PAYLOAD(tb[IFLA_CAN_BITRATE_CONST]) / + sizeof(*bitrate_const); + int i; + __u32 bitrate = 0; + + if (tb[IFLA_CAN_BITTIMING]) { + struct can_bittiming *bt = + RTA_DATA(tb[IFLA_CAN_BITTIMING]); + bitrate = bt->bitrate; + } + + fprintf(f, "\n bitrate %u", bitrate); + fprintf(f, "\n ["); + + for (i = 0; i < bitrate_cnt - 1; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) + fprintf(f, "\n "); + + fprintf(f, "%8u, ", bitrate_const[i]); + } + + if (!(i % 6) && i) + fprintf(f, "\n "); + fprintf(f, "%8u ]", bitrate_const[i]); + } + + /* data bittiming is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) { struct can_bittiming *dbt = RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]); @@ -315,7 +357,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) dbt->phase_seg2, dbt->sjw); } - if (tb[IFLA_CAN_DATA_BITTIMING_CONST]) { + /* data bittiming const is irrelevant if fixed bitrate is defined */ + if (tb[IFLA_CAN_DATA_BITTIMING_CONST] && + !tb[IFLA_CAN_DATA_BITRATE_CONST]) { struct can_bittiming_const *dbtc = RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]); @@ -326,6 +370,52 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc); } + if (tb[IFLA_CAN_DATA_BITRATE_CONST]) { + __u32 *dbitrate_const = + RTA_DATA(tb[IFLA_CAN_DATA_BITRATE_CONST]); + int dbitrate_cnt = + RTA_PAYLOAD(tb[IFLA_CAN_DATA_BITRATE_CONST]) / + sizeof(*dbitrate_const); + int i; + __u32 dbitrate = 0; + + if (tb[IFLA_CAN_DATA_BITTIMING]) { + struct can_bittiming *dbt = + RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]); + dbitrate = dbt->bitrate; + } + + fprintf(f, "\n dbitrate %u", dbitrate); + fprintf(f, "\n ["); + + for (i = 0; i < dbitrate_cnt - 1; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) + fprintf(f, "\n "); + + fprintf(f, "%8u, ", dbitrate_const[i]); + } + + if (!(i % 6) && i) + fprintf(f, "\n "); + fprintf(f, "%8u ]", dbitrate_const[i]); + } + + if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) { + __u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]); + __u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]); + int trm_cnt = RTA_PAYLOAD(tb[IFLA_CAN_TERMINATION_CONST]) / + sizeof(*trm_const); + int i; + + fprintf(f, "\n termination %hu [ ", *trm); + + for (i = 0; i < trm_cnt - 1; ++i) + fprintf(f, "%hu, ", trm_const[i]); + + fprintf(f, "%hu ]", trm_const[i]); + } + if (tb[IFLA_CAN_CLOCK]) { struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]); -- 2.13.0