diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e357c7a0a77be19261238e08d10117ec0e6bd7b5..3f45225fe91c67b12929cf23fa249ce7774676c4 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -87,6 +87,7 @@ struct Qdisc { struct hlist_node hash; u32 handle; u32 parent; + int depth; struct netdev_queue *dev_queue; diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index fc43ea55f0f37c430cfe0e9eaf45a9561830278d..e1575bc906bd925a42e01212e00e1f894f4f6243 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1044,6 +1044,9 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, if (parent == NULL) { unsigned int i, num_q, ingress; + if (new) + new->depth = 0; + ingress = 0; num_q = dev->num_tx_queues; if ((q && q->flags & TCQ_F_INGRESS) || @@ -1124,9 +1127,15 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, NL_SET_ERR_MSG(extack, "STAB not supported on a non root"); return -EINVAL; } + if (new && parent->depth >= 7) { + NL_SET_ERR_MSG(extack, "Qdisc hierarchy is too deep"); + return -E2BIG; + } err = cops->graft(parent, cl, new, &old, extack); if (err) return err; + if (new) + new->depth = parent->depth + 1; notify_and_destroy(net, skb, n, classid, old, new); } return 0;