summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/systemd/systemd
diff options
context:
space:
mode:
authorRanjitsinh Rathod <ranjitsinh.rathod@kpit.com>2021-09-22 21:08:08 +0530
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-10-07 15:10:33 +0100
commitf3452bf99367ed2270a4deb47e6f03039af7d39d (patch)
tree4f843091972e2297f6f67809c7eec1c68dab761f /meta/recipes-core/systemd/systemd
parent3d5a3e009a6ff92b16ab205ec9123f52fca23c77 (diff)
downloadpoky-f3452bf99367ed2270a4deb47e6f03039af7d39d.tar.gz
systemd: Add fix for systemd-networkd crash during free
We are observing systemd-network service crash during link down while freeing link->ifname pointer Backtrace: (gdb) bt 0 __GI_abort () at abort.c:107 1 0x0000007f861d32b4 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f8628d500 "%s\n") at ../sysdeps/posix/libc_fatal.c:155 2 0x0000007f861da51c in malloc_printerr (str=str@entry=0x7f86289070 "free(): invalid next size (fast)") at malloc.c:5347 3 0x0000007f861dbd58 in _int_free (av=0x7f862c9a28 <main_arena>, p=0x558aa28eb0, have_lock=0) at malloc.c:4249 4 0x0000005569249cf0 in link_free (link=0x558aa1c0d0) at ../git/src/network/networkd-link.c:715 5 link_unref (p=0x558aa1c0d0) at ../git/src/network/networkd-link.c:734 6 0x000000556920f34c in manager_rtnl_process_link (rtnl=<optimized out>, message=0x558aa2a430, userdata=0x558a9fc630) While checking upstream code change with regards to link->ifname memory allocation and free, we found below PR which also fixes random systemd-networkd crash: https://github.com/systemd/systemd/pull/19631 https://github.com/systemd/systemd/issues/19629 (From OE-Core rev: adca61c61d84f022fdedd2d616e7c2df00661af8) Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> Signed-off-by: Ranjitsinh Rathod <ranjitsinhrathod1991@gmail.com> Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-core/systemd/systemd')
-rw-r--r--meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch78
-rw-r--r--meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch35
-rw-r--r--meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch285
-rw-r--r--meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch50
-rw-r--r--meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch278
-rw-r--r--meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch67
6 files changed, 793 insertions, 0 deletions
diff --git a/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch
new file mode 100644
index 0000000000..86d9b0499a
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch
@@ -0,0 +1,78 @@
1From 1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Tue, 1 Sep 2020 12:42:35 +0200
4Subject: [PATCH] basic: pass allocation info for ordered_set_new() and
5 introduce ordered_set_ensure_put()
6
7Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1]
8Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
9
10---
11 src/basic/ordered-set.c | 21 +++++++++++++++++++++
12 src/basic/ordered-set.h | 18 +++++++-----------
13 2 files changed, 28 insertions(+), 11 deletions(-)
14
15diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
16index 7fdb47e064..fb82c17b5a 100644
17--- a/src/basic/ordered-set.c
18+++ b/src/basic/ordered-set.c
19@@ -4,6 +4,27 @@
20 #include "ordered-set.h"
21 #include "strv.h"
22
23+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) {
24+ if (*s)
25+ return 0;
26+
27+ *s = _ordered_set_new(ops HASHMAP_DEBUG_PASS_ARGS);
28+ if (!*s)
29+ return -ENOMEM;
30+
31+ return 0;
32+}
33+
34+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS) {
35+ int r;
36+
37+ r = _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_PASS_ARGS);
38+ if (r < 0)
39+ return r;
40+
41+ return ordered_set_put(*s, p);
42+}
43+
44 int ordered_set_consume(OrderedSet *s, void *p) {
45 int r;
46
47diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
48index a42a57eb49..2c241a808b 100644
49--- a/src/basic/ordered-set.h
50+++ b/src/basic/ordered-set.h
51@@ -7,20 +7,16 @@
52
53 typedef struct OrderedSet OrderedSet;
54
55-static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) {
56- return (OrderedSet*) ordered_hashmap_new(ops);
57+static inline OrderedSet* _ordered_set_new(const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) {
58+ return (OrderedSet*) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_PASS_ARGS);
59 }
60+#define ordered_set_new(ops) _ordered_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
61
62-static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) {
63- if (*s)
64- return 0;
65+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS);
66+#define ordered_set_ensure_allocated(s, ops) _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_SRC_ARGS)
67
68- *s = ordered_set_new(ops);
69- if (!*s)
70- return -ENOMEM;
71-
72- return 0;
73-}
74+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS);
75+#define ordered_set_ensure_put(s, hash_ops, key) _ordered_set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
76
77 static inline OrderedSet* ordered_set_free(OrderedSet *s) {
78 return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s);
diff --git a/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch
new file mode 100644
index 0000000000..42b6e05b55
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch
@@ -0,0 +1,35 @@
1From d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5 Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 26 Apr 2021 23:52:40 +0900
4Subject: [PATCH] ordered-set: introduce
5 ordered_set_clear/free_with_destructor()
6
7Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5]
8Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
9
10---
11 src/basic/ordered-set.h | 11 +++++++++++
12 1 file changed, 11 insertions(+)
13
14diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
15index a377f20b1f..64df41766f 100644
16--- a/src/basic/ordered-set.h
17+++ b/src/basic/ordered-set.h
18@@ -63,6 +63,17 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s);
19 #define ORDERED_SET_FOREACH(e, s, i) \
20 for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
21
22+#define ordered_set_clear_with_destructor(s, f) \
23+ ({ \
24+ OrderedSet *_s = (s); \
25+ void *_item; \
26+ while ((_item = ordered_set_steal_first(_s))) \
27+ f(_item); \
28+ _s; \
29+ })
30+#define ordered_set_free_with_destructor(s, f) \
31+ ordered_set_free(ordered_set_clear_with_destructor(s, f))
32+
33 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
34 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
35
diff --git a/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch
new file mode 100644
index 0000000000..06c523834d
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch
@@ -0,0 +1,285 @@
1From 19d9a5adf0c1a6b5a243eea0390f6f6526d569de Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Fri, 7 May 2021 15:39:16 +0900
4Subject: [PATCH] network: add skeleton of request queue
5
6This will be used in later commits.
7
8Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/19d9a5adf0c1a6b5a243eea0390f6f6526d569de]
9Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
10
11---
12 src/network/meson.build | 2 +
13 src/network/networkd-link.c | 20 +++++-
14 src/network/networkd-manager.c | 7 ++
15 src/network/networkd-manager.h | 2 +
16 src/network/networkd-queue.c | 121 +++++++++++++++++++++++++++++++++
17 src/network/networkd-queue.h | 42 ++++++++++++
18 6 files changed, 192 insertions(+), 2 deletions(-)
19 create mode 100644 src/network/networkd-queue.c
20 create mode 100644 src/network/networkd-queue.h
21
22diff --git a/src/network/meson.build b/src/network/meson.build
23index 4fca3106dc..a8b9232e64 100644
24--- a/src/network/meson.build
25+++ b/src/network/meson.build
26@@ -105,6 +105,8 @@ sources = files('''
27 networkd-network.h
28 networkd-nexthop.c
29 networkd-nexthop.h
30+ networkd-queue.c
31+ networkd-queue.h
32 networkd-route.c
33 networkd-route.h
34 networkd-routing-policy-rule.c
35diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
36index 34359b2541..2f33305a27 100644
37--- a/src/network/networkd-link.c
38+++ b/src/network/networkd-link.c
39@@ -30,6 +30,7 @@
40 #include "networkd-manager.h"
41 #include "networkd-ndisc.h"
42 #include "networkd-neighbor.h"
43+#include "networkd-queue.h"
44 #include "networkd-radv.h"
45 #include "networkd-routing-policy-rule.h"
46 #include "networkd-wifi.h"
47
48@@ -2232,6 +2244,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
49 if (r < 0)
50 return r;
51
52+ link_drop_requests(link);
53+
54 r = link_drop_config(link);
55 if (r < 0)
56 return r;
57@@ -2664,6 +2678,8 @@ static int link_carrier_lost(Link *link) {
58 return r;
59 }
60
61+ link_drop_requests(link);
62+
63 r = link_drop_config(link);
64 if (r < 0)
65 return r;
66diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
67index 562ce5ca54..fd576169a9 100644
68--- a/src/network/networkd-manager.c
69+++ b/src/network/networkd-manager.c
70@@ -34,6 +34,7 @@
71 #include "networkd-manager-bus.h"
72 #include "networkd-manager.h"
73 #include "networkd-network-bus.h"
74+#include "networkd-queue.h"
75 #include "networkd-speed-meter.h"
76 #include "ordered-set.h"
77 #include "path-util.h"
78@@ -406,6 +407,10 @@ int manager_new(Manager **ret) {
79 if (r < 0)
80 return r;
81
82+ r = sd_event_add_post(m->event, NULL, manager_process_requests, m);
83+ if (r < 0)
84+ return r;
85+
86 r = manager_connect_rtnl(m);
87 if (r < 0)
88 return r;
89@@ -446,6 +451,8 @@ Manager* manager_free(Manager *m) {
90
91 free(m->state_file);
92
93+ m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free);
94+
95 while ((a = hashmap_first_key(m->dhcp6_prefixes)))
96 (void) dhcp6_prefix_remove(m, a);
97 m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes);
98diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
99index 301b97c1a1..26e8802871 100644
100--- a/src/network/networkd-manager.h
101+++ b/src/network/networkd-manager.h
102@@ -91,6 +91,8 @@ struct Manager {
103 usec_t speed_meter_usec_old;
104
105 bool dhcp4_prefix_root_cannot_set_table;
106+
107+ OrderedSet *request_queue;
108 };
109
110 int manager_new(Manager **ret);
111diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c
112new file mode 100644
113index 0000000000..24bb2c845d
114--- /dev/null
115+++ b/src/network/networkd-queue.c
116@@ -0,0 +1,121 @@
117+/* SPDX-License-Identifier: LGPL-2.1-or-later */
118+
119+#include "networkd-address.h"
120+#include "networkd-manager.h"
121+#include "networkd-neighbor.h"
122+#include "networkd-nexthop.h"
123+#include "networkd-route.h"
124+#include "networkd-routing-policy-rule.h"
125+#include "networkd-queue.h"
126+
127+static void request_free_object(RequestType type, void *object) {
128+ switch(type) {
129+ default:
130+ assert_not_reached("invalid request type.");
131+ }
132+}
133+
134+Request *request_free(Request *req) {
135+ if (!req)
136+ return NULL;
137+
138+ if (req->on_free)
139+ req->on_free(req);
140+ if (req->consume_object)
141+ request_free_object(req->type, req->object);
142+ if (req->link && req->link->manager)
143+ ordered_set_remove(req->link->manager->request_queue, req);
144+ link_unref(req->link);
145+
146+ return mfree(req);
147+}
148+
149+DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
150+
151+void request_drop(Request *req) {
152+ if (req->message_counter)
153+ (*req->message_counter)--;
154+
155+ request_free(req);
156+}
157+
158+int link_queue_request(
159+ Link *link,
160+ RequestType type,
161+ void *object,
162+ bool consume_object,
163+ unsigned *message_counter,
164+ link_netlink_message_handler_t netlink_handler,
165+ Request **ret) {
166+
167+ _cleanup_(request_freep) Request *req = NULL;
168+ int r;
169+
170+ assert(link);
171+ assert(link->manager);
172+ assert(type >= 0 && type < _REQUEST_TYPE_MAX);
173+ assert(object);
174+ assert(netlink_handler);
175+
176+ req = new(Request, 1);
177+ if (!req) {
178+ if (consume_object)
179+ request_free_object(type, object);
180+ return -ENOMEM;
181+ }
182+
183+ *req = (Request) {
184+ .link = link,
185+ .type = type,
186+ .object = object,
187+ .consume_object = consume_object,
188+ .message_counter = message_counter,
189+ .netlink_handler = netlink_handler,
190+ };
191+
192+ link_ref(link);
193+
194+ r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req);
195+ if (r < 0)
196+ return r;
197+
198+ if (req->message_counter)
199+ (*req->message_counter)++;
200+
201+ if (ret)
202+ *ret = req;
203+
204+ TAKE_PTR(req);
205+ return 0;
206+}
207+
208+int manager_process_requests(sd_event_source *s, void *userdata) {
209+ Manager *manager = userdata;
210+ int r;
211+
212+ assert(manager);
213+
214+ for (;;) {
215+ bool processed = false;
216+ Request *req;
217+ Iterator i;
218+ ORDERED_SET_FOREACH(req, manager->request_queue, i) {
219+ switch(req->type) {
220+ default:
221+ return -EINVAL;
222+ }
223+ if (r < 0)
224+ link_enter_failed(req->link);
225+ if (r > 0) {
226+ ordered_set_remove(manager->request_queue, req);
227+ request_free(req);
228+ processed = true;
229+ }
230+ }
231+
232+ if (!processed)
233+ break;
234+ }
235+
236+ return 0;
237+}
238diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h
239new file mode 100644
240index 0000000000..4558ae548f
241--- /dev/null
242+++ b/src/network/networkd-queue.h
243@@ -0,0 +1,42 @@
244+/* SPDX-License-Identifier: LGPL-2.1-or-later */
245+#pragma once
246+
247+#include "sd-event.h"
248+
249+#include "networkd-link.h"
250+
251+typedef struct Request Request;
252+
253+typedef int (*request_after_configure_handler_t)(Request*, void*);
254+typedef void (*request_on_free_handler_t)(Request*);
255+
256+typedef enum RequestType {
257+ _REQUEST_TYPE_MAX,
258+ _REQUEST_TYPE_INVALID = -EINVAL,
259+} RequestType;
260+
261+typedef struct Request {
262+ Link *link;
263+ RequestType type;
264+ bool consume_object;
265+ void *object;
266+ void *userdata;
267+ unsigned *message_counter;
268+ link_netlink_message_handler_t netlink_handler;
269+ request_after_configure_handler_t after_configure;
270+ request_on_free_handler_t on_free;
271+} Request;
272+
273+Request *request_free(Request *req);
274+void request_drop(Request *req);
275+
276+int link_queue_request(
277+ Link *link,
278+ RequestType type,
279+ void *object,
280+ bool consume_object,
281+ unsigned *message_counter,
282+ link_netlink_message_handler_t netlink_handler,
283+ Request **ret);
284+
285+int manager_process_requests(sd_event_source *s, void *userdata);
diff --git a/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch
new file mode 100644
index 0000000000..4c402e7e55
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch
@@ -0,0 +1,50 @@
1From 56001f023305ea99329e27141d6e6067596491a9 Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 17 May 2021 15:32:57 +0900
4Subject: [PATCH] network: also drop requests when link enters linger state
5
6Otherwise, if link is removed, several references to the link in remain
7exist in requests.
8
9Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/56001f023305ea99329e27141d6e6067596491a9]
10Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
11
12---
13 src/network/networkd-link.c | 24 +++++++++++++-----------
14 1 file changed, 13 insertions(+), 11 deletions(-)
15
16diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
17index 67d01ac44d..b56c232eca 100644
18--- a/src/network/networkd-link.c
19+++ b/src/network/networkd-link.c
20@@ -1771,6 +1771,18 @@ static void link_drop_from_master(Link *link, NetDev *netdev) {
21 link_unref(set_remove(master->slaves, link));
22 }
23
24+static void link_drop_requests(Link *link) {
25+ Request *req;
26+ Iterator i;
27+
28+ assert(link);
29+ assert(link->manager);
30+
31+ ORDERED_SET_FOREACH(req, link->manager->request_queue, i)
32+ if (req->link == link)
33+ request_drop(req);
34+}
35+
36 void link_drop(Link *link) {
37 if (!link)
38 return;
39@@ -1782,6 +1793,8 @@ void link_drop(Link *link) {
40 /* Drop all references from other links and manager. Note that async netlink calls may have
41 * references to the link, and they will be dropped when we receive replies. */
42
43+ link_drop_requests(link);
44+
45 link_free_carrier_maps(link);
46
47 if (link->network) {
48--
492.17.1
50
diff --git a/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch
new file mode 100644
index 0000000000..a186bb4095
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch
@@ -0,0 +1,278 @@
1From cc2d7efc5ca09a7de4bec55e80476986839a655c Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Fri, 14 May 2021 15:58:15 +0900
4Subject: [PATCH] network: fix Link reference counter issue
5
6Previously, when link_new() fails, `link_unref()` was called, so,
7`Manager::links` may become dirty.
8This introduces `link_drop_or_unref()` and it will be called on
9failure.
10
11Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/cc2d7efc5ca09a7de4bec55e80476986839a655c]
12Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
13
14---
15 src/network/networkd-link.c | 240 ++++++++++++++++++------------------
16 1 file changed, 122 insertions(+), 118 deletions(-)
17
18diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
19index b56c232eca..d493afda4c 100644
20--- a/src/network/networkd-link.c
21+++ b/src/network/networkd-link.c
22@@ -540,109 +540,6 @@ static int link_update_flags(Link *link,
23 return 0;
24 }
25
26-static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
27- _cleanup_(link_unrefp) Link *link = NULL;
28- uint16_t type;
29- const char *ifname, *kind = NULL;
30- int r, ifindex;
31- unsigned short iftype;
32-
33- assert(manager);
34- assert(message);
35- assert(ret);
36-
37- /* check for link kind */
38- r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
39- if (r == 0) {
40- (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind);
41- r = sd_netlink_message_exit_container(message);
42- if (r < 0)
43- return r;
44- }
45-
46- r = sd_netlink_message_get_type(message, &type);
47- if (r < 0)
48- return r;
49- else if (type != RTM_NEWLINK)
50- return -EINVAL;
51-
52- r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
53- if (r < 0)
54- return r;
55- else if (ifindex <= 0)
56- return -EINVAL;
57-
58- r = sd_rtnl_message_link_get_type(message, &iftype);
59- if (r < 0)
60- return r;
61-
62- r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
63- if (r < 0)
64- return r;
65-
66- link = new(Link, 1);
67- if (!link)
68- return -ENOMEM;
69-
70- *link = (Link) {
71- .n_ref = 1,
72- .manager = manager,
73- .state = LINK_STATE_PENDING,
74- .ifindex = ifindex,
75- .iftype = iftype,
76-
77- .n_dns = (unsigned) -1,
78- .dns_default_route = -1,
79- .llmnr = _RESOLVE_SUPPORT_INVALID,
80- .mdns = _RESOLVE_SUPPORT_INVALID,
81- .dnssec_mode = _DNSSEC_MODE_INVALID,
82- .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
83- };
84-
85- link->ifname = strdup(ifname);
86- if (!link->ifname)
87- return -ENOMEM;
88-
89- if (kind) {
90- link->kind = strdup(kind);
91- if (!link->kind)
92- return -ENOMEM;
93- }
94-
95- r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex);
96- if (r < 0)
97- log_link_debug_errno(link, r, "New device has no master, continuing without");
98-
99- r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
100- if (r < 0)
101- log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
102-
103- if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
104- return -ENOMEM;
105-
106- if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
107- return -ENOMEM;
108-
109- if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
110- return -ENOMEM;
111-
112- r = hashmap_ensure_allocated(&manager->links, NULL);
113- if (r < 0)
114- return r;
115-
116- r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
117- if (r < 0)
118- return r;
119-
120- r = link_update_flags(link, message, false);
121- if (r < 0)
122- return r;
123-
124- *ret = TAKE_PTR(link);
125-
126- return 0;
127-}
128-
129 void link_ntp_settings_clear(Link *link) {
130 link->ntp = strv_free(link->ntp);
131 }
132@@ -2030,9 +1927,9 @@ static void link_drop_requests(Link *lin
133 request_drop(req);
134 }
135
136-void link_drop(Link *link) {
137+Link *link_drop(Link *link) {
138 if (!link)
139- return;
140+ return NULL;
141
142 assert(link->manager);
143
144@@ -2057,7 +1954,7 @@ void link_drop(Link *link) {
145
146 /* The following must be called at last. */
147 assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
148- link_unref(link);
149+ return link_unref(link);
150 }
151
152 static int link_joined(Link *link) {
153@@ -3295,6 +3192,112 @@ ipv4ll_address_fail:
154
155 return 0;
156 }
157+
158+static Link *link_drop_or_unref(Link *link) {
159+ if (!link)
160+ return NULL;
161+ if (!link->manager)
162+ return link_unref(link);
163+ return link_drop(link);
164+}
165+
166+DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref);
167+
168+static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
169+ _cleanup_(link_drop_or_unrefp) Link *link = NULL;
170+ uint16_t type;
171+ _cleanup_free_ char *ifname = NULL, *kind = NULL;
172+ int r, ifindex;
173+ unsigned short iftype;
174+
175+ assert(manager);
176+ assert(message);
177+ assert(ret);
178+
179+ r = sd_netlink_message_get_type(message, &type);
180+ if (r < 0)
181+ return r;
182+ else if (type != RTM_NEWLINK)
183+ return -EINVAL;
184+
185+ r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
186+ if (r < 0)
187+ return r;
188+ else if (ifindex <= 0)
189+ return -EINVAL;
190+
191+ r = sd_rtnl_message_link_get_type(message, &iftype);
192+ if (r < 0)
193+ return r;
194+
195+ r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, &ifname);
196+ if (r < 0)
197+ return r;
198+
199+ /* check for link kind */
200+ r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
201+ if (r >= 0) {
202+ (void) sd_netlink_message_read_string_strdup(message, IFLA_INFO_KIND, &kind);
203+ r = sd_netlink_message_exit_container(message);
204+ if (r < 0)
205+ return r;
206+ }
207+
208+ link = new(Link, 1);
209+ if (!link)
210+ return -ENOMEM;
211+
212+ *link = (Link) {
213+ .n_ref = 1,
214+ .state = LINK_STATE_PENDING,
215+ .ifindex = ifindex,
216+ .iftype = iftype,
217+ .ifname = TAKE_PTR(ifname),
218+ .kind = TAKE_PTR(kind),
219+
220+ .n_dns = (unsigned) -1,
221+ .dns_default_route = -1,
222+ .llmnr = _RESOLVE_SUPPORT_INVALID,
223+ .mdns = _RESOLVE_SUPPORT_INVALID,
224+ .dnssec_mode = _DNSSEC_MODE_INVALID,
225+ .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
226+ };
227+
228+ r = hashmap_ensure_allocated(&manager->links, NULL);
229+ if (r < 0)
230+ return r;
231+
232+ r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
233+ if (r < 0)
234+ return r;
235+
236+ link->manager = manager;
237+
238+ r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t*) &link->master_ifindex);
239+ if (r < 0)
240+ log_link_debug_errno(link, r, "New device has no master, continuing without");
241+
242+ r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
243+ if (r < 0)
244+ log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
245+
246+ if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
247+ return -ENOMEM;
248+
249+ if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
250+ return -ENOMEM;
251+
252+ if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
253+ return -ENOMEM;
254+
255+ r = link_update_flags(link, message, false);
256+ if (r < 0)
257+ return r;
258+
259+ *ret = TAKE_PTR(link);
260+
261+ return 0;
262+}
263
264 int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
265 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
266
267--- a/src/network/networkd-link.h 2021-09-02 18:04:16.900542857 +0530
268+++ b/src/network/networkd-link.h 2021-09-02 18:18:56.776571563 +0530
269@@ -175,7 +175,7 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_d
270
271 int link_get(Manager *m, int ifindex, Link **ret);
272 int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
273-void link_drop(Link *link);
274+Link *link_drop(Link *link);
275
276 int link_down(Link *link, link_netlink_message_handler_t callback);
277
278
diff --git a/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch
new file mode 100644
index 0000000000..65bdc611df
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch
@@ -0,0 +1,67 @@
1From 63130eb36dc51e4fd50716c585f98ebe456ca7cf Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 17 May 2021 15:40:15 +0900
4Subject: [PATCH] network: merge link_drop() and link_detach_from_manager()
5
6link_detach_from_manager() is only called by link_drop(). It is not
7necessary to split such tiny function.
8
9Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/63130eb36dc51e4fd50716c585f98ebe456ca7cf]
10Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
11
12---
13 src/network/networkd-link.c | 27 ++++++++++++---------------
14 1 file changed, 12 insertions(+), 15 deletions(-)
15
16diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
17index 9d30e16b0a..67d01ac44d 100644
18--- a/src/network/networkd-link.c
19+++ b/src/network/networkd-link.c
20@@ -2019,24 +2019,17 @@ static void link_drop_from_master(Link *link, NetDev *netdev) {
21 link_unref(set_remove(master->slaves, link));
22 }
23
24-static void link_detach_from_manager(Link *link) {
25- if (!link || !link->manager)
26- return;
27-
28- link_unref(set_remove(link->manager->links_requesting_uuid, link));
29- link_clean(link);
30-
31- /* The following must be called at last. */
32- assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
33- link_unref(link);
34-}
35-
36 void link_drop(Link *link) {
37- if (!link || link->state == LINK_STATE_LINGER)
38+ if (!link)
39 return;
40
41+ assert(link->manager);
42+
43 link_set_state(link, LINK_STATE_LINGER);
44
45+ /* Drop all references from other links and manager. Note that async netlink calls may have
46+ * references to the link, and they will be dropped when we receive replies. */
47+
48 link_free_carrier_maps(link);
49
50 if (link->network) {
51@@ -2044,10 +2037,14 @@ void link_drop(Link *link) {
52 link_drop_from_master(link, link->network->bond);
53 }
54
55- log_link_debug(link, "Link removed");
56+ link_unref(set_remove(link->manager->links_requesting_uuid, link));
57
58 (void) unlink(link->state_file);
59- link_detach_from_manager(link);
60+ link_clean(link);
61+
62+ /* The following must be called at last. */
63+ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
64+ link_unref(link);
65 }
66
67 static int link_joined(Link *link) {