summaryrefslogtreecommitdiffstats
path: root/src/network/tc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 03:50:40 +0000
commitfc53809803cd2bc2434e312b19a18fa36776da12 (patch)
treeb4b43bd6538f51965ce32856e9c053d0f90919c8 /src/network/tc
parentAdding upstream version 255.5. (diff)
downloadsystemd-fc53809803cd2bc2434e312b19a18fa36776da12.tar.xz
systemd-fc53809803cd2bc2434e312b19a18fa36776da12.zip
Adding upstream version 256.upstream/256
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/network/tc')
-rw-r--r--src/network/tc/qdisc.c58
-rw-r--r--src/network/tc/qdisc.h2
-rw-r--r--src/network/tc/tclass.c57
-rw-r--r--src/network/tc/tclass.h2
4 files changed, 81 insertions, 38 deletions
diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c
index f9b9437..38dee2c 100644
--- a/src/network/tc/qdisc.c
+++ b/src/network/tc/qdisc.c
@@ -155,8 +155,8 @@ static void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) {
assert(qdisc);
assert(state);
- siphash24_compress(&qdisc->handle, sizeof(qdisc->handle), state);
- siphash24_compress(&qdisc->parent, sizeof(qdisc->parent), state);
+ siphash24_compress_typesafe(qdisc->handle, state);
+ siphash24_compress_typesafe(qdisc->parent, state);
siphash24_compress_string(qdisc_get_tca_kind(qdisc), state);
}
@@ -285,37 +285,57 @@ int link_find_qdisc(Link *link, uint32_t handle, const char *kind, QDisc **ret)
return -ENOENT;
}
-QDisc* qdisc_drop(QDisc *qdisc) {
+void qdisc_mark_recursive(QDisc *qdisc) {
TClass *tclass;
- Link *link;
assert(qdisc);
+ assert(qdisc->link);
- link = ASSERT_PTR(qdisc->link);
+ if (qdisc_is_marked(qdisc))
+ return;
- qdisc_mark(qdisc); /* To avoid stack overflow. */
+ qdisc_mark(qdisc);
- /* also drop all child classes assigned to the qdisc. */
- SET_FOREACH(tclass, link->tclasses) {
- if (tclass_is_marked(tclass))
+ /* also mark all child classes assigned to the qdisc. */
+ SET_FOREACH(tclass, qdisc->link->tclasses) {
+ if (TC_H_MAJ(tclass->classid) != qdisc->handle)
continue;
- if (TC_H_MAJ(tclass->classid) != qdisc->handle)
+ tclass_mark_recursive(tclass);
+ }
+}
+
+void link_qdisc_drop_marked(Link *link) {
+ QDisc *qdisc;
+
+ assert(link);
+
+ SET_FOREACH(qdisc, link->qdiscs) {
+ if (!qdisc_is_marked(qdisc))
continue;
- tclass_drop(tclass);
+ qdisc_unmark(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");
}
+}
- qdisc_unmark(qdisc);
- qdisc_enter_removed(qdisc);
+QDisc* qdisc_drop(QDisc *qdisc) {
+ assert(qdisc);
+ assert(qdisc->link);
- if (qdisc->state == 0) {
- log_qdisc_debug(qdisc, link, "Forgetting");
- qdisc = qdisc_free(qdisc);
- } else
- log_qdisc_debug(qdisc, link, "Removed");
+ qdisc_mark_recursive(qdisc);
+
+ /* link_qdisc_drop_marked() may invalidate qdisc, so run link_tclass_drop_marked() first. */
+ link_tclass_drop_marked(qdisc->link);
+ link_qdisc_drop_marked(qdisc->link);
- return qdisc;
+ return NULL;
}
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, QDisc *qdisc) {
diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h
index a62b941..cbba1be 100644
--- a/src/network/tc/qdisc.h
+++ b/src/network/tc/qdisc.h
@@ -77,7 +77,9 @@ 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);
+void qdisc_mark_recursive(QDisc *qdisc);
QDisc* qdisc_drop(QDisc *qdisc);
+void link_qdisc_drop_marked(Link *link);
int link_find_qdisc(Link *link, uint32_t handle, const char *kind, QDisc **qdisc);
diff --git a/src/network/tc/tclass.c b/src/network/tc/tclass.c
index 394e06d..fcbe8cb 100644
--- a/src/network/tc/tclass.c
+++ b/src/network/tc/tclass.c
@@ -125,8 +125,8 @@ static void tclass_hash_func(const TClass *tclass, struct siphash *state) {
assert(tclass);
assert(state);
- siphash24_compress(&tclass->classid, sizeof(tclass->classid), state);
- siphash24_compress(&tclass->parent, sizeof(tclass->parent), state);
+ siphash24_compress_typesafe(tclass->classid, state);
+ siphash24_compress_typesafe(tclass->parent, state);
siphash24_compress_string(tclass_get_tca_kind(tclass), state);
}
@@ -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) {
diff --git a/src/network/tc/tclass.h b/src/network/tc/tclass.h
index e73e23c..85df57d 100644
--- a/src/network/tc/tclass.h
+++ b/src/network/tc/tclass.h
@@ -58,7 +58,9 @@ 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);
+void tclass_mark_recursive(TClass *tclass);
TClass* tclass_drop(TClass *tclass);
+void link_tclass_drop_marked(Link *link);
int link_find_tclass(Link *link, uint32_t classid, TClass **ret);