* [Qemu-devel] [RFC PATCH 0/2] Decouple netdev from nic
@ 2012-05-02 16:06 Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 1/2] Implement netdev_set command Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 2/2] virtio-net: re-initialize tap device for new netdev Vasilis Liaskovitis
0 siblings, 2 replies; 3+ messages in thread
From: Vasilis Liaskovitis @ 2012-05-02 16:06 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, armbru, lcapitulino, Vasilis Liaskovitis, snaiksat
Virtualization management layers would like to decouple host network device
(netdev) creation/deletion/setup from guest network adapters.
This would allow to independently:
- provision VMs with NIC(s)
- create and manage network devices on the host
First discussed here:
http://lists.gnu.org/archive/html/qemu-devel/2011-10/msg03614.html
Explicit plug/unplug of a backend netdev device to a VM NIC at runtime would be
needed. This patch introduces a command "netdev_set" to attach a netdev device
to a guest nic. This allows the following use cases:
1) qemu can start with detached nic and backend netdevs
E.g. at boot time nic0 and netdev are not connected:
-netdev type=tap,id=netdev0 -device virtio-net-pci,id=nic0
Warning: netdev guest0 has no peer
Warning: nic net0 has no peer
The following sequence would connect backend device netdev0 to nic nic0
(qemu) set_link nic0 off
(qemu) netdev_set nic0 netdev0
(qemu) set_link nic0 up
Setting the link up/down is done separately with the existing set_link command,
but could be added to the semantics of the new command if desired.
2) change of backend netdev at runtime.
E.g. at boot time, nic0 is connected to netdev netdev0:
-netdev type=tap,id=netdev0 -device virtio-net-pci,netdev=netdev0,id=nic0
The following sequence would change the backend device for nic0 to netdev1:
(qemu) set_link nic0 off
(qemu) netdev_del netdevnic0
(qemu) netdev_add id=netdev1,type=tap
(qemu) netdev_set nic0 netdev1
(qemu) set_link nic0 up
(netdev_del will currently call the link_status_changed callback for the guest
device it is attached to, so afaict the first step "set_link off" for the guest
device is not strictly needed in this example)
- is this feature of interest upstream? If yes, what's the desired way to implement
it in qom? Is there a legitimate way to change a qdev property after a device has
been initialized? The netdev property of a guest nic is set at nic
initialization time - if we attach a new backend device, how can we update the
netdev property?
- A link property for a nic device (link=up/down) which denotes initial status of a
nic can also be implemented (not yet in this patch). This way a nic could be
initialized with disabled carrier at the command line using link=down.
thoughts, comments welcome.
series is based on
http://repo.or.cz/w/qemu/qmp-unstable.git/qmp-wip/qapi-commands-conv/netdev-add/v2
and can be found here:
https://github.com/vliaskov/qemu-kvm/commits/netdev-decouple
Vasilis Liaskovitis (2):
Implement netdev_set command
virtio-net: re-initialize tap device for new netdev
hmp-commands.hx | 14 +++++++++++++
hmp.c | 10 +++++++++
hmp.h | 1 +
hw/virtio-net.c | 30 +++++++++++++++++++++++++++
net.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
net.h | 1 +
qapi-schema.json | 16 ++++++++++++++
qmp-commands.hx | 25 +++++++++++++++++++++++
8 files changed, 155 insertions(+), 0 deletions(-)
--
1.7.9
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Qemu-devel] [RFC PATCH 1/2] Implement netdev_set command
2012-05-02 16:06 [Qemu-devel] [RFC PATCH 0/2] Decouple netdev from nic Vasilis Liaskovitis
@ 2012-05-02 16:06 ` Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 2/2] virtio-net: re-initialize tap device for new netdev Vasilis Liaskovitis
1 sibling, 0 replies; 3+ messages in thread
From: Vasilis Liaskovitis @ 2012-05-02 16:06 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, armbru, lcapitulino, Vasilis Liaskovitis, snaiksat
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.liaskovitis@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
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [Qemu-devel] [RFC PATCH 2/2] virtio-net: re-initialize tap device for new netdev
2012-05-02 16:06 [Qemu-devel] [RFC PATCH 0/2] Decouple netdev from nic Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 1/2] Implement netdev_set command Vasilis Liaskovitis
@ 2012-05-02 16:06 ` Vasilis Liaskovitis
1 sibling, 0 replies; 3+ messages in thread
From: Vasilis Liaskovitis @ 2012-05-02 16:06 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, armbru, lcapitulino, Vasilis Liaskovitis, snaiksat
When a nic's backend netdev device is changed, the tap device needs to be
re-initialized for vnet_hdr and offload features. Also, vhost will have to
be re-initialized. This is currently implemented in the virtio set_status
callback function.
Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
---
hw/virtio-net.c | 30 ++++++++++++++++++++++++++++++
1 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index bc5e3a8..858434a 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -63,6 +63,7 @@ typedef struct VirtIONet
} mac_table;
uint32_t *vlans;
DeviceState *qdev;
+ VLANClientState *old_peer;
} VirtIONet;
/* TODO
@@ -137,10 +138,38 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
}
}
+static int peer_has_vnet_hdr(VirtIONet *n);
+
static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
{
VirtIONet *n = to_virtio_net(vdev);
+ uint32_t features;
+
+ /* re-initialize backend netdev if it is has been changed */
+ if (n->old_peer != n->nic->nc.peer) {
+ features = vdev->guest_features;
+
+ if (peer_has_vnet_hdr(n))
+ tap_using_vnet_hdr(n->nic->nc.peer, 1);
+
+ if (n->has_vnet_hdr) {
+ tap_set_offload(n->nic->nc.peer,
+ (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
+ (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
+ (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
+ (features >> VIRTIO_NET_F_GUEST_ECN) & 1,
+ (features >> VIRTIO_NET_F_GUEST_UFO) & 1);
+ }
+ if ((n->nic->nc.peer->info->type == NET_CLIENT_TYPE_TAP) &&
+ tap_get_vhost_net(n->nic->nc.peer)) {
+ vhost_net_ack_features(tap_get_vhost_net(n->nic->nc.peer), features);
+ }
+ /* vhost will have to be restarted */
+ if (n->vhost_started)
+ n->vhost_started = 0;
+ n->old_peer = n->nic->nc.peer;
+ }
virtio_net_vhost_status(n, status);
if (!n->tx_waiting) {
@@ -1044,6 +1073,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
n->vlans = g_malloc0(MAX_VLAN >> 3);
n->qdev = dev;
+ n->old_peer = conf->peer;
register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
virtio_net_save, virtio_net_load, n);
--
1.7.9
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2012-05-02 16:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-02 16:06 [Qemu-devel] [RFC PATCH 0/2] Decouple netdev from nic Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 1/2] Implement netdev_set command Vasilis Liaskovitis
2012-05-02 16:06 ` [Qemu-devel] [RFC PATCH 2/2] virtio-net: re-initialize tap device for new netdev Vasilis Liaskovitis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).