chiark / gitweb /
networkd: netdev - take ref when creating netdevs
[elogind.git] / src / network / networkd-netdev.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "networkd.h"
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
29 #include "list.h"
30 #include "siphash24.h"
31
32 #define VLANID_MAX 4094
33
34 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
35         [NETDEV_KIND_BRIDGE] = "bridge",
36         [NETDEV_KIND_BOND] = "bond",
37         [NETDEV_KIND_VLAN] = "vlan",
38         [NETDEV_KIND_MACVLAN] = "macvlan",
39         [NETDEV_KIND_VXLAN] = "vxlan",
40         [NETDEV_KIND_IPIP] = "ipip",
41         [NETDEV_KIND_GRE] = "gre",
42         [NETDEV_KIND_SIT] = "sit",
43         [NETDEV_KIND_VETH] = "veth",
44         [NETDEV_KIND_VTI] = "vti"
45 };
46
47 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
48 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
49
50 static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
51         [NETDEV_MACVLAN_MODE_PRIVATE] = "private",
52         [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
53         [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
54         [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
55 };
56
57 DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
58 DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
59
60 static void netdev_cancel_callbacks(NetDev *netdev) {
61         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
62         netdev_enslave_callback *callback;
63
64         if (!netdev)
65                 return;
66
67         rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
68
69         while ((callback = netdev->callbacks)) {
70                 if (m) {
71                         assert(callback->link);
72                         assert(callback->callback);
73                         assert(netdev->manager);
74                         assert(netdev->manager->rtnl);
75
76                         callback->callback(netdev->manager->rtnl, m, link);
77                 }
78
79                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
80                 free(callback);
81         }
82 }
83
84 static void netdev_free(NetDev *netdev) {
85         if (!netdev)
86                 return;
87
88         netdev_cancel_callbacks(netdev);
89
90         if (netdev->ifname)
91                 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
92
93         free(netdev->filename);
94
95         free(netdev->description);
96         free(netdev->ifname);
97         free(netdev->ifname_peer);
98         free(netdev->mac);
99         free(netdev->mac_peer);
100
101         condition_free_list(netdev->match_host);
102         condition_free_list(netdev->match_virt);
103         condition_free_list(netdev->match_kernel);
104         condition_free_list(netdev->match_arch);
105
106         free(netdev);
107 }
108
109 NetDev *netdev_unref(NetDev *netdev) {
110         if (netdev && (-- netdev->n_ref <= 0))
111                 netdev_free(netdev);
112
113         return NULL;
114 }
115
116 NetDev *netdev_ref(NetDev *netdev) {
117         if (netdev)
118                 assert_se(++ netdev->n_ref >= 2);
119
120         return netdev;
121 }
122
123 void netdev_drop(NetDev *netdev) {
124         if (!netdev || netdev->state == NETDEV_STATE_LINGER)
125                 return;
126
127         netdev->state = NETDEV_STATE_LINGER;
128
129         log_debug_netdev(netdev, "netdev removed");
130
131         netdev_cancel_callbacks(netdev);
132
133         netdev_unref(netdev);
134
135         return;
136 }
137
138 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
139         NetDev *netdev;
140
141         assert(manager);
142         assert(name);
143         assert(ret);
144
145         netdev = hashmap_get(manager->netdevs, name);
146         if (!netdev) {
147                 *ret = NULL;
148                 return -ENOENT;
149         }
150
151         *ret = netdev;
152
153         return 0;
154 }
155
156 static int netdev_enter_failed(NetDev *netdev) {
157         netdev->state = NETDEV_STATE_FAILED;
158
159         return 0;
160 }
161
162 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
163         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
164         int r;
165
166         assert(netdev);
167         assert(netdev->state == NETDEV_STATE_READY);
168         assert(netdev->manager);
169         assert(netdev->manager->rtnl);
170         assert(link);
171         assert(callback);
172
173         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
174                                      RTM_SETLINK, link->ifindex);
175         if (r < 0) {
176                 log_error_netdev(netdev,
177                                  "Could not allocate RTM_SETLINK message: %s",
178                                  strerror(-r));
179                 return r;
180         }
181
182         r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
183         if (r < 0) {
184                 log_error_netdev(netdev,
185                                  "Could not append IFLA_MASTER attribute: %s",
186                                  strerror(-r));
187                 return r;
188         }
189
190         r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
191         if (r < 0) {
192                 log_error_netdev(netdev,
193                                  "Could not send rtnetlink message: %s",
194                                  strerror(-r));
195                 return r;
196         }
197
198         log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
199
200         return 0;
201 }
202
203 static int netdev_enter_ready(NetDev *netdev) {
204         netdev_enslave_callback *callback;
205
206         assert(netdev);
207         assert(netdev->ifname);
208
209         if (netdev->state != NETDEV_STATE_CREATING)
210                 return 0;
211
212         netdev->state = NETDEV_STATE_READY;
213
214         log_info_netdev(netdev, "netdev ready");
215
216         LIST_FOREACH(callbacks, callback, netdev->callbacks) {
217                 /* enslave the links that were attempted to be enslaved before the
218                  * link was ready */
219                 netdev_enslave_ready(netdev, callback->link, callback->callback);
220         }
221
222         return 0;
223 }
224
225 /* callback for netdev's created without a backing Link */
226 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
227         _cleanup_netdev_unref_ NetDev *netdev = userdata;
228         int r;
229
230         assert(netdev->state != _NETDEV_STATE_INVALID);
231
232         r = sd_rtnl_message_get_errno(m);
233         if (r == -EEXIST)
234                 log_debug_netdev(netdev, "netdev exists, using existing");
235         else if (r < 0) {
236                 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
237                 netdev_drop(netdev);
238
239                 return 1;
240         }
241
242         return 1;
243 }
244
245 int config_parse_tunnel_address(const char *unit,
246                                 const char *filename,
247                                 unsigned line,
248                                 const char *section,
249                                 unsigned section_line,
250                                 const char *lvalue,
251                                 int ltype,
252                                 const char *rvalue,
253                                 void *data,
254                                 void *userdata) {
255         NetDev *n = data;
256         unsigned char family = AF_INET;
257         int r;
258
259         assert(filename);
260         assert(lvalue);
261         assert(rvalue);
262         assert(data);
263
264         r = net_parse_inaddr(rvalue, &family, n);
265         if (r < 0) {
266                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
267                            "Tunnel address is invalid, ignoring assignment: %s", rvalue);
268                 return 0;
269         }
270        return 0;
271 }
272
273 static int netdev_create(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
274         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
275         const char *kind;
276         int r;
277
278         assert(netdev);
279         assert(!(netdev->kind == NETDEV_KIND_VLAN || netdev->kind == NETDEV_KIND_MACVLAN) ||
280                (link && callback));
281         assert(netdev->ifname);
282         assert(netdev->manager);
283         assert(netdev->manager->rtnl);
284
285         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
286         if (r < 0) {
287                 log_error_netdev(netdev,
288                                  "Could not allocate RTM_NEWLINK message: %s",
289                                  strerror(-r));
290                 return r;
291         }
292
293         if (link) {
294                 r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
295                 if (r < 0) {
296                         log_error_netdev(netdev,
297                                          "Could not append IFLA_LINK attribute: %s",
298                                          strerror(-r));
299                         return r;
300                 }
301         }
302
303         r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
304         if (r < 0) {
305                 log_error_netdev(netdev,
306                                  "Could not append IFLA_IFNAME attribute: %s",
307                                  strerror(-r));
308                 return r;
309         }
310
311         if (netdev->mtu) {
312                 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
313                 if (r < 0) {
314                         log_error_netdev(netdev,
315                                          "Could not append IFLA_MTU attribute: %s",
316                                          strerror(-r));
317                         return r;
318                 }
319         }
320
321         if (netdev->mac) {
322                 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
323                 if (r < 0) {
324                         log_error_netdev(netdev,
325                                          "Colud not append IFLA_ADDRESS attribute: %s",
326                                          strerror(-r));
327                     return r;
328                 }
329         }
330
331         r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
332         if (r < 0) {
333                 log_error_netdev(netdev,
334                                  "Could not open IFLA_LINKINFO container: %s",
335                                  strerror(-r));
336                 return r;
337         }
338
339         kind = netdev_kind_to_string(netdev->kind);
340         if (!kind) {
341                 log_error_netdev(netdev, "Invalid kind");
342                 return -EINVAL;
343         }
344
345         r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
346         if (r < 0) {
347                 log_error_netdev(netdev,
348                                  "Could not open IFLA_INFO_DATA container: %s",
349                                   strerror(-r));
350                 return r;
351         }
352
353         if (netdev->vlanid <= VLANID_MAX) {
354                 r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
355                 if (r < 0) {
356                         log_error_netdev(netdev,
357                                          "Could not append IFLA_VLAN_ID attribute: %s",
358                                          strerror(-r));
359                         return r;
360                 }
361         }
362
363         if (netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
364         r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, netdev->macvlan_mode);
365         if (r < 0) {
366                 log_error_netdev(netdev,
367                                  "Could not append IFLA_MACVLAN_MODE attribute: %s",
368                                  strerror(-r));
369                         return r;
370                 }
371         }
372
373         r = sd_rtnl_message_close_container(req);
374         if (r < 0) {
375                 log_error_netdev(netdev,
376                                  "Could not close IFLA_INFO_DATA container %s",
377                                  strerror(-r));
378                 return r;
379         }
380
381         r = sd_rtnl_message_close_container(req);
382         if (r < 0) {
383                 log_error_netdev(netdev,
384                                  "Could not close IFLA_LINKINFO container %s",
385                                  strerror(-r));
386                 return r;
387         }
388
389         if (link)
390                 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
391         else {
392                 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
393
394                 netdev_ref(netdev);
395         } if (r < 0) {
396                 log_error_netdev(netdev,
397                                  "Could not send rtnetlink message: %s", strerror(-r));
398                 return r;
399         }
400
401         log_debug_netdev(netdev, "creating netdev");
402
403         netdev->state = NETDEV_STATE_CREATING;
404
405         return 0;
406 }
407
408 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
409 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
410         int r;
411
412         switch(netdev->kind) {
413         case NETDEV_KIND_VLAN:
414         case NETDEV_KIND_MACVLAN:
415                 return netdev_create(netdev, link, callback);
416         case NETDEV_KIND_VXLAN:
417                 return netdev_create_vxlan(netdev, link, callback);
418         case NETDEV_KIND_IPIP:
419         case NETDEV_KIND_GRE:
420         case NETDEV_KIND_SIT:
421         case NETDEV_KIND_VTI:
422                 return netdev_create_tunnel(netdev, link, callback);
423         default:
424                 break;
425         }
426
427         if (netdev->state == NETDEV_STATE_READY) {
428                 r = netdev_enslave_ready(netdev, link, callback);
429                 if (r < 0)
430                         return r;
431         } else {
432                 /* the netdev is not yet read, save this request for when it is*/
433                 netdev_enslave_callback *cb;
434
435                 cb = new0(netdev_enslave_callback, 1);
436                 if (!cb)
437                         return log_oom();
438
439                 cb->callback = callback;
440                 cb->link = link;
441
442                 LIST_PREPEND(callbacks, netdev->callbacks, cb);
443         }
444
445         return 0;
446 }
447
448 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
449         uint16_t type;
450         const char *kind;
451         char *received_kind;
452         char *received_name;
453         int r, ifindex;
454
455         assert(netdev);
456         assert(message);
457
458         r = sd_rtnl_message_get_type(message, &type);
459         if (r < 0) {
460                 log_error_netdev(netdev, "Could not get rtnl message type");
461                 return r;
462         }
463
464         if (type != RTM_NEWLINK) {
465                 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
466                 return -EINVAL;
467         }
468
469         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
470         if (r < 0) {
471                 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
472                 netdev_enter_failed(netdev);
473                 return r;
474         } else if (ifindex <= 0) {
475                 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
476                 netdev_enter_failed(netdev);
477                 return r;
478         }
479
480         if (netdev->ifindex > 0) {
481                 if (netdev->ifindex != ifindex) {
482                         log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
483                                          ifindex, netdev->ifindex);
484                         netdev_enter_failed(netdev);
485                         return -EEXIST;
486                 } else
487                         /* ifindex already set to the same for this netdev */
488                         return 0;
489         }
490
491         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
492         if (r < 0) {
493                 log_error_netdev(netdev, "Could not get IFNAME");
494                 return r;
495         }
496
497         if (!streq(netdev->ifname, received_name)) {
498                 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
499                                  received_name);
500                 netdev_enter_failed(netdev);
501                 return r;
502         }
503
504         r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
505         if (r < 0) {
506                 log_error_netdev(netdev, "Could not get LINKINFO");
507                 return r;
508         }
509
510         r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
511         if (r < 0) {
512                 log_error_netdev(netdev, "Could not get KIND");
513                 return r;
514         }
515
516         r = sd_rtnl_message_exit_container(message);
517         if (r < 0) {
518                 log_error_netdev(netdev, "Could not exit container");
519                 return r;
520         }
521
522         kind = netdev_kind_to_string(netdev->kind);
523         if (!kind) {
524                 log_error_netdev(netdev, "Could not get kind");
525                 netdev_enter_failed(netdev);
526                 return -EINVAL;
527         }
528
529         if (!streq(kind, received_kind)) {
530                 log_error_netdev(netdev, "Received newlink with wrong KIND %s, "
531                                  "expected %s", received_kind, kind);
532                 netdev_enter_failed(netdev);
533                 return r;
534         }
535
536         netdev->ifindex = ifindex;
537
538         log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
539
540         netdev_enter_ready(netdev);
541
542         return 0;
543 }
544
545 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
546
547 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
548         _cleanup_free_ struct ether_addr *mac = NULL;
549         uint8_t result[8];
550         size_t l, sz;
551         uint8_t *v;
552         int r;
553
554         assert(ifname);
555         assert(ret);
556
557         mac = new0(struct ether_addr, 1);
558         if (!mac)
559                 return -ENOMEM;
560
561         l = strlen(ifname);
562         sz = sizeof(sd_id128_t) + l;
563         v = alloca(sz);
564
565         /* fetch some persistent data unique to the machine */
566         r = sd_id128_get_machine((sd_id128_t*) v);
567         if (r < 0)
568                 return r;
569
570         /* combine with some data unique (on this machine) to this
571          * netdev */
572         memcpy(v + sizeof(sd_id128_t), ifname, l);
573
574         /* Let's hash the host machine ID plus the container name. We
575          * use a fixed, but originally randomly created hash key here. */
576         siphash24(result, v, sz, HASH_KEY.bytes);
577
578         assert_cc(ETH_ALEN <= sizeof(result));
579         memcpy(mac->ether_addr_octet, result, ETH_ALEN);
580
581         /* see eth_random_addr in the kernel */
582         mac->ether_addr_octet[0] &= 0xfe;        /* clear multicast bit */
583         mac->ether_addr_octet[0] |= 0x02;        /* set local assignment bit (IEEE802) */
584
585         *ret = mac;
586         mac = NULL;
587
588         return 0;
589 }
590
591 static int netdev_load_one(Manager *manager, const char *filename) {
592         _cleanup_netdev_unref_ NetDev *netdev = NULL;
593         _cleanup_fclose_ FILE *file = NULL;
594         int r;
595
596         assert(manager);
597         assert(filename);
598
599         if (null_or_empty_path(filename)) {
600                 log_debug("skipping empty file: %s", filename);
601                 return 0;
602         }
603
604         file = fopen(filename, "re");
605         if (!file) {
606                 if (errno == ENOENT)
607                         return 0;
608                 else
609                         return -errno;
610         }
611
612         netdev = new0(NetDev, 1);
613         if (!netdev)
614                 return log_oom();
615
616         netdev->n_ref = 1;
617         netdev->manager = manager;
618         netdev->state = _NETDEV_STATE_INVALID;
619         netdev->kind = _NETDEV_KIND_INVALID;
620         netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
621         netdev->vlanid = VLANID_MAX + 1;
622         netdev->vxlanid = VXLAN_VID_MAX + 1;
623         netdev->tunnel_pmtudisc = true;
624         netdev->learning = true;
625
626         r = config_parse(NULL, filename, file,
627                          "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0",
628                          config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
629                          false, false, netdev);
630         if (r < 0) {
631                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
632                 return r;
633         }
634
635         if (netdev->kind == _NETDEV_KIND_INVALID) {
636                 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
637                 return 0;
638         }
639
640         if (!netdev->ifname) {
641                 log_warning("NetDev without Name configured in %s. Ignoring", filename);
642                 return 0;
643         }
644
645         if (netdev->kind == NETDEV_KIND_VLAN && netdev->vlanid > VLANID_MAX) {
646                 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
647                 return 0;
648         }
649
650         if (netdev->kind == NETDEV_KIND_VXLAN && netdev->vxlanid > VXLAN_VID_MAX) {
651                 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
652                 return 0;
653         }
654
655         if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) {
656                 log_warning("VLAN Id configured for a %s in %s. Ignoring",
657                             netdev_kind_to_string(netdev->kind), filename);
658                 return 0;
659         }
660
661         if (netdev->kind != NETDEV_KIND_VXLAN && netdev->vxlanid <= VXLAN_VID_MAX) {
662                 log_warning("VXLAN Id configured for a %s in %s. Ignoring",
663                             netdev_kind_to_string(netdev->kind), filename);
664                 return 0;
665         }
666
667         if (netdev->kind != NETDEV_KIND_MACVLAN &&
668             netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
669                 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
670                             netdev_kind_to_string(netdev->kind), filename);
671                 return 0;
672         }
673
674         netdev->filename = strdup(filename);
675         if (!netdev->filename)
676                 return log_oom();
677
678         if (net_match_config(NULL, NULL, NULL, NULL, NULL,
679                              netdev->match_host, netdev->match_virt,
680                              netdev->match_kernel, netdev->match_arch,
681                              NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
682                 return 0;
683
684         if (!netdev->mac) {
685                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
686                 if (r < 0) {
687                         log_error("Failed to generate predictable MAC address for %s",
688                                   netdev->ifname);
689                         return r;
690                 }
691         }
692
693         r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
694         if (r < 0)
695                 return r;
696
697         LIST_HEAD_INIT(netdev->callbacks);
698
699         switch (netdev->kind) {
700         case NETDEV_KIND_VETH:
701                 if (!netdev->ifname_peer) {
702                         log_warning("Veth NetDev without peer name configured "
703                                     "in %s. Ignoring", filename);
704                         return 0;
705                 }
706
707                 if (!netdev->mac) {
708                         r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
709                         if (r < 0) {
710                                 log_error("Failed to generate predictable MAC address for %s",
711                                           netdev->ifname_peer);
712                                 return r;
713                         }
714                 }
715
716                 r = netdev_create_veth(netdev, netdev_create_handler);
717                 if (r < 0)
718                         return r;
719
720                 break;
721         case NETDEV_KIND_BRIDGE:
722         case NETDEV_KIND_BOND:
723                 r = netdev_create(netdev, NULL, NULL);
724                 if (r < 0)
725                         return r;
726                 break;
727         default:
728                 break;
729         }
730
731         log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
732
733         netdev = NULL;
734
735         return 0;
736 }
737
738 int netdev_load(Manager *manager) {
739         NetDev *netdev;
740         char **files, **f;
741         int r;
742
743         assert(manager);
744
745         while ((netdev = hashmap_first(manager->netdevs)))
746                 netdev_unref(netdev);
747
748         r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
749         if (r < 0) {
750                 log_error("Failed to enumerate netdev files: %s", strerror(-r));
751                 return r;
752         }
753
754         STRV_FOREACH_BACKWARDS(f, files) {
755                 r = netdev_load_one(manager, *f);
756                 if (r < 0)
757                         return r;
758         }
759
760         strv_free(files);
761
762         return 0;
763 }