• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14872145375

06 May 2025 09:07PM UTC coverage: 72.232% (+0.02%) from 72.214%
14872145375

push

github

DaanDeMeyer
string-table: annotate _to_string and _from_string with _const_ and _pure_, respectively

Follow-up for c94f6ab1b

297286 of 411572 relevant lines covered (72.23%)

695615.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.22
/src/network/networkd-setlink.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <linux/if.h>
4
#include <linux/if_arp.h>
5
#include <linux/if_bridge.h>
6
#include <linux/ipv6.h>
7
#include <netinet/in.h>
8

9
#include "device-private.h"
10
#include "missing_network.h"
11
#include "netif-util.h"
12
#include "netlink-util.h"
13
#include "networkd-address.h"
14
#include "networkd-can.h"
15
#include "networkd-ipv4acd.h"
16
#include "networkd-ipv4ll.h"
17
#include "networkd-link.h"
18
#include "networkd-manager.h"
19
#include "networkd-queue.h"
20
#include "networkd-setlink.h"
21
#include "networkd-sriov.h"
22
#include "networkd-wiphy.h"
23

24
static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
939✔
25
        return link_getlink_handler_internal(rtnl, m, link, "Failed to sync link information");
939✔
26
}
27

28
static int get_link_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
32✔
29
        if (get_link_default_handler(rtnl, m, link) > 0)
32✔
30
                link->master_set = true;
32✔
31
        return 0;
32✔
32
}
33

34
static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
776✔
35
        assert(link);
776✔
36
        assert(link->set_flags_messages > 0);
776✔
37

38
        link->set_flags_messages--;
776✔
39

40
        return get_link_default_handler(rtnl, m, link);
776✔
41
}
42

43
static int set_link_handler_internal(
293✔
44
                sd_netlink *rtnl,
45
                sd_netlink_message *m,
46
                Request *req,
47
                Link *link,
48
                bool ignore,
49
                link_netlink_message_handler_t get_link_handler) {
50

51
        int r;
293✔
52

53
        assert(m);
293✔
54
        assert(req);
293✔
55
        assert(link);
293✔
56

57
        r = sd_netlink_message_get_errno(m);
293✔
58
        if (r < 0) {
293✔
59
                log_link_message_warning_errno(link, m, r, "Failed to set %s%s",
×
60
                                               request_type_to_string(req->type),
61
                                               ignore ? ", ignoring" : "");
62

63
                if (!ignore)
×
64
                        link_enter_failed(link);
×
65
                return 0;
×
66
        }
67

68
        log_link_debug(link, "%s set.", request_type_to_string(req->type));
293✔
69

70
        if (get_link_handler) {
293✔
71
                r = link_call_getlink(link, get_link_handler);
163✔
72
                if (r < 0) {
163✔
73
                        link_enter_failed(link);
×
74
                        return 0;
×
75
                }
76
        }
77

78
        if (link->set_link_messages == 0)
293✔
79
                link_check_ready(link);
205✔
80

81
        return 1;
82
}
83

84
static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
71✔
85
        int r;
71✔
86

87
        r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
71✔
88
        if (r <= 0)
71✔
89
                return r;
90

91
        r = link_drop_ipv6ll_addresses(link);
71✔
92
        if (r < 0) {
71✔
93
                log_link_warning_errno(link, r, "Failed to drop IPv6LL addresses: %m");
×
94
                link_enter_failed(link);
×
95
        }
96

97
        return 0;
98
}
99

100
static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
10✔
101
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
10✔
102
}
103

104
static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
29✔
105
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
29✔
106
}
107

108
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
10✔
109
        int r;
10✔
110

111
        assert(link);
10✔
112

113
        r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
10✔
114
        if (r <= 0)
10✔
115
                return r;
116

117
        link->bridge_vlan_set = true;
10✔
118
        return 0;
10✔
119
}
120

121
static int link_del_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
10✔
122
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
10✔
123
}
124

125
static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
×
126
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
×
127
}
128

129
static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
85✔
130
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler);
85✔
131
}
132

133
static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
×
134
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
×
135
}
136

137
static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
×
138
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
×
139
}
140

141
static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
5✔
142
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
5✔
143
}
144

145
static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
5✔
146
        int r;
5✔
147

148
        assert(m);
5✔
149
        assert(link);
5✔
150

151
        r = sd_netlink_message_get_errno(m);
5✔
152
        if (r == -EBUSY) {
5✔
153
                /* Most real network devices refuse to set its hardware address with -EBUSY when its
154
                 * operstate is not down. See, eth_prepare_mac_addr_change() in net/ethernet/eth.c
155
                 * of kernel. */
156

157
                log_link_message_debug_errno(link, m, r, "Failed to set MAC address, retrying again: %m");
×
158

159
                r = link_request_to_set_mac(link, /* allow_retry = */ false);
×
160
                if (r < 0)
×
161
                        link_enter_failed(link);
×
162

163
                return 0;
×
164
        }
165

166
        return link_set_mac_handler(rtnl, m, req, link, userdata);
5✔
167
}
168

169
static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
32✔
170
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler);
32✔
171
}
172

173
static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
×
174
        /* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */
175
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler);
×
176
}
177

178
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
41✔
179
        return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
41✔
180
}
181

182
static int link_get_arp(Link *link) {
852✔
183
        assert(link);
852✔
184

185
        /* This returns tristate. */
186

187
        if (!link->network)
852✔
188
                return -1;
189

190
        /* If ARP= is explicitly specified, use the setting. */
191
        if (link->network->arp >= 0)
852✔
192
                return link->network->arp;
193

194
        /* Enable ARP when IPv4ACD is enabled. */
195
        if (link_ipv4acd_enabled(link))
852✔
196
                return true;
197

198
        /* Similarly, enable ARP when IPv4LL is enabled. */
199
        if (link_ipv4ll_enabled(link))
848✔
200
                return true;
166✔
201

202
        /* Otherwise, do not change the flag. */
203
        return -1;
204
}
205

