ip: add handling for new CAN netlink interface

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.kollataj@mobica.com>
This commit is contained in:
Remigiusz Kołłątaj 2017-05-19 14:54:49 +02:00 committed by Stephen Hemminger
parent f6fc1055e4
commit 759fa6086e
1 changed files with 94 additions and 4 deletions

View File

@ -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]);