2022-01-06 10:30:04

by Vincent MAILHOL

[permalink] [raw]
Subject: [RFC PATCH v3] iplink_can: add ctrlmode_{supported,_static} to the "--details --json" output

This patch is the userland counterpart of [1]. Indeed, [1] allows the
can netlink interface to report the CAN controller capabilities.

Previously, only the options which were switched on were reported
(i.e. can_priv::ctrlmode). Here, we add two additional pieces of
information to the json report:

- ctrlmode_supported: the options that can be modified by netlink

- ctrlmode_static: option which are statically enabled by the driver
(i.e. can not be turned off)

For your information, we borrowed the naming convention from struct
can_priv [2].

Contrary to the ctrlmode, the ctrlmode_{supported,_static} are only
reported in the json context. The reason is that this newly added
information can quickly become very verbose and we do not want to
overload the default output. You can think of the "ip --details link
show canX" output as the verbose mode and the "ip --details --json
link show canX" output as the *very* verbose mode.

*Example:*

This is how the output would look like for a dummy driver which would
have:

- CAN_CTRLMODE_LOOPBACK, CAN_CTRLMODE_LISTENONLY,
CAN_CTRLMODE_3_SAMPLES, CAN_CTRLMODE_FD, CAN_CTRLMODE_CC_LEN8_DLC
and TDC-AUTO supported by the driver

- CAN_CTRLMODE_CC_LEN8_DLC turned on by the user

- CAN_CTRLMODE_FD_NON_ISO statically enabled by the driver

| $ ip link set can0 type can cc-len8-dlc on
| $ ip --details --json --pretty link show can0
| [ {
| "ifindex": 1,
| "ifname": "can0",
| "flags": [ "NOARP","ECHO" ],
| "mtu": 16,
| "qdisc": "noop",
| "operstate": "DOWN",
| "linkmode": "DEFAULT",
| "group": "default",
| "txqlen": 10,
| "link_type": "can",
| "promiscuity": 0,
| "min_mtu": 0,
| "max_mtu": 0,
| "linkinfo": {
| "info_kind": "can",
| "info_data": {
| "ctrlmode": [ "FD-NON-ISO","CC-LEN8-DLC" ],
| "ctrlmode_supported": [ "LOOPBACK","LISTEN-ONLY","TRIPLE-SAMPLING","FD","CC-LEN8-DLC","TDC-AUTO" ],
| "ctrlmode_static": [ "FD-NON-ISO" ],
| "state": "STOPPED",
| "restart_ms": 0,
| "bittiming_const": {
| "name": "DUMMY_CAN_DEV",
| "tseg1": {
| "min": 2,
| "max": 256
| },
| "tseg2": {
| "min": 2,
| "max": 128
| },
| "sjw": {
| "min": 1,
| "max": 128
| },
| "brp": {
| "min": 1,
| "max": 512
| },
| "brp_inc": 1
| },
| "data_bittiming_const": {
| "name": "DUMMY_CAN_DEV",
| "tseg1": {
| "min": 2,
| "max": 32
| },
| "tseg2": {
| "min": 1,
| "max": 16
| },
| "sjw": {
| "min": 1,
| "max": 8
| },
| "brp": {
| "min": 1,
| "max": 32
| },
| "brp_inc": 1,
| "tdc": {
| "tdco": {
| "min": 0,
| "max": 127
| },
| "tdcf": {
| "min": 0,
| "max": 127
| }
| }
| },
| "clock": 80000000
| }
| },
| "num_tx_queues": 1,
| "num_rx_queues": 1,
| "gso_max_size": 65536,
| "gso_max_segs": 65535,
| "parentbus": "usb",
| "parentdev": "1-10:1.1"
| } ]

As mentioned above, the default output remains unchanged:

| $ ip --details link show can0
| 1: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
| link/can promiscuity 0 minmtu 0 maxmtu 0
| can <FD-NON-ISO,CC-LEN8-DLC> state STOPPED restart-ms 0
| DUMMY_CAN_DEV: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1
| DUMMY_CAN_DEV: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 dbrp_inc 1
| tdco 0..127 tdcf 0..127
| clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 parentbus usb parentdev 1-10:1.1

