diff options
Diffstat (limited to 'src/network/tc/tclass.c')
-rw-r--r-- | src/network/tc/tclass.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c index 63229ec6e8..fcbe8cbcf4 100644 --- a/src/network/tc/tclass.c +++ b/src/network/tc/tclass.c @@ -252,37 +252,56 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) { strna(tclass_get_tca_kind(tclass))); } -TClass* tclass_drop(TClass *tclass) { +void tclass_mark_recursive(TClass *tclass) { QDisc *qdisc; - Link *link; assert(tclass); + assert(tclass->link); - link = ASSERT_PTR(tclass->link); + if (tclass_is_marked(tclass)) + return; - tclass_mark(tclass); /* To avoid stack overflow. */ + tclass_mark(tclass); - /* Also drop all child qdiscs assigned to the class. */ - SET_FOREACH(qdisc, link->qdiscs) { - if (qdisc_is_marked(qdisc)) + /* Also mark all child qdiscs assigned to the class. */ + SET_FOREACH(qdisc, tclass->link->qdiscs) { + if (qdisc->parent != tclass->classid) continue; - if (qdisc->parent != tclass->classid) + qdisc_mark_recursive(qdisc); + } +} + +void link_tclass_drop_marked(Link *link) { + TClass *tclass; + + assert(link); + + SET_FOREACH(tclass, link->tclasses) { + if (!tclass_is_marked(tclass)) continue; - qdisc_drop(qdisc); + tclass_unmark(tclass); + tclass_enter_removed(tclass); + + if (tclass->state == 0) { + log_tclass_debug(tclass, link, "Forgetting"); + tclass_free(tclass); + } else + log_tclass_debug(tclass, link, "Removed"); } +} - tclass_unmark(tclass); - tclass_enter_removed(tclass); +TClass* tclass_drop(TClass *tclass) { + assert(tclass); - if (tclass->state == 0) { - log_tclass_debug(tclass, link, "Forgetting"); - tclass = tclass_free(tclass); - } else - log_tclass_debug(tclass, link, "Removed"); + tclass_mark_recursive(tclass); + + /* link_tclass_drop_marked() may invalidate tclass, so run link_qdisc_drop_marked() first. */ + link_qdisc_drop_marked(tclass->link); + link_tclass_drop_marked(tclass->link); - return tclass; + return NULL; } static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) { |