]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/tclass: do not save tclass to Link before it is configured
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 2 Sep 2024 04:15:49 +0000 (13:15 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 2 Sep 2024 05:12:49 +0000 (14:12 +0900)
Otherwise, if the same kind of tclass is already assigned, parameters
configured in .network file will not be used. So, let's first copy the
tclass and put it on Request, then on success generate a new copy based
on the netlink notification and store it to Link.

This is the same as 0a0c2672dbd22dc85d660e5baa7e1bef701beb88,
65f5f581568448d6098358b704cae10a656d09f0, and friends, but for tclass.

src/network/tc/tc.c
src/network/tc/tclass.c
src/network/tc/tclass.h

index 37e30441e163fd48b85ff38acce96a6f1d079576..4679e86ac978983d4c61500213a62588b4e5cf5c 100644 (file)
@@ -26,7 +26,7 @@ int link_request_traffic_control(Link *link) {
         HASHMAP_FOREACH(tclass, link->network->tclasses_by_section) {
                 r = link_request_tclass(link, tclass);
                 if (r < 0)
-                        return r;
+                        return log_link_warning_errno(link, r, "Failed to request TClass: %m");
         }
 
         if (link->tc_messages == 0) {
index 3c74f95992ce219b12610c6de95dbd1cd4af9a54..684f917c50562bcc36004162b39ada1d2f9d60f3 100644 (file)
@@ -345,11 +345,15 @@ void link_tclass_drop_marked(Link *link) {
         assert(link);
 
         SET_FOREACH(tclass, link->tclasses) {
+                Request *req;
+
                 if (!tclass_is_marked(tclass))
                         continue;
 
                 tclass_unmark(tclass);
                 tclass_enter_removed(tclass);
+                if (tclass_get_request(link, tclass, &req) >= 0)
+                        tclass_enter_removed(req->userdata);
 
                 if (tclass->state == 0) {
                         log_tclass_debug(tclass, link, "Forgetting");
@@ -433,6 +437,7 @@ static bool tclass_is_ready_to_configure(TClass *tclass, Link *link) {
 }
 
 static int tclass_process_request(Request *req, Link *link, TClass *tclass) {
+        TClass *existing;
         int r;
 
         assert(req);
@@ -447,54 +452,56 @@ static int tclass_process_request(Request *req, Link *link, TClass *tclass) {
                 return log_link_warning_errno(link, r, "Failed to configure TClass: %m");
 
         tclass_enter_configuring(tclass);
+        if (tclass_get(link, tclass, &existing) >= 0)
+                tclass_enter_configuring(existing);
+
         return 1;
 }
 
-int link_request_tclass(Link *link, TClass *tclass) {
-        TClass *existing;
+int link_request_tclass(Link *link, const TClass *tclass) {
+        _cleanup_(tclass_unrefp) TClass *tmp = NULL;
+        TClass *existing = NULL;
         int r;
 
         assert(link);
         assert(tclass);
+        assert(tclass->source != NETWORK_CONFIG_SOURCE_FOREIGN);
 
         if (tclass_get_request(link, tclass, NULL) >= 0)
                 return 0; /* already requested, skipping. */
 
-        if (tclass_get(link, tclass, &existing) < 0) {
-                _cleanup_(tclass_unrefp) TClass *tmp = NULL;
-
-                r = tclass_dup(tclass, &tmp);
-                if (r < 0)
-                        return log_oom();
-
-                r = tclass_attach(link, tmp);
-                if (r < 0)
-                        return log_link_warning_errno(link, r, "Failed to store TClass: %m");
+        r = tclass_dup(tclass, &tmp);
+        if (r < 0)
+                return r;
 
-                existing = tmp;
-        } else
-                existing->source = tclass->source;
+        if (tclass_get(link, tclass, &existing) >= 0)
+                /* Copy state for logging below. */
+                tmp->state = existing->state;
 
-        log_tclass_debug(existing, link, "Requesting");
+        log_tclass_debug(tmp, link, "Requesting");
         r = link_queue_request_safe(link, REQUEST_TYPE_TC_CLASS,
-                                    existing, NULL,
+                                    tmp,
+                                    tclass_unref,
                                     tclass_hash_func,
                                     tclass_compare_func,
                                     tclass_process_request,
                                     &link->tc_messages,
                                     tclass_handler,
                                     NULL);
-        if (r < 0)
-                return log_link_warning_errno(link, r, "Failed to request TClass: %m");
-        if (r == 0)
-                return 0;
+        if (r <= 0)
+                return r;
 
-        tclass_enter_requesting(existing);
+        tclass_enter_requesting(tmp);
+        if (existing)
+                tclass_enter_requesting(existing);
+
+        TAKE_PTR(tmp);
         return 1;
 }
 
 int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
         _cleanup_(tclass_unrefp) TClass *tmp = NULL;
+        Request *req = NULL;
         TClass *tclass = NULL;
         Link *link;
         uint16_t type;
@@ -559,39 +566,42 @@ int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, M
         }
 
         (void) tclass_get(link, tmp, &tclass);
+        (void) tclass_get_request(link, tmp, &req);
 
-        switch (type) {
-        case RTM_NEWTCLASS:
-                if (tclass) {
-                        tclass_enter_configured(tclass);
-                        log_tclass_debug(tclass, link, "Received remembered");
-                } else {
-                        tclass_enter_configured(tmp);
-                        log_tclass_debug(tmp, link, "Received new");
-
-                        r = tclass_attach(link, tmp);
-                        if (r < 0) {
-                                log_link_warning_errno(link, r, "Failed to remember TClass, ignoring: %m");
-                                return 0;
-                        }
-
-                        tclass = tmp;
-                }
-
-                break;
-
-        case RTM_DELTCLASS:
+        if (type == RTM_DELTCLASS) {
                 if (tclass)
                         tclass_drop(tclass);
                 else
                         log_tclass_debug(tmp, link, "Kernel removed unknown");
 
-                break;
+                return 0;
+        }
 
-        default:
-                assert_not_reached();
+        bool is_new = false;
+        if (!tclass) {
+                /* If we did not know the tclass, then save it. */
+                r = tclass_attach(link, tmp);
+                if (r < 0) {
+                        log_link_warning_errno(link, r, "Failed to remember TClass, ignoring: %m");
+                        return 0;
+                }
+
+                tclass = tmp;
+                is_new = true;
         }
 
+        /* Also update information that cannot be obtained through netlink notification. */
+        if (req && req->waiting_reply) {
+                TClass *t = ASSERT_PTR(req->userdata);
+
+                tclass->source = t->source;
+        }
+
+        tclass_enter_configured(tclass);
+        if (req)
+                tclass_enter_configured(req->userdata);
+
+        log_tclass_debug(tclass, link, is_new ? "Remembering" : "Received remembered");
         return 1;
 }
 
index ce51b2499ecc8e4e4e599bcd83179f5310a937e6..31374d6da8dccbc81950a4468dae497ccbc4b924 100644 (file)
@@ -66,7 +66,7 @@ void link_tclass_drop_marked(Link *link);
 
 int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
 
-int link_request_tclass(Link *link, TClass *tclass);
+int link_request_tclass(Link *link, const TClass *tclass);
 
 void network_drop_invalid_tclass(Network *network);