xref: /openbmc/qemu/net/vmnet-host.c (revision a75ed3c43064528f3409f0be286b62b9c3a47218)
1  /*
2   * vmnet-host.c
3   *
4   * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
5   *
6   * This work is licensed under the terms of the GNU GPL, version 2 or later.
7   * See the COPYING file in the top-level directory.
8   *
9   */
10  
11  #include "qemu/osdep.h"
12  #include "qemu/uuid.h"
13  #include "qapi/qapi-types-net.h"
14  #include "qapi/error.h"
15  #include "clients.h"
16  #include "vmnet_int.h"
17  
18  #include <vmnet/vmnet.h>
19  
20  
21  static bool validate_options(const Netdev *netdev, Error **errp)
22  {
23      const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
24  
25  #if defined(MAC_OS_VERSION_11_0) && \
26      MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
27  
28      QemuUUID net_uuid;
29      if (options->net_uuid &&
30          qemu_uuid_parse(options->net_uuid, &net_uuid) < 0) {
31          error_setg(errp, "Invalid UUID provided in 'net-uuid'");
32          return false;
33      }
34  #else
35      if (options->has_isolated) {
36          error_setg(errp,
37                     "vmnet-host.isolated feature is "
38                     "unavailable: outdated vmnet.framework API");
39          return false;
40      }
41  
42      if (options->net_uuid) {
43          error_setg(errp,
44                     "vmnet-host.net-uuid feature is "
45                     "unavailable: outdated vmnet.framework API");
46          return false;
47      }
48  #endif
49  
50      if ((options->start_address ||
51           options->end_address ||
52           options->subnet_mask) &&
53          !(options->start_address &&
54            options->end_address &&
55            options->subnet_mask)) {
56          error_setg(errp,
57                     "'start-address', 'end-address', 'subnet-mask' "
58                     "should be provided together");
59          return false;
60      }
61  
62      return true;
63  }
64  
65  static xpc_object_t build_if_desc(const Netdev *netdev)
66  {
67      const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
68      xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
69  
70      xpc_dictionary_set_uint64(if_desc,
71                                vmnet_operation_mode_key,
72                                VMNET_HOST_MODE);
73  
74  #if defined(MAC_OS_VERSION_11_0) && \
75      MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
76  
77      xpc_dictionary_set_bool(if_desc,
78                              vmnet_enable_isolation_key,
79                              options->isolated);
80  
81      QemuUUID net_uuid;
82      if (options->net_uuid) {
83          qemu_uuid_parse(options->net_uuid, &net_uuid);
84          xpc_dictionary_set_uuid(if_desc,
85                                  vmnet_network_identifier_key,
86                                  net_uuid.data);
87      }
88  #endif
89  
90      if (options->start_address) {
91          xpc_dictionary_set_string(if_desc,
92                                    vmnet_start_address_key,
93                                    options->start_address);
94          xpc_dictionary_set_string(if_desc,
95                                    vmnet_end_address_key,
96                                    options->end_address);
97          xpc_dictionary_set_string(if_desc,
98                                    vmnet_subnet_mask_key,
99                                    options->subnet_mask);
100      }
101  
102      return if_desc;
103  }
104  
105  static NetClientInfo net_vmnet_host_info = {
106      .type = NET_CLIENT_DRIVER_VMNET_HOST,
107      .size = sizeof(VmnetState),
108      .receive = vmnet_receive_common,
109      .cleanup = vmnet_cleanup_common,
110  };
111  
112  int net_init_vmnet_host(const Netdev *netdev, const char *name,
113                          NetClientState *peer, Error **errp)
114  {
115      NetClientState *nc = qemu_new_net_client(&net_vmnet_host_info,
116                                               peer, "vmnet-host", name);
117      xpc_object_t if_desc;
118      int result = -1;
119  
120      if (!validate_options(netdev, errp)) {
121          return result;
122      }
123  
124      if_desc = build_if_desc(netdev);
125      result = vmnet_if_create(nc, if_desc, errp);
126      xpc_release(if_desc);
127      return result;
128  }
129