network/tc: drop child tree of traffic control nodes on remove
When a node of traffic control tree is removed, all child nodes are also removed but their removal are not notified by the kernel. So, previously, removed TC classes or qdiscs under the removed node were kept in the memory of networkd, and may cause failure on reconfigure.
This commit is contained in:
+30
-8
@@ -293,6 +293,33 @@ int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *ki
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
QDisc* qdisc_drop(QDisc *qdisc) {
|
||||
TClass *tclass;
|
||||
Link *link;
|
||||
|
||||
assert(qdisc);
|
||||
|
||||
link = ASSERT_PTR(qdisc->link);
|
||||
|
||||
/* also drop all child classes assigned to the qdisc. */
|
||||
SET_FOREACH(tclass, link->tclasses) {
|
||||
if (TC_H_MAJ(tclass->classid) != qdisc->handle)
|
||||
continue;
|
||||
|
||||
tclass_drop(tclass);
|
||||
}
|
||||
|
||||
qdisc_enter_removed(qdisc);
|
||||
|
||||
if (qdisc->state == 0) {
|
||||
log_qdisc_debug(qdisc, link, "Forgetting");
|
||||
qdisc = qdisc_free(qdisc);
|
||||
} else
|
||||
log_qdisc_debug(qdisc, link, "Removed");
|
||||
|
||||
return qdisc;
|
||||
}
|
||||
|
||||
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) {
|
||||
int r;
|
||||
|
||||
@@ -512,14 +539,9 @@ int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Ma
|
||||
break;
|
||||
|
||||
case RTM_DELQDISC:
|
||||
if (qdisc) {
|
||||
qdisc_enter_removed(qdisc);
|
||||
if (qdisc->state == 0) {
|
||||
log_qdisc_debug(qdisc, link, "Forgetting");
|
||||
qdisc_free(qdisc);
|
||||
} else
|
||||
log_qdisc_debug(qdisc, link, "Removed");
|
||||
} else
|
||||
if (qdisc)
|
||||
qdisc_drop(qdisc);
|
||||
else
|
||||
log_qdisc_debug(tmp, link, "Kernel removed unknown");
|
||||
|
||||
break;
|
||||
|
||||
@@ -77,6 +77,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc);
|
||||
QDisc* qdisc_free(QDisc *qdisc);
|
||||
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
|
||||
|
||||
QDisc* qdisc_drop(QDisc *qdisc);
|
||||
|
||||
int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc);
|
||||
|
||||
int link_request_qdisc(Link *link, QDisc *qdisc);
|
||||
|
||||
+30
-8
@@ -255,6 +255,33 @@ static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
|
||||
strna(tclass_get_tca_kind(tclass)));
|
||||
}
|
||||
|
||||
TClass* tclass_drop(TClass *tclass) {
|
||||
QDisc *qdisc;
|
||||
Link *link;
|
||||
|
||||
assert(tclass);
|
||||
|
||||
link = ASSERT_PTR(tclass->link);
|
||||
|
||||
/* Also drop all child qdiscs assigned to the class. */
|
||||
SET_FOREACH(qdisc, link->qdiscs) {
|
||||
if (qdisc->parent != tclass->classid)
|
||||
continue;
|
||||
|
||||
qdisc_drop(qdisc);
|
||||
}
|
||||
|
||||
tclass_enter_removed(tclass);
|
||||
|
||||
if (tclass->state == 0) {
|
||||
log_tclass_debug(tclass, link, "Forgetting");
|
||||
tclass = tclass_free(tclass);
|
||||
} else
|
||||
log_tclass_debug(tclass, link, "Removed");
|
||||
|
||||
return tclass;
|
||||
}
|
||||
|
||||
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, TClass *tclass) {
|
||||
int r;
|
||||
|
||||
@@ -464,14 +491,9 @@ int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, M
|
||||
break;
|
||||
|
||||
case RTM_DELTCLASS:
|
||||
if (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");
|
||||
} else
|
||||
if (tclass)
|
||||
(void) tclass_drop(tclass);
|
||||
else
|
||||
log_tclass_debug(tmp, link, "Kernel removed unknown");
|
||||
|
||||
break;
|
||||
|
||||
@@ -58,6 +58,8 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass);
|
||||
TClass* tclass_free(TClass *tclass);
|
||||
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
|
||||
|
||||
TClass* tclass_drop(TClass *tclass);
|
||||
|
||||
int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
|
||||
|
||||
int link_request_tclass(Link *link, TClass *tclass);
|
||||
|
||||
Reference in New Issue
Block a user