206
static int link_configure_fill_message(
293✔
207
                Link *link,
208
                sd_netlink_message *req,
209
                RequestType type,
210
                void *userdata) {
211
        int r;
293✔
212

213
        switch (type) {
293✔
214
        case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE:
71✔
215
                r = ipv6ll_addrgen_mode_fill_message(req, PTR_TO_UINT8(userdata));
71✔
216
                if (r < 0)
71✔
217
                        return r;
×
218
                break;
219
        case REQUEST_TYPE_SET_LINK_BOND:
10✔
220
                r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
10✔
221
                if (r < 0)
10✔
222
                        return r;
223

224
                r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
10✔
225
                if (r < 0)
10✔
226
                        return r;
227

228
                if (link->network->active_slave) {
10✔
229
                        r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
5✔
230
                        if (r < 0)
5✔
231
                                return r;
232
                }
233

234
                if (link->network->primary_slave) {
10✔
235
                        r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
1✔
236
                        if (r < 0)
1✔
237
                                return r;
238
                }
239

240
                r = sd_netlink_message_close_container(req);
10✔
241
                if (r < 0)
10✔
242
                        return r;
243

244
                r = sd_netlink_message_close_container(req);
10✔
245
                if (r < 0)
10✔
246
                        return r;
×
247

248
                break;
249
        case REQUEST_TYPE_SET_LINK_BRIDGE:
29✔
250
                r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
29✔
251
                if (r < 0)
29✔
252
                        return r;
253

254
                r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
29✔
255
                if (r < 0)
29✔
256
                        return r;
257

258
                if (link->network->use_bpdu >= 0) {
29✔
259
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
8✔
260
                        if (r < 0)
8✔
261
                                return r;
262
                }
263

264
                if (link->network->hairpin >= 0) {
29✔
265
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
7✔
266
                        if (r < 0)
7✔
267
                                return r;
268
                }
269

270
                if (link->network->isolated >= 0) {
29✔
271
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_ISOLATED, link->network->isolated);
6✔
272
                        if (r < 0)
6✔
273
                                return r;
274
                }
275

276
                if (link->network->fast_leave >= 0) {
29✔
277
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
7✔
278
                        if (r < 0)
7✔
279
                                return r;
280
                }
281

282
                if (link->network->allow_port_to_be_root >= 0) {
29✔
283
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
7✔
284
                        if (r < 0)
7✔
285
                                return r;
286
                }
287

288
                if (link->network->unicast_flood >= 0) {
29✔
289
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
7✔
290
                        if (r < 0)
7✔
291
                                return r;
292
                }
293

294
                if (link->network->multicast_flood >= 0) {
29✔
295
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
7✔
296
                        if (r < 0)
7✔
297
                                return r;
298
                }
299

300
                if (link->network->multicast_to_unicast >= 0) {
29✔
301
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
7✔
302
                        if (r < 0)
7✔
303
                                return r;
304
                }
305

306
                if (link->network->neighbor_suppression >= 0) {
29✔
307
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
7✔
308
                        if (r < 0)
7✔
309
                                return r;
310
                }
311

312
                if (link->network->learning >= 0) {
29✔
313
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
8✔
314
                        if (r < 0)
8✔
315
                                return r;
316
                }
317

318
                if (link->network->bridge_proxy_arp >= 0) {
29✔
319
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp);
×
320
                        if (r < 0)
×
321
                                return r;
322
                }
323

324
                if (link->network->bridge_proxy_arp_wifi >= 0) {
29✔
325
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi);
×
326
                        if (r < 0)
×
327
                                return r;
328
                }
329

330
                if (link->network->cost != 0) {
29✔
331
                        r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
7✔
332
                        if (r < 0)
7✔
333
                                return r;
334
                }
335

336
                if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
29✔
337
                        r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
10✔
338
                        if (r < 0)
10✔
339
                                return r;
340
                }
341

342
                if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
29✔
343
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
1✔
344
                        if (r < 0)
1✔
345
                                return r;
346
                }
347

348
                if (link->network->bridge_locked >= 0) {
29✔
349
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LOCKED, link->network->bridge_locked);
3✔
350
                        if (r < 0)
3✔
351
                                return r;
352
                }
353

354
                if (link->network->bridge_mac_authentication_bypass >= 0) {
29✔
355
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MAB, link->network->bridge_mac_authentication_bypass);
3✔
356
                        if (r < 0)
3✔
357
                                return r;
358
                }
359

360
                if (link->network->bridge_vlan_tunnel >= 0) {
29✔
361
                        r = sd_netlink_message_append_u8(req, IFLA_BRPORT_VLAN_TUNNEL, link->network->bridge_vlan_tunnel);
2✔
362
                        if (r < 0)
2✔
363
                                return r;
364
                }
365

366
                r = sd_netlink_message_close_container(req);
29✔
367
                if (r < 0)
29✔
368
                        return r;
×
369
                break;
370
        case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
10✔
371
                r = bridge_vlan_set_message(link, req, /* is_set = */ true);
10✔
372
                if (r < 0)
10✔
373
                        return r;
×
374
                break;
375
        case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
10✔
376
                r = bridge_vlan_set_message(link, req, /* is_set = */ false);
10✔
377
                if (r < 0)
10✔
378
                        return r;
×
379
                break;
380
        case REQUEST_TYPE_SET_LINK_CAN:
×
381
                r = can_set_netlink_message(link, req);
×
382
                if (r < 0)
×
383
                        return r;
×
384
                break;
385
        case REQUEST_TYPE_SET_LINK_FLAGS: {
85✔
386
                unsigned ifi_change = 0, ifi_flags = 0;
85✔
387

388
                int arp = link_get_arp(link);
85✔
389

390
                if (arp >= 0) {
85✔
391
                        ifi_change |= IFF_NOARP;
85✔
392
                        SET_FLAG(ifi_flags, IFF_NOARP, arp == 0);
85✔
393
                }
394

395
                if (link->network->multicast >= 0) {
85✔
396
                        ifi_change |= IFF_MULTICAST;
×
397
                        SET_FLAG(ifi_flags, IFF_MULTICAST, link->network->multicast);
×
398
                }
399

400
                if (link->network->allmulticast >= 0) {
85✔
401
                        ifi_change |= IFF_ALLMULTI;
×
402
                        SET_FLAG(ifi_flags, IFF_ALLMULTI, link->network->allmulticast);
×
403
                }
404

405
                if (link->network->promiscuous >= 0) {
85✔
406
                        ifi_change |= IFF_PROMISC;
×
407
                        SET_FLAG(ifi_flags, IFF_PROMISC, link->network->promiscuous);
×
408
                }
409

410
                r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
85✔
411
                if (r < 0)
85✔
412
                        return r;
×
413

414
                break;
415
        }
