]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tc: introduce order dependency of traffic control
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 26 Jan 2022 04:01:19 +0000 (13:01 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 9 Feb 2022 05:43:19 +0000 (14:43 +0900)
src/network/tc/qdisc.c
src/network/tc/qdisc.h
src/network/tc/tclass.c
src/network/tc/tclass.h

index 4fa1a6f5eac89284d9f4d4ad36264ef7a632e941..7df6449de632d7cacc3145fd0472ee7d6a6db997 100644 (file)
@@ -260,6 +260,44 @@ static void log_qdisc_debug(QDisc *qdisc, Link *link, const char *str) {
                        strna(qdisc_get_tca_kind(qdisc)));
 }
 
+int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **ret) {
+        TrafficControl *tc;
+
+        assert(link);
+
+        handle = TC_H_MAJ(handle);
+
+        SET_FOREACH(tc, link->traffic_control) {
+                QDisc *qdisc;
+
+                if (tc->kind != TC_KIND_QDISC)
+                        continue;
+
+                qdisc = TC_TO_QDISC(tc);
+
+                if (qdisc->handle != handle)
+                        continue;
+
+                if (qdisc->parent != parent)
+                        continue;
+
+                if (qdisc->source == NETWORK_CONFIG_SOURCE_FOREIGN)
+                        continue;
+
+                if (!qdisc_exists(qdisc))
+                        continue;
+
+                if (kind && !streq_ptr(kind, qdisc_get_tca_kind(qdisc)))
+                        continue;
+
+                if (ret)
+                        *ret = qdisc;
+                return 0;
+        }
+
+        return -ENOENT;
+}
+
 static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -326,7 +364,10 @@ int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc) {
         assert(link);
         assert(qdisc);
 
-        return true;
+        if (IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT)) /* TC_H_CLSACT == TC_H_INGRESS */
+                return true;
+
+        return link_find_tclass(link, qdisc->parent, NULL) >= 0;
 }
 
 int link_request_qdisc(Link *link, QDisc *qdisc) {
index dc4156ad0af0674f75c87b1101598f33c74bdd6e..1e4b72e271f6e7c1a70230fa3c8011ee88ff65f9 100644 (file)
@@ -83,6 +83,8 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
 void qdisc_hash_func(const QDisc *qdic, struct siphash *state);
 int qdisc_compare_func(const QDisc *a, const QDisc *b);
 
+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);
 int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc);
 int qdisc_configure(Link *link, QDisc *qdisc);
index 2553caa76d9cda39ca712e9d2e210db69a22c0d7..903ff28336213b475d3f801ea292b7b0df24f1a5 100644 (file)
@@ -213,6 +213,36 @@ static int tclass_dup(const TClass *src, TClass **ret) {
         return 0;
 }
 
+int link_find_tclass(Link *link, uint32_t classid, TClass **ret) {
+        TrafficControl *tc;
+
+        assert(link);
+
+        SET_FOREACH(tc, link->traffic_control) {
+                TClass *tclass;
+
+                if (tc->kind != TC_KIND_TCLASS)
+                        continue;
+
+                tclass = TC_TO_TCLASS(tc);
+
+                if (tclass->classid != classid)
+                        continue;
+
+                if (tclass->source == NETWORK_CONFIG_SOURCE_FOREIGN)
+                        continue;
+
+                if (!tclass_exists(tclass))
+                        continue;
+
+                if (ret)
+                        *ret = tclass;
+                return 0;
+        }
+
+        return -ENOENT;
+}
+
 static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
         _cleanup_free_ char *state = NULL;
 
@@ -297,7 +327,7 @@ int tclass_is_ready_to_configure(Link *link, TClass *tclass) {
         assert(link);
         assert(tclass);
 
-        return true;
+        return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0;
 }
 
 int link_request_tclass(Link *link, TClass *tclass) {
index 525630a87cbf63e3d61985310ec6fedd36001f3a..6b12fba1e8bda1823d9d9f5652648bdf8d98dce0 100644 (file)
@@ -65,6 +65,8 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
 void tclass_hash_func(const TClass *tclass, struct siphash *state);
 int tclass_compare_func(const TClass *a, const TClass *b);
 
+int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
+
 int link_request_tclass(Link *link, TClass *tclass);
 int tclass_is_ready_to_configure(Link *link, TClass *tclass);
 int tclass_configure(Link *link, TClass *tclass);