| From foo@baz Sat 11 Jan 2020 09:13:20 AM CET |
| From: Petr Machata <petrm@mellanox.com> |
| Date: Mon, 6 Jan 2020 18:01:56 +0000 |
| Subject: net: sch_prio: When ungrafting, replace with FIFO |
| |
| From: Petr Machata <petrm@mellanox.com> |
| |
| [ Upstream commit 240ce7f6428ff5188b9eedc066e1e4d645b8635f ] |
| |
| When a child Qdisc is removed from one of the PRIO Qdisc's bands, it is |
| replaced unconditionally by a NOOP qdisc. As a result, any traffic hitting |
| that band gets dropped. That is incorrect--no Qdisc was explicitly added |
| when PRIO was created, and after removal, none should have to be added |
| either. |
| |
| Fix PRIO by first attempting to create a default Qdisc and only falling |
| back to noop when that fails. This pattern of attempting to create an |
| invisible FIFO, using NOOP only as a fallback, is also seen in other |
| Qdiscs. |
| |
| Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") |
| Signed-off-by: Petr Machata <petrm@mellanox.com> |
| Acked-by: Jiri Pirko <jiri@mellanox.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/sched/sch_prio.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| --- a/net/sched/sch_prio.c |
| +++ b/net/sched/sch_prio.c |
| @@ -292,8 +292,14 @@ static int prio_graft(struct Qdisc *sch, |
| struct tc_prio_qopt_offload graft_offload; |
| unsigned long band = arg - 1; |
| |
| - if (new == NULL) |
| - new = &noop_qdisc; |
| + if (!new) { |
| + new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
| + TC_H_MAKE(sch->handle, arg), extack); |
| + if (!new) |
| + new = &noop_qdisc; |
| + else |
| + qdisc_hash_add(new, true); |
| + } |
| |
| *old = qdisc_replace(sch, new, &q->queues[band]); |
| |