1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
24 #include "conf-files.h"
25 #include "conf-parser.h"
28 #include "netlink-util.h"
29 #include "network-internal.h"
30 #include "netdev/netdev.h"
31 #include "networkd-manager.h"
32 #include "networkd-link.h"
33 #include "siphash24.h"
34 #include "stat-util.h"
35 #include "string-table.h"
36 #include "string-util.h"
38 #include "netdev/bridge.h"
39 #include "netdev/bond.h"
40 #include "netdev/geneve.h"
41 #include "netdev/vlan.h"
42 #include "netdev/macvlan.h"
43 #include "netdev/ipvlan.h"
44 #include "netdev/vxlan.h"
45 #include "netdev/tunnel.h"
46 #include "netdev/tuntap.h"
47 #include "netdev/veth.h"
48 #include "netdev/dummy.h"
49 #include "netdev/vrf.h"
50 #include "netdev/vcan.h"
51 #include "netdev/vxcan.h"
52 #include "netdev/wireguard.h"
54 const NetDevVTable
* const netdev_vtable
[_NETDEV_KIND_MAX
] = {
55 [NETDEV_KIND_BRIDGE
] = &bridge_vtable
,
56 [NETDEV_KIND_BOND
] = &bond_vtable
,
57 [NETDEV_KIND_VLAN
] = &vlan_vtable
,
58 [NETDEV_KIND_MACVLAN
] = &macvlan_vtable
,
59 [NETDEV_KIND_MACVTAP
] = &macvtap_vtable
,
60 [NETDEV_KIND_IPVLAN
] = &ipvlan_vtable
,
61 [NETDEV_KIND_VXLAN
] = &vxlan_vtable
,
62 [NETDEV_KIND_IPIP
] = &ipip_vtable
,
63 [NETDEV_KIND_GRE
] = &gre_vtable
,
64 [NETDEV_KIND_GRETAP
] = &gretap_vtable
,
65 [NETDEV_KIND_IP6GRE
] = &ip6gre_vtable
,
66 [NETDEV_KIND_IP6GRETAP
] = &ip6gretap_vtable
,
67 [NETDEV_KIND_SIT
] = &sit_vtable
,
68 [NETDEV_KIND_VTI
] = &vti_vtable
,
69 [NETDEV_KIND_VTI6
] = &vti6_vtable
,
70 [NETDEV_KIND_VETH
] = &veth_vtable
,
71 [NETDEV_KIND_DUMMY
] = &dummy_vtable
,
72 [NETDEV_KIND_TUN
] = &tun_vtable
,
73 [NETDEV_KIND_TAP
] = &tap_vtable
,
74 [NETDEV_KIND_IP6TNL
] = &ip6tnl_vtable
,
75 [NETDEV_KIND_VRF
] = &vrf_vtable
,
76 [NETDEV_KIND_VCAN
] = &vcan_vtable
,
77 [NETDEV_KIND_GENEVE
] = &geneve_vtable
,
78 [NETDEV_KIND_VXCAN
] = &vxcan_vtable
,
79 [NETDEV_KIND_WIREGUARD
] = &wireguard_vtable
,
82 static const char* const netdev_kind_table
[_NETDEV_KIND_MAX
] = {
83 [NETDEV_KIND_BRIDGE
] = "bridge",
84 [NETDEV_KIND_BOND
] = "bond",
85 [NETDEV_KIND_VLAN
] = "vlan",
86 [NETDEV_KIND_MACVLAN
] = "macvlan",
87 [NETDEV_KIND_MACVTAP
] = "macvtap",
88 [NETDEV_KIND_IPVLAN
] = "ipvlan",
89 [NETDEV_KIND_VXLAN
] = "vxlan",
90 [NETDEV_KIND_IPIP
] = "ipip",
91 [NETDEV_KIND_GRE
] = "gre",
92 [NETDEV_KIND_GRETAP
] = "gretap",
93 [NETDEV_KIND_IP6GRE
] = "ip6gre",
94 [NETDEV_KIND_IP6GRETAP
] = "ip6gretap",
95 [NETDEV_KIND_SIT
] = "sit",
96 [NETDEV_KIND_VETH
] = "veth",
97 [NETDEV_KIND_VTI
] = "vti",
98 [NETDEV_KIND_VTI6
] = "vti6",
99 [NETDEV_KIND_DUMMY
] = "dummy",
100 [NETDEV_KIND_TUN
] = "tun",
101 [NETDEV_KIND_TAP
] = "tap",
102 [NETDEV_KIND_IP6TNL
] = "ip6tnl",
103 [NETDEV_KIND_VRF
] = "vrf",
104 [NETDEV_KIND_VCAN
] = "vcan",
105 [NETDEV_KIND_GENEVE
] = "geneve",
106 [NETDEV_KIND_VXCAN
] = "vxcan",
107 [NETDEV_KIND_WIREGUARD
] = "wireguard",
110 DEFINE_STRING_TABLE_LOOKUP(netdev_kind
, NetDevKind
);
111 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind
, netdev_kind
, NetDevKind
, "Failed to parse netdev kind");
113 static void netdev_cancel_callbacks(NetDev
*netdev
) {
114 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
115 netdev_join_callback
*callback
;
117 if (!netdev
|| !netdev
->manager
)
120 rtnl_message_new_synthetic_error(netdev
->manager
->rtnl
, -ENODEV
, 0, &m
);
122 while ((callback
= netdev
->callbacks
)) {
124 assert(callback
->link
);
125 assert(callback
->callback
);
126 assert(netdev
->manager
);
127 assert(netdev
->manager
->rtnl
);
129 callback
->callback(netdev
->manager
->rtnl
, m
, callback
->link
);
132 LIST_REMOVE(callbacks
, netdev
->callbacks
, callback
);
133 link_unref(callback
->link
);
138 static void netdev_free(NetDev
*netdev
) {
142 netdev_cancel_callbacks(netdev
);
144 if (netdev
->ifname
&& netdev
->manager
)
145 hashmap_remove(netdev
->manager
->netdevs
, netdev
->ifname
);
147 free(netdev
->filename
);
149 free(netdev
->description
);
150 free(netdev
->ifname
);
153 condition_free_list(netdev
->match_host
);
154 condition_free_list(netdev
->match_virt
);
155 condition_free_list(netdev
->match_kernel_cmdline
);
156 condition_free_list(netdev
->match_kernel_version
);
157 condition_free_list(netdev
->match_arch
);
159 /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that
160 * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure
161 * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full,
162 * comprehensive NetDev structure allocation with enough space for whatever the specific kind needs). Now, in
163 * the first case we shouldn't try to destruct the per-kind NetDev fields on destruction, in the second case we
164 * should. We use the state field to discern the two cases: it's _NETDEV_STATE_INVALID on the first "raw"
166 if (netdev
->state
!= _NETDEV_STATE_INVALID
&&
167 NETDEV_VTABLE(netdev
) &&
168 NETDEV_VTABLE(netdev
)->done
)
169 NETDEV_VTABLE(netdev
)->done(netdev
);
174 NetDev
*netdev_unref(NetDev
*netdev
) {
175 if (netdev
&& (-- netdev
->n_ref
<= 0))
181 NetDev
*netdev_ref(NetDev
*netdev
) {
183 assert_se(++ netdev
->n_ref
>= 2);
188 void netdev_drop(NetDev
*netdev
) {
189 if (!netdev
|| netdev
->state
== NETDEV_STATE_LINGER
)
192 netdev
->state
= NETDEV_STATE_LINGER
;
194 log_netdev_debug(netdev
, "netdev removed");
196 netdev_cancel_callbacks(netdev
);
198 netdev_unref(netdev
);
203 int netdev_get(Manager
*manager
, const char *name
, NetDev
**ret
) {
210 netdev
= hashmap_get(manager
->netdevs
, name
);
221 static int netdev_enter_failed(NetDev
*netdev
) {
222 netdev
->state
= NETDEV_STATE_FAILED
;
224 netdev_cancel_callbacks(netdev
);
229 static int netdev_enslave_ready(NetDev
*netdev
, Link
* link
, sd_netlink_message_handler_t callback
) {
230 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
;
234 assert(netdev
->state
== NETDEV_STATE_READY
);
235 assert(netdev
->manager
);
236 assert(netdev
->manager
->rtnl
);
237 assert(IN_SET(netdev
->kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
, NETDEV_KIND_VRF
));
241 if (link
->flags
& IFF_UP
) {
242 log_netdev_debug(netdev
, "Link '%s' was up when attempting to enslave it. Bringing link down.", link
->ifname
);
245 return log_netdev_error_errno(netdev
, r
, "Could not bring link down: %m");
248 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &req
, RTM_SETLINK
, link
->ifindex
);
250 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_SETLINK message: %m");
252 r
= sd_netlink_message_append_u32(req
, IFLA_MASTER
, netdev
->ifindex
);
254 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MASTER attribute: %m");
256 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
258 return log_netdev_error(netdev
, "Could not send rtnetlink message: %m");
262 log_netdev_debug(netdev
, "Enslaving link '%s'", link
->ifname
);
267 static int netdev_enter_ready(NetDev
*netdev
) {
268 netdev_join_callback
*callback
, *callback_next
;
272 assert(netdev
->ifname
);
274 if (netdev
->state
!= NETDEV_STATE_CREATING
)
277 netdev
->state
= NETDEV_STATE_READY
;
279 log_netdev_info(netdev
, "netdev ready");
281 LIST_FOREACH_SAFE(callbacks
, callback
, callback_next
, netdev
->callbacks
) {
282 /* enslave the links that were attempted to be enslaved before the
284 r
= netdev_enslave_ready(netdev
, callback
->link
, callback
->callback
);
288 LIST_REMOVE(callbacks
, netdev
->callbacks
, callback
);
289 link_unref(callback
->link
);
293 if (NETDEV_VTABLE(netdev
)->post_create
)
294 NETDEV_VTABLE(netdev
)->post_create(netdev
, NULL
, NULL
);
299 /* callback for netdev's created without a backing Link */
300 static int netdev_create_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, void *userdata
) {
301 _cleanup_netdev_unref_ NetDev
*netdev
= userdata
;
304 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
306 r
= sd_netlink_message_get_errno(m
);
308 log_netdev_info(netdev
, "netdev exists, using existing without changing its parameters");
310 log_netdev_warning_errno(netdev
, r
, "netdev could not be created: %m");
316 log_netdev_debug(netdev
, "Created");
321 int netdev_enslave(NetDev
*netdev
, Link
*link
, sd_netlink_message_handler_t callback
) {
325 assert(netdev
->manager
);
326 assert(netdev
->manager
->rtnl
);
327 assert(IN_SET(netdev
->kind
, NETDEV_KIND_BRIDGE
, NETDEV_KIND_BOND
, NETDEV_KIND_VRF
));
329 if (netdev
->state
== NETDEV_STATE_READY
) {
330 r
= netdev_enslave_ready(netdev
, link
, callback
);
333 } else if (IN_SET(netdev
->state
, NETDEV_STATE_LINGER
, NETDEV_STATE_FAILED
)) {
334 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
336 r
= rtnl_message_new_synthetic_error(netdev
->manager
->rtnl
, -ENODEV
, 0, &m
);
338 callback(netdev
->manager
->rtnl
, m
, link
);
340 /* the netdev is not yet read, save this request for when it is */
341 netdev_join_callback
*cb
;
343 cb
= new0(netdev_join_callback
, 1);
347 cb
->callback
= callback
;
351 LIST_PREPEND(callbacks
, netdev
->callbacks
, cb
);
353 log_netdev_debug(netdev
, "Will enslave '%s', when ready", link
->ifname
);
359 int netdev_set_ifindex(NetDev
*netdev
, sd_netlink_message
*message
) {
362 const char *received_kind
;
363 const char *received_name
;
369 r
= sd_netlink_message_get_type(message
, &type
);
371 return log_netdev_error_errno(netdev
, r
, "Could not get rtnl message type: %m");
373 if (type
!= RTM_NEWLINK
) {
374 log_netdev_error(netdev
, "Cannot set ifindex from unexpected rtnl message type.");
378 r
= sd_rtnl_message_link_get_ifindex(message
, &ifindex
);
380 log_netdev_error_errno(netdev
, r
, "Could not get ifindex: %m");
381 netdev_enter_failed(netdev
);
383 } else if (ifindex
<= 0) {
384 log_netdev_error(netdev
, "Got invalid ifindex: %d", ifindex
);
385 netdev_enter_failed(netdev
);
389 if (netdev
->ifindex
> 0) {
390 if (netdev
->ifindex
!= ifindex
) {
391 log_netdev_error(netdev
, "Could not set ifindex to %d, already set to %d",
392 ifindex
, netdev
->ifindex
);
393 netdev_enter_failed(netdev
);
396 /* ifindex already set to the same for this netdev */
400 r
= sd_netlink_message_read_string(message
, IFLA_IFNAME
, &received_name
);
402 return log_netdev_error_errno(netdev
, r
, "Could not get IFNAME: %m");
404 if (!streq(netdev
->ifname
, received_name
)) {
405 log_netdev_error(netdev
, "Received newlink with wrong IFNAME %s", received_name
);
406 netdev_enter_failed(netdev
);
410 r
= sd_netlink_message_enter_container(message
, IFLA_LINKINFO
);
412 return log_netdev_error_errno(netdev
, r
, "Could not get LINKINFO: %m");
414 r
= sd_netlink_message_read_string(message
, IFLA_INFO_KIND
, &received_kind
);
416 return log_netdev_error_errno(netdev
, r
, "Could not get KIND: %m");
418 r
= sd_netlink_message_exit_container(message
);
420 return log_netdev_error_errno(netdev
, r
, "Could not exit container: %m");
422 if (netdev
->kind
== NETDEV_KIND_TAP
)
423 /* the kernel does not distinguish between tun and tap */
426 kind
= netdev_kind_to_string(netdev
->kind
);
428 log_netdev_error(netdev
, "Could not get kind");
429 netdev_enter_failed(netdev
);
434 if (!streq(kind
, received_kind
)) {
435 log_netdev_error(netdev
,
436 "Received newlink with wrong KIND %s, "
437 "expected %s", received_kind
, kind
);
438 netdev_enter_failed(netdev
);
442 netdev
->ifindex
= ifindex
;
444 log_netdev_debug(netdev
, "netdev has index %d", netdev
->ifindex
);
446 netdev_enter_ready(netdev
);
451 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
453 int netdev_get_mac(const char *ifname
, struct ether_addr
**ret
) {
454 _cleanup_free_
struct ether_addr
*mac
= NULL
;
463 mac
= new0(struct ether_addr
, 1);
468 sz
= sizeof(sd_id128_t
) + l
;
471 /* fetch some persistent data unique to the machine */
472 r
= sd_id128_get_machine((sd_id128_t
*) v
);
476 /* combine with some data unique (on this machine) to this
478 memcpy(v
+ sizeof(sd_id128_t
), ifname
, l
);
480 /* Let's hash the host machine ID plus the container name. We
481 * use a fixed, but originally randomly created hash key here. */
482 result
= siphash24(v
, sz
, HASH_KEY
.bytes
);
484 assert_cc(ETH_ALEN
<= sizeof(result
));
485 memcpy(mac
->ether_addr_octet
, &result
, ETH_ALEN
);
487 /* see eth_random_addr in the kernel */
488 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
489 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
491 *ret
= TAKE_PTR(mac
);
496 static int netdev_create(NetDev
*netdev
, Link
*link
,
497 sd_netlink_message_handler_t callback
) {
501 assert(!link
|| callback
);
504 if (NETDEV_VTABLE(netdev
)->create
) {
507 r
= NETDEV_VTABLE(netdev
)->create(netdev
);
511 log_netdev_debug(netdev
, "Created");
513 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
515 r
= sd_rtnl_message_new_link(netdev
->manager
->rtnl
, &m
, RTM_NEWLINK
, 0);
517 return log_netdev_error_errno(netdev
, r
, "Could not allocate RTM_NEWLINK message: %m");
519 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, netdev
->ifname
);
521 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_IFNAME, attribute: %m");
524 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, netdev
->mac
);
526 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_ADDRESS attribute: %m");
530 r
= sd_netlink_message_append_u32(m
, IFLA_MTU
, netdev
->mtu
);
532 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MTU attribute: %m");
536 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, link
->ifindex
);
538 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINK attribute: %m");
541 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
543 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
545 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, netdev_kind_to_string(netdev
->kind
));
547 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
549 if (NETDEV_VTABLE(netdev
)->fill_message_create
) {
550 r
= NETDEV_VTABLE(netdev
)->fill_message_create(netdev
, link
, m
);
555 r
= sd_netlink_message_close_container(m
);
557 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_INFO_DATA attribute: %m");
559 r
= sd_netlink_message_close_container(m
);
561 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_LINKINFO attribute: %m");
564 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, callback
, link
, 0, NULL
);
566 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
570 r
= sd_netlink_call_async(netdev
->manager
->rtnl
, m
, netdev_create_handler
, netdev
, 0, NULL
);
572 return log_netdev_error_errno(netdev
, r
, "Could not send rtnetlink message: %m");
577 netdev
->state
= NETDEV_STATE_CREATING
;
579 log_netdev_debug(netdev
, "Creating");
585 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
586 int netdev_join(NetDev
*netdev
, Link
*link
, sd_netlink_message_handler_t callback
) {
590 assert(netdev
->manager
);
591 assert(netdev
->manager
->rtnl
);
592 assert(NETDEV_VTABLE(netdev
));
594 switch (NETDEV_VTABLE(netdev
)->create_type
) {
595 case NETDEV_CREATE_MASTER
:
596 r
= netdev_enslave(netdev
, link
, callback
);
601 case NETDEV_CREATE_STACKED
:
602 r
= netdev_create(netdev
, link
, callback
);
608 assert_not_reached("Can not join independent netdev");
614 static int netdev_load_one(Manager
*manager
, const char *filename
) {
615 _cleanup_netdev_unref_ NetDev
*netdev_raw
= NULL
, *netdev
= NULL
;
616 _cleanup_fclose_
FILE *file
= NULL
;
617 const char *dropin_dirname
;
618 bool independent
= false;
624 file
= fopen(filename
, "re");
632 if (null_or_empty_fd(fileno(file
))) {
633 log_debug("Skipping empty file: %s", filename
);
637 netdev_raw
= new0(NetDev
, 1);
641 netdev_raw
->n_ref
= 1;
642 netdev_raw
->kind
= _NETDEV_KIND_INVALID
;
643 netdev_raw
->state
= _NETDEV_STATE_INVALID
; /* an invalid state means done() of the implementation won't be called on destruction */
645 dropin_dirname
= strjoina(basename(filename
), ".d");
646 r
= config_parse_many(filename
, network_dirs
, dropin_dirname
,
648 config_item_perf_lookup
, network_netdev_gperf_lookup
,
649 CONFIG_PARSE_WARN
|CONFIG_PARSE_RELAXED
, netdev_raw
);
653 /* skip out early if configuration does not match the environment */
654 if (net_match_config(NULL
, NULL
, NULL
, NULL
, NULL
,
655 netdev_raw
->match_host
, netdev_raw
->match_virt
,
656 netdev_raw
->match_kernel_cmdline
, netdev_raw
->match_kernel_version
,
657 netdev_raw
->match_arch
,
658 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) <= 0)
661 if (netdev_raw
->kind
== _NETDEV_KIND_INVALID
) {
662 log_warning("NetDev has no Kind configured in %s. Ignoring", filename
);
666 if (!netdev_raw
->ifname
) {
667 log_warning("NetDev without Name configured in %s. Ignoring", filename
);
671 r
= fseek(file
, 0, SEEK_SET
);
675 netdev
= malloc0(NETDEV_VTABLE(netdev_raw
)->object_size
);
680 netdev
->manager
= manager
;
681 netdev
->kind
= netdev_raw
->kind
;
682 netdev
->state
= NETDEV_STATE_LOADING
; /* we initialize the state here for the first time, so that done() will be called on destruction */
684 if (NETDEV_VTABLE(netdev
)->init
)
685 NETDEV_VTABLE(netdev
)->init(netdev
);
687 r
= config_parse(NULL
, filename
, file
,
688 NETDEV_VTABLE(netdev
)->sections
,
689 config_item_perf_lookup
, network_netdev_gperf_lookup
,
690 CONFIG_PARSE_WARN
, netdev
);
694 /* verify configuration */
695 if (NETDEV_VTABLE(netdev
)->config_verify
) {
696 r
= NETDEV_VTABLE(netdev
)->config_verify(netdev
, filename
);
701 netdev
->filename
= strdup(filename
);
702 if (!netdev
->filename
)
705 if (!netdev
->mac
&& netdev
->kind
!= NETDEV_KIND_VLAN
) {
706 r
= netdev_get_mac(netdev
->ifname
, &netdev
->mac
);
708 return log_error_errno(r
, "Failed to generate predictable MAC address for %s: %m", netdev
->ifname
);
711 r
= hashmap_put(netdev
->manager
->netdevs
, netdev
->ifname
, netdev
);
715 LIST_HEAD_INIT(netdev
->callbacks
);
717 log_netdev_debug(netdev
, "loaded %s", netdev_kind_to_string(netdev
->kind
));
719 switch (NETDEV_VTABLE(netdev
)->create_type
) {
720 case NETDEV_CREATE_MASTER
:
721 case NETDEV_CREATE_INDEPENDENT
:
722 r
= netdev_create(netdev
, NULL
, NULL
);
731 switch (netdev
->kind
) {
732 case NETDEV_KIND_IPIP
:
733 independent
= IPIP(netdev
)->independent
;
735 case NETDEV_KIND_GRE
:
736 independent
= GRE(netdev
)->independent
;
738 case NETDEV_KIND_GRETAP
:
739 independent
= GRETAP(netdev
)->independent
;
741 case NETDEV_KIND_IP6GRE
:
742 independent
= IP6GRE(netdev
)->independent
;
744 case NETDEV_KIND_IP6GRETAP
:
745 independent
= IP6GRETAP(netdev
)->independent
;
747 case NETDEV_KIND_SIT
:
748 independent
= SIT(netdev
)->independent
;
750 case NETDEV_KIND_VTI
:
751 independent
= VTI(netdev
)->independent
;
753 case NETDEV_KIND_VTI6
:
754 independent
= VTI6(netdev
)->independent
;
756 case NETDEV_KIND_IP6TNL
:
757 independent
= IP6TNL(netdev
)->independent
;
764 r
= netdev_create(netdev
, NULL
, NULL
);
774 int netdev_load(Manager
*manager
) {
775 _cleanup_strv_free_
char **files
= NULL
;
782 while ((netdev
= hashmap_first(manager
->netdevs
)))
783 netdev_unref(netdev
);
785 r
= conf_files_list_strv(&files
, ".netdev", NULL
, 0, network_dirs
);
787 return log_error_errno(r
, "Failed to enumerate netdev files: %m");
789 STRV_FOREACH_BACKWARDS(f
, files
) {
790 r
= netdev_load_one(manager
, *f
);