181ad2964SVladislav Yaroshchuk /*
281ad2964SVladislav Yaroshchuk * vmnet-host.c
381ad2964SVladislav Yaroshchuk *
481ad2964SVladislav Yaroshchuk * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
581ad2964SVladislav Yaroshchuk *
681ad2964SVladislav Yaroshchuk * This work is licensed under the terms of the GNU GPL, version 2 or later.
781ad2964SVladislav Yaroshchuk * See the COPYING file in the top-level directory.
881ad2964SVladislav Yaroshchuk *
981ad2964SVladislav Yaroshchuk */
1081ad2964SVladislav Yaroshchuk
1181ad2964SVladislav Yaroshchuk #include "qemu/osdep.h"
125cfa6437SVladislav Yaroshchuk #include "qemu/uuid.h"
1381ad2964SVladislav Yaroshchuk #include "qapi/qapi-types-net.h"
1481ad2964SVladislav Yaroshchuk #include "qapi/error.h"
155cfa6437SVladislav Yaroshchuk #include "clients.h"
165cfa6437SVladislav Yaroshchuk #include "vmnet_int.h"
1781ad2964SVladislav Yaroshchuk
1881ad2964SVladislav Yaroshchuk #include <vmnet/vmnet.h>
1981ad2964SVladislav Yaroshchuk
205cfa6437SVladislav Yaroshchuk
validate_options(const Netdev * netdev,Error ** errp)215cfa6437SVladislav Yaroshchuk static bool validate_options(const Netdev *netdev, Error **errp)
225cfa6437SVladislav Yaroshchuk {
235cfa6437SVladislav Yaroshchuk const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
245cfa6437SVladislav Yaroshchuk QemuUUID net_uuid;
25*3bf445fbSAkihiko Odaki
267480874aSMarkus Armbruster if (options->net_uuid &&
275cfa6437SVladislav Yaroshchuk qemu_uuid_parse(options->net_uuid, &net_uuid) < 0) {
285cfa6437SVladislav Yaroshchuk error_setg(errp, "Invalid UUID provided in 'net-uuid'");
295cfa6437SVladislav Yaroshchuk return false;
305cfa6437SVladislav Yaroshchuk }
315cfa6437SVladislav Yaroshchuk
327480874aSMarkus Armbruster if ((options->start_address ||
337480874aSMarkus Armbruster options->end_address ||
347480874aSMarkus Armbruster options->subnet_mask) &&
357480874aSMarkus Armbruster !(options->start_address &&
367480874aSMarkus Armbruster options->end_address &&
377480874aSMarkus Armbruster options->subnet_mask)) {
385cfa6437SVladislav Yaroshchuk error_setg(errp,
395cfa6437SVladislav Yaroshchuk "'start-address', 'end-address', 'subnet-mask' "
405cfa6437SVladislav Yaroshchuk "should be provided together");
415cfa6437SVladislav Yaroshchuk return false;
425cfa6437SVladislav Yaroshchuk }
435cfa6437SVladislav Yaroshchuk
445cfa6437SVladislav Yaroshchuk return true;
455cfa6437SVladislav Yaroshchuk }
465cfa6437SVladislav Yaroshchuk
build_if_desc(const Netdev * netdev)475cfa6437SVladislav Yaroshchuk static xpc_object_t build_if_desc(const Netdev *netdev)
485cfa6437SVladislav Yaroshchuk {
495cfa6437SVladislav Yaroshchuk const NetdevVmnetHostOptions *options = &(netdev->u.vmnet_host);
505cfa6437SVladislav Yaroshchuk xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
515cfa6437SVladislav Yaroshchuk
525cfa6437SVladislav Yaroshchuk xpc_dictionary_set_uint64(if_desc,
535cfa6437SVladislav Yaroshchuk vmnet_operation_mode_key,
545cfa6437SVladislav Yaroshchuk VMNET_HOST_MODE);
555cfa6437SVladislav Yaroshchuk
565cfa6437SVladislav Yaroshchuk xpc_dictionary_set_bool(if_desc,
575cfa6437SVladislav Yaroshchuk vmnet_enable_isolation_key,
585cfa6437SVladislav Yaroshchuk options->isolated);
595cfa6437SVladislav Yaroshchuk
605cfa6437SVladislav Yaroshchuk QemuUUID net_uuid;
617480874aSMarkus Armbruster if (options->net_uuid) {
625cfa6437SVladislav Yaroshchuk qemu_uuid_parse(options->net_uuid, &net_uuid);
635cfa6437SVladislav Yaroshchuk xpc_dictionary_set_uuid(if_desc,
645cfa6437SVladislav Yaroshchuk vmnet_network_identifier_key,
655cfa6437SVladislav Yaroshchuk net_uuid.data);
665cfa6437SVladislav Yaroshchuk }
675cfa6437SVladislav Yaroshchuk
687480874aSMarkus Armbruster if (options->start_address) {
695cfa6437SVladislav Yaroshchuk xpc_dictionary_set_string(if_desc,
705cfa6437SVladislav Yaroshchuk vmnet_start_address_key,
715cfa6437SVladislav Yaroshchuk options->start_address);
725cfa6437SVladislav Yaroshchuk xpc_dictionary_set_string(if_desc,
735cfa6437SVladislav Yaroshchuk vmnet_end_address_key,
745cfa6437SVladislav Yaroshchuk options->end_address);
755cfa6437SVladislav Yaroshchuk xpc_dictionary_set_string(if_desc,
765cfa6437SVladislav Yaroshchuk vmnet_subnet_mask_key,
775cfa6437SVladislav Yaroshchuk options->subnet_mask);
785cfa6437SVladislav Yaroshchuk }
795cfa6437SVladislav Yaroshchuk
805cfa6437SVladislav Yaroshchuk return if_desc;
815cfa6437SVladislav Yaroshchuk }
825cfa6437SVladislav Yaroshchuk
835cfa6437SVladislav Yaroshchuk static NetClientInfo net_vmnet_host_info = {
845cfa6437SVladislav Yaroshchuk .type = NET_CLIENT_DRIVER_VMNET_HOST,
855cfa6437SVladislav Yaroshchuk .size = sizeof(VmnetState),
865cfa6437SVladislav Yaroshchuk .receive = vmnet_receive_common,
875cfa6437SVladislav Yaroshchuk .cleanup = vmnet_cleanup_common,
885cfa6437SVladislav Yaroshchuk };
895cfa6437SVladislav Yaroshchuk
net_init_vmnet_host(const Netdev * netdev,const char * name,NetClientState * peer,Error ** errp)9081ad2964SVladislav Yaroshchuk int net_init_vmnet_host(const Netdev *netdev, const char *name,
915cfa6437SVladislav Yaroshchuk NetClientState *peer, Error **errp)
925cfa6437SVladislav Yaroshchuk {
935cfa6437SVladislav Yaroshchuk NetClientState *nc = qemu_new_net_client(&net_vmnet_host_info,
945cfa6437SVladislav Yaroshchuk peer, "vmnet-host", name);
955cfa6437SVladislav Yaroshchuk xpc_object_t if_desc;
965cfa6437SVladislav Yaroshchuk int result = -1;
975cfa6437SVladislav Yaroshchuk
985cfa6437SVladislav Yaroshchuk if (!validate_options(netdev, errp)) {
995cfa6437SVladislav Yaroshchuk return result;
1005cfa6437SVladislav Yaroshchuk }
1015cfa6437SVladislav Yaroshchuk
1025cfa6437SVladislav Yaroshchuk if_desc = build_if_desc(netdev);
1035cfa6437SVladislav Yaroshchuk result = vmnet_if_create(nc, if_desc, errp);
1045cfa6437SVladislav Yaroshchuk xpc_release(if_desc);
1055cfa6437SVladislav Yaroshchuk return result;
10681ad2964SVladislav Yaroshchuk }
107