416
        case REQUEST_TYPE_SET_LINK_GROUP:
×
417
                r = sd_netlink_message_append_u32(req, IFLA_GROUP, (uint32_t) link->network->group);
×
418
                if (r < 0)
×
419
                        return r;
×
420
                break;
421
        case REQUEST_TYPE_SET_LINK_MAC:
5✔
422
                r = netlink_message_append_hw_addr(req, IFLA_ADDRESS, &link->requested_hw_addr);
5✔
423
                if (r < 0)
5✔
424
                        return r;
×
425
                break;
426
        case REQUEST_TYPE_SET_LINK_IPOIB:
×
427
                r = ipoib_set_netlink_message(link, req);
×
428
                if (r < 0)
×
429
                        return r;
×
430
                break;
431
        case REQUEST_TYPE_SET_LINK_MASTER:
32✔
432
                r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata));
32✔
433
                if (r < 0)
32✔
434
                        return r;
×
435
                break;
436
        case REQUEST_TYPE_SET_LINK_MTU:
41✔
437
                r = sd_netlink_message_append_u32(req, IFLA_MTU, PTR_TO_UINT32(userdata));
41✔
438
                if (r < 0)
41✔
439
                        return r;
×
440
                break;
441
        default:
×
442
                assert_not_reached();
×
443
        }
444

445
        return 0;
446
}
447

448
static int link_configure(Link *link, Request *req) {
293✔
449
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
293✔
450
        int r;
293✔
451

452
        assert(link);
293✔
453
        assert(link->manager);
293✔
454
        assert(req);
293✔
455

456
        log_link_debug(link, "Setting %s", request_type_to_string(req->type));
293✔
457

458
        if (req->type == REQUEST_TYPE_SET_LINK_BOND)
293✔
459
                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
10✔
460
        else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB))
283✔
461
                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
×
462
        else if (req->type == REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN)
283✔
463
                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_DELLINK, link->ifindex);
10✔
464
        else
465
                r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
273✔
466
        if (r < 0)
293✔
467
                return r;
468

469
        r = link_configure_fill_message(link, m, req->type, req->userdata);
293✔
470
        if (r < 0)
293✔
471
                return r;
472

473
        return request_call_netlink_async(link->manager->rtnl, m, req);
293✔
474
}
475

476
static bool netdev_is_ready(NetDev *netdev) {
178✔
477
        assert(netdev);
178✔
478

479
        if (netdev->state != NETDEV_STATE_READY)
178✔
480
                return false;
481
        if (netdev->ifindex == 0)
41✔
482
                return false;
×
483

484
        return true;
485
}
486

487
static uint32_t link_adjust_mtu(Link *link, uint32_t mtu) {
52✔
488
        const char *origin;
52✔
489
        uint32_t min_mtu;
52✔
490

491
        assert(link);
52✔
492
        assert(link->network);
52✔
493

494
        min_mtu = link->min_mtu;
52✔
495
        origin = "the minimum MTU of the interface";
52✔
496
        if (link_ipv6_enabled(link)) {
52✔
497
                /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes on the interface. Bump up
498
                 * MTU bytes to IPV6_MTU_MIN. */
499
                if (min_mtu < IPV6_MIN_MTU) {
37✔
500
                        min_mtu = IPV6_MIN_MTU;
37✔
501
                        origin = "the minimum IPv6 MTU";
37✔
502
                }
503
                if (min_mtu < link->network->ipv6_mtu) {
37✔
504
                        min_mtu = link->network->ipv6_mtu;
8✔
505
                        origin = "the requested IPv6 MTU in IPv6MTUBytes=";
8✔
506
                }
507
        }
508

509
        if (mtu < min_mtu) {
52✔
510
                log_link_warning(link, "Bumping the requested MTU %"PRIu32" to %s (%"PRIu32")",
×
511
                                 mtu, origin, min_mtu);
512
                mtu = min_mtu;
513
        }
514

515
        if (mtu > link->max_mtu) {
52✔
516
                log_link_warning(link, "Reducing the requested MTU %"PRIu32" to the interface's maximum MTU %"PRIu32".",
×
517
                                 mtu, link->max_mtu);
518
                mtu = link->max_mtu;
×
519
        }
520

521
        return mtu;
52✔
522
}
523

