This command can be used to attach a host backend network device (netdev) to a guest nic. Syntax is: netdev_set nicid netdevid
This patch adds qmp and hmp support for the command. Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovi...@profitbricks.com> --- hmp-commands.hx | 14 +++++++++++++ hmp.c | 10 +++++++++ hmp.h | 1 + net.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ net.h | 1 + qapi-schema.json | 16 ++++++++++++++ qmp-commands.hx | 25 +++++++++++++++++++++++ 7 files changed, 125 insertions(+), 0 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 54b8592..65ae0bf 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1032,6 +1032,20 @@ STEXI Remove host network device. ETEXI + { + .name = "netdev_set", + .args_type = "nicid:s,netdevid:s", + .params = "nicid netdevid", + .help = "attach host network device to nic", + .mhandler.cmd = hmp_netdev_set, + }, + +STEXI +@item netdev_del +@findex netdev_del +Attach host network device to nic. +ETEXI + #ifdef CONFIG_SLIRP { .name = "hostfwd_add", diff --git a/hmp.c b/hmp.c index 17fddb9..2a817ee 100644 --- a/hmp.c +++ b/hmp.c @@ -973,3 +973,13 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) qmp_netdev_del(id, &err); hmp_handle_error(mon, &err); } + +void hmp_netdev_set(Monitor *mon, const QDict *qdict) +{ + const char *nicid = qdict_get_str(qdict, "nicid"); + const char *netdevid = qdict_get_str(qdict, "netdevid"); + Error *err = NULL; + + qmp_netdev_set(nicid, netdevid, &err); + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index ca005df..90b12cd 100644 --- a/hmp.h +++ b/hmp.h @@ -63,5 +63,6 @@ void hmp_migrate(Monitor *mon, const QDict *qdict); void hmp_device_del(Monitor *mon, const QDict *qdict); void hmp_netdev_add(Monitor *mon, const QDict *qdict); void hmp_netdev_del(Monitor *mon, const QDict *qdict); +void hmp_netdev_set(Monitor *mon, const QDict *qdict); #endif diff --git a/net.c b/net.c index 4aa416c..a8358a7 100644 --- a/net.c +++ b/net.c @@ -674,6 +674,21 @@ VLANClientState *qemu_find_netdev(const char *id) return NULL; } +VLANClientState *qemu_find_nic(const char *id) +{ + VLANClientState *vc; + + QTAILQ_FOREACH(vc, &non_vlan_clients, next) { + if (vc->info->type != NET_CLIENT_TYPE_NIC) + continue; + if (!strcmp(vc->name, id)) { + return vc; + } + } + + return NULL; +} + static int nic_get_free_idx(void) { int index; @@ -1283,6 +1298,49 @@ void qmp_netdev_del(const char *id, Error **errp) qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id)); } +void qmp_netdev_set(const char *nicid, const char *netdevid, Error **errp) +{ + VLANClientState *vc, *nic; + NICState *nicstate; + DeviceState *qdev; + + nic = qemu_find_nic(nicid); + if (!nic) { + error_set(errp, QERR_DEVICE_NOT_FOUND, nicid); + } + + qdev = qdev_find_recursive(sysbus_get_default(), nicid); + if (!qdev) { + error_set(errp, QERR_DEVICE_NOT_FOUND, nicid); + } + + vc = qemu_find_netdev(netdevid); + if (!vc) { + error_set(errp, QERR_DEVICE_NOT_FOUND, netdevid); + return; + } + + /* for now, only allow tap device assignment*/ + if (vc->info->type != NET_CLIENT_TYPE_TAP) { + error_set(errp, QERR_INVALID_PARAMETER, netdevid); + return; + } + + vc->peer = nic; + if (nic->peer) + nic->peer->peer = NULL; + nic->peer = vc; + + nicstate = DO_UPCAST(NICState, nc, nic); + if (nicstate->peer_deleted == true) + nicstate->peer_deleted = false; + nicstate->conf->peer = vc; + + /* this is a hack, qdev properties should not be set after nic + * initialization */ + qdev_prop_parse(qdev, "netdev", netdevid); +} + static void print_net_client(Monitor *mon, VLANClientState *vc) { monitor_printf(mon, "%s: type=%s,%s\n", vc->name, diff --git a/net.h b/net.h index bdc2a06..c8abf17 100644 --- a/net.h +++ b/net.h @@ -90,6 +90,7 @@ struct VLANState { VLANState *qemu_find_vlan(int id, int allocate); VLANClientState *qemu_find_netdev(const char *id); +VLANClientState *qemu_find_nic(const char *id); VLANClientState *qemu_new_net_client(NetClientInfo *info, VLANState *vlan, VLANClientState *peer, diff --git a/qapi-schema.json b/qapi-schema.json index 5b4ba12..9127238 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1765,3 +1765,19 @@ # Since: 0.14.0 ## { 'command': 'netdev_del', 'data': {'id': 'str'} } + +## +# @netdev_set: +# +# Attach a network backend to a network device. +# +# @id: the name of the network device to attach to +# @netdev: the name of the network backend to attach +# +# Returns: Nothing on success +# If @id is not a valid network device, DeviceNotFound +# If @netdev is not a valid network backend, DeviceNotFound +# +# Since: 0.14.0 +## +{ 'command': 'netdev_set', 'data': {'nicid': 'str', 'netdevid': 'str'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 7a68cad..ee278e4 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -657,6 +657,31 @@ Example: EQMP { + .name = "netdev_set", + .args_type = "nicid:s,netdevid:s", + .mhandler.cmd_new = qmp_marshal_input_netdev_set, + }, + +SQMP +netdev_set +---------- + +Attach host network device to guest nic. + +Arguments: + +- "nicid": the nic device's ID, must be unique (json-string) +- "netdevid": the host network device's ID, must be unique (json-string) + +Example: + +-> { "execute": "netdev_set", "arguments": { "nicid": "nic1", "netdevid": "netdev1" } } +<- { "return": {} } + + +EQMP + + { .name = "block_resize", .args_type = "device:B,size:o", .mhandler.cmd_new = qmp_marshal_input_block_resize, -- 1.7.9