diff mbox

[iproute2] ip: add handling for new CAN netlink interface

Message ID 20170519125449.7214-1-remigiusz.kollataj@mobica.com
State Accepted, archived
Delegated to: stephen hemminger
Headers show

Commit Message

Remigiusz Kołłątaj May 19, 2017, 12:54 p.m. UTC
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>
---
 ip/iplink_can.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 94 insertions(+), 4 deletions(-)

Comments

Stephen Hemminger May 22, 2017, 8:37 p.m. UTC | #1
On Fri, 19 May 2017 14:54:49 +0200
Remigiusz Kołłątaj         <remigiusz.kollataj@mobica.com> wrote:

> 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>

What is output without the -d flag?
In general iproute2 show commands are designed to be invertable.
I.e the show command looks like the same command to set.

Printing the bitrates and the format of the state output looks quite different
than the set command. Is it limited to detail (-d)?
Remigiusz Kołłątaj May 23, 2017, 8:47 a.m. UTC | #2
Hi Stephen,

On 22 May 2017 at 22:37, Stephen Hemminger <stephen@networkplumber.org> wrote:
> On Fri, 19 May 2017 14:54:49 +0200
> Remigiusz Kołłątaj         <remigiusz.kollataj@mobica.com> wrote:
>
>> 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>
>
> What is output without the -d flag?

Output _before_ changes:

$ ip link show can0
7: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc fq_codel state UNKNOWN
mode DEFAULT group default qlen 10
    link/can

7: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc fq_codel state UNKNOWN
mode DEFAULT group default qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
          bitrate 1000000 sample-point 0.000
          tq 0 prop-seg 0 phase-seg1 0 phase-seg2 0 sjw 0
          clock 0numtxqueues 1 numrxqueues 1 gso_max_size 65536
gso_max_segs 65535

Output _after_ changes:

$ ./ip link show can0
7: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc fq_codel state UNKNOWN
mode DEFAULT group default qlen 10
    link/can

$ ./ip -d link show can0
7: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc fq_codel state UNKNOWN
mode DEFAULT group default qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
          bitrate 1000000
             [   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

> In general iproute2 show commands are designed to be invertable.
> I.e the show command looks like the same command to set.
>
> Printing the bitrates and the format of the state output looks quite different
> than the set command. Is it limited to detail (-d)?

The change is limited to -d indeed.

4.11 kernel introduced new mechanism for devices that have predefined
bitrates. Before the change there was no possibility to pass to user
space supported bitrate values (other than printk).

I was also wondering about changing the output to:

$ ./ip -d link show can0
7: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc fq_codel state UNKNOWN
mode DEFAULT group default qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
          bitrate 1000000
          bitrate_const  20000,    33333,    50000,    80000,
83333,   100000,
                125000,   150000,   175000,   200000,   225000,   250000,
                275000,   300000,   500000,   625000,   800000,  1000000
          termination 0
          termination_const 0, 120
          clock 0numtxqueues 1 numrxqueues 1 gso_max_size 65536
gso_max_segs 65535

Is it better from your point of view?


Regards,
Remik
Stephen Hemminger May 31, 2017, 12:40 a.m. UTC | #3
On Fri, 19 May 2017 14:54:49 +0200
Remigiusz Kołłątaj         <remigiusz.kollataj@mobica.com> wrote:

> 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>

Applied, thanks for confirming the output change.
diff mbox

Patch

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