524
static int link_is_ready_to_set_link(Link *link, Request *req) {
1,477✔
525
        int r;
1,477✔
526

527
        assert(link);
1,477✔
528
        assert(link->manager);
1,477✔
529
        assert(link->network);
1,477✔
530
        assert(req);
1,477✔
531

532
        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1,477✔
533
                return false;
534

535
        switch (req->type) {
1,365✔
536
        case REQUEST_TYPE_SET_LINK_BOND:
714✔
537
        case REQUEST_TYPE_SET_LINK_BRIDGE:
538
                if (!link->master_set)
714✔
539
                        return false;
540

541
                if (link->network->keep_master && link->master_ifindex <= 0)
39✔
542
                        return false;
×
543
                break;
544

545
        case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
32✔
546
                if (!link->master_set)
32✔
547
                        return false;
548

549
                if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
10✔
550
                        return false;
×
551
                break;
552

553
        case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
228✔
554
                return link->bridge_vlan_set;
228✔
555

556
        case REQUEST_TYPE_SET_LINK_CAN:
×
557
                /* Do not check link->set_flags_messages here, as it is ok even if link->flags
558
                 * is outdated, and checking the counter causes a deadlock. */
559
                if (FLAGS_SET(link->flags, IFF_UP)) {
×
560
                        /* The CAN interface must be down to configure bitrate, etc... */
561
                        r = link_down_now(link);
×
562
                        if (r < 0)
×
563
                                return r;
×
564
                }
565
                break;
566

567
        case REQUEST_TYPE_SET_LINK_MAC:
5✔
568
                if (req->netlink_handler == link_set_mac_handler) {
5✔
569
                        /* This is the second attempt to set hardware address. On the first attempt
570
                         * req->netlink_handler points to link_set_mac_allow_retry_handler().
571
                         * The first attempt failed as the interface was up. */
572
                        r = link_down_now(link);
×
573
                        if (r < 0)
×
574
                                return r;
575

576
                        /* If the kind of the link is "bond", we need
577
                         * set the slave link down as well. */
578
                        if (streq_ptr(link->kind, "bond")) {
×
579
                                r = link_down_slave_links(link);
×
580
                                if (r < 0)
×
581
                                        return r;
×
582
                        }
583
                }
584
                break;
585

586
        case REQUEST_TYPE_SET_LINK_MASTER: {
178✔
587
                uint32_t m = 0;
178✔
588
                Request req_mac = {
178✔
589
                        .link = link,
590
                        .type = REQUEST_TYPE_SET_LINK_MAC,
591
                };
592

593
                if (link->network->batadv) {
178✔
594
                        if (!netdev_is_ready(link->network->batadv))
×
595
                                return false;
146✔
596
                        m = link->network->batadv->ifindex;
×
597
                } else if (link->network->bond) {
178✔
598
                        if (ordered_set_contains(link->manager->request_queue, &req_mac))
22✔
599
                                return false;
600
                        if (!netdev_is_ready(link->network->bond))
22✔
601
                                return false;
602
                        m = link->network->bond->ifindex;
9✔
603
                } else if (link->network->bridge) {
156✔
604
                        if (ordered_set_contains(link->manager->request_queue, &req_mac))
152✔
605
                                return false;
606
                        if (!netdev_is_ready(link->network->bridge))
152✔
607
                                return false;
608
                        m = link->network->bridge->ifindex;
28✔
609
                } else if (link->network->vrf) {
4✔
610
                        if (!netdev_is_ready(link->network->vrf))
4✔
611
                                return false;
612
                        m = link->network->vrf->ifindex;
4✔
613
                }
614

615
                if (m == (uint32_t) link->master_ifindex) {
41✔
616
                        /* The requested master is already set. */
617
                        link->master_set = true;
9✔
618
                        return -EALREADY; /* indicate to cancel the request. */
9✔
619
                }
620

621
                /* Do not check link->set_flags_messages here, as it is ok even if link->flags is outdated,
622
                 * and checking the counter causes a deadlock. */
623
                if (link->network->bond && FLAGS_SET(link->flags, IFF_UP)) {
32✔
624
                        /* link must be down when joining to bond master. */
625
                        r = link_down_now(link);
×
626
                        if (r < 0)
×
627
                                return r;
628
                }
629

630
                if (link->network->bridge && !FLAGS_SET(link->flags, IFF_UP) && link->dev) {
32✔
631
                        /* Some devices require the port to be up before joining the bridge.
632
                         *
633
                         * E.g. Texas Instruments SoC Ethernet running in switch mode:
634
                         * https://docs.kernel.org/networking/device_drivers/ethernet/ti/am65_nuss_cpsw_switchdev.html#enabling-switch
635
                         * > Port’s netdev devices have to be in UP before joining to the bridge to avoid
636
                         * > overwriting of bridge configuration as CPSW switch driver completely reloads its
637
                         * > configuration when first port changes its state to UP. */
638

639
                        r = device_get_property_bool(link->dev, "ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE");
21✔
640
                        if (r < 0 && r != -ENOENT)
21✔
641
                                log_link_warning_errno(link, r, "Failed to get or parse ID_NET_BRING_UP_BEFORE_JOINING_BRIDGE property, ignoring: %m");
×
642
                        else if (r > 0) {
21✔
643
                                r = link_up_now(link);
×
644
                                if (r < 0)
×
645
                                        return r;
646
                        }
647
                }
648

649
                req->userdata = UINT32_TO_PTR(m);
32✔
650
                break;
32✔
651
        }
652
        case REQUEST_TYPE_SET_LINK_MTU: {
52✔
653
                if (ordered_set_contains(link->manager->request_queue,
52✔
654
                                         &(const Request) {
52✔
655
                                                 .link = link,
656
                                                 .type = REQUEST_TYPE_SET_LINK_IPOIB,
657
                                         }))
658
                        return false;
×
659

660
                /* Changing FD mode may affect MTU.
661
                 * See https://docs.kernel.org/networking/can.html#can-fd-flexible-data-rate-driver-support
662
                 *   MTU = 16 (CAN_MTU)   => Classical CAN device
663
                 *   MTU = 72 (CANFD_MTU) => CAN FD capable device */
664
                if (ordered_set_contains(link->manager->request_queue,
52✔
665
                                         &(const Request) {
52✔
666
                                                 .link = link,
667
                                                 .type = REQUEST_TYPE_SET_LINK_CAN,
668
                                         }))
669
                        return false;
×
670

671
                /* Now, it is ready to set MTU, but before setting, adjust requested MTU. */
672
                uint32_t mtu = link_adjust_mtu(link, PTR_TO_UINT32(req->userdata));
52✔
673
                if (mtu == link->mtu)
52✔
674
                        return -EALREADY; /* Not necessary to set the same value. */
675

676
                req->userdata = UINT32_TO_PTR(mtu);
41✔
677
                break;
41✔
678
        }
679
        default:
680
                ;
681
        }
682

683
        return true;
684
}
685

