[libvirt] [PATCH v4] Automaticly create tap device for VIR_DOMAIN_NET_TYPE_ETHERNET
Vasiliy Tolstov
v.tolstov at selfip.ru
Mon Mar 9 18:42:08 UTC 2015
Ping...
27 февр. 2015 г. 16:30 пользователь "Vasiliy Tolstov" <v.tolstov at selfip.ru>
написал:
> If a user specify ehernet device create it via libvirt and run
> script if it provided. After this commit user does not need to
> run external script to create tap device or add root to qemu
> process.
>
> Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
> ---
> src/qemu/qemu_command.c | 135
> +++++++++++++++++++++++++++++-------------------
> src/qemu/qemu_hotplug.c | 13 ++---
> src/qemu/qemu_process.c | 6 +++
> 3 files changed, 93 insertions(+), 61 deletions(-)
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 24b2ad9..284a97c 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -278,10 +278,41 @@ static int
> qemuCreateInBridgePortWithHelper(virQEMUDriverConfigPtr cfg,
> return *tapfd < 0 ? -1 : 0;
> }
>
> +/**
> + * qemuExecuteEthernetScript:
> + * @ifname: the interface name
> + * @script: the script name
> + * This function executes script for new tap device created by libvirt.
> + * Returns 0 in case of success or -1 on failure
> + */
> +static int qemuExecuteEthernetScript(const char *ifname, const char
> *script)
> +{
> + virCommandPtr cmd;
> + int ret;
> +
> + cmd = virCommandNew(script);
> + virCommandAddArgFormat(cmd, "%s", ifname);
> + virCommandClearCaps(cmd);
> +#ifdef CAP_NET_ADMIN
> + virCommandAllowCap(cmd, CAP_NET_ADMIN);
> +#endif
> + virCommandAddEnvPassCommon(cmd);
> +
> + if (virCommandRun(cmd, NULL) < 0) {
> + ret = -1;
> + } else {
> + ret = 0;
> + }
> +
> + virCommandFree(cmd);
> + return ret;
> +}
> +
> /* qemuNetworkIfaceConnect - *only* called if actualType is
> - * VIR_DOMAIN_NET_TYPE_NETWORK or VIR_DOMAIN_NET_TYPE_BRIDGE (i.e. if
> - * the connection is made with a tap device connecting to a bridge
> - * device)
> + * VIR_DOMAIN_NET_TYPE_NETWORK, VIR_DOMAIN_NET_TYPE_BRIDGE or
> + * VIR_DOMAIN_NET_TYPE_ETHERNET (i.e. if the connection is
> + * made with a tap device connecting to a bridge device or
> + * used ethernet tap device)
> */
> int
> qemuNetworkIfaceConnect(virDomainDefPtr def,
> @@ -307,11 +338,6 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
> }
> }
>
> - if (!(brname = virDomainNetGetActualBridgeName(net))) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing bridge
> name"));
> - goto cleanup;
> - }
> -
> if (!net->ifname ||
> STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) ||
> strchr(net->ifname, '%')) {
> @@ -327,45 +353,61 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
> tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
> }
>
> - if (cfg->privileged) {
> - if (virNetDevTapCreateInBridgePort(brname, &net->ifname,
> &net->mac,
> - def->uuid, tunpath, tapfd,
> *tapfdSize,
> -
> virDomainNetGetActualVirtPortProfile(net),
> - virDomainNetGetActualVlan(net),
> - tap_create_flags) < 0) {
> + if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
> + if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, *tapfdSize,
> + tap_create_flags) < 0) {
> virDomainAuditNetDevice(def, net, tunpath, false);
> goto cleanup;
> }
> - if (virDomainNetGetActualBridgeMACTableManager(net)
> - == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
> - /* libvirt is managing the FDB of the bridge this device
> - * is attaching to, so we need to turn off learning and
> - * unicast_flood on the device to prevent the kernel from
> - * adding any FDB entries for it. We will add add an fdb
> - * entry ourselves (during qemuInterfaceStartDevices(),
> - * using the MAC address from the interface config.
> - */
> - if (virNetDevBridgePortSetLearning(brname, net->ifname,
> false) < 0)
> - goto cleanup;
> - if (virNetDevBridgePortSetUnicastFlood(brname, net->ifname,
> false) < 0)
> + if (net->script) {
> + if (qemuExecuteEthernetScript(net->ifname, net->script) < 0)
> goto cleanup;
> }
> } else {
> - if (qemuCreateInBridgePortWithHelper(cfg, brname,
> - &net->ifname,
> - tapfd, tap_create_flags) <
> 0) {
> - virDomainAuditNetDevice(def, net, tunpath, false);
> + if (!(brname = virDomainNetGetActualBridgeName(net))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing
> bridge name"));
> goto cleanup;
> }
> - /* qemuCreateInBridgePortWithHelper can only create a single FD */
> - if (*tapfdSize > 1) {
> - VIR_WARN("Ignoring multiqueue network request");
> - *tapfdSize = 1;
> +
> + if (cfg->privileged) {
> + if (virNetDevTapCreateInBridgePort(brname, &net->ifname,
> &net->mac,
> + def->uuid, tunpath, tapfd,
> *tapfdSize,
> +
> virDomainNetGetActualVirtPortProfile(net),
> +
> virDomainNetGetActualVlan(net),
> + tap_create_flags) < 0) {
> + virDomainAuditNetDevice(def, net, tunpath, false);
> + goto cleanup;
> + }
> + if (virDomainNetGetActualBridgeMACTableManager(net)
> + == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
> + /* libvirt is managing the FDB of the bridge this device
> + * is attaching to, so we need to turn off learning and
> + * unicast_flood on the device to prevent the kernel from
> + * adding any FDB entries for it. We will add add an fdb
> + * entry ourselves (during qemuInterfaceStartDevices(),
> + * using the MAC address from the interface config.
> + */
> + if (virNetDevBridgePortSetLearning(brname, net->ifname,
> false) < 0)
> + goto cleanup;
> + if (virNetDevBridgePortSetUnicastFlood(brname,
> net->ifname, false) < 0)
> + goto cleanup;
> + }
> + } else {
> + if (qemuCreateInBridgePortWithHelper(cfg, brname,
> + &net->ifname,
> + tapfd, tap_create_flags)
> < 0) {
> + virDomainAuditNetDevice(def, net, tunpath, false);
> + goto cleanup;
> + }
> + /* qemuCreateInBridgePortWithHelper can only create a single
> FD */
> + if (*tapfdSize > 1) {
> + VIR_WARN("Ignoring multiqueue network request");
> + *tapfdSize = 1;
> + }
> }
> + virDomainAuditNetDevice(def, net, tunpath, true);
> }
>
> - virDomainAuditNetDevice(def, net, tunpath, true);
> -
> if (cfg->macFilter &&
> ebtablesAddForwardAllowIn(driver->ebtables,
> net->ifname,
> @@ -4959,6 +5001,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> case VIR_DOMAIN_NET_TYPE_NETWORK:
> case VIR_DOMAIN_NET_TYPE_DIRECT:
> + case VIR_DOMAIN_NET_TYPE_ETHERNET:
> virBufferAsprintf(&buf, "tap%c", type_sep);
> /* for one tapfd 'fd=' shall be used,
> * for more than one 'fds=' is the right choice */
> @@ -4976,20 +5019,6 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
> is_tap = true;
> break;
>
> - case VIR_DOMAIN_NET_TYPE_ETHERNET:
> - virBufferAddLit(&buf, "tap");
> - if (net->ifname) {
> - virBufferAsprintf(&buf, "%cifname=%s", type_sep, net->ifname);
> - type_sep = ',';
> - }
> - if (net->script) {
> - virBufferAsprintf(&buf, "%cscript=%s", type_sep,
> - net->script);
> - type_sep = ',';
> - }
> - is_tap = true;
> - break;
> -
> case VIR_DOMAIN_NET_TYPE_CLIENT:
> virBufferAsprintf(&buf, "socket%cconnect=%s:%d",
> type_sep,
> @@ -7785,7 +7814,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
> /* Currently nothing besides TAP devices supports multiqueue. */
> if (net->driver.virtio.queues > 0 &&
> !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
> - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
> + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
> + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("Multiqueue network is not supported for: %s"),
> virDomainNetTypeToString(actualType));
> @@ -7802,7 +7832,8 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
> }
>
> if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
> - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
> + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
> + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
> tapfdSize = net->driver.virtio.queues;
> if (!tapfdSize)
> tapfdSize = 1;
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index 08047ce..c34486a 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -896,7 +896,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
> /* Currently nothing besides TAP devices supports multiqueue. */
> if (net->driver.virtio.queues > 0 &&
> !(actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
> - actualType == VIR_DOMAIN_NET_TYPE_BRIDGE)) {
> + actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
> + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET)) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("Multiqueue network is not supported for: %s"),
> virDomainNetTypeToString(actualType));
> @@ -904,7 +905,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
> }
>
> if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
> - actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
> + actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
> + actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
> tapfdSize = vhostfdSize = net->driver.virtio.queues;
> if (!tapfdSize)
> tapfdSize = vhostfdSize = 1;
> @@ -935,13 +937,6 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
> iface_connected = true;
> if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd,
> &vhostfdSize) < 0)
> goto cleanup;
> - } else if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET) {
> - vhostfdSize = 1;
> - if (VIR_ALLOC(vhostfd) < 0)
> - goto cleanup;
> - *vhostfd = -1;
> - if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, vhostfd,
> &vhostfdSize) < 0)
> - goto cleanup;
> }
>
> /* Set device online immediately */
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 515402e..468e509 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -5288,6 +5288,12 @@ void qemuProcessStop(virQEMUDriverPtr driver,
> cfg->stateDir));
> VIR_FREE(net->ifname);
> break;
> + case VIR_DOMAIN_NET_TYPE_ETHERNET:
> + if (net->ifname) {
> + ignore_value(virNetDevTapDelete(net->ifname,
> net->backend.tap));
> + VIR_FREE(net->ifname);
> + }
> + break;
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> case VIR_DOMAIN_NET_TYPE_NETWORK:
> #ifdef VIR_NETDEV_TAP_REQUIRE_MANUAL_CLEANUP
> --
> 2.2.2
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150309/1d24ccd6/attachment-0001.htm>
More information about the libvir-list
mailing list