[1] commit 383f0993fc77 ("can: netlink: report the CAN controller mode
supported flags")
https://lore.kernel.org/linux-can/[email protected]/T/#u

[2] https://elixir.bootlin.com/linux/v5.14/source/include/linux/can/dev.h#61

Signed-off-by: Vincent Mailhol <[email protected]>
---
I am sending a last RFC because I would like to gather people's
opinion on the output format. I will reply to my own message just
after with more details.

* Changelog *

v2 -> v3

- Rebased on the latest version of iproute2-next.
- Minor changes in the commit description.

v1 -> v2

- The kernel uapi was modified to use a new NLA_NESTED entry instead
of reusing struct can_ctrlmode. The second and third patch of the
series were updated accordingly.

Vincent Mailhol (3):
iplink_can: code refactoring of print_ctrlmode()
iplink_can: add ctrlmode_{supported,_static} to the "--details --json"
output
can: netlink: add new field to struct can_ctrlmode to report
capabilities
---
ip/iplink_can.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index f4b37528..854ccc31 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -396,6 +396,20 @@ static void can_print_tdc_const_opt(FILE *f, struct rtattr *tdc_attr)
close_json_object();
}

+static void can_print_ctrlmode_ext(FILE *f, struct rtattr *ctrlmode_ext_attr,
+ __u32 cm_flags)
+{
+ struct rtattr *tb[IFLA_CAN_CTRLMODE_MAX + 1];
+
+ parse_rtattr_nested(tb, IFLA_CAN_CTRLMODE_MAX, ctrlmode_ext_attr);
+ if (tb[IFLA_CAN_CTRLMODE_SUPPORTED]) {
+ __u32 *supported = RTA_DATA(tb[IFLA_CAN_CTRLMODE_SUPPORTED]);
+
+ print_ctrlmode(PRINT_JSON, *supported, "ctrlmode_supported");
+ print_ctrlmode(PRINT_JSON, cm_flags & ~*supported, "ctrlmode_static");
+ }
+}
+
static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
@@ -405,6 +419,9 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);

print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode");
+ if (tb[IFLA_CAN_CTRLMODE_EXT])
+ can_print_ctrlmode_ext(f, tb[IFLA_CAN_CTRLMODE_EXT],
+ cm->flags);
}

if (tb[IFLA_CAN_STATE]) {
--
2.34.1



2022-01-06 11:08:05

by Vincent MAILHOL

[permalink] [raw]
Subject: Re: [RFC PATCH v3] iplink_can: add ctrlmode_{supported,_static} to the "--details --json" output

Hi,

First of all, let me which a happy new year to the members of the
linux-can mailing list (and to the members of the other mailings
in CC as well).

I am not fully confident of how to format the output. Above patch
is my best shot, but I would like to gather other people's
opinion on two topics before dropping the RFC tag.

On Tue, 6 Jan. 2022 at 19:29, Vincent Mailhol
<[email protected]> wrote:
> This patch is the userland counterpart of [1]. Indeed, [1] allows the
> can netlink interface to report the CAN controller capabilities.
>
> Previously, only the options which were switched on were reported
> (i.e. can_priv::ctrlmode). Here, we add two additional pieces of
> information to the json report:
>
> - ctrlmode_supported: the options that can be modified by netlink
>
> - ctrlmode_static: option which are statically enabled by the driver
> (i.e. can not be turned off)
>
> For your information, we borrowed the naming convention from struct
> can_priv [2].
>
> Contrary to the ctrlmode, the ctrlmode_{supported,_static} are only
> reported in the json context. The reason is that this newly added
> information can quickly become very verbose and we do not want to
> overload the default output. You can think of the "ip --details link
> show canX" output as the verbose mode and the "ip --details --json
> link show canX" output as the *very* verbose mode.
>
> *Example:*
>
> This is how the output would look like for a dummy driver which would
> have:
>
> - CAN_CTRLMODE_LOOPBACK, CAN_CTRLMODE_LISTENONLY,
> CAN_CTRLMODE_3_SAMPLES, CAN_CTRLMODE_FD, CAN_CTRLMODE_CC_LEN8_DLC
> and TDC-AUTO supported by the driver
>
> - CAN_CTRLMODE_CC_LEN8_DLC turned on by the user
>
> - CAN_CTRLMODE_FD_NON_ISO statically enabled by the driver
>
> | $ ip link set can0 type can cc-len8-dlc on
> | $ ip --details --json --pretty link show can0
> | [ {
> | "ifindex": 1,
> | "ifname": "can0",
> | "flags": [ "NOARP","ECHO" ],
> | "mtu": 16,
> | "qdisc": "noop",
> | "operstate": "DOWN",
> | "linkmode": "DEFAULT",
> | "group": "default",
> | "txqlen": 10,
> | "link_type": "can",
> | "promiscuity": 0,
> | "min_mtu": 0,
> | "max_mtu": 0,
> | "linkinfo": {
> | "info_kind": "can",
> | "info_data": {
> | "ctrlmode": [ "FD-NON-ISO","CC-LEN8-DLC" ],
> | "ctrlmode_supported": [ "LOOPBACK","LISTEN-ONLY","TRIPLE-SAMPLING","FD","CC-LEN8-DLC","TDC-AUTO" ],
> | "ctrlmode_static": [ "FD-NON-ISO" ],

Here, I propose to just add two new members to the json
object "info_data".

One alternative option I am thinking of is to group everything
under a new json object called "ctrlmode" like that:

| "info_data": {
| "ctrlmode": {
| "enabled": [ "FD-NON-ISO","CC-LEN8-DLC" ],
| "supported": [
"LOOPBACK","LISTEN-ONLY","TRIPLE-SAMPLING","FD","CC-LEN8-DLC","TDC-AUTO"
],
| "static": [ "FD-NON-ISO" ]
| },
| "state": "STOPPED",
| ...

The drawback of doing so is that it would break any tools relying
on the current format to retrieve the ctrlmode enabled
features. For example, this command:

| ip --details --json --pretty link show can0 | jq
'.[].linkinfo.info_data.ctrlmode'

will yield a different result before and after the change.

So here is my question: it is acceptable to break current format?
If yes, I would prefer the alternate solution listed here, if
not, I will keep things as proposed in this RFC.

> | "state": "STOPPED",
> | "restart_ms": 0,
> | "bittiming_const": {
> | "name": "DUMMY_CAN_DEV",
> | "tseg1": {
> | "min": 2,
> | "max": 256
> | },
> | "tseg2": {
> | "min": 2,
> | "max": 128
> | },
> | "sjw": {
> | "min": 1,
> | "max": 128
> | },
> | "brp": {
> | "min": 1,
> | "max": 512
> | },
> | "brp_inc": 1
> | },
> | "data_bittiming_const": {
> | "name": "DUMMY_CAN_DEV",
> | "tseg1": {
> | "min": 2,
> | "max": 32
> | },
> | "tseg2": {
> | "min": 1,
> | "max": 16
> | },
> | "sjw": {
> | "min": 1,
> | "max": 8
> | },
> | "brp": {
> | "min": 1,
> | "max": 32
> | },
> | "brp_inc": 1,
> | "tdc": {
> | "tdco": {
> | "min": 0,
> | "max": 127
> | },
> | "tdcf": {
> | "min": 0,
> | "max": 127
> | }
> | }
> | },
> | "clock": 80000000
> | }
> | },
> | "num_tx_queues": 1,
> | "num_rx_queues": 1,
> | "gso_max_size": 65536,
> | "gso_max_segs": 65535,
> | "parentbus": "usb",
> | "parentdev": "1-10:1.1"
> | } ]
>
> As mentioned above, the default output remains unchanged:
>
> | $ ip --details link show can0
> | 1: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
> | link/can promiscuity 0 minmtu 0 maxmtu 0
> | can <FD-NON-ISO,CC-LEN8-DLC> state STOPPED restart-ms 0

If had a long thought and couldn't come with anything pretty for
the default (non-json) output. My best idea is to use some
suffixes, something like that:

'-' to indicate that the feature is supported but disabled.

'+' to indicate that the feature is supported and enabled.

'*' to indicate a static feature.

If I reuse the example used in above json output, that would
become:

| $ ip --details link show can0
| 1: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT
group default qlen 10
| link/can promiscuity 0 minmtu 0 maxmtu 0
| can <LOOPBACK-,LISTEN-ONLY-,TRIPLE-SAMPLING-,FD-,FD-NON-ISO*,CC-LEN8-DLC+,TDC-AUTO->
state STOPPED restart-ms 0
| DUMMY_CAN_DEV: tseg1 2..256 tseg2 2..128 sjw 1..128 brp
1..512 brp_inc 1

I don't think this is easy to read.

Another option is to output three arrays, similar to the json
output. But I think that this is too busy. So my preferred
solution is to do no changes. Does this make sense? Or would you
still prefer to have the enabled and static features reported in
the normal output as well? And if yes, in which format?

> | DUMMY_CAN_DEV: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1
> | DUMMY_CAN_DEV: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 dbrp_inc 1
> | tdco 0..127 tdcf 0..127
> | clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 parentbus usb parentdev 1-10:1.1

That's all for my current doubts. If I receive no feedback by the
end of the week, I will assume that everyone is happy with this
RFC and will resend the patch without the RFC tag to have it
included in iproute 5.17.

Thank you,


Yours sincerely,
Vincent Mailhol