686
static int link_process_set_link(Request *req, Link *link, void *userdata) {
1,477✔
687
        int r;
1,477✔
688

689
        assert(req);
1,477✔
690
        assert(link);
1,477✔
691

692
        r = link_is_ready_to_set_link(link, req);
1,477✔
693
        if (r == -EALREADY)
1,477✔
694
                return 1; /* Cancel the request. */
695
        if (r <= 0)
1,457✔
696
                return r;
697

698
        r = link_configure(link, req);
293✔
699
        if (r < 0)
293✔
700
                return log_link_warning_errno(link, r, "Failed to set %s", request_type_to_string(req->type));
×
701

702
        return 1;
703
}
704

705
static int link_request_set_link(
326✔
706
                Link *link,
707
                RequestType type,
708
                request_netlink_handler_t netlink_handler,
709
                Request **ret) {
710

711
        Request *req;
326✔
712
        int r;
326✔
713

714
        assert(link);
326✔
715

716
        r = link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
326✔
717
                                    link_process_set_link,
718
                                    &link->set_link_messages,
719
                                    netlink_handler,
720
                                    &req);
721
        if (r < 0)
326✔
722
                return log_link_warning_errno(link, r, "Failed to request to set %s: %m",
×
723
                                              request_type_to_string(type));
724

725
        log_link_debug(link, "Requested to set %s", request_type_to_string(type));
326✔
726

727
        if (ret)
326✔
728
                *ret = req;
124✔
729
        return 0;
730
}
731

732
int link_request_to_set_addrgen_mode(Link *link) {
767✔
733
        IPv6LinkLocalAddressGenMode mode;
767✔
734
        Request *req;
767✔
735
        int r;
767✔
736

737
        assert(link);
767✔
738
        assert(link->network);
767✔
739

740
        if (!socket_ipv6_is_supported())
767✔
741
                return 0;
767✔
742

743
        mode = link_get_ipv6ll_addrgen_mode(link);
767✔
744

745
        if (mode == link->ipv6ll_address_gen_mode)
767✔
746
                return 0;
747

748
        /* If the link is already up, then changing the mode by netlink does not take effect until the
749
         * link goes down. Hence, we need to reset the interface. However, setting the mode by sysctl
750
         * does not need that. Let's use the sysctl interface when the link is already up.
751
         * See also issue #22424. */
752
        if (mode != IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE &&
74✔
753
            FLAGS_SET(link->flags, IFF_UP)) {
4✔
754
                r = link_set_ipv6ll_addrgen_mode(link, mode);
3✔
755
                if (r < 0)
3✔
756
                        log_link_warning_errno(link, r, "Cannot set IPv6 address generation mode, ignoring: %m");
×
757

758
                return 0;
3✔
759
        }
760

761
        r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE,
71✔
762
                                  link_set_addrgen_mode_handler,
763
                                  &req);
764
        if (r < 0)
71✔
765
                return r;
766

767
        req->userdata = UINT8_TO_PTR(mode);
71✔
768
        return 0;
71✔
769
}
770

771
int link_request_to_set_bond(Link *link) {
767✔
772
        assert(link);
767✔
773
        assert(link->network);
767✔
774

775
        if (!link->network->bond) {
767✔
776
                Link *master;
758✔
777

778
                if (!link->network->keep_master)
758✔
779
                        return 0;
757✔
780

781
                if (link_get_master(link, &master) < 0)
2✔
782
                        return 0;
783

784
                if (!streq_ptr(master->kind, "bond"))
2✔
785
                        return 0;
786
        }
787

788
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BOND,
10✔
789
                                     link_set_bond_handler, NULL);
790
}
791

792
int link_request_to_set_bridge(Link *link) {
767✔
793
        assert(link);
767✔
794
        assert(link->network);
767✔
795

796
        if (!link->network->bridge) {
767✔
797
                Link *master;
733✔
798

799
                if (!link->network->keep_master)
733✔
800
                        return 0;
732✔
801

802
                if (link_get_master(link, &master) < 0)
2✔
803
                        return 0;
804

805
                if (!streq_ptr(master->kind, "bridge"))
2✔
806
                        return 0;
807
        }
808

809
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE,
35✔
810
                                     link_set_bridge_handler,
811
                                     NULL);
812
}
813

814
int link_request_to_set_bridge_vlan(Link *link) {
767✔
815
        int r;
767✔
816

817
        assert(link);
767✔
818
        assert(link->network);
767✔
819

820
        /* If nothing configured, use the default vlan ID. */
821
        if (memeqzero(link->network->bridge_vlan_bitmap, BRIDGE_VLAN_BITMAP_LEN * sizeof(uint32_t)) &&
767✔
822
            link->network->bridge_vlan_pvid == BRIDGE_VLAN_KEEP_PVID)
759✔
823
                return 0;
824

825
        if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) {
10✔
826
                Link *master;
×
827

828
                if (!link->network->keep_master)
×
829
                        return 0;
×
830

831
                if (link_get_master(link, &master) < 0)
×
832
                        return 0;
833

834
                if (!streq_ptr(master->kind, "bridge"))
×
835
                        return 0;
836
        }
837

838
        link->bridge_vlan_set = false;
10✔
839

840
        r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
10✔
841
                                  link_set_bridge_vlan_handler,
842
                                  NULL);
843
        if (r < 0)
10✔
844
                return r;
845

846
        r = link_request_set_link(link, REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN,
10✔
847
                                  link_del_bridge_vlan_handler,
848
                                  NULL);
849
        if (r < 0)
10✔
850
                return r;
×
851

852
        return 0;
853
}
854

855
int link_request_to_set_can(Link *link) {
6✔
856
        assert(link);
6✔
857
        assert(link->network);
6✔
858

859
        if (link->iftype != ARPHRD_CAN)
6✔
860
                return 0;
861

862
        if (!streq_ptr(link->kind, "can"))
6✔
863
                return 0;
864

865
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_CAN,
×
866
                                     link_set_can_handler,
867
                                     NULL);
868
}
869

870
int link_request_to_set_flags(Link *link) {
767✔
871
        assert(link);
767✔
872
        assert(link->network);
767✔
873

874
        if (link_get_arp(link) < 0 &&
767✔
875
            link->network->multicast < 0 &&
682✔
876
            link->network->allmulticast < 0 &&
682✔
877
            link->network->promiscuous < 0)
682✔
878
                return 0;
879

880
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_FLAGS,
85✔
881
                                     link_set_flags_handler,
882
                                     NULL);
883
}
884

885
int link_request_to_set_group(Link *link) {
767✔
886
        assert(link);
767✔
887
        assert(link->network);
767✔
888

889
        if (link->network->group < 0)
767✔
890
                return 0;
891

892
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_GROUP,
×
893
                                     link_set_group_handler,
894
                                     NULL);
895
}
896

897
int link_request_to_set_mac(Link *link, bool allow_retry) {
767✔
898
        int r;
767✔
899

900
        assert(link);
767✔
901
        assert(link->network);
767✔
902

903
        if (link->network->hw_addr.length == 0)
767✔
904
                return 0;
905

906
        link->requested_hw_addr = link->network->hw_addr;
6✔
907
        r = net_verify_hardware_address(link->ifname, /* is_static = */ true,
12✔
908
                                        link->iftype, &link->hw_addr, &link->requested_hw_addr);
6✔
909
        if (r < 0)
6✔
910
                return r;
911

912
        if (hw_addr_equal(&link->hw_addr, &link->requested_hw_addr))
6✔
913
                return 0;
914

915
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MAC,
5✔
916
                                     allow_retry ? link_set_mac_allow_retry_handler : link_set_mac_handler,
917
                                     NULL);
918
}
919

920
int link_request_to_set_ipoib(Link *link) {
767✔
921
        assert(link);
767✔
922
        assert(link->network);
767✔
923

924
        if (link->iftype != ARPHRD_INFINIBAND)
767✔
925
                return 0;
926

927
        if (link->network->ipoib_mode < 0 &&
×
928
            link->network->ipoib_umcast < 0)
×
929
                return 0;
930

931
        return link_request_set_link(link, REQUEST_TYPE_SET_LINK_IPOIB,
×
932
                                     link_set_ipoib_handler,
933
                                     NULL);
934
}
935

936
int link_request_to_set_master(Link *link) {
767✔
937
        assert(link);
767✔
938
        assert(link->network);
767✔
939

940
        if (link->network->keep_master) {
767✔
941
                /* When KeepMaster=yes, BatmanAdvanced=, Bond=, Bridge=, and VRF= are ignored. */
942
                link->master_set = true;
2✔
943
                return 0;
2✔
944

945
        } else if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) {
765✔
946
                link->master_set = false;
47✔
947
                return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
47✔
948
                                             link_set_master_handler,
949
                                             NULL);
950

951
        } else if (link->master_ifindex != 0) {
718✔
952
                /* Unset master only when it is set. */
953
                link->master_set = false;
×
954
                return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
×
955
                                             link_unset_master_handler,
956
                                             NULL);
957

958
        } else {
959
                /* Nothing we need to do. */
960
                link->master_set = true;
718✔
961
                return 0;
718✔
962
        }
963
}
964

965
int link_request_to_set_mtu(Link *link, uint32_t mtu) {
53✔
966
        Request *req;
53✔
967
        int r;
53✔
968

969
        assert(link);
53✔
970

971
        if (mtu == 0)
53✔
972
                return 0;
53✔
973

974
        r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU,
53✔
975
                                  link_set_mtu_handler,
976
                                  &req);
977
        if (r < 0)
53✔
978
                return r;
979

980
        req->userdata = UINT32_TO_PTR(mtu);
53✔
981
        return 0;
53✔
982
}
983

984
static bool link_reduces_vlan_mtu(Link *link) {
10✔
985
        /* See netif_reduces_vlan_mtu() in kernel. */
986
        return streq_ptr(link->kind, "macsec");
10✔
987
}
988

989
static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) {
742✔
990
        uint32_t mtu = 0;
742✔
991
        NetDev *dev;
742✔
992

993
        HASHMAP_FOREACH(dev, link->network->stacked_netdevs)
877✔
994
                if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
135✔
995
                        /* See vlan_dev_change_mtu() in kernel. */
996
                        mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu);
10✔
997

998
                else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
125✔
999
                        /* See macvlan_change_mtu() in kernel. */
1000
                        mtu = dev->mtu;
12✔
1001

1002
        return mtu;
742✔
1003
}
1004

1005
int link_configure_mtu(Link *link) {
773✔
1006
        uint32_t mtu;
773✔
1007

1008
        assert(link);
773✔
1009
        assert(link->network);
773✔
1010

1011
        if (link->network->mtu > 0)
773✔
1012
                return link_request_to_set_mtu(link, link->network->mtu);
31✔
1013

1014
        mtu = link_get_requested_mtu_by_stacked_netdevs(link);
742✔
1015
        if (link->mtu >= mtu)
742✔
1016
                return 0;
1017

1018
        log_link_notice(link, "Bumping MTU bytes from %"PRIu32" to %"PRIu32" because of stacked device. "
16✔
1019
                        "If it is not desired, then please explicitly specify MTUBytes= setting.",
1020
                        link->mtu, mtu);
1021

1022
        return link_request_to_set_mtu(link, mtu);
16✔
1023
}
1024

1025
static int link_up_dsa_slave(Link *link) {
1✔
1026
        Link *master;
1✔
1027
        int r;
1✔
1028

1029
        assert(link);
1✔
1030

1031
        /* For older kernels (specifically, older than 9d5ef190e5615a7b63af89f88c4106a5bc127974, kernel-5.12),
1032
         * it is necessary to bring up a DSA slave that its master interface is already up. And bringing up
1033
         * the slave fails with -ENETDOWN. So, let's bring up the master even if it is not managed by us,
1034
         * and try to bring up the slave after the master becomes up. */
1035

1036
        if (link->dsa_master_ifindex <= 0)
1✔
1037
                return 0;
1✔
1038

1039
        if (!streq_ptr(link->driver, "dsa"))
×
1040
                return 0;
1041

1042
        if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
×
1043
                return 0;
1044

1045
        if (master->state == LINK_STATE_UNMANAGED) {
×
1046
                /* If the DSA master interface is unmanaged, then it will never become up.
1047
                 * Let's request to bring up the master. */
1048
                r = link_request_to_bring_up_or_down(master, /* up = */ true);
×
1049
                if (r < 0)
×
1050
                        return r;
1051
        }
1052

1053
        r = link_request_to_bring_up_or_down(link, /* up = */ true);
×
1054
        if (r < 0)
×
1055
                return r;
×
1056

1057
        return 1;
1058
}
1059

1060
static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
776✔
1061
        bool on_activate, up;
776✔
1062
        int r;
776✔
1063

1064
        assert(m);
776✔
1065
        assert(req);
776✔
1066
        assert(link);
776✔
1067

1068
        on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK;
776✔
1069
        up = PTR_TO_INT(req->userdata);
776✔
1070

1071
        r = sd_netlink_message_get_errno(m);
776✔
1072
        if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0)
776✔
1073
                log_link_message_debug_errno(link, m, r, "Could not bring up dsa slave, retrying again after dsa master becomes up");
×
1074
        else if (r < 0)
776✔
1075
                log_link_message_warning_errno(link, m, r, "Could not bring %s interface, ignoring", up ? "up" : "down");
1✔
1076

1077
        r = link_call_getlink(link, get_link_update_flag_handler);
776✔
1078
        if (r < 0) {
776✔
1079
                link_enter_failed(link);
×
1080
                return 0;
×
1081
        }
1082

1083
        link->set_flags_messages++;
776✔
1084

1085
        if (on_activate) {
776✔
1086
                link->activated = true;
755✔
1087
                link_check_ready(link);
755✔
1088
        }
1089

1090
        return 0;
1091
}
1092

1093
static const char *up_or_down(bool up) {
807✔
1094
        return up ? "up" : "down";
807✔
1095
}
1096

1097
static int link_up_or_down(Link *link, bool up, Request *req) {
781✔
1098
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
781✔
1099
        int r;
781✔
1100

1101
        assert(link);
781✔
1102
        assert(link->manager);
781✔
1103
        assert(link->manager->rtnl);
781✔
1104
        assert(req);
781✔
1105

1106
        /* The log message is checked in the test. Please also update test_bond_active_slave() in
1107
         * test/test-network/systemd-networkd-tests.py. when the log message below is modified. */
1108
        log_link_debug(link, "Bringing link %s", up_or_down(up));
781✔
1109

1110
        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
781✔
1111
        if (r < 0)
781✔
1112
                return r;
1113

1114
        r = sd_rtnl_message_link_set_flags(m, up ? IFF_UP : 0, IFF_UP);
781✔
1115
        if (r < 0)
781✔
1116
                return r;
1117

1118
        return request_call_netlink_async(link->manager->rtnl, m, req);
781✔
1119
}
1120

1121
static bool link_is_ready_to_activate_one(Link *link, bool allow_unmanaged) {
2,804✔
1122
        assert(link);
2,804✔
1123

1124
        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
2,804✔
1125
                return false;
1126

1127
        if (!link->network)
2,748✔
1128
                return allow_unmanaged;
1129

1130
        if (link->set_link_messages > 0)
2,748✔
1131
                return false;
1,993✔
1132

1133
        return true;
1134
}
1135

1136
 static bool link_is_ready_to_activate(Link *link, bool up) {
2,804✔
1137
        assert(link);
2,804✔
1138

1139
        if (!check_ready_for_all_sr_iov_ports(link, /* allow_unmanaged = */ false,
2,804✔
1140
                                              link_is_ready_to_activate_one))
1141
                return false;
1142

1143
        if (up && link_rfkilled(link) > 0)
755✔
1144
                return false;
×
1145

1146
        return true;
1147
}
1148

1149
static int link_process_activation(Request *req, Link *link, void *userdata) {
2,804✔
1150
        bool up = PTR_TO_INT(userdata);
2,804✔
1151
        int r;
2,804✔
1152

1153
        assert(req);
2,804✔
1154
        assert(link);
2,804✔
1155

1156
        if (!link_is_ready_to_activate(link, up))
2,804✔
1157
                return 0;
1158

1159
        r = link_up_or_down(link, up, req);
755✔
1160
        if (r < 0)
755✔
1161
                return log_link_warning_errno(link, r, "Failed to activate link: %m");
×
1162

1163
        return 1;
1164
}
1165

1166
int link_request_to_activate(Link *link) {
773✔
1167
        bool up;
773✔
1168
        int r;
773✔
1169

1170
        assert(link);
773✔
1171
        assert(link->network);
773✔
1172

1173
        switch (link->network->activation_policy) {
773✔
1174
        case ACTIVATION_POLICY_BOUND:
5✔
1175
                r = link_handle_bound_to_list(link);
5✔
1176
                if (r < 0)
5✔
1177
                        return r;
1178
                _fallthrough_;
12✔
1179
        case ACTIVATION_POLICY_MANUAL:
1180
                link->activated = true;
12✔
1181
                link_check_ready(link);
12✔
1182
                return 0;
12✔
1183
        case ACTIVATION_POLICY_UP:
1184
        case ACTIVATION_POLICY_ALWAYS_UP:
1185
                up = true;
1186
                break;
1187
        case ACTIVATION_POLICY_DOWN:
10✔
1188
        case ACTIVATION_POLICY_ALWAYS_DOWN:
1189
                up = false;
10✔
1190
                break;
10✔
1191
        default:
×
1192
                assert_not_reached();
×
1193
        }
1194

1195
        link->activated = false;
761✔
1196

1197
        r = link_queue_request_full(link, REQUEST_TYPE_ACTIVATE_LINK,
1,522✔
1198
                                    INT_TO_PTR(up), NULL, NULL, NULL,
761✔
1199
                                    link_process_activation,
1200
                                    &link->set_flags_messages,
1201
                                    link_up_or_down_handler, NULL);
1202
        if (r < 0)
761✔
1203
                return log_link_error_errno(link, r, "Failed to request to activate link: %m");
×
1204

1205
        log_link_debug(link, "Requested to activate link");
761✔
1206
        return 0;
1207
}
1208

1209
static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) {
26✔
1210
        assert(link);
26✔
1211

1212
        if (up && link->dsa_master_ifindex > 0) {
26✔
1213
                Link *master;
×
1214

1215
                /* The master interface must be up. See comments in link_up_dsa_slave(). */
1216

1217
                if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
×
1218
                        return false;
×
1219

1220
                if (!FLAGS_SET(master->flags, IFF_UP))
×
1221
                        return false;
1222
        }
1223

1224
        if (link->state == LINK_STATE_UNMANAGED)
26✔
1225
                return true;
1226

1227
        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
26✔
1228
                return false;
1229

1230
        if (link->set_link_messages > 0)
26✔
1231
                return false;
1232

1233
        if (!link->activated)
26✔
1234
                return false;
1235

1236
        if (up && link_rfkilled(link) > 0)
26✔
1237
                return false;
×
1238

1239
        return true;
1240
}
1241

1242
static int link_process_up_or_down(Request *req, Link *link, void *userdata) {
26✔
1243
        bool up = PTR_TO_INT(userdata);
26✔
1244
        int r;
26✔
1245

1246
        assert(req);
26✔
1247
        assert(link);
26✔
1248

1249
        if (!link_is_ready_to_bring_up_or_down(link, up))
26✔
1250
                return 0;
1251

1252
        r = link_up_or_down(link, up, req);
26✔
1253
        if (r < 0)
26✔
1254
                return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up));
×
1255

1256
        return 1;
1257
}
1258

1259
int link_request_to_bring_up_or_down(Link *link, bool up) {
26✔
1260
        int r;
26✔
1261

1262
        assert(link);
26✔
1263

1264
        r = link_queue_request_full(link, REQUEST_TYPE_UP_DOWN,
52✔
1265
                                    INT_TO_PTR(up), NULL, NULL, NULL,
26✔
1266
                                    link_process_up_or_down,
1267
                                    &link->set_flags_messages,
1268
                                    link_up_or_down_handler, NULL);
1269
        if (r < 0)
26✔
1270
                return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
×
1271
                                              up_or_down(up));
1272

1273
        log_link_debug(link, "Requested to bring link %s", up_or_down(up));
26✔
1274
        return 0;
1275
}
1276

1277
static int link_up_or_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link, bool up) {
×
1278
        int r;
×
1279

1280
        assert(m);
×
1281
        assert(link);
×
1282
        assert(link->set_flags_messages > 0);
×
1283

1284
        link->set_flags_messages--;
×
1285

1286
        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
×
1287
                return 0;
1288

1289
        r = sd_netlink_message_get_errno(m);
×
1290
        if (r < 0)
×
1291
                log_link_message_warning_errno(link, m, r, "Could not bring %s interface, ignoring", up ? "up" : "down");
×
1292

1293
        r = link_call_getlink(link, get_link_update_flag_handler);
×
1294
        if (r < 0) {
×
1295
                link_enter_failed(link);
×
1296
                return 0;
×
1297
        }
1298

1299
        link->set_flags_messages++;
×
1300
        return 0;
×
1301
}
1302

1303
static int link_up_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
×
1304
        return link_up_or_down_now_handler(rtnl, m, link, /* up = */ true);
×
1305
}
1306

1307
static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
×
1308
        return link_up_or_down_now_handler(rtnl, m, link, /* up = */ false);
×
1309
}
1310

1311
int link_up_or_down_now(Link *link, bool up) {
×
1312
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
×
1313
        int r;
×
1314

1315
        assert(link);
×
1316
        assert(link->manager);
×
1317
        assert(link->manager->rtnl);
×
1318

1319
        log_link_debug(link, "Bringing link %s", up ? "up" : "down");
×
1320

1321
        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
×
1322
        if (r < 0)
×
1323
                return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
×
1324

1325
        r = sd_rtnl_message_link_set_flags(req, up ? IFF_UP : 0, IFF_UP);
×
1326
        if (r < 0)
×
1327
                return log_link_warning_errno(link, r, "Could not set link flags: %m");
×
1328

1329
        r = netlink_call_async(link->manager->rtnl, NULL, req,
×
1330
                               up ? link_up_now_handler : link_down_now_handler,
1331
                               link_netlink_destroy_callback, link);
1332
        if (r < 0)
×
1333
                return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
×
1334

1335
        link->set_flags_messages++;
×
1336
        link_ref(link);
×
1337
        return 0;
1338
}
1339

1340
int link_down_slave_links(Link *link) {
×
1341
        Link *slave;
×
1342
        int r;
×
1343

1344
        assert(link);
×
1345

1346
        SET_FOREACH(slave, link->slaves) {
×
1347
                r = link_down_now(slave);
×
1348
                if (r < 0)
×
1349
                        return r;
×
1350
        }
1351

1352
        return 0;
×
1353
}
1354

1355
static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
2✔
1356
        int r;
2✔
1357

1358
        assert(m);
2✔
1359
        assert(link);
2✔
1360

1361
        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2✔
1362
                return 0;
1363

1364
        r = sd_netlink_message_get_errno(m);
×
1365
        if (r < 0)
×
1366
                log_link_message_warning_errno(link, m, r, "Could not remove interface, ignoring");
×
1367

1368
        return 0;
1369
}
1370

1371
int link_remove(Link *link) {
2✔
1372
        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
2✔
1373
        int r;
2✔
1374

1375
        assert(link);
2✔
1376
        assert(link->manager);
2✔
1377
        assert(link->manager->rtnl);
2✔
1378

1379
        log_link_debug(link, "Removing link.");
2✔
1380

1381
        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_DELLINK, link->ifindex);
2✔
1382
        if (r < 0)
2✔
1383
                return log_link_debug_errno(link, r, "Could not allocate RTM_DELLINK message: %m");
×
1384

1385
        r = netlink_call_async(link->manager->rtnl, NULL, req, link_remove_handler,
2✔
1386
                               link_netlink_destroy_callback, link);
1387
        if (r < 0)
2✔
1388
                return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
×
1389

1390
        link_ref(link);
2✔
1391

1392
        return 0;
1393
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc