diff mbox series

[RFC,iproute2] tc/mqprio: json-ify output

Message ID 20201127152625.61874-1-bluca@debian.org
State Superseded
Headers show
Series [RFC,iproute2] tc/mqprio: json-ify output | expand

Commit Message

Luca Boccassi Nov. 27, 2020, 3:26 p.m. UTC
As reported by a Debian user, mqprio output in json mode is
invalid:

{
     "kind": "mqprio",
     "handle": "8021:",
     "dev": "enp1s0f0",
     "root": true,
     "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0
          queues:(0:3) (4:7)
          mode:channel
          shaper:dcb}
}

json-ify it, while trying to maintain the same formatting
for standard output.

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

Signed-off-by: Luca Boccassi <bluca@debian.org>
---
I do not have hardware where I can configure mqprio, so I can't really
test this apart from compiling it. Stephen and David, do you have machines
where you can quickly check that this works as expected? Thanks!

 tc/q_mqprio.c | 34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

Comments

Stephen Hemminger Nov. 28, 2020, 5:21 a.m. UTC | #1
On Fri, 27 Nov 2020 15:26:25 +0000
Luca Boccassi <bluca@debian.org> wrote:

> As reported by a Debian user, mqprio output in json mode is

> invalid:

> 

> {

>      "kind": "mqprio",

>      "handle": "8021:",

>      "dev": "enp1s0f0",

>      "root": true,

>      "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0

>           queues:(0:3) (4:7)

>           mode:channel

>           shaper:dcb}

> }

> 

> json-ify it, while trying to maintain the same formatting

> for standard output.

> 

> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

> 

> Signed-off-by: Luca Boccassi <bluca@debian.org>


Did you try feeding that into the python parser?
What is before/after?
Luca Boccassi Nov. 28, 2020, 12:17 p.m. UTC | #2
On Fri, 2020-11-27 at 21:21 -0800, Stephen Hemminger wrote:
> On Fri, 27 Nov 2020 15:26:25 +0000

> Luca Boccassi <bluca@debian.org> wrote:

> 

> > As reported by a Debian user, mqprio output in json mode is

> > invalid:

> > 

> > {

> >      "kind": "mqprio",

> >      "handle": "8021:",

> >      "dev": "enp1s0f0",

> >      "root": true,

> >      "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0

> >           queues:(0:3) (4:7)

> >           mode:channel

> >           shaper:dcb}

> > }

> > 

> > json-ify it, while trying to maintain the same formatting

> > for standard output.

> > 

> > https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

> > 

> > Signed-off-by: Luca Boccassi <bluca@debian.org>

> 

> Did you try feeding that into the python parser?

> What is before/after?


Uh, which python parser?

The reporter tested the patch, there's a small error. Before is above,
after is:

{
    "kind": "mqprio",
    "handle": "8001:",
    "root": true,
    "options": {
        "tc": 2,
        "map": [ 0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0 ],
        "queues": [
            "": [ 0,3 ],
            "": [ 4,7 ] ],
        "mode": "channel",
        "shaper": "dcb"
    }
}

Will fix the "queues" to remove the empty name in v2.

-- 
Kind regards,
Luca Boccassi
Luca Boccassi Nov. 28, 2020, 3:24 p.m. UTC | #3
On Sat, 2020-11-28 at 12:21 +0000, Luca Boccassi wrote:
> As reported by a Debian user, mqprio output in json mode is

> invalid:

> 

> {

>      "kind": "mqprio",

>      "handle": "8021:",

>      "dev": "enp1s0f0",

>      "root": true,

>      "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0

>           queues:(0:3) (4:7)

>           mode:channel

>           shaper:dcb}

> }

> 

> json-ify it, while trying to maintain the same formatting

> for standard output.

> 

> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

> 

> Reported-by: Roméo GINON <romeo.ginon@ilexia.com>

> Signed-off-by: Luca Boccassi <bluca@debian.org>

> ---

> v1: I do not have hardware where I can configure mqprio, so I can't

> really

> test this apart from compiling it. Stephen and David, do you have

> machines

> where you can quickly check that this works as expected? Thanks!

> 

> v2: the original reporter tested the patch and reported this is the

> new output:

> 

> {

>     "kind": "mqprio",

>     "handle": "8001:",

>     "root": true,

>     "options": {

>         "tc": 2,

>         "map": [ 0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0 ],

>         "queues": [

>             "": [ 0,3 ],

>             "": [ 4,7 ] ],

>         "mode": "channel",

>         "shaper": "dcb"

>     }

> }

> 

> Changed in v2 to make the inner queues arrays anonymous

> ("" -> NULL for open/close_json_array)

> 

> Still would appreciate testing from someone else who has hardware

> that supports this feature and can enable this, as I am flying blind.


The reporter confirmed the json output is now valid with this patch on
the debian bug report.

-- 
Kind regards,
Luca Boccassi
Stephen Hemminger Nov. 28, 2020, 5:34 p.m. UTC | #4
On Sat, 28 Nov 2020 12:17:00 +0000
Luca Boccassi <bluca@debian.org> wrote:

> On Fri, 2020-11-27 at 21:21 -0800, Stephen Hemminger wrote:

> > On Fri, 27 Nov 2020 15:26:25 +0000

> > Luca Boccassi <bluca@debian.org> wrote:

> >   

> > > As reported by a Debian user, mqprio output in json mode is

> > > invalid:

> > > 

> > > {

> > >      "kind": "mqprio",

> > >      "handle": "8021:",

> > >      "dev": "enp1s0f0",

> > >      "root": true,

> > >      "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0

> > >           queues:(0:3) (4:7)

> > >           mode:channel

> > >           shaper:dcb}

> > > }

> > > 

> > > json-ify it, while trying to maintain the same formatting

> > > for standard output.

> > > 

> > > https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

> > > 

> > > Signed-off-by: Luca Boccassi <bluca@debian.org>  

> > 

> > Did you try feeding that into the python parser?

> > What is before/after?  

> 

> Uh, which python parser?

> 

> The reporter tested the patch, there's a small error. Before is above,

> after is:

> 

> {

>     "kind": "mqprio",

>     "handle": "8001:",

>     "root": true,

>     "options": {

>         "tc": 2,

>         "map": [ 0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0 ],

>         "queues": [

>             "": [ 0,3 ],

>             "": [ 4,7 ] ],

>         "mode": "channel",

>         "shaper": "dcb"

>     }

> }

> 

> Will fix the "queues" to remove the empty name in v2.


Try:
  $ tc -j qdisc | pythom -m json.tools

The empty tags are non-standard practice can it be done better?
Luca Boccassi Nov. 28, 2020, 5:59 p.m. UTC | #5
On Sat, 2020-11-28 at 09:34 -0800, Stephen Hemminger wrote:
> On Sat, 28 Nov 2020 12:17:00 +0000

> Luca Boccassi <bluca@debian.org> wrote:

> 

> > On Fri, 2020-11-27 at 21:21 -0800, Stephen Hemminger wrote:

> > > On Fri, 27 Nov 2020 15:26:25 +0000

> > > Luca Boccassi <bluca@debian.org> wrote:

> > >   

> > > > As reported by a Debian user, mqprio output in json mode is

> > > > invalid:

> > > > 

> > > > {

> > > >      "kind": "mqprio",

> > > >      "handle": "8021:",

> > > >      "dev": "enp1s0f0",

> > > >      "root": true,

> > > >      "options": { tc 2 map 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0

> > > >           queues:(0:3) (4:7)

> > > >           mode:channel

> > > >           shaper:dcb}

> > > > }

> > > > 

> > > > json-ify it, while trying to maintain the same formatting

> > > > for standard output.

> > > > 

> > > > https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784

> > > > 

> > > > Signed-off-by: Luca Boccassi <bluca@debian.org>  

> > > 

> > > Did you try feeding that into the python parser?

> > > What is before/after?  

> > 

> > Uh, which python parser?

> > 

> > The reporter tested the patch, there's a small error. Before is

> > above,

> > after is:

> > 

> > {

> >     "kind": "mqprio",

> >     "handle": "8001:",

> >     "root": true,

> >     "options": {

> >         "tc": 2,

> >         "map": [ 0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0 ],

> >         "queues": [

> >             "": [ 0,3 ],

> >             "": [ 4,7 ] ],

> >         "mode": "channel",

> >         "shaper": "dcb"

> >     }

> > }

> > 

> > Will fix the "queues" to remove the empty name in v2.

> 

> Try:

>   $ tc -j qdisc | pythom -m json.tools

> 

> The empty tags are non-standard practice can it be done better?


Yes, v2 that I sent earlier fixed the empty tags. Python's json.tools
is happy.

The test of v2 from the reporter gave this output:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972784#27

[{"kind":"mqprio","handle":"8001:","root":true,"options":{"tc":2,"map":[0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0],"queues":[[0,3],[4,7]],"mode":"channel","shaper":"dcb"}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:8","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:7","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:6","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:5","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:4","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:3","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:2","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}},{"kind":"pfifo_fast","handle":"0:","parent":"8001:1","options":{"bands":3,"priomap ":[1,2,2,2,1,2,0,0,1,1,1,1,1,1,1,1],"multiqueue":false}}]

Which when fed to python3 -m json.utils gives:

[
    {
        "kind": "mqprio",
        "handle": "8001:",
        "root": true,
        "options": {
            "tc": 2,
            "map": [
                0,
                0,
                0,
                1,
                0,
                1,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0,
                0
            ],
            "queues": [
                [
                    0,
                    3
                ],
                [
                    4,
                    7
                ]
            ],
            "mode": "channel",
            "shaper": "dcb"
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:8",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:7",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:6",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:5",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:4",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:3",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:2",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    },
    {
        "kind": "pfifo_fast",
        "handle": "0:",
        "parent": "8001:1",
        "options": {
            "bands": 3,
            "priomap ": [
                1,
                2,
                2,
                2,
                1,
                2,
                0,
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                1
            ],
            "multiqueue": false
        }
    }
]

-- 
Kind regards,
Luca Boccassi
diff mbox series

Patch

diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c
index f26ba8d7..f62ccbc6 100644
--- a/tc/q_mqprio.c
+++ b/tc/q_mqprio.c
@@ -243,13 +243,19 @@  static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 
 	qopt = RTA_DATA(opt);
 
-	fprintf(f, " tc %u map ", qopt->num_tc);
+	print_uint(PRINT_ANY, "tc", "tc %u ", qopt->num_tc);
+	open_json_array(PRINT_ANY, is_json_context() ? "map" : "map ");
 	for (i = 0; i <= TC_PRIO_MAX; i++)
-		fprintf(f, "%u ", qopt->prio_tc_map[i]);
-	fprintf(f, "\n             queues:");
-	for (i = 0; i < qopt->num_tc; i++)
-		fprintf(f, "(%u:%u) ", qopt->offset[i],
-			qopt->offset[i] + qopt->count[i] - 1);
+		print_uint(PRINT_ANY, NULL, "%u ", qopt->prio_tc_map[i]);
+	close_json_array(PRINT_ANY, "");
+	open_json_array(PRINT_ANY, is_json_context() ? "queues" : "\n             queues:");
+	for (i = 0; i < qopt->num_tc; i++) {
+		open_json_array(PRINT_JSON, "");
+		print_uint(PRINT_ANY, NULL, "(%u:", qopt->offset[i]);
+		print_uint(PRINT_ANY, NULL, "%u) ", qopt->offset[i] + qopt->count[i] - 1);
+		close_json_array(PRINT_JSON, "");
+	}
+	close_json_array(PRINT_ANY, "");
 
 	if (len > 0) {
 		struct rtattr *tb[TCA_MQPRIO_MAX + 1];
@@ -262,18 +268,18 @@  static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 			__u16 *mode = RTA_DATA(tb[TCA_MQPRIO_MODE]);
 
 			if (*mode == TC_MQPRIO_MODE_CHANNEL)
-				fprintf(f, "\n             mode:channel");
+				print_string(PRINT_ANY, "mode", "\n             mode:%s", "channel");
 		} else {
-			fprintf(f, "\n             mode:dcb");
+			print_string(PRINT_ANY, "mode", "\n             mode:%s", "dcb");
 		}
 
 		if (tb[TCA_MQPRIO_SHAPER]) {
 			__u16 *shaper = RTA_DATA(tb[TCA_MQPRIO_SHAPER]);
 
 			if (*shaper == TC_MQPRIO_SHAPER_BW_RATE)
-				fprintf(f, "\n             shaper:bw_rlimit");
+				print_string(PRINT_ANY, "shaper", "\n             shaper:%s", "bw_rlimit");
 		} else {
-			fprintf(f, "\n             shaper:dcb");
+			print_string(PRINT_ANY, "shaper", "\n             shaper:%s", "dcb");
 		}
 
 		if (tb[TCA_MQPRIO_MIN_RATE64]) {
@@ -287,9 +293,9 @@  static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 					return -1;
 				*(min++) = rta_getattr_u64(r);
 			}
-			fprintf(f, "	min_rate:");
+			open_json_array(PRINT_ANY, is_json_context() ? "min_rate" : "	min_rate:");
 			for (i = 0; i < qopt->num_tc; i++)
-				fprintf(f, "%s ", sprint_rate(min_rate64[i], b1));
+				print_string(PRINT_ANY, NULL, "%s ", sprint_rate(min_rate64[i], b1));
 		}
 
 		if (tb[TCA_MQPRIO_MAX_RATE64]) {
@@ -303,9 +309,9 @@  static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
 					return -1;
 				*(max++) = rta_getattr_u64(r);
 			}
-			fprintf(f, "	max_rate:");
+			open_json_array(PRINT_ANY, is_json_context() ? "max_rate" : "	max_rate:");
 			for (i = 0; i < qopt->num_tc; i++)
-				fprintf(f, "%s ", sprint_rate(max_rate64[i], b1));
+				print_string(PRINT_ANY, NULL, "%s ", sprint_rate(max_rate64[i], b1));
 		}
 	}
 	return 0;