[libvirt] ANNOUNCE: Libvirt TCK release v1.1.0

2018-12-24 Thread Daniel P . Berrangé
I'm pleased to announce a new release of the libvirt TCK is now
available for download:

  https://libvirt.org/sources/tck/Sys-Virt-TCK-v1.1.0.tar.gz

The GPG signature:

  https://libvirt.org/sources/tck/Sys-Virt-TCK-v1.1.0.tar.gz.asc

Is created with my key with a fingerprint:

  DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF  (4096R)

All historical releases are available from:

  https://libvirt.org/sources/tck/

Changes in this release are:

 - Prevent netdev name overflowing max length
 - Avoid commonly virtual network subnet for tests
 - Ensure secrets are cleaned up in encryption test
 - Stop using deprecated brctl
 - Fix typo related to SSH host key checking
 - Fix undefined global in disk encryption test
 - Fix selinux static relabelling test
 - Increase timeout in nwfilter concurrency test
 - Remove bogus warning about deleting everything on host
 - Add tests for virtual network connections from guests
 - Switch to using positional args for tests

Thanks to everyone who has contributed to this release

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH] lxc: allow empty path in URI for historical compatibility

2018-12-24 Thread Daniel P . Berrangé
The use of 'lxc://' was mistakenly broken in:

  commit 4c8574c85c554e68de0d8bf9b85727954a5bea91
  Author: Daniel P. Berrangé 
  Date:   Wed Mar 28 12:49:29 2018 +0100

driver: ensure NULL URI isn't passed to drivers with whitelisted URIs

Allow it again for historical compatibility.

Signed-off-by: Daniel P. Berrangé 
---
 src/lxc/lxc_driver.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index de045c80bb..df15a0da50 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -140,7 +140,8 @@ static virDrvOpenStatus lxcConnectOpen(virConnectPtr conn,
 virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
 
 /* If path isn't '/' then they typoed, tell them correct path */
-if (STRNEQ(conn->uri->path, "/") &&
+if (STRNEQ(conn->uri->path, "") &&
+STRNEQ(conn->uri->path, "/") &&
 STRNEQ(conn->uri->path, "/system")) {
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected LXC URI path '%s', try lxc:///system"),
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 27/27] conf: switch over to use network port APIs for virt drivers

2018-12-24 Thread Daniel P . Berrangé
Change the domain conf so invoke the new network port public APIs instead
of the network callbacks.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c  | 125 ++
 src/conf/domain_conf.h  |  21 +
 src/network/bridge_driver.c | 172 
 3 files changed, 90 insertions(+), 228 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e384c60dfd..689a397e44 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -11022,6 +11022,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
 char *type = NULL;
 char *network = NULL;
 char *portgroup = NULL;
+char *portid = NULL;
 char *bridge = NULL;
 char *dev = NULL;
 char *ifname = NULL;
@@ -11104,6 +11105,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
virXMLNodeNameEqual(cur, "source")) {
 network = virXMLPropString(cur, "network");
 portgroup = virXMLPropString(cur, "portgroup");
+portid = virXMLPropString(cur, "portid");
 } else if (!internal &&
def->type == VIR_DOMAIN_NET_TYPE_INTERNAL &&
virXMLNodeNameEqual(cur, "source")) {
@@ -11312,12 +11314,20 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
  "specified with "));
 goto error;
 }
+if (portid &&
+virUUIDParse(portid, def->data.network.portid) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Unable to parse port id '%s'"), portid);
+goto error;
+}
+
 def->data.network.name = network;
 network = NULL;
 def->data.network.portgroup = portgroup;
 portgroup = NULL;
 def->data.network.actual = actual;
 actual = NULL;
+
 break;
 
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@@ -11830,6 +11840,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
 VIR_FREE(macaddr);
 VIR_FREE(network);
 VIR_FREE(portgroup);
+VIR_FREE(portid);
 VIR_FREE(address);
 VIR_FREE(port);
 VIR_FREE(vhostuser_type);
@@ -24941,6 +24952,11 @@ virDomainActualNetDefContentsFormat(virBufferPtr buf,
   def->data.network.name);
 virBufferEscapeString(buf, " portgroup='%s'",
   def->data.network.portgroup);
+if (virUUIDIsValid(def->data.network.portid)) {
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+virUUIDFormat(def->data.network.portid, uuidstr);
+virBufferAsprintf(buf, " portid='%s'", uuidstr);
+}
 }
 if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
 actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
@@ -30519,6 +30535,7 @@ virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr 
iface,
 if (VIR_STRDUP(actual->data.bridge.brname,
port->plug.bridge.brname) < 0)
 goto error;
+actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
 actual->data.bridge.macTableManager = 
port->plug.bridge.macTableManager;
 break;
 
@@ -30526,10 +30543,12 @@ 
virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface,
 if (VIR_STRDUP(actual->data.direct.linkdev,
port->plug.direct.linkdev) < 0)
 goto error;
+actual->type = VIR_DOMAIN_NET_TYPE_DIRECT;
 actual->data.direct.mode = port->plug.direct.mode;
 break;
 
 case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI:
+actual->type = VIR_DOMAIN_NET_TYPE_HOSTDEV;
 actual->data.hostdev.def.parent = iface;
 actual->data.hostdev.def.info = >info;
 actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
@@ -30707,48 +30726,82 @@ virDomainNetDefActualToNetworkPort(virDomainDefPtr 
dom,
 return NULL;
 }
 
-static virDomainNetAllocateActualDeviceImpl netAllocate;
-static virDomainNetNotifyActualDeviceImpl netNotify;
-static virDomainNetReleaseActualDeviceImpl netRelease;
 static virDomainNetBandwidthChangeAllowedImpl netBandwidthChangeAllowed;
 static virDomainNetBandwidthUpdateImpl netBandwidthUpdate;
 
 
 void
-virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate,
-  virDomainNetNotifyActualDeviceImpl notify,
-  virDomainNetReleaseActualDeviceImpl release,
-  virDomainNetBandwidthChangeAllowedImpl 
bandwidthChangeAllowed,
+virDomainNetSetDeviceImpl(virDomainNetBandwidthChangeAllowedImpl 
bandwidthChangeAllowed,
   virDomainNetBandwidthUpdateImpl bandwidthUpdate)
 {
-netAllocate = allocate;
-netNotify = notify;
-netRelease = release;
 netBandwidthChangeAllowed = bandwidthChangeAllowed;
 netBandwidthUpdate = bandwidthUpdate;
 }
 
-int

[libvirt] [PATCH 26/27] network: add implementation of network port APIs

2018-12-24 Thread Daniel P . Berrangé
This initial implementation just wires up the APIs and does tracking of
the port XML definitions. It is not yet integrated into the resource
allocation logic.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 233 
 1 file changed, 233 insertions(+)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 37c49abde7..8401b72bc8 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2836,6 +2836,8 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
 
 VIR_DEBUG("Beginning network startup process");
 
+virNetworkObjDeleteAllPorts(obj, driver->stateDir);
+
 VIR_DEBUG("Setting current network def as transient");
 if (virNetworkObjSetDefTransient(obj, true) < 0)
 goto cleanup;
@@ -4009,6 +4011,9 @@ networkDestroy(virNetworkPtr net)
 
 if ((ret = networkShutdownNetwork(driver, obj)) < 0)
 goto cleanup;
+
+virNetworkObjDeleteAllPorts(obj, driver->stateDir);
+
 /* @def replaced in virNetworkObjUnsetDefTransient*/
 def = virNetworkObjGetDef(obj);
 
@@ -5669,6 +5674,229 @@ networkBandwidthUpdate(virDomainNetDefPtr iface,
 }
 
 
+static virNetworkPortPtr
+networkPortLookupByUUID(virNetworkPtr net,
+const unsigned char *uuid)
+{
+virNetworkObjPtr obj;
+virNetworkDefPtr def;
+virNetworkPortDefPtr portdef = NULL;
+virNetworkPortPtr ret = NULL;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+virUUIDFormat(uuid, uuidstr);
+
+if (!(obj = networkObjFromNetwork(net)))
+return ret;
+
+def = virNetworkObjGetDef(obj);
+
+if (!(portdef = virNetworkObjLookupPort(obj, uuid)))
+goto cleanup;
+
+if (virNetworkPortLookupByUUIDEnsureACL(net->conn, def, portdef) < 0)
+goto cleanup;
+
+if (!virNetworkObjIsActive(obj)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   _("network '%s' is not active"),
+   def->name);
+goto cleanup;
+}
+
+ret = virGetNetworkPort(net, uuid);
+
+ cleanup:
+virNetworkObjEndAPI();
+return ret;
+}
+
+
+static virNetworkPortPtr
+networkPortCreateXML(virNetworkPtr net,
+ const char *xmldesc,
+ unsigned int flags)
+{
+virNetworkDriverStatePtr driver = networkGetDriver();
+virNetworkObjPtr obj;
+virNetworkDefPtr def;
+virNetworkPortDefPtr portdef = NULL;
+virNetworkPortPtr ret = NULL;
+int rc;
+
+virCheckFlags(VIR_NETWORK_PORT_CREATE_RECLAIM, NULL);
+
+if (!(obj = networkObjFromNetwork(net)))
+return ret;
+
+def = virNetworkObjGetDef(obj);
+
+if (!(portdef = virNetworkPortDefParseString(xmldesc)))
+goto cleanup;
+
+if (virNetworkPortCreateXMLEnsureACL(net->conn, def, portdef) < 0)
+goto cleanup;
+
+if (!virNetworkObjIsActive(obj)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   _("network '%s' is not active"),
+   def->name);
+goto cleanup;
+}
+
+if (portdef->plugtype == VIR_NETWORK_PORT_PLUG_TYPE_NONE) {
+if (flags & VIR_NETWORK_PORT_CREATE_RECLAIM) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Port reclaim requested but plug type is none"));
+goto cleanup;
+}
+} else {
+if (!(flags & VIR_NETWORK_PORT_CREATE_RECLAIM)) {
+virReportError(VIR_ERR_INVALID_ARG, "%s",
+   _("Port reclaim not requested but plug type is not 
none"));
+goto cleanup;
+}
+}
+
+if (virNetworkObjAddPort(obj, portdef, driver->stateDir) < 0) {
+virNetworkPortDefFree(portdef);
+goto cleanup;
+}
+
+if (flags & VIR_NETWORK_PORT_CREATE_RECLAIM)
+rc = networkNotifyPort(obj, portdef);
+else
+rc = networkAllocatePort(obj, portdef);
+if (rc < 0) {
+virErrorPtr saved;
+saved = virSaveLastError();
+virNetworkObjDeletePort(obj, portdef->uuid, driver->stateDir);
+virSetError(saved);
+virFreeError(saved);
+goto cleanup;
+}
+
+ret = virGetNetworkPort(net, portdef->uuid);
+ cleanup:
+virNetworkObjEndAPI();
+return ret;
+}
+
+
+static char *
+networkPortGetXMLDesc(virNetworkPortPtr port,
+  unsigned int flags)
+{
+virNetworkObjPtr obj;
+virNetworkDefPtr def;
+virNetworkPortDefPtr portdef = NULL;
+char *ret = NULL;
+
+virCheckFlags(0, NULL);
+
+if (!(obj = networkObjFromNetwork(port->net)))
+return ret;
+
+def = virNetworkObjGetDef(obj);
+
+if (!(portdef = virNetworkObjLookupPort(obj, port->uuid)))
+goto cleanup;
+
+if (virNetworkPortGetXMLDescEnsureACL(port->net->conn, def, portdef) < 0)
+goto cleanup;
+
+if (!virNetworkObjIsActive(obj)) {
+virReportError(VIR_ERR_OPERATION_INVALID,
+   _("network '%s' is not active"),
+   

[libvirt] [PATCH 24/27] virsh: add support for network port APIs

2018-12-24 Thread Daniel P . Berrangé
Signed-off-by: Daniel P. Berrangé 
---
 tools/virsh-completer.c |  51 +
 tools/virsh-completer.h |   4 +
 tools/virsh-network.c   | 399 +++-
 tools/virsh-network.h   |   5 +
 4 files changed, 458 insertions(+), 1 deletion(-)

diff --git a/tools/virsh-completer.c b/tools/virsh-completer.c
index cfbfeae328..e9ff09b696 100644
--- a/tools/virsh-completer.c
+++ b/tools/virsh-completer.c
@@ -22,6 +22,7 @@
 
 #include "virsh-completer.h"
 #include "virsh-domain.h"
+#include "virsh-network.h"
 #include "virsh.h"
 #include "virsh-pool.h"
 #include "virsh-nodedev.h"
@@ -382,6 +383,56 @@ virshNetworkNameCompleter(vshControl *ctl,
 }
 
 
+char **
+virshNetworkPortUUIDCompleter(vshControl *ctl,
+  const vshCmd *cmd ATTRIBUTE_UNUSED,
+  unsigned int flags)
+{
+virshControlPtr priv = ctl->privData;
+virNetworkPtr net = NULL;
+virNetworkPortPtr *ports = NULL;
+int nports = 0;
+size_t i = 0;
+char **ret = NULL;
+
+virCheckFlags(0, NULL);
+
+if (!priv->conn || virConnectIsAlive(priv->conn) <= 0)
+return NULL;
+
+if (!(net = virshCommandOptNetwork(ctl, cmd, NULL)))
+return false;
+
+if ((nports = virNetworkListAllPorts(net, , flags)) < 0)
+return NULL;
+
+if (VIR_ALLOC_N(ret, nports + 1) < 0)
+goto error;
+
+for (i = 0; i < nports; i++) {
+char uuid[VIR_UUID_STRING_BUFLEN];
+
+if (virNetworkPortGetUUIDString(ports[i], uuid) < 0 ||
+VIR_STRDUP(ret[i], uuid) < 0)
+goto error;
+
+virNetworkPortFree(ports[i]);
+}
+VIR_FREE(ports);
+
+return ret;
+
+ error:
+for (; i < nports; i++)
+virNetworkPortFree(ports[i]);
+VIR_FREE(ports);
+for (i = 0; i < nports; i++)
+VIR_FREE(ret[i]);
+VIR_FREE(ret);
+return NULL;
+}
+
+
 char **
 virshNodeDeviceNameCompleter(vshControl *ctl,
  const vshCmd *cmd ATTRIBUTE_UNUSED,
diff --git a/tools/virsh-completer.h b/tools/virsh-completer.h
index 4069d976b8..e9f999567d 100644
--- a/tools/virsh-completer.h
+++ b/tools/virsh-completer.h
@@ -58,6 +58,10 @@ char ** virshNetworkNameCompleter(vshControl *ctl,
   const vshCmd *cmd,
   unsigned int flags);
 
+char ** virshNetworkPortUUIDCompleter(vshControl *ctl,
+  const vshCmd *cmd,
+  unsigned int flags);
+
 char ** virshNodeDeviceNameCompleter(vshControl *ctl,
  const vshCmd *cmd,
  unsigned int flags);
diff --git a/tools/virsh-network.c b/tools/virsh-network.c
index 440b23d8a8..38e57efe74 100644
--- a/tools/virsh-network.c
+++ b/tools/virsh-network.c
@@ -1,7 +1,7 @@
 /*
  * virsh-network.c: Commands to manage network
  *
- * Copyright (C) 2005, 2007-2016 Red Hat, Inc.
+ * Copyright (C) 2005, 2007-2018 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -58,6 +58,16 @@
 #define VIRSH_COMMON_OPT_NETWORK_OT_STRING_FULL(cflags) \
 VIRSH_COMMON_OPT_NETWORK_OT_STRING(N_("network name or uuid"), cflags)
 
+#define VIRSH_COMMON_OPT_NETWORK_PORT(cflags) \
+{.name = "port", \
+ .type = VSH_OT_DATA, \
+ .flags = VSH_OFLAG_REQ, \
+ .help = N_("port UUID"), \
+ .completer = virshNetworkPortUUIDCompleter, \
+ .completer_flags = cflags, \
+}
+
+
 virNetworkPtr
 virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
  const char **name, unsigned int flags)
@@ -96,6 +106,35 @@ virshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
 return network;
 }
 
+
+virNetworkPortPtr
+virshCommandOptNetworkPort(vshControl *ctl, const vshCmd *cmd,
+   virNetworkPtr net,
+   const char **name)
+{
+virNetworkPortPtr port = NULL;
+const char *n = NULL;
+const char *optname = "port";
+
+if (vshCommandOptStringReq(ctl, cmd, optname, ) < 0)
+return NULL;
+
+vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
+ cmd->def->name, optname, n);
+
+if (name)
+*name = n;
+
+vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n",
+ cmd->def->name, optname);
+port = virNetworkPortLookupByUUIDString(net, n);
+
+if (!port)
+vshError(ctl, _("failed to get network port '%s'"), n);
+
+return port;
+}
+
 /*
  * "net-autostart" command
  */
@@ -1427,6 +1466,340 @@ cmdNetworkDHCPLeases(vshControl *ctl, const vshCmd *cmd)
 return ret;
 }
 
+/*
+ * "net-port-create" command
+ */
+static const vshCmdInfo info_network_port_create[] = {
+{.name = "help",
+ .data = N_("create a network port from an XML file")
+},
+{.name = "desc",
+ .data = N_("Create a network port.")
+

[libvirt] [PATCH 25/27] conf: support recording ports against virNetworkObjPtr

2018-12-24 Thread Daniel P . Berrangé
The virNetworkObjPtr state will need to maintain a record of all
virNetworkPortDefPtr objects associated with the network. Record these
in a hash and add APIs for manipulating them.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/virnetworkobj.c | 303 +++
 src/conf/virnetworkobj.h |  30 
 src/libvirt_private.syms |   5 +
 3 files changed, 338 insertions(+)

diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c
index e6b01388f5..935edcea57 100644
--- a/src/conf/virnetworkobj.c
+++ b/src/conf/virnetworkobj.c
@@ -58,6 +58,8 @@ struct _virNetworkObj {
 
 /* Immutable pointer, self locking APIs */
 virMacMapPtr macmap;
+
+virHashTablePtr ports; /* uuid -> virNetworkPortDefPtr */
 };
 
 struct _virNetworkObjList {
@@ -86,6 +88,17 @@ virNetworkObjOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(virNetworkObj)
 
+static int
+virNetworkObjLoadAllPorts(virNetworkObjPtr net,
+  const char *stateDir);
+
+
+static void
+virNetworkObjPortFree(void *val, const void *key ATTRIBUTE_UNUSED)
+{
+virNetworkPortDefFree(val);
+}
+
 virNetworkObjPtr
 virNetworkObjNew(void)
 {
@@ -106,6 +119,10 @@ virNetworkObjNew(void)
 virBitmapSetBitExpand(obj->classIdMap, 2) < 0)
 goto error;
 
+if (!(obj->ports = virHashCreate(10,
+ virNetworkObjPortFree)))
+goto error;
+
 virObjectLock(obj);
 
 return obj;
@@ -458,6 +475,7 @@ virNetworkObjDispose(void *opaque)
 {
 virNetworkObjPtr obj = opaque;
 
+virHashFree(obj->ports);
 virNetworkDefFree(obj->def);
 virNetworkDefFree(obj->newDef);
 virBitmapFree(obj->classIdMap);
@@ -1073,9 +1091,16 @@ virNetworkObjLoadAllState(virNetworkObjListPtr nets,
 continue;
 
 obj = virNetworkLoadState(nets, stateDir, entry->d_name);
+
+if (obj &&
+virNetworkObjLoadAllPorts(obj, stateDir) < 0) {
+virNetworkObjEndAPI();
+goto cleanup;
+}
 virNetworkObjEndAPI();
 }
 
+ cleanup:
 VIR_DIR_CLOSE(dir);
 return ret;
 }
@@ -1585,3 +1610,281 @@ virNetworkObjListPrune(virNetworkObjListPtr nets,
 virHashRemoveSet(nets->objs, virNetworkObjListPruneHelper, );
 virObjectRWUnlock(nets);
 }
+
+
+static char *
+virNetworkObjGetPortStatusDir(virNetworkObjPtr net,
+  const char *stateDir)
+{
+char *ret;
+ignore_value(virAsprintf(, "%s/%s/ports", stateDir, net->def->name));
+return ret;
+}
+
+int
+virNetworkObjAddPort(virNetworkObjPtr net,
+ virNetworkPortDefPtr portdef,
+ const char *stateDir)
+{
+int ret = -1;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+char *dir = NULL;
+
+virUUIDFormat(portdef->uuid, uuidstr);
+
+if (virHashLookup(net->ports, uuidstr)) {
+virReportError(VIR_ERR_NETWORK_PORT_EXIST,
+   _("Network port with UUID %s already exists"),
+   uuidstr);
+goto cleanup;
+}
+
+if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+goto cleanup;
+
+if (virHashAddEntry(net->ports, uuidstr, portdef) < 0)
+goto cleanup;
+
+if (virNetworkPortDefSaveStatus(portdef, dir) < 0) {
+virHashRemoveEntry(net->ports, uuidstr);
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+return ret;
+}
+
+
+virNetworkPortDefPtr
+virNetworkObjLookupPort(virNetworkObjPtr net,
+const unsigned char *uuid)
+{
+virNetworkPortDefPtr ret = NULL;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+virUUIDFormat(uuid, uuidstr);
+
+if (!(ret = virHashLookup(net->ports, uuidstr))) {
+virReportError(VIR_ERR_NO_NETWORK_PORT,
+   _("Network port with UUID %s does not exist"),
+   uuidstr);
+goto cleanup;
+}
+
+ cleanup:
+return ret;
+}
+
+
+int
+virNetworkObjDeletePort(virNetworkObjPtr net,
+const unsigned char *uuid,
+const char *stateDir)
+{
+int ret = -1;
+char uuidstr[VIR_UUID_STRING_BUFLEN];
+char *dir = NULL;
+virNetworkPortDefPtr portdef;
+
+virUUIDFormat(uuid, uuidstr);
+
+if (!(portdef = virHashLookup(net->ports, uuidstr))) {
+virReportError(VIR_ERR_NO_NETWORK_PORT,
+   _("Network port with UUID %s does not exist"),
+   uuidstr);
+goto cleanup;
+}
+
+if (!(dir = virNetworkObjGetPortStatusDir(net, stateDir)))
+goto cleanup;
+
+if (virNetworkPortDefDeleteStatus(portdef, dir) < 0)
+goto cleanup;
+
+if (virHashRemoveEntry(net->ports, uuidstr) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+VIR_FREE(dir);
+return ret;
+}
+
+
+int
+virNetworkObjDeleteAllPorts(virNetworkObjPtr net,
+const char *stateDir)
+{
+char *dir;
+DIR *dh;
+struct dirent *de;
+int rc;
+int ret = -1;

[libvirt] [PATCH 23/27] remote: add support for new network port APIs

2018-12-24 Thread Daniel P . Berrangé
Define the wire protocol for the virNetworkPort APIs and enable the
client/server RPC dispatch.

Signed-off-by: Daniel P. Berrangé 
---
 src/remote/remote_daemon_dispatch.c | 25 
 src/remote/remote_driver.c  | 28 +
 src/remote/remote_protocol.x| 89 -
 src/remote_protocol-structs | 47 +++
 src/rpc/gendispatch.pl  | 18 --
 5 files changed, 200 insertions(+), 7 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index fcd602304f..2620699600 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -83,6 +83,7 @@ struct daemonClientEventCallback {
 
 static virDomainPtr get_nonnull_domain(virConnectPtr conn, 
remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network(virConnectPtr conn, 
remote_nonnull_network network);
+static virNetworkPortPtr get_nonnull_network_port(virConnectPtr conn, 
remote_nonnull_network_port port);
 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, 
remote_nonnull_interface iface);
 static virStoragePoolPtr get_nonnull_storage_pool(virConnectPtr conn, 
remote_nonnull_storage_pool pool);
 static virStorageVolPtr get_nonnull_storage_vol(virConnectPtr conn, 
remote_nonnull_storage_vol vol);
@@ -93,6 +94,7 @@ static virDomainSnapshotPtr 
get_nonnull_domain_snapshot(virDomainPtr dom, remote
 static virNodeDevicePtr get_nonnull_node_device(virConnectPtr conn, 
remote_nonnull_node_device dev);
 static int make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr 
dom_src) ATTRIBUTE_RETURN_CHECK;
 static int make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr 
net_src) ATTRIBUTE_RETURN_CHECK;
+static int make_nonnull_network_port(remote_nonnull_network_port *port_dst, 
virNetworkPortPtr port_src) ATTRIBUTE_RETURN_CHECK;
 static int make_nonnull_interface(remote_nonnull_interface *interface_dst, 
virInterfacePtr interface_src) ATTRIBUTE_RETURN_CHECK;
 static int make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, 
virStoragePoolPtr pool_src) ATTRIBUTE_RETURN_CHECK;
 static int make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, 
virStorageVolPtr vol_src) ATTRIBUTE_RETURN_CHECK;
@@ -7202,6 +7204,19 @@ get_nonnull_network(virConnectPtr conn, 
remote_nonnull_network network)
 return virGetNetwork(conn, network.name, BAD_CAST network.uuid);
 }
 
+static virNetworkPortPtr
+get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port)
+{
+virNetworkPortPtr ret;
+virNetworkPtr net;
+net = virGetNetwork(conn, port.net.name, BAD_CAST port.net.uuid);
+if (!net)
+return NULL;
+ret = virGetNetworkPort(net, BAD_CAST port.uuid);
+virObjectUnref(net);
+return ret;
+}
+
 static virInterfacePtr
 get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface)
 {
@@ -7274,6 +7289,16 @@ make_nonnull_network(remote_nonnull_network *net_dst, 
virNetworkPtr net_src)
 return 0;
 }
 
+static int
+make_nonnull_network_port(remote_nonnull_network_port *port_dst, 
virNetworkPortPtr port_src)
+{
+if (VIR_STRDUP(port_dst->net.name, port_src->net->name) < 0)
+return -1;
+memcpy(port_dst->net.uuid, port_src->net->uuid, VIR_UUID_BUFLEN);
+memcpy(port_dst->uuid, port_src->uuid, VIR_UUID_BUFLEN);
+return 0;
+}
+
 static int
 make_nonnull_interface(remote_nonnull_interface *interface_dst,
virInterfacePtr interface_src)
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 058e4c926b..d2e8ce2473 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -138,6 +138,7 @@ static int remoteAuthPolkit(virConnectPtr conn, struct 
private_data *priv,
 
 static virDomainPtr get_nonnull_domain(virConnectPtr conn, 
remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network(virConnectPtr conn, 
remote_nonnull_network network);
+static virNetworkPortPtr get_nonnull_network_port(virConnectPtr conn, 
remote_nonnull_network_port port);
 static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, 
remote_nonnull_nwfilter nwfilter);
 static virNWFilterBindingPtr get_nonnull_nwfilter_binding(virConnectPtr conn, 
remote_nonnull_nwfilter_binding binding);
 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, 
remote_nonnull_interface iface);
@@ -148,6 +149,7 @@ static virSecretPtr get_nonnull_secret(virConnectPtr conn, 
remote_nonnull_secret
 static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr domain, 
remote_nonnull_domain_snapshot snapshot);
 static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr 
dom_src);
 static void make_nonnull_network(remote_nonnull_network *net_dst, 
virNetworkPtr net_src);
+static void make_nonnull_network_port(remote_nonnull_network_port *port_dst, 
virNetworkPortPtr port_src);
 static void make_nonnull_interface(remote_nonnull_interface 

[libvirt] [PATCH 21/27] network: add public APIs for network port object

2018-12-24 Thread Daniel P . Berrangé
Introduce a new virNetworPort object that will present an attachment to
a virtual network from a VM.

Signed-off-by: Daniel P. Berrangé 
---
 include/libvirt/libvirt-network.h |  49 +
 include/libvirt/virterror.h   |   3 +
 src/datatypes.c   |  60 +
 src/datatypes.h   |  41 
 src/driver-network.h  |  27 +++
 src/libvirt-network.c | 351 ++
 src/libvirt_private.syms  |   2 +
 src/libvirt_public.syms   |  14 ++
 src/util/virerror.c   |   9 +
 9 files changed, 556 insertions(+)

diff --git a/include/libvirt/libvirt-network.h 
b/include/libvirt/libvirt-network.h
index 5115251fbe..08b91e6021 100644
--- a/include/libvirt/libvirt-network.h
+++ b/include/libvirt/libvirt-network.h
@@ -46,6 +46,22 @@ typedef struct _virNetwork virNetwork;
  */
 typedef virNetwork *virNetworkPtr;
 
+/**
+ * virNetworkPort:
+ *
+ * a virNetworkPort is a private structure representing a virtual network
+ * port
+ */
+typedef struct _virNetworkPort virNetworkPort;
+
+/**
+ * virNetworkPortPtr:
+ *
+ * a virNetworkPortPtr is pointer to a virNetworkPort private structure,
+ * this is the type used to reference a virtual network port in the API.
+ */
+typedef virNetworkPort *virNetworkPortPtr;
+
 /*
  * Get connection from network.
  */
@@ -333,4 +349,37 @@ int virConnectNetworkEventRegisterAny(virConnectPtr conn,
 int virConnectNetworkEventDeregisterAny(virConnectPtr conn,
 int callbackID);
 
+virNetworkPortPtr virNetworkPortLookupByUUID(virNetworkPtr net,
+ const unsigned char *uuid);
+
+virNetworkPortPtr virNetworkPortLookupByUUIDString(virNetworkPtr net,
+   const char *uuidstr);
+
+typedef enum {
+VIR_NETWORK_PORT_CREATE_RECLAIM = (1 << 0), /* reclaim existing used 
resources */
+} virNetworkPortCreateFlags;
+
+virNetworkPortPtr virNetworkPortCreateXML(virNetworkPtr net,
+  const char *xmldesc,
+  unsigned int flags);
+
+virNetworkPtr virNetworkPortGetNetwork(virNetworkPortPtr port);
+
+char *virNetworkPortGetXMLDesc(virNetworkPortPtr port,
+   unsigned int flags);
+
+int virNetworkPortGetUUID(virNetworkPortPtr port,
+  unsigned char *uuid);
+int virNetworkPortGetUUIDString(virNetworkPortPtr port,
+char *buf);
+
+int virNetworkPortDelete(virNetworkPortPtr port,
+ unsigned int flags);
+
+int virNetworkListAllPorts(virNetworkPtr network,
+   virNetworkPortPtr **ports,
+   unsigned int flags);
+
+int virNetworkPortFree(virNetworkPortPtr port);
+
 #endif /* LIBVIRT_NETWORK_H */
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index fbbe2d5624..3db8067391 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -321,6 +321,9 @@ typedef enum {
 VIR_ERR_DEVICE_MISSING = 99,/* fail to find the desired device */
 VIR_ERR_INVALID_NWFILTER_BINDING = 100,  /* invalid nwfilter binding */
 VIR_ERR_NO_NWFILTER_BINDING = 101,  /* no nwfilter binding */
+VIR_ERR_INVALID_NETWORK_PORT = 102, /* invalid network port object */
+VIR_ERR_NETWORK_PORT_EXIST = 103,   /* the network port already exist */
+VIR_ERR_NO_NETWORK_PORT = 104,  /* network port not found */
 
 # ifdef VIR_ENUM_SENTINELS
 VIR_ERR_NUMBER_LAST
diff --git a/src/datatypes.c b/src/datatypes.c
index caf035f178..30c98d62a5 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -39,6 +39,7 @@ virClassPtr virDomainClass;
 virClassPtr virDomainSnapshotClass;
 virClassPtr virInterfaceClass;
 virClassPtr virNetworkClass;
+virClassPtr virNetworkPortClass;
 virClassPtr virNodeDeviceClass;
 virClassPtr virNWFilterClass;
 virClassPtr virNWFilterBindingClass;
@@ -53,6 +54,7 @@ static void virDomainDispose(void *obj);
 static void virDomainSnapshotDispose(void *obj);
 static void virInterfaceDispose(void *obj);
 static void virNetworkDispose(void *obj);
+static void virNetworkPortDispose(void *obj);
 static void virNodeDeviceDispose(void *obj);
 static void virNWFilterDispose(void *obj);
 static void virNWFilterBindingDispose(void *obj);
@@ -89,6 +91,7 @@ virDataTypesOnceInit(void)
 DECLARE_CLASS(virDomainSnapshot);
 DECLARE_CLASS(virInterface);
 DECLARE_CLASS(virNetwork);
+DECLARE_CLASS(virNetworkPort);
 DECLARE_CLASS(virNodeDevice);
 DECLARE_CLASS(virNWFilter);
 DECLARE_CLASS(virNWFilterBinding);
@@ -385,6 +388,63 @@ virNetworkDispose(void *obj)
 }
 
 
+/**
+ * virGetNetworkPort:
+ * @net: the network object
+ * @uuid: pointer to the uuid
+ *
+ * Allocates a new network port object. When the object is no longer needed,
+ * virObjectUnref() must be called in order to not leak data.
+ *
+ * Returns a 

[libvirt] [PATCH 10/27] network: stop passing virDomainNetDefPtr into bandwidth functions

2018-12-24 Thread Daniel P . Berrangé
The networkPlugBandwidth & networkUnplugBandwidth methods currently take
a virDomainNetDefPtr. To remove the dependency on the domain config
struct, pass individual parameters instead.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 94 -
 1 file changed, 50 insertions(+), 44 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 8cb108ea46..1014b53201 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -170,11 +170,14 @@ networkRefreshDaemons(virNetworkDriverStatePtr driver);
 
 static int
 networkPlugBandwidth(virNetworkObjPtr obj,
- virDomainNetDefPtr iface);
+ virMacAddrPtr mac,
+ virNetDevBandwidthPtr ifaceBand,
+ unsigned int *class_id);
 
 static int
 networkUnplugBandwidth(virNetworkObjPtr obj,
-   virDomainNetDefPtr iface);
+   virNetDevBandwidthPtr ifaceBand,
+   unsigned int *class_id);
 
 static void
 networkNetworkObjTaint(virNetworkObjPtr obj,
@@ -4567,7 +4570,9 @@ networkAllocateActualDevice(virNetworkPtr net,
 goto error;
 }
 
-if (networkPlugBandwidth(obj, iface) < 0)
+if (networkPlugBandwidth(obj, >mac, iface->bandwidth,
+ iface->data.network.actual ?
+ >data.network.actual->class_id : NULL) 
< 0)
 goto error;
 break;
 
@@ -4660,7 +4665,9 @@ networkAllocateActualDevice(virNetworkPtr net,
 }
 }
 
-if (networkPlugBandwidth(obj, iface) < 0)
+if (networkPlugBandwidth(obj, >mac, iface->bandwidth,
+ iface->data.network.actual ?
+ >data.network.actual->class_id : 
NULL) < 0)
 goto error;
 break;
 }
@@ -5129,14 +5136,17 @@ networkReleaseActualDevice(virNetworkPtr net,
 case VIR_NETWORK_FORWARD_NAT:
 case VIR_NETWORK_FORWARD_ROUTE:
 case VIR_NETWORK_FORWARD_OPEN:
-if (iface->data.network.actual && networkUnplugBandwidth(obj, iface) < 
0)
+if (iface->data.network.actual &&
+networkUnplugBandwidth(obj, iface->bandwidth,
+   >data.network.actual->class_id) < 0)
 goto error;
 break;
 
 case VIR_NETWORK_FORWARD_BRIDGE:
 if (iface->data.network.actual &&
 actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-networkUnplugBandwidth(obj, iface) < 0)
+networkUnplugBandwidth(obj, iface->bandwidth,
+   >data.network.actual->class_id) < 0)
 goto error;
 break;
 case VIR_NETWORK_FORWARD_PRIVATE:
@@ -5276,7 +5286,7 @@ static int
 networkCheckBandwidth(virNetworkObjPtr obj,
   virNetDevBandwidthPtr ifaceBand,
   virNetDevBandwidthPtr oldBandwidth,
-  virMacAddr ifaceMac,
+  virMacAddrPtr ifaceMac,
   unsigned long long *new_rate)
 {
 int ret = -1;
@@ -5286,7 +5296,7 @@ networkCheckBandwidth(virNetworkObjPtr obj,
 unsigned long long tmp_new_rate = 0;
 char ifmac[VIR_MAC_STRING_BUFLEN];
 
-virMacAddrFormat(, ifmac);
+virMacAddrFormat(ifaceMac, ifmac);
 
 if (ifaceBand && ifaceBand->in && ifaceBand->in->floor &&
 !(netBand && netBand->in)) {
@@ -5371,44 +5381,45 @@ networkNextClassID(virNetworkObjPtr obj)
 
 static int
 networkPlugBandwidthImpl(virNetworkObjPtr obj,
- virDomainNetDefPtr iface,
+ virMacAddrPtr mac,
  virNetDevBandwidthPtr ifaceBand,
+ unsigned int *class_id,
  unsigned long long new_rate)
 {
 virNetworkDriverStatePtr driver = networkGetDriver();
 virNetworkDefPtr def = virNetworkObjGetDef(obj);
 virBitmapPtr classIdMap = virNetworkObjGetClassIdMap(obj);
 unsigned long long tmp_floor_sum = virNetworkObjGetFloorSum(obj);
-ssize_t class_id = 0;
+ssize_t next_id = 0;
 int plug_ret;
 int ret = -1;
 
 /* generate new class_id */
-if ((class_id = networkNextClassID(obj)) < 0) {
+if ((next_id = networkNextClassID(obj)) < 0) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not generate next class ID"));
 goto cleanup;
 }
 
 plug_ret = virNetDevBandwidthPlug(def->bridge, def->bandwidth,
-  >mac, ifaceBand, class_id);
+  mac, ifaceBand, next_id);
 if (plug_ret < 0) {
-ignore_value(virNetDevBandwidthUnplug(def->bridge, class_id));
+ignore_value(virNetDevBandwidthUnplug(def->bridge, next_id));
 goto cleanup;
 }
 
 /* QoS was set, generate new 

[libvirt] [PATCH 22/27] access: add permissions for network port objects

2018-12-24 Thread Daniel P . Berrangé
Signed-off-by: Daniel P. Berrangé 
---
 src/access/genpolkit.pl|  2 +-
 src/access/viraccessdriver.h   |  6 +
 src/access/viraccessdrivernop.c| 11 +
 src/access/viraccessdriverpolkit.c | 26 
 src/access/viraccessdriverstack.c  | 25 
 src/access/viraccessmanager.c  | 16 +
 src/access/viraccessmanager.h  |  6 +
 src/access/viraccessperm.c |  8 ++-
 src/access/viraccessperm.h | 38 ++
 9 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/src/access/genpolkit.pl b/src/access/genpolkit.pl
index e074c90eb6..f8f20caf65 100755
--- a/src/access/genpolkit.pl
+++ b/src/access/genpolkit.pl
@@ -21,7 +21,7 @@ use strict;
 use warnings;
 
 my @objects = (
-"CONNECT", "DOMAIN", "INTERFACE",
+"CONNECT", "DOMAIN", "INTERFACE", "NETWORK_PORT",
 "NETWORK","NODE_DEVICE", "NWFILTER_BINDING", "NWFILTER",
 "SECRET", "STORAGE_POOL", "STORAGE_VOL",
 );
diff --git a/src/access/viraccessdriver.h b/src/access/viraccessdriver.h
index 2cc3950f60..590d86fdf0 100644
--- a/src/access/viraccessdriver.h
+++ b/src/access/viraccessdriver.h
@@ -39,6 +39,11 @@ typedef int 
(*virAccessDriverCheckNetworkDrv)(virAccessManagerPtr manager,
   const char *driverName,
   virNetworkDefPtr network,
   virAccessPermNetwork av);
+typedef int (*virAccessDriverCheckNetworkPortDrv)(virAccessManagerPtr manager,
+  const char *driverName,
+  virNetworkDefPtr network,
+  virNetworkPortDefPtr port,
+  virAccessPermNetworkPort av);
 typedef int (*virAccessDriverCheckNodeDeviceDrv)(virAccessManagerPtr manager,
  const char *driverName,
  virNodeDeviceDefPtr nodedev,
@@ -82,6 +87,7 @@ struct _virAccessDriver {
 virAccessDriverCheckDomainDrv checkDomain;
 virAccessDriverCheckInterfaceDrv checkInterface;
 virAccessDriverCheckNetworkDrv checkNetwork;
+virAccessDriverCheckNetworkPortDrv checkNetworkPort;
 virAccessDriverCheckNodeDeviceDrv checkNodeDevice;
 virAccessDriverCheckNWFilterDrv checkNWFilter;
 virAccessDriverCheckNWFilterBindingDrv checkNWFilterBinding;
diff --git a/src/access/viraccessdrivernop.c b/src/access/viraccessdrivernop.c
index 98ef9206c5..5e9d9db759 100644
--- a/src/access/viraccessdrivernop.c
+++ b/src/access/viraccessdrivernop.c
@@ -57,6 +57,16 @@ virAccessDriverNopCheckNetwork(virAccessManagerPtr manager 
ATTRIBUTE_UNUSED,
 return 1; /* Allow */
 }
 
+static int
+virAccessDriverNopCheckNetworkPort(virAccessManagerPtr manager 
ATTRIBUTE_UNUSED,
+   const char *driverName ATTRIBUTE_UNUSED,
+   virNetworkDefPtr network ATTRIBUTE_UNUSED,
+   virNetworkPortDefPtr port ATTRIBUTE_UNUSED,
+   virAccessPermNetworkPort perm 
ATTRIBUTE_UNUSED)
+{
+return 1; /* Allow */
+}
+
 static int
 virAccessDriverNopCheckNodeDevice(virAccessManagerPtr manager ATTRIBUTE_UNUSED,
   const char *driverName ATTRIBUTE_UNUSED,
@@ -119,6 +129,7 @@ virAccessDriver accessDriverNop = {
 .checkDomain = virAccessDriverNopCheckDomain,
 .checkInterface = virAccessDriverNopCheckInterface,
 .checkNetwork = virAccessDriverNopCheckNetwork,
+.checkNetworkPort = virAccessDriverNopCheckNetworkPort,
 .checkNodeDevice = virAccessDriverNopCheckNodeDevice,
 .checkNWFilter = virAccessDriverNopCheckNWFilter,
 .checkNWFilterBinding = virAccessDriverNopCheckNWFilterBinding,
diff --git a/src/access/viraccessdriverpolkit.c 
b/src/access/viraccessdriverpolkit.c
index 6954d74a15..b1473cd0a4 100644
--- a/src/access/viraccessdriverpolkit.c
+++ b/src/access/viraccessdriverpolkit.c
@@ -237,6 +237,31 @@ virAccessDriverPolkitCheckNetwork(virAccessManagerPtr 
manager,
   attrs);
 }
 
+static int
+virAccessDriverPolkitCheckNetworkPort(virAccessManagerPtr manager,
+  const char *driverName,
+  virNetworkDefPtr network,
+  virNetworkPortDefPtr port,
+  virAccessPermNetworkPort perm)
+{
+char uuidstr1[VIR_UUID_STRING_BUFLEN];
+char uuidstr2[VIR_UUID_STRING_BUFLEN];
+const char *attrs[] = {
+"connect_driver", driverName,
+"network_name", network->name,
+"network_uuid", uuidstr1,
+"port_uuid", uuidstr2,
+NULL,
+};
+virUUIDFormat(network->uuid, uuidstr1);
+

[libvirt] [PATCH 14/27] network: convert networkAllocateActualDevice to virNetworkPortDef

2018-12-24 Thread Daniel P . Berrangé
Convert the virDomainNetDef object into a virNetworkPortDef object
at the start of networkAllocateActualDevice. This largely decouples
the method impl from the domain object type.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 222 +++-
 1 file changed, 91 insertions(+), 131 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 8d1a1b95d2..594574db8c 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -68,6 +68,7 @@
 #include "network_event.h"
 #include "virhook.h"
 #include "virjson.h"
+#include "conf/virnetworkportdef.h"
 
 #define VIR_FROM_THIS VIR_FROM_NETWORK
 #define MAX_BRIDGE_ID 256
@@ -4447,17 +4448,16 @@ networkAllocateActualDevice(virNetworkPtr net,
 virDomainNetDefPtr iface)
 {
 virNetworkDriverStatePtr driver = networkGetDriver();
-virDomainNetType actualType = iface->type;
 virNetworkObjPtr obj = NULL;
 virNetworkDefPtr netdef = NULL;
-virNetDevBandwidthPtr bandwidth = NULL;
 virPortGroupDefPtr portgroup = NULL;
-virNetDevVPortProfilePtr virtport = iface->virtPortProfile;
-virNetDevVlanPtr vlan = NULL;
 virNetworkForwardIfDefPtr dev = NULL;
 size_t i;
 int ret = -1;
+virNetDevVPortProfilePtr portprofile = NULL;
+virNetworkPortDefPtr port = NULL;
 
+VIR_DEBUG("Allocating port from net %s", net->name);
 obj = virNetworkObjFindByName(driver->networks, net->name);
 if (!obj) {
 virReportError(VIR_ERR_NO_NETWORK,
@@ -4472,9 +4472,6 @@ networkAllocateActualDevice(virNetworkPtr net,
 goto error;
 }
 
-virDomainActualNetDefFree(iface->data.network.actual);
-iface->data.network.actual = NULL;
-
 netdef = virNetworkObjGetDef(obj);
 
 if (!virNetworkObjIsActive(obj)) {
@@ -4484,99 +4481,84 @@ networkAllocateActualDevice(virNetworkPtr net,
 goto error;
 }
 
-if (VIR_ALLOC(iface->data.network.actual) < 0)
+if (!(port = virDomainNetDefToNetworkPort(dom, iface)))
 goto error;
 
+VIR_DEBUG("Interface port group %s", port->group);
 /* portgroup can be present for any type of network, in particular
  * for bandwidth information, so we need to check for that and
  * fill it in appropriately for all forward types.
  */
-portgroup = virPortGroupFindByName(netdef, iface->data.network.portgroup);
-
-/* If there is already interface-specific bandwidth, just use that
- * (already in NetDef). Otherwise, if there is bandwidth info in
- * the portgroup, fill that into the ActualDef.
- */
-
-if (iface->bandwidth)
-bandwidth = iface->bandwidth;
-else if (portgroup && portgroup->bandwidth)
-bandwidth = portgroup->bandwidth;
+portgroup = virPortGroupFindByName(netdef, port->group);
 
-if (bandwidth && 
virNetDevBandwidthCopy(>data.network.actual->bandwidth,
-bandwidth) < 0)
-goto error;
+if (!port->bandwidth) {
+if (portgroup && portgroup->bandwidth &&
+virNetDevBandwidthCopy(>bandwidth,
+   portgroup->bandwidth) < 0)
+goto error;
+}
 
-/* copy appropriate vlan info to actualNet */
-if (iface->vlan.nTags > 0)
-vlan = >vlan;
-else if (portgroup && portgroup->vlan.nTags > 0)
-vlan = >vlan;
-else if (netdef->vlan.nTags > 0)
-vlan = >vlan;
+if (port->vlan.nTags == 0) {
+virNetDevVlanPtr vlan = NULL;
+if (portgroup && portgroup->vlan.nTags > 0)
+vlan = >vlan;
+else if (netdef->vlan.nTags > 0)
+vlan = >vlan;
 
-if (vlan && virNetDevVlanCopy(>data.network.actual->vlan, vlan) < 0)
-goto error;
+if (vlan && virNetDevVlanCopy(>vlan, vlan) < 0)
+goto error;
+}
 
-if (iface->trustGuestRxFilters)
-   iface->data.network.actual->trustGuestRxFilters
-  = iface->trustGuestRxFilters;
-else if (portgroup && portgroup->trustGuestRxFilters)
-   iface->data.network.actual->trustGuestRxFilters
-  = portgroup->trustGuestRxFilters;
-else if (netdef->trustGuestRxFilters)
-   iface->data.network.actual->trustGuestRxFilters
-  = netdef->trustGuestRxFilters;
+if (!port->trustGuestRxFilters) {
+if (portgroup && portgroup->trustGuestRxFilters)
+port->trustGuestRxFilters = portgroup->trustGuestRxFilters;
+else if (netdef->trustGuestRxFilters)
+port->trustGuestRxFilters = netdef->trustGuestRxFilters;
+}
 
 /* merge virtualports from interface, network, and portgroup to
  * arrive at actual virtualport to use
  */
-if 
(virNetDevVPortProfileMerge3(>data.network.actual->virtPortProfile,
-iface->virtPortProfile,
+if (virNetDevVPortProfileMerge3(,
+port->virtPortProfile,
 

[libvirt] [PATCH 18/27] network: introduce networkAllocatePort

2018-12-24 Thread Daniel P . Berrangé
Separate network port allocation code from the domain driver network
callback implementation.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 143 +++-
 1 file changed, 77 insertions(+), 66 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c3875cb68e..ebce90d89a 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4425,60 +4425,38 @@ networkLogAllocation(virNetworkDefPtr netdef,
  * "backend" function table.
  */
 
-/* networkAllocateActualDevice:
- * @dom: domain definition that @iface belongs to
- * @iface: the original NetDef from the domain
+/* networkAllocatePort:
+ * @obj: the network to allocate from
+ * @port: the port definition to allocate
  *
- * Looks up the network reference by iface, allocates a physical
+ * Looks up the network reference by port, allocates a physical
  * device from that network (if appropriate), and returns with the
- * virDomainActualNetDef filled in accordingly. If there are no
- * changes to be made in the netdef, then just leave the actualdef
- * empty.
+ * port configuration filled in accordingly.
  *
  * Returns 0 on success, -1 on failure.
  */
 static int
-networkAllocateActualDevice(virNetworkPtr net,
-virDomainDefPtr dom,
-virDomainNetDefPtr iface)
+networkAllocatePort(virNetworkObjPtr obj,
+virNetworkPortDefPtr port)
 {
 virNetworkDriverStatePtr driver = networkGetDriver();
-virNetworkObjPtr obj = NULL;
 virNetworkDefPtr netdef = NULL;
 virPortGroupDefPtr portgroup = NULL;
 virNetworkForwardIfDefPtr dev = NULL;
 size_t i;
 int ret = -1;
 virNetDevVPortProfilePtr portprofile = NULL;
-virNetworkPortDefPtr port = NULL;
-
-VIR_DEBUG("Allocating port from net %s", net->name);
-obj = virNetworkObjFindByName(driver->networks, net->name);
-if (!obj) {
-virReportError(VIR_ERR_NO_NETWORK,
-   _("no network with matching name '%s'"),
-   net->name);
-goto error;
-}
-
-if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Expected a interface for a virtual network"));
-goto error;
-}
 
 netdef = virNetworkObjGetDef(obj);
+VIR_DEBUG("Allocating port from net %s", netdef->name);
 
 if (!virNetworkObjIsActive(obj)) {
 virReportError(VIR_ERR_OPERATION_INVALID,
_("network '%s' is not active"),
netdef->name);
-goto error;
+goto cleanup;
 }
 
-if (!(port = virDomainNetDefToNetworkPort(dom, iface)))
-goto error;
-
 VIR_DEBUG("Interface port group %s", port->group);
 /* portgroup can be present for any type of network, in particular
  * for bandwidth information, so we need to check for that and
@@ -4490,7 +4468,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 if (portgroup && portgroup->bandwidth &&
 virNetDevBandwidthCopy(>bandwidth,
portgroup->bandwidth) < 0)
-goto error;
+goto cleanup;
 }
 
 if (port->vlan.nTags == 0) {
@@ -4501,7 +4479,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 vlan = >vlan;
 
 if (vlan && virNetDevVlanCopy(>vlan, vlan) < 0)
-goto error;
+goto cleanup;
 }
 
 if (!port->trustGuestRxFilters) {
@@ -4519,7 +4497,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 netdef->virtPortProfile,
 portgroup
 ? portgroup->virtPortProfile : NULL) < 0) {
-goto error;
+goto cleanup;
 }
 if (portprofile) {
 VIR_FREE(port->virtPortProfile);
@@ -4535,7 +4513,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE;
 
 if (VIR_STRDUP(port->plug.bridge.brname, netdef->bridge) < 0)
-goto error;
+goto cleanup;
 port->plug.bridge.macTableManager = netdef->macTableManager;
 
 if (port->virtPortProfile) {
@@ -4544,18 +4522,18 @@ networkAllocateActualDevice(virNetworkPtr net,
  "'%s' which uses IP forwarding"),

virNetDevVPortTypeToString(port->virtPortProfile->virtPortType),
netdef->name);
-goto error;
+goto cleanup;
 }
 
 if (networkPlugBandwidth(obj, >mac, port->bandwidth, 
>class_id) < 0)
-goto error;
+goto cleanup;
 break;
 
 case VIR_NETWORK_FORWARD_HOSTDEV: {
 port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI;
 
 if (networkCreateInterfacePool(netdef) < 0)
-goto error;
+

[libvirt] [PATCH 09/27] conf: introduce virNetworkPortDefPtr struct and XML support

2018-12-24 Thread Daniel P . Berrangé
Introduce a virNetworkPortDefPtr struct to represent the data associated
with a virtual network port. Add APIs for parsing/formatting XML docs
with the data.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/Makefile.inc.am  |   2 +
 src/conf/virnetworkportdef.c  | 497 ++
 src/conf/virnetworkportdef.h  | 112 
 src/libvirt_private.syms  |  10 +
 tests/Makefile.am |   7 +
 .../plug-bridge-mactbl.xml|   9 +
 .../virnetworkportxml2xmldata/plug-bridge.xml |   9 +
 .../virnetworkportxml2xmldata/plug-direct.xml |  12 +
 .../plug-hostdev-pci.xml  |  12 +
 tests/virnetworkportxml2xmldata/plug-none.xml |   8 +
 tests/virnetworkportxml2xmltest.c | 104 
 11 files changed, 782 insertions(+)
 create mode 100644 src/conf/virnetworkportdef.c
 create mode 100644 src/conf/virnetworkportdef.h
 create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge-mactbl.xml
 create mode 100644 tests/virnetworkportxml2xmldata/plug-bridge.xml
 create mode 100644 tests/virnetworkportxml2xmldata/plug-direct.xml
 create mode 100644 tests/virnetworkportxml2xmldata/plug-hostdev-pci.xml
 create mode 100644 tests/virnetworkportxml2xmldata/plug-none.xml
 create mode 100644 tests/virnetworkportxml2xmltest.c

diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index 219ff350d7..eec861591f 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -5,6 +5,8 @@ NETDEV_CONF_SOURCES = \
conf/netdev_vport_profile_conf.c \
conf/netdev_vlan_conf.h \
conf/netdev_vlan_conf.c \
+   conf/virnetworkportdef.h \
+   conf/virnetworkportdef.c \
$(NULL)
 
 DOMAIN_CONF_SOURCES = \
diff --git a/src/conf/virnetworkportdef.c b/src/conf/virnetworkportdef.c
new file mode 100644
index 00..12b5f086ab
--- /dev/null
+++ b/src/conf/virnetworkportdef.c
@@ -0,0 +1,497 @@
+/*
+ * virnetworkportdef.c: network port XML processing
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * .
+ */
+
+#include 
+
+#include "viralloc.h"
+#include "virerror.h"
+#include "virstring.h"
+#include "virfile.h"
+#include "virnetworkportdef.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
+VIR_ENUM_IMPL(virNetworkPortPlug, VIR_NETWORK_PORT_PLUG_TYPE_LAST,
+  "none", "bridge", "direct", "hostdev-pci");
+
+void
+virNetworkPortDefFree(virNetworkPortDefPtr def)
+{
+if (!def)
+return;
+
+VIR_FREE(def->ownername);
+VIR_FREE(def->group);
+
+virNetDevBandwidthFree(def->bandwidth);
+virNetDevVlanClear(>vlan);
+VIR_FREE(def->virtPortProfile);
+
+switch ((virNetworkPortPlugType)def->plugtype) {
+case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
+VIR_FREE(def->plug.bridge.brname);
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT:
+VIR_FREE(def->plug.direct.linkdev);
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI:
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_LAST:
+default:
+break;
+}
+
+VIR_FREE(def);
+}
+
+
+
+static virNetworkPortDefPtr
+virNetworkPortDefParseXML(xmlXPathContextPtr ctxt)
+{
+virNetworkPortDefPtr def;
+char *uuid = NULL;
+xmlNodePtr virtPortNode;
+xmlNodePtr vlanNode;
+xmlNodePtr bandwidthNode;
+xmlNodePtr addressNode;
+char *trustGuestRxFilters = NULL;
+char *mac = NULL;
+char *macmgr = NULL;
+char *mode = NULL;
+char *plugtype = NULL;
+char *managed = NULL;
+char *driver = NULL;
+
+if (VIR_ALLOC(def) < 0)
+return NULL;
+
+uuid = virXPathString("string(./uuid)", ctxt);
+if (!uuid) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   "%s", _("network port has no uuid"));
+goto error;
+}
+if (virUUIDParse(uuid, def->uuid) < 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Unable to parse UUID '%s'"), uuid);
+goto error;
+}
+
+def->ownername = virXPathString("string(./owner/name)", ctxt);
+if (!def->ownername) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   "%s", _("network port has no owner 

[libvirt] [PATCH 16/27] network: convert networkReleaseActualDevice to virNetworkPortDef

2018-12-24 Thread Daniel P . Berrangé
Convert the virDomainNetDef object into a virNetworkPortDef object
at the start of networkReleaseActualDevice. This largely decouples
the method impl from the domain object type.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 137 +++-
 1 file changed, 56 insertions(+), 81 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 109d284791..e75c596120 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -5060,10 +5060,10 @@ networkReleaseActualDevice(virNetworkPtr net,
virDomainNetDefPtr iface)
 {
 virNetworkDriverStatePtr driver = networkGetDriver();
-virDomainNetType actualType = virDomainNetGetActualType(iface);
 virNetworkObjPtr obj;
 virNetworkDefPtr netdef;
 virNetworkForwardIfDefPtr dev = NULL;
+virNetworkPortDefPtr port = NULL;
 size_t i;
 int ret = -1;
 
@@ -5072,77 +5072,49 @@ networkReleaseActualDevice(virNetworkPtr net,
 virReportError(VIR_ERR_NO_NETWORK,
_("no network with matching name '%s'"),
net->name);
-goto error;
+goto cleanup;
 }
 
 if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Expected a interface for a virtual network"));
-goto error;
+goto cleanup;
 }
 
+if (iface->data.network.actual == NULL) {
+ret = 0;
+goto cleanup;
+}
+
+if (!(port = virDomainNetDefActualToNetworkPort(dom, iface)))
+goto cleanup;
+
 netdef = virNetworkObjGetDef(obj);
 
-switch ((virNetworkForwardType) netdef->forward.type) {
-case VIR_NETWORK_FORWARD_NONE:
-case VIR_NETWORK_FORWARD_NAT:
-case VIR_NETWORK_FORWARD_ROUTE:
-case VIR_NETWORK_FORWARD_OPEN:
-if (iface->data.network.actual &&
-networkUnplugBandwidth(obj, iface->bandwidth,
-   >data.network.actual->class_id) < 0)
-goto error;
+switch ((virNetworkPortPlugType)port->plugtype) {
+case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
+VIR_DEBUG("Releasing network device with no plug type");
 break;
 
-case VIR_NETWORK_FORWARD_BRIDGE:
-if (iface->data.network.actual &&
-actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-networkUnplugBandwidth(obj, iface->bandwidth,
-   >data.network.actual->class_id) < 0)
-goto error;
-break;
-case VIR_NETWORK_FORWARD_PRIVATE:
-case VIR_NETWORK_FORWARD_VEPA:
-case VIR_NETWORK_FORWARD_PASSTHROUGH:
-case VIR_NETWORK_FORWARD_HOSTDEV:
+case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
+if (networkUnplugBandwidth(obj, port->bandwidth,
+   >class_id) < 0)
+goto cleanup;
 break;
 
-case VIR_NETWORK_FORWARD_LAST:
-default:
-virReportEnumRangeError(virNetworkForwardType, netdef->forward.type);
-goto error;
-}
-
-if ((!iface->data.network.actual) ||
-((actualType != VIR_DOMAIN_NET_TYPE_DIRECT) &&
- (actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV))) {
-VIR_DEBUG("Nothing to release to network %s", 
iface->data.network.name);
-goto success;
-}
-
-if (netdef->forward.nifs == 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("network '%s' uses a direct/hostdev mode, but "
- "has no forward dev and no interface pool"),
-   netdef->name);
-goto error;
-}
-
-if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
-const char *actualDev;
-
-actualDev = virDomainNetGetActualDirectDev(iface);
-if (!actualDev) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("the interface uses a direct mode, "
- "but has no source dev"));
-goto error;
+case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT:
+if (netdef->forward.nifs == 0) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("network '%s' uses a direct mode, but "
+ "has no forward dev and no interface pool"),
+   netdef->name);
+goto cleanup;
 }
 
 for (i = 0; i < netdef->forward.nifs; i++) {
 if (netdef->forward.ifs[i].type
 == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV &&
-STREQ(actualDev, netdef->forward.ifs[i].device.dev)) {
+STREQ(port->plug.direct.linkdev, 
netdef->forward.ifs[i].device.dev)) {
 dev = >forward.ifs[i];
 break;
 }
@@ -5152,23 +5124,24 @@ networkReleaseActualDevice(virNetworkPtr net,
 virReportError(VIR_ERR_INTERNAL_ERROR,
_("network '%s' doesn't have 

[libvirt] [PATCH 20/27] network: introduce networkReleasePort

2018-12-24 Thread Daniel P . Berrangé
Separate network port deletion code from the domain driver network
callback implementation.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 91 -
 1 file changed, 59 insertions(+), 32 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 25e856a7e2..37c49abde7 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -5068,9 +5068,9 @@ networkNotifyActualDevice(virNetworkPtr net,
 }
 
 
-/* networkReleaseActualDevice:
- * @dom: domain definition that @iface belongs to
- * @iface:  a domain's NetDef (interface definition)
+/* networkReleasePort:
+ * @obj: the network to release from
+ * @port: the port definition to release
  *
  * Given a domain  element that previously had its 
  * element filled in (and possibly a physical device allocated to it),
@@ -5080,40 +5080,15 @@ networkNotifyActualDevice(virNetworkPtr net,
  * Returns 0 on success, -1 on failure.
  */
 static int
-networkReleaseActualDevice(virNetworkPtr net,
-   virDomainDefPtr dom,
-   virDomainNetDefPtr iface)
+networkReleasePort(virNetworkObjPtr obj,
+   virNetworkPortDefPtr port)
 {
 virNetworkDriverStatePtr driver = networkGetDriver();
-virNetworkObjPtr obj;
 virNetworkDefPtr netdef;
 virNetworkForwardIfDefPtr dev = NULL;
-virNetworkPortDefPtr port = NULL;
 size_t i;
 int ret = -1;
 
-obj = virNetworkObjFindByName(driver->networks, net->name);
-if (!obj) {
-virReportError(VIR_ERR_NO_NETWORK,
-   _("no network with matching name '%s'"),
-   net->name);
-goto cleanup;
-}
-
-if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Expected a interface for a virtual network"));
-goto cleanup;
-}
-
-if (iface->data.network.actual == NULL) {
-ret = 0;
-goto cleanup;
-}
-
-if (!(port = virDomainNetDefActualToNetworkPort(dom, iface)))
-goto cleanup;
-
 netdef = virNetworkObjGetDef(obj);
 
 switch ((virNetworkPortPlugType)port->plugtype) {
@@ -5192,7 +5167,7 @@ networkReleaseActualDevice(virNetworkPtr net,
 goto cleanup;
 }
 
-virNetworkObjMacMgrDel(obj, driver->dnsmasqStateDir, dom->name, 
>mac);
+virNetworkObjMacMgrDel(obj, driver->dnsmasqStateDir, port->ownername, 
>mac);
 
 netdef->connections--;
 if (dev)
@@ -5200,7 +5175,59 @@ networkReleaseActualDevice(virNetworkPtr net,
 /* finally we can call the 'unplugged' hook script if any */
 networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_DELETED,
VIR_HOOK_SUBOP_BEGIN);
-networkLogAllocation(netdef, dev, >mac, false);
+networkLogAllocation(netdef, dev, >mac, false);
+
+ret = 0;
+ cleanup:
+return ret;
+}
+
+
+/* networkReleaseActualDevice:
+ * @dom: domain definition that @iface belongs to
+ * @iface:  a domain's NetDef (interface definition)
+ *
+ * Given a domain  element that previously had its 
+ * element filled in (and possibly a physical device allocated to it),
+ * free up the physical device for use by someone else, and free the
+ * virDomainActualNetDef.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int
+networkReleaseActualDevice(virNetworkPtr net,
+   virDomainDefPtr dom,
+   virDomainNetDefPtr iface)
+{
+virNetworkDriverStatePtr driver = networkGetDriver();
+virNetworkObjPtr obj;
+virNetworkPortDefPtr port = NULL;
+int ret = -1;
+
+obj = virNetworkObjFindByName(driver->networks, net->name);
+if (!obj) {
+virReportError(VIR_ERR_NO_NETWORK,
+   _("no network with matching name '%s'"),
+   net->name);
+goto cleanup;
+}
+
+if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Expected a interface for a virtual network"));
+goto cleanup;
+}
+
+if (iface->data.network.actual == NULL) {
+ret = 0;
+goto cleanup;
+}
+
+if (!(port = virDomainNetDefActualToNetworkPort(dom, iface)))
+goto cleanup;
+
+if (networkReleasePort(obj, port) < 0)
+goto cleanup;
 
 ret = 0;
  cleanup:
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 19/27] network: introduce networkNotifyPort

2018-12-24 Thread Daniel P . Berrangé
Separate network port notification code from the domain driver network
callback implementation.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 159 
 1 file changed, 89 insertions(+), 70 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index ebce90d89a..25e856a7e2 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4806,46 +4806,26 @@ networkAllocateActualDevice(virNetworkPtr net,
 }
 
 
-/* networkNotifyActualDevice:
- * @dom: domain definition that @iface belongs to
- * @iface:  the domain's NetDef with an "actual" device already filled in.
+/* networkNotifyPort:
+ * @obj: the network to notify
+ * @port: the port definition to notify
  *
  * Called to notify the network driver when libvirtd is restarted and
  * finds an already running domain. If appropriate it will force an
  * allocation of the actual->direct.linkdev to get everything back in
  * order, or re-attach the interface's tap device to the network's
  * bridge.
- *
- * No return value (but does log any failures)
  */
-static void
-networkNotifyActualDevice(virNetworkPtr net,
-  virDomainDefPtr dom,
-  virDomainNetDefPtr iface)
+static int
+networkNotifyPort(virNetworkObjPtr obj,
+  virNetworkPortDefPtr port)
 {
-virNetworkDriverStatePtr driver = networkGetDriver();
-virDomainNetType actualType = virDomainNetGetActualType(iface);
-virNetworkObjPtr obj;
 virNetworkDefPtr netdef;
 virNetworkForwardIfDefPtr dev = NULL;
-virNetworkPortDefPtr port = NULL;
 size_t i;
 char *master = NULL;
 bool useOVS = false;
-
-obj = virNetworkObjFindByName(driver->networks, net->name);
-if (!obj) {
-virReportError(VIR_ERR_NO_NETWORK,
-   _("no network with matching name '%s'"),
-   net->name);
-goto error;
-}
-
-if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("Expected a interface for a virtual network"));
-goto error;
-}
+int ret = -1;
 
 netdef = virNetworkObjGetDef(obj);
 
@@ -4853,55 +4833,32 @@ networkNotifyActualDevice(virNetworkPtr net,
 virReportError(VIR_ERR_OPERATION_INVALID,
_("network '%s' is not active"),
netdef->name);
-goto error;
-}
-
-/* if we're restarting libvirtd after an upgrade from a version
- * that didn't save bridge name in actualNetDef for
- * actualType==network, we need to copy it in so that it will be
- * available in all cases
- */
-if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-!iface->data.network.actual->data.bridge.brname &&
-(VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
-netdef->bridge) < 0))
-goto error;
-
-/* Older libvirtd uses actualType==network, but we now
- * just use actualType==bridge, as nothing needs to
- * distinguish the two cases, and this simplifies virt
- * drive code */
-if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
-iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-actualType = VIR_DOMAIN_NET_TYPE_BRIDGE;
-}
-
-if (!(port = virDomainNetDefActualToNetworkPort(dom, iface)))
 goto cleanup;
+}
 
 switch (port->plugtype) {
 case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpectedly got a network port without a plug"));
-goto error;
+goto cleanup;
 
 case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
 /* see if we're connected to the correct bridge */
 if (!netdef->bridge) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unexpectedly got a network port plugged into a 
bridge"));
-goto error;
+goto cleanup;
 }
 
 if (virNetDevGetMaster(port->plug.bridge.brname, ) < 0)
-goto error;
+goto cleanup;
 
 /* IFLA_MASTER for a tap on an OVS switch is always "ovs-system" */
 if (STREQ_NULLABLE(master, "ovs-system")) {
 useOVS = true;
 VIR_FREE(master);
 if 
(virNetDevOpenvswitchInterfaceGetMaster(port->plug.bridge.brname, ) < 0)
-goto error;
+goto cleanup;
 }
 
 if (STRNEQ_NULLABLE(netdef->bridge, master)) {
@@ -4926,14 +4883,14 @@ networkNotifyActualDevice(virNetworkPtr net,
  port->virtPortProfile,
  >vlan,
  0, NULL) < 0) {
-goto error;
+goto cleanup;
 }
 }
 break;
 
 case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT:
 if 

[libvirt] [PATCH 12/27] util: add API for copying virtual port profile data

2018-12-24 Thread Daniel P . Berrangé
Signed-off-by: Daniel P. Berrangé 
---
 src/libvirt_private.syms |  1 +
 src/util/virnetdevvportprofile.c | 16 
 src/util/virnetdevvportprofile.h |  2 ++
 3 files changed, 19 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0b363f8ec8..0a0079ae06 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2454,6 +2454,7 @@ virNetDevVlanFree;
 virNetDevVPortProfileAssociate;
 virNetDevVPortProfileCheckComplete;
 virNetDevVPortProfileCheckNoExtras;
+virNetDevVPortProfileCopy;
 virNetDevVPortProfileDisassociate;
 virNetDevVPortProfileEqual;
 virNetDevVPortProfileMerge3;
diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
index 09c212bc4d..6aa0c9267b 100644
--- a/src/util/virnetdevvportprofile.c
+++ b/src/util/virnetdevvportprofile.c
@@ -123,6 +123,22 @@ virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, 
virNetDevVPortProfilePtr
 return true;
 }
 
+
+int virNetDevVPortProfileCopy(virNetDevVPortProfilePtr *dst, const 
virNetDevVPortProfile *src)
+{
+if (!src) {
+*dst = NULL;
+return 0;
+}
+
+if (VIR_ALLOC(*dst) < 0)
+return -1;
+
+memcpy(*dst, src, sizeof(*src));
+return 0;
+}
+
+
 /* virNetDevVPortProfileCheckComplete() checks that all attributes
  * required for the type of virtport are specified. When
  * generateMissing is true, any missing attribute that can be
diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h
index da52d00708..af98c7e1f7 100644
--- a/src/util/virnetdevvportprofile.h
+++ b/src/util/virnetdevvportprofile.h
@@ -79,6 +79,8 @@ struct _virNetDevVPortProfile {
 
 bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a,
 virNetDevVPortProfilePtr b);
+int virNetDevVPortProfileCopy(virNetDevVPortProfilePtr *dst,
+  const virNetDevVPortProfile *src);
 
 int virNetDevVPortProfileCheckComplete(virNetDevVPortProfilePtr virtport,
bool generateMissing);
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 17/27] network: convert hook script to take a network port XML

2018-12-24 Thread Daniel P . Berrangé
When (un)plugging an interface into a network, the 'plugged'
and 'unplugged' operations are invoked in the hook script.

The data provided to the script contains the network XML, the
domain XML and the domain interface XML. When we strictly split the
drivers up this will no longer be possible and thus breakage is
unavoidable. The hook scripts are not considered to be covered by the
API guarantee so this is OK.

To avoid existing scripts taking the wrong action, the existing
operations are changed to 'port-created' and 'port-deleted'
instead. These will receive the network XML and the network port
XML.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 27 +++
 src/util/virhook.c  |  4 ++--
 src/util/virhook.h  |  4 ++--
 3 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index e75c596120..c3875cb68e 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -206,14 +206,13 @@ networkObjFromNetwork(virNetworkPtr net)
 
 static int
 networkRunHook(virNetworkObjPtr obj,
-   virDomainDefPtr dom,
-   virDomainNetDefPtr iface,
+   virNetworkPortDefPtr port,
int op,
int sub_op)
 {
 virNetworkDefPtr def;
 virBuffer buf = VIR_BUFFER_INITIALIZER;
-char *xml = NULL, *net_xml = NULL, *dom_xml = NULL;
+char *xml = NULL;
 int hookret;
 int ret = -1;
 
@@ -227,12 +226,10 @@ networkRunHook(virNetworkObjPtr obj,
 
 virBufferAddLit(, "\n");
 virBufferAdjustIndent(, 2);
-if (iface && virDomainNetDefFormat(, iface, NULL, 0) < 0)
+if (port && virNetworkPortDefFormatBuf(, port) < 0)
 goto cleanup;
 if (virNetworkDefFormatBuf(, def, 0) < 0)
 goto cleanup;
-if (dom && virDomainDefFormatInternal(dom, NULL, 0, , NULL) < 0)
-goto cleanup;
 
 virBufferAdjustIndent(, -2);
 virBufferAddLit(, "");
@@ -257,8 +254,6 @@ networkRunHook(virNetworkObjPtr obj,
  cleanup:
 virBufferFreeAndReset();
 VIR_FREE(xml);
-VIR_FREE(net_xml);
-VIR_FREE(dom_xml);
 return ret;
 }
 
@@ -2847,7 +2842,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
 
 /* Run an early hook to set-up missing devices.
  * If the script raised an error abort the launch. */
-if (networkRunHook(obj, NULL, NULL,
+if (networkRunHook(obj, NULL,
VIR_HOOK_NETWORK_OP_START,
VIR_HOOK_SUBOP_BEGIN) < 0)
 goto cleanup;
@@ -2889,7 +2884,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
 }
 
 /* finally we can call the 'started' hook script if any */
-if (networkRunHook(obj, NULL, NULL,
+if (networkRunHook(obj, NULL,
VIR_HOOK_NETWORK_OP_STARTED,
VIR_HOOK_SUBOP_BEGIN) < 0)
 goto cleanup;
@@ -2973,7 +2968,7 @@ networkShutdownNetwork(virNetworkDriverStatePtr driver,
 }
 
 /* now that we know it's stopped call the hook if present */
-networkRunHook(obj, NULL, NULL, VIR_HOOK_NETWORK_OP_STOPPED,
+networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_STOPPED,
VIR_HOOK_SUBOP_END);
 
 virNetworkObjSetActive(obj, false);
@@ -3947,7 +3942,7 @@ networkUpdate(virNetworkPtr net,
 }
 
 /* call the 'updated' network hook script */
-if (networkRunHook(obj, NULL, NULL, VIR_HOOK_NETWORK_OP_UPDATED,
+if (networkRunHook(obj, NULL, VIR_HOOK_NETWORK_OP_UPDATED,
VIR_HOOK_SUBOP_BEGIN) < 0)
 goto cleanup;
 
@@ -4768,8 +4763,8 @@ networkAllocateActualDevice(virNetworkPtr net,
 if (dev)
 dev->connections++;
 /* finally we can call the 'plugged' hook script if any */
-if (networkRunHook(obj, dom, iface,
-   VIR_HOOK_NETWORK_OP_IFACE_PLUGGED,
+if (networkRunHook(obj, port,
+   VIR_HOOK_NETWORK_OP_PORT_CREATED,
VIR_HOOK_SUBOP_BEGIN) < 0) {
 /* adjust for failure */
 netdef->connections--;
@@ -5022,7 +5017,7 @@ networkNotifyActualDevice(virNetworkPtr net,
 if (dev)
 dev->connections++;
 /* finally we can call the 'plugged' hook script if any */
-if (networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_PLUGGED,
+if (networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_CREATED,
VIR_HOOK_SUBOP_BEGIN) < 0) {
 /* adjust for failure */
 if (dev)
@@ -5173,7 +5168,7 @@ networkReleaseActualDevice(virNetworkPtr net,
 if (dev)
 dev->connections--;
 /* finally we can call the 'unplugged' hook script if any */
-networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED,
+networkRunHook(obj, port, VIR_HOOK_NETWORK_OP_PORT_DELETED,
VIR_HOOK_SUBOP_BEGIN);
 networkLogAllocation(netdef, dev, >mac, false);
 
diff --git 

[libvirt] [PATCH 11/27] network: make networkLogAllocation independent of domain conf

2018-12-24 Thread Daniel P . Berrangé
Stop passing a virDomainNetDefPtr parameter to networkLogAllocation,
instead just pass in the MAC address. The actual device type is also not
required, since virNetworkForwardIfDefPtr has a type field that can be
used instad.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 1014b53201..8d1a1b95d2 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4392,32 +4392,29 @@ networkGetDHCPLeases(virNetworkPtr net,
 
 static void
 networkLogAllocation(virNetworkDefPtr netdef,
- virDomainNetType actualType,
  virNetworkForwardIfDefPtr dev,
- virDomainNetDefPtr iface,
+ virMacAddrPtr mac,
  bool inUse)
 {
 char macStr[VIR_MAC_STRING_BUFLEN];
 const char *verb = inUse ? "using" : "releasing";
 
+virMacAddrFormat(mac, macStr);
 if (!dev) {
 VIR_INFO("MAC %s %s network %s (%d connections)",
- virMacAddrFormat(>mac, macStr), verb,
- netdef->name, netdef->connections);
+ macStr, verb, netdef->name, netdef->connections);
 } else {
-if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+if (dev->type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
 VIR_INFO("MAC %s %s network %s (%d connections) "
  "physical device %04x:%02x:%02x.%x (%d connections)",
- virMacAddrFormat(>mac, macStr), verb,
- netdef->name, netdef->connections,
+ macStr, verb, netdef->name, netdef->connections,
  dev->device.pci.domain, dev->device.pci.bus,
  dev->device.pci.slot, dev->device.pci.function,
  dev->connections);
 } else {
 VIR_INFO("MAC %s %s network %s (%d connections) "
  "physical device %s (%d connections)",
- virMacAddrFormat(>mac, macStr), verb,
- netdef->name, netdef->connections,
+ macStr, verb, netdef->name, netdef->connections,
  dev->device.dev, dev->connections);
 }
 }
@@ -4826,7 +4823,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 dev->connections--;
 goto error;
 }
-networkLogAllocation(netdef, actualType, dev, iface, true);
+networkLogAllocation(netdef, dev, >mac, true);
 
 ret = 0;
 
@@ -5079,7 +5076,7 @@ networkNotifyActualDevice(virNetworkPtr net,
 netdef->connections--;
 goto error;
 }
-networkLogAllocation(netdef, actualType, dev, iface, true);
+networkLogAllocation(netdef, dev, >mac, true);
 
  cleanup:
 virNetworkObjEndAPI();
@@ -5246,7 +5243,7 @@ networkReleaseActualDevice(virNetworkPtr net,
 /* finally we can call the 'unplugged' hook script if any */
 networkRunHook(obj, dom, iface, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED,
VIR_HOOK_SUBOP_BEGIN);
-networkLogAllocation(netdef, actualType, dev, iface, false);
+networkLogAllocation(netdef, dev, >mac, false);
 }
 ret = 0;
  cleanup:
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 04/27] conf: simplify link from hostdev back to network device

2018-12-24 Thread Daniel P . Berrangé
hostdevs have a link back to the original network device. This is fairly
generic accepting any type of device, however, we don't intend to make
use of this approach in future. It can thus be specialized to network
devices.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c | 18 --
 src/conf/domain_conf.h |  8 +++-
 src/libxl/libxl_driver.c   |  4 ++--
 src/network/bridge_driver.c|  3 +--
 src/qemu/qemu_command.c|  3 +--
 src/qemu/qemu_domain_address.c |  4 ++--
 src/qemu/qemu_driver.c |  2 +-
 src/qemu/qemu_hotplug.c| 14 ++
 src/qemu/qemu_hotplug.h|  2 +-
 src/util/virhostdev.c  | 17 -
 10 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3320a03572..2181940144 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2614,7 +2614,7 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
 /* If there is a parent device object, it will handle freeing
  * def->info.
  */
-if (def->parent.type == VIR_DOMAIN_DEVICE_NONE)
+if (!def->parent)
 virDomainDeviceInfoFree(def->info);
 
 switch (def->mode) {
@@ -2685,7 +2685,7 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
 /* If there is a parent device object, it will handle freeing
  * the memory.
  */
-if (def->parent.type == VIR_DOMAIN_DEVICE_NONE)
+if (!def->parent)
 VIR_FREE(def);
 }
 
@@ -5061,7 +5061,7 @@ virDomainDefCollectBootOrder(virDomainDefPtr def 
ATTRIBUTE_UNUSED,
 return 0;
 
 if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
-dev->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE) {
+dev->data.hostdev->parent) {
 /* This hostdev is a child of a higher level device
  * (e.g. interface), and thus already being counted on the
  * list for the other device type.
@@ -5902,7 +5902,7 @@ virDomainDeviceDefValidateAliasesIterator(virDomainDefPtr 
def,
 return 0;
 
 if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
-dev->data.hostdev->parent.type == VIR_DOMAIN_DEVICE_NET) {
+dev->data.hostdev->parent) {
 /* This hostdev is a copy of some previous interface.
  * Aliases are duplicated. */
 return 0;
@@ -10842,8 +10842,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
 } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
 virDomainHostdevDefPtr hostdev = >data.hostdev.def;
 
-hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
-hostdev->parent.data.net = parent;
+hostdev->parent = parent;
 hostdev->info = >info;
 /* The helper function expects type to already be found and
  * passed in as a string, since it is in a different place in
@@ -11499,8 +11498,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
 
 case VIR_DOMAIN_NET_TYPE_HOSTDEV:
 hostdev = >data.hostdev.def;
-hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
-hostdev->parent.data.net = def;
+hostdev->parent = def;
 hostdev->info = >info;
 /* The helper function expects type to already be found and
  * passed in as a string, since it is in a different place in
@@ -28656,11 +28654,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 }
 
 for (n = 0; n < def->nhostdevs; n++) {
-/* If parent.type != NONE, this is just a pointer to the
+/* If parent != NONE, this is just a pointer to the
  * hostdev in a higher-level device (e.g. virDomainNetDef),
  * and will have already been formatted there.
  */
-if (def->hostdevs[n]->parent.type == VIR_DOMAIN_DEVICE_NONE &&
+if (!def->hostdevs[n]->parent &&
 virDomainHostdevDefFormat(buf, def->hostdevs[n], flags) < 0) {
 goto error;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e611457314..829d7cd83e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -444,7 +444,13 @@ struct _virDomainHostdevCaps {
 
 /* basic device for direct passthrough */
 struct _virDomainHostdevDef {
-virDomainDeviceDef parent; /* higher level Def containing this */
+/* If 'parent' is non-NULL it means this host dev was
+ * not originally present in the XML. It was copied from
+ * a network interface for convenience when handling
+ * hostdevs internally. This hostdev should never be
+ * visible to the user except as part of the interface
+ */
+virDomainNetDefPtr parent;
 
 int mode; /* enum virDomainHostdevMode */
 int startupPolicy; /* enum virDomainStartupPolicy */
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index faebb40d31..1690400db6 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -3921,9 +3921,9 @@ libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
 /* If 

[libvirt] [PATCH 15/27] network: convert networkNotifyActualDevice to virNetworkPortDef

2018-12-24 Thread Daniel P . Berrangé
Convert the virDomainNetDef object into a virNetworkPortDef object
at the start of networkNotifyActualDevice. This largely decouples
the method impl from the domain object type.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 127 +---
 1 file changed, 61 insertions(+), 66 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 594574db8c..109d284791 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4822,8 +4822,10 @@ networkNotifyActualDevice(virNetworkPtr net,
 virNetworkObjPtr obj;
 virNetworkDefPtr netdef;
 virNetworkForwardIfDefPtr dev = NULL;
+virNetworkPortDefPtr port = NULL;
 size_t i;
 char *master = NULL;
+bool useOVS = false;
 
 obj = virNetworkObjFindByName(driver->networks, net->name);
 if (!obj) {
@@ -4868,29 +4870,42 @@ networkNotifyActualDevice(virNetworkPtr net,
 actualType = VIR_DOMAIN_NET_TYPE_BRIDGE;
 }
 
-/* see if we're connected to the correct bridge */
-if (netdef->bridge) {
-bool useOVS = false;
+if (!(port = virDomainNetDefActualToNetworkPort(dom, iface)))
+goto cleanup;
+
+switch (port->plugtype) {
+case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly got a network port without a plug"));
+goto error;
 
-if (virNetDevGetMaster(iface->ifname, ) < 0)
+case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
+/* see if we're connected to the correct bridge */
+if (!netdef->bridge) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly got a network port plugged into a 
bridge"));
+goto error;
+}
+
+if (virNetDevGetMaster(port->plug.bridge.brname, ) < 0)
 goto error;
 
 /* IFLA_MASTER for a tap on an OVS switch is always "ovs-system" */
 if (STREQ_NULLABLE(master, "ovs-system")) {
 useOVS = true;
 VIR_FREE(master);
-if (virNetDevOpenvswitchInterfaceGetMaster(iface->ifname, ) 
< 0)
+if 
(virNetDevOpenvswitchInterfaceGetMaster(port->plug.bridge.brname, ) < 0)
 goto error;
 }
 
 if (STRNEQ_NULLABLE(netdef->bridge, master)) {
 /* disconnect from current (incorrect) bridge */
 if (master) {
-VIR_INFO("Removing %s from %s", iface->ifname, master);
+VIR_INFO("Removing %s from %s", port->plug.bridge.brname, 
master);
 if (useOVS)
-ignore_value(virNetDevOpenvswitchRemovePort(master, 
iface->ifname));
+ignore_value(virNetDevOpenvswitchRemovePort(master, 
port->plug.bridge.brname));
 else
-ignore_value(virNetDevBridgeRemovePort(master, 
iface->ifname));
+ignore_value(virNetDevBridgeRemovePort(master, 
port->plug.bridge.brname));
 }
 
 /* attach/reattach to correct bridge.
@@ -4898,51 +4913,28 @@ networkNotifyActualDevice(virNetworkPtr net,
  * so there is no point in trying to learn the actualMTU
  * (final arg to virNetDevTapAttachBridge())
  */
-VIR_INFO("Attaching %s to %s", iface->ifname, netdef->bridge);
-if (virNetDevTapAttachBridge(iface->ifname, netdef->bridge,
- >mac, dom->uuid,
- 
virDomainNetGetActualVirtPortProfile(iface),
- virDomainNetGetActualVlan(iface),
- iface->mtu, NULL) < 0) {
+VIR_INFO("Attaching %s to %s", port->plug.bridge.brname, 
netdef->bridge);
+/* XXX MTU is bad perhaps ? */
+if (virNetDevTapAttachBridge(port->plug.bridge.brname, 
netdef->bridge,
+ >mac, port->owneruuid,
+ port->virtPortProfile,
+ >vlan,
+ 0, NULL) < 0) {
 goto error;
 }
 }
-}
-
-if (!iface->data.network.actual ||
-(actualType != VIR_DOMAIN_NET_TYPE_DIRECT &&
- actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV)) {
-VIR_DEBUG("Nothing to claim from network %s", 
iface->data.network.name);
-goto success;
-}
-
-if (networkCreateInterfacePool(netdef) < 0)
-goto error;
-
-if (netdef->forward.nifs == 0) {
-virReportError(VIR_ERR_INTERNAL_ERROR,
-   _("network '%s' uses a direct or hostdev mode, "
- "but has no forward dev and no interface pool"),
-   netdef->name);
-goto error;
-}
-
-if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
-const 

[libvirt] [PATCH 03/27] network: pass a virNetworkPtr to port management APIs

2018-12-24 Thread Daniel P . Berrangé
The APIs for allocating/notifying/removing network ports just take
an internal domain interface struct right now. As a step towards
turning these into public facing APIs, add a virNetworkPtr argument
to all of them.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c  | 40 
 src/conf/domain_conf.h  | 18 +++
 src/libxl/libxl_domain.c| 30 +-
 src/libxl/libxl_driver.c| 26 +++-
 src/lxc/lxc_driver.c| 24 +++---
 src/lxc/lxc_process.c   | 27 ++--
 src/network/bridge_driver.c | 54 ++--
 src/qemu/qemu_hotplug.c | 62 +++--
 src/qemu/qemu_process.c | 30 +-
 9 files changed, 223 insertions(+), 88 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a3b539ccaa..3320a03572 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30473,37 +30473,65 @@ 
virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate,
 }
 
 int
-virDomainNetAllocateActualDevice(virDomainDefPtr dom,
+virDomainNetAllocateActualDevice(virConnectPtr conn,
+ virDomainDefPtr dom,
  virDomainNetDefPtr iface)
 {
+virNetworkPtr net = NULL;
+int ret = -1;
+
 if (!netAllocate) {
 virReportError(VIR_ERR_NO_SUPPORT, "%s",
_("Virtual networking driver is not available"));
 return -1;
 }
 
-return netAllocate(dom, iface);
+if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
+return -1;
+
+ret = netAllocate(net, dom, iface);
+
+virObjectUnref(net);
+return ret;
 }
 
 void
-virDomainNetNotifyActualDevice(virDomainDefPtr dom,
+virDomainNetNotifyActualDevice(virConnectPtr conn,
+   virDomainDefPtr dom,
virDomainNetDefPtr iface)
 {
+virNetworkPtr net = NULL;
+
 if (!netNotify)
 return;
 
-netNotify(dom, iface);
+if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
+return;
+
+netNotify(net, dom, iface);
+
+virObjectUnref(net);
 }
 
 
 int
-virDomainNetReleaseActualDevice(virDomainDefPtr dom,
+virDomainNetReleaseActualDevice(virConnectPtr conn,
+virDomainDefPtr dom,
 virDomainNetDefPtr iface)
 {
+virNetworkPtr net = NULL;
+int ret;
+
 if (!netRelease)
 return 0;
 
-return netRelease(dom, iface);
+if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
+return -1;
+
+ret = netRelease(net, dom, iface);
+
+virObjectUnref(net);
+return ret;
 }
 
 bool
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5814997bdb..e611457314 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3600,15 +3600,18 @@ virDomainDefLifecycleActionAllowed(virDomainLifecycle 
type,
virDomainLifecycleAction action);
 
 typedef int
-(*virDomainNetAllocateActualDeviceImpl)(virDomainDefPtr dom,
+(*virDomainNetAllocateActualDeviceImpl)(virNetworkPtr net,
+virDomainDefPtr dom,
 virDomainNetDefPtr iface);
 
 typedef void
-(*virDomainNetNotifyActualDeviceImpl)(virDomainDefPtr dom,
+(*virDomainNetNotifyActualDeviceImpl)(virNetworkPtr net,
+  virDomainDefPtr dom,
   virDomainNetDefPtr iface);
 
 typedef int
-(*virDomainNetReleaseActualDeviceImpl)(virDomainDefPtr dom,
+(*virDomainNetReleaseActualDeviceImpl)(virNetworkPtr net,
+   virDomainDefPtr dom,
virDomainNetDefPtr iface);
 
 typedef bool
@@ -3628,17 +3631,20 @@ 
virDomainNetSetDeviceImpl(virDomainNetAllocateActualDeviceImpl allocate,
   virDomainNetBandwidthUpdateImpl bandwidthUpdate);
 
 int
-virDomainNetAllocateActualDevice(virDomainDefPtr dom,
+virDomainNetAllocateActualDevice(virConnectPtr conn,
+ virDomainDefPtr dom,
  virDomainNetDefPtr iface)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 void
-virDomainNetNotifyActualDevice(virDomainDefPtr dom,
+virDomainNetNotifyActualDevice(virConnectPtr conn,
+   virDomainDefPtr dom,
virDomainNetDefPtr iface)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
 int
-virDomainNetReleaseActualDevice(virDomainDefPtr dom,
+virDomainNetReleaseActualDevice(virConnectPtr conn,
+virDomainDefPtr dom,
 virDomainNetDefPtr iface)
 ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
 
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 

[libvirt] [PATCH 08/27] network: unconditionally merge port profiles

2018-12-24 Thread Daniel P . Berrangé
All but one of the network types supports port profiles. Rather than
duplicating the code to merge profiles 3 times, do it once and then
later report an error if used from the wrong place.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 54 +++--
 1 file changed, 21 insertions(+), 33 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 822da7c6ac..8cb108ea46 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4528,6 +4528,18 @@ networkAllocateActualDevice(virNetworkPtr net,
iface->data.network.actual->trustGuestRxFilters
   = netdef->trustGuestRxFilters;
 
+/* merge virtualports from interface, network, and portgroup to
+ * arrive at actual virtualport to use
+ */
+if 
(virNetDevVPortProfileMerge3(>data.network.actual->virtPortProfile,
+iface->virtPortProfile,
+netdef->virtPortProfile,
+portgroup
+? portgroup->virtPortProfile : NULL) < 0) {
+goto error;
+}
+virtport = iface->data.network.actual->virtPortProfile;
+
 switch ((virNetworkForwardType) netdef->forward.type) {
 case VIR_NETWORK_FORWARD_NONE:
 case VIR_NETWORK_FORWARD_NAT:
@@ -4546,6 +4558,15 @@ networkAllocateActualDevice(virNetworkPtr net,
 iface->data.network.actual->data.bridge.macTableManager
= netdef->macTableManager;
 
+if (virtport) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _(" not supported for 
network "
+ "'%s' which uses IP forwarding"),
+   virNetDevVPortTypeToString(virtport->virtPortType),
+   netdef->name);
+goto error;
+}
+
 if (networkPlugBandwidth(obj, iface) < 0)
 goto error;
 break;
@@ -4598,17 +4619,6 @@ networkAllocateActualDevice(virNetworkPtr net,
 
iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.backend
 = backend;
 
-/* merge virtualports from interface, network, and portgroup to
- * arrive at actual virtualport to use
- */
-if 
(virNetDevVPortProfileMerge3(>data.network.actual->virtPortProfile,
-iface->virtPortProfile,
-netdef->virtPortProfile,
-portgroup
-? portgroup->virtPortProfile : NULL) < 
0) {
-goto error;
-}
-virtport = iface->data.network.actual->virtPortProfile;
 if (virtport) {
 /* make sure type is supported for hostdev connections */
 if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG &&
@@ -4638,17 +4648,6 @@ networkAllocateActualDevice(virNetworkPtr net,
 iface->data.network.actual->data.bridge.macTableManager
= netdef->macTableManager;
 
-/* merge virtualports from interface, network, and portgroup to
- * arrive at actual virtualport to use
- */
-if 
(virNetDevVPortProfileMerge3(>data.network.actual->virtPortProfile,
-iface->virtPortProfile,
-netdef->virtPortProfile,
-portgroup
-? portgroup->virtPortProfile : 
NULL) < 0) {
-goto error;
-}
-virtport = iface->data.network.actual->virtPortProfile;
 if (virtport) {
 /* only type='openvswitch' is allowed for bridges */
 if (virtport->virtPortType != 
VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
@@ -4687,17 +4686,6 @@ networkAllocateActualDevice(virNetworkPtr net,
 iface->data.network.actual->data.direct.mode =
 
virNetDevMacVLanModeTypeFromString(virNetworkForwardTypeToString(netdef->forward.type));
 
-/* merge virtualports from interface, network, and portgroup to
- * arrive at actual virtualport to use
- */
-if 
(virNetDevVPortProfileMerge3(>data.network.actual->virtPortProfile,
-iface->virtPortProfile,
-netdef->virtPortProfile,
-portgroup
-? portgroup->virtPortProfile : NULL) < 
0) {
-goto error;
-}
-virtport = iface->data.network.actual->virtPortProfile;
 if (virtport) {
 /* make sure type is supported for macvtap connections */
 if (virtport->virtPortType != VIR_NETDEV_VPORT_PROFILE_8021QBG &&
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com

[libvirt] [PATCH 13/27] conf: add APIs to convert virDomainNetDef to virNetworkPortDef

2018-12-24 Thread Daniel P . Berrangé
Helper APIs are needed to

 - Populate basic virNetworkPortDef from virDomainNetDef
 - Set a virDomainActualNetDef from virNetworkPortDef
 - Populate a full virNetworkPortDef from virDomainActualNetDef

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c   | 258 +++
 src/conf/domain_conf.h   |  17 +++
 src/libvirt_private.syms |   3 +
 3 files changed, 278 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2181940144..e384c60dfd 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -39,6 +39,7 @@
 #include "virbuffer.h"
 #include "virlog.h"
 #include "nwfilter_conf.h"
+#include "virnetworkportdef.h"
 #include "storage_conf.h"
 #include "virstoragefile.h"
 #include "virfile.h"
@@ -30449,6 +30450,263 @@ virDomainNetTypeSharesHostView(const virDomainNetDef 
*net)
 return false;
 }
 
+virNetworkPortDefPtr
+virDomainNetDefToNetworkPort(virDomainDefPtr dom,
+ virDomainNetDefPtr iface)
+{
+virNetworkPortDefPtr port;
+
+if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Expected an interface of type 'network' not '%s'"),
+   virDomainNetTypeToString(iface->type));
+return NULL;
+}
+
+if (VIR_ALLOC(port) < 0)
+return NULL;
+
+virUUIDGenerate(port->uuid);
+
+memcpy(port->owneruuid, dom->uuid, VIR_UUID_BUFLEN);
+if (VIR_STRDUP(port->ownername, dom->name) < 0)
+goto error;
+
+if (VIR_STRDUP(port->group, iface->data.network.portgroup) < 0)
+goto error;
+
+memcpy(>mac, >mac, VIR_MAC_BUFLEN);
+
+if (virNetDevVPortProfileCopy(>virtPortProfile, 
iface->virtPortProfile) < 0)
+goto error;
+
+if (virNetDevBandwidthCopy(>bandwidth, iface->bandwidth) < 0)
+goto error;
+
+if (virNetDevVlanCopy(>vlan, >vlan) < 0)
+goto error;
+
+port->trustGuestRxFilters = iface->trustGuestRxFilters;
+
+return port;
+
+ error:
+virNetworkPortDefFree(port);
+return NULL;
+}
+
+int
+virDomainNetDefActualFromNetworkPort(virDomainNetDefPtr iface,
+ virNetworkPortDefPtr port)
+{
+virDomainActualNetDefPtr actual = NULL;
+
+if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Expected an interface of type 'network' not '%s'"),
+   virDomainNetTypeToString(iface->type));
+return -1;
+}
+
+if (VIR_ALLOC(actual) < 0)
+return -1;
+
+switch ((virNetworkPortPlugType)port->plugtype) {
+case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
+if (VIR_STRDUP(actual->data.bridge.brname,
+   port->plug.bridge.brname) < 0)
+goto error;
+actual->data.bridge.macTableManager = 
port->plug.bridge.macTableManager;
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT:
+if (VIR_STRDUP(actual->data.direct.linkdev,
+   port->plug.direct.linkdev) < 0)
+goto error;
+actual->data.direct.mode = port->plug.direct.mode;
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI:
+actual->data.hostdev.def.parent = iface;
+actual->data.hostdev.def.info = >info;
+actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+actual->data.hostdev.def.managed = port->plug.hostdevpci.managed;
+actual->data.hostdev.def.source.subsys.type = 
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+actual->data.hostdev.def.source.subsys.u.pci.addr = 
port->plug.hostdevpci.addr;
+switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) 
{
+case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT:
+actual->data.hostdev.def.source.subsys.u.pci.backend =
+VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT;
+break;
+
+case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM:
+actual->data.hostdev.def.source.subsys.u.pci.backend =
+VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
+break;
+
+case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO:
+actual->data.hostdev.def.source.subsys.u.pci.backend =
+VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
+break;
+
+case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST:
+default:
+virReportEnumRangeError(virNetworkForwardDriverNameType,
+port->plug.hostdevpci.driver);
+goto error;
+}
+
+break;
+
+case VIR_NETWORK_PORT_PLUG_TYPE_LAST:
+default:
+virReportEnumRangeError(virNetworkPortPlugType, port->plugtype);
+goto error;
+}
+
+if (virNetDevVPortProfileCopy(>virtPortProfile, 
port->virtPortProfile) < 0)
+goto error;
+
+if (virNetDevBandwidthCopy(>bandwidth, 

[libvirt] [PATCH 06/27] network: use 'bridge' as actual type instead of 'network'

2018-12-24 Thread Daniel P . Berrangé
Ports allocated on virtual networks with type=nat|route|open all get
given an actual type of 'network'.

Only ports in networks with type=bridge use an actual type of 'bridge'.

This distinction makes little sense since the virtualization drivers
will treat both actual types in exactly the same way, as they're all
just bridge devices a VM needs to be connected to.

This doesn't affect user visible XML since the "actual" device XML
is internal only, but we need code to convert the data upgrades.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 2639b5ce61..822da7c6ac 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -4533,11 +4533,7 @@ networkAllocateActualDevice(virNetworkPtr net,
 case VIR_NETWORK_FORWARD_NAT:
 case VIR_NETWORK_FORWARD_ROUTE:
 case VIR_NETWORK_FORWARD_OPEN:
-/* for these forward types, the actual net type really *is*
- * NETWORK; we just keep the info from the portgroup in
- * iface->data.network.actual
- */
-iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
+iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
 
 /* we also store the bridge device and macTableManager settings
  * in iface->data.network.actual->data.bridge for later use
@@ -4905,12 +4901,21 @@ networkNotifyActualDevice(virNetworkPtr net,
  * actualType==network, we need to copy it in so that it will be
  * available in all cases
  */
-if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK &&
+if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
 !iface->data.network.actual->data.bridge.brname &&
 (VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
 netdef->bridge) < 0))
 goto error;
 
+/* Older libvirtd uses actualType==network, but we now
+ * just use actualType==bridge, as nothing needs to
+ * distinguish the two cases, and this simplifies virt
+ * drive code */
+if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
+iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+actualType = VIR_DOMAIN_NET_TYPE_BRIDGE;
+}
+
 /* see if we're connected to the correct bridge */
 if (netdef->bridge) {
 bool useOVS = false;
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 07/27] virt drivers: don't handle type=network after resolving actual network type

2018-12-24 Thread Daniel P . Berrangé
The call to resolve the actual network type will turn any NICs with
type=network into one of the other types. Thus there should be no need
to handle type=network in later switch() statements jumping off the
actual type.

Signed-off-by: Daniel P. Berrangé 
---
 src/libxl/libxl_conf.c| 21 +++--
 src/lxc/lxc_driver.c  | 15 +++
 src/qemu/qemu_command.c   |  8 ++--
 src/qemu/qemu_hotplug.c   | 13 +++--
 src/qemu/qemu_interface.c | 12 ++--
 src/qemu/qemu_process.c   |  5 -
 6 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 73e988a3dc..e7d0480b34 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -1341,25 +1341,10 @@ libxlMakeNic(virDomainDefPtr def,
 }
 break;
 case VIR_DOMAIN_NET_TYPE_NETWORK:
-{
-if (!(conn = virConnectOpen("xen:///system")))
-goto cleanup;
-
-if (!(network =
-  virNetworkLookupByName(conn, l_nic->data.network.name))) {
-goto cleanup;
-}
-
-if (l_nic->guestIP.nips > 0) {
-x_nic->ip = xenMakeIPList(_nic->guestIP);
-if (!x_nic->ip)
-goto cleanup;
-}
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly found type=network for actual NIC 
type"));
+goto cleanup;
 
-if (!(x_nic->bridge = virNetworkGetBridgeName(network)))
-goto cleanup;
-break;
-}
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
 case VIR_DOMAIN_NET_TYPE_USER:
 case VIR_DOMAIN_NET_TYPE_SERVER:
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index f4138a0e10..6162c05c46 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -3881,8 +3881,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
 actualType = virDomainNetGetActualType(net);
 
 switch (actualType) {
-case VIR_DOMAIN_NET_TYPE_BRIDGE:
-case VIR_DOMAIN_NET_TYPE_NETWORK: {
+case VIR_DOMAIN_NET_TYPE_BRIDGE: {
 const char *brname = virDomainNetGetActualBridgeName(net);
 if (!brname) {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -3900,6 +3899,10 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
 if (!(veth = virLXCProcessSetupInterfaceDirect(conn, vm->def, net)))
 goto cleanup;
 }   break;
+case VIR_DOMAIN_NET_TYPE_NETWORK:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly found type=network for actual NIC 
type"));
+goto cleanup;
 case VIR_DOMAIN_NET_TYPE_USER:
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
 case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -3945,7 +3948,6 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
 } else if (veth) {
 switch (actualType) {
 case VIR_DOMAIN_NET_TYPE_BRIDGE:
-case VIR_DOMAIN_NET_TYPE_NETWORK:
 case VIR_DOMAIN_NET_TYPE_ETHERNET:
 ignore_value(virNetDevVethDelete(veth));
 break;
@@ -3954,6 +3956,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
 ignore_value(virNetDevMacVLanDelete(veth));
 break;
 
+case VIR_DOMAIN_NET_TYPE_NETWORK:
 case VIR_DOMAIN_NET_TYPE_USER:
 case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
 case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -4385,7 +4388,6 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
 
 switch (actualType) {
 case VIR_DOMAIN_NET_TYPE_BRIDGE:
-case VIR_DOMAIN_NET_TYPE_NETWORK:
 case VIR_DOMAIN_NET_TYPE_ETHERNET:
 if (virNetDevVethDelete(detach->ifname) < 0) {
 virDomainAuditNet(vm, detach, NULL, "detach", false);
@@ -4393,6 +4395,11 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
 }
 break;
 
+case VIR_DOMAIN_NET_TYPE_NETWORK:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly found type=network for actual NIC 
type"));
+goto cleanup;
+
 /* It'd be nice to support this, but with macvlan
  * once assigned to a container nothing exists on
  * the host side. Further the container can change
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8bce416d83..b9274e5a81 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8527,7 +8527,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
 }
 
 switch (actualType) {
-case VIR_DOMAIN_NET_TYPE_NETWORK:
 case VIR_DOMAIN_NET_TYPE_BRIDGE:
 tapfdSize = net->driver.virtio.queues;
 if (!tapfdSize)
@@ -8605,6 +8604,11 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
 
 break;
 
+case VIR_DOMAIN_NET_TYPE_NETWORK:
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+   _("Unexpectedly found type=network for actual NIC 
type"));
+  

[libvirt] [PATCH 02/27] network: restrict usage of port management APIs

2018-12-24 Thread Daniel P . Berrangé
The port allocation APIs are currently called unconditionally for all
types of NIC, but (mostly) only do anything for NICs with type=network.

The exception is the port allocate API which does some validation even
for NICs with type!=network. Relying on this validation is flawed,
however, since the network driver may not even be installed. IOW virt
drivers must not delegate validation to the network driver for NICs
with type != network.

This change allows us to report errors when the virtual network driver
is not registered.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/domain_conf.c  | 12 +++
 src/libxl/libxl_domain.c|  6 ++--
 src/libxl/libxl_driver.c|  9 +++--
 src/lxc/lxc_driver.c|  6 ++--
 src/lxc/lxc_process.c   | 10 --
 src/network/bridge_driver.c | 66 ++---
 src/qemu/qemu_hotplug.c | 17 ++
 src/qemu/qemu_process.c |  9 +++--
 8 files changed, 76 insertions(+), 59 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 706ee361ff..a3b539ccaa 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30476,13 +30476,11 @@ int
 virDomainNetAllocateActualDevice(virDomainDefPtr dom,
  virDomainNetDefPtr iface)
 {
-/* Just silently ignore if network driver isn't present. If something
- * has tried to use a NIC with type=network, other code will already
- * cause an error. This ensures type=bridge doesn't break when
- * network driver is compiled out.
- */
-if (!netAllocate)
-return 0;
+if (!netAllocate) {
+virReportError(VIR_ERR_NO_SUPPORT, "%s",
+   _("Virtual networking driver is not available"));
+return -1;
+}
 
 return netAllocate(dom, iface);
 }
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 3ada51f517..e595e552b0 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -898,7 +898,8 @@ libxlDomainCleanup(libxlDriverPrivatePtr driver,
 
 /* cleanup actual device */
 virDomainNetRemoveHostdev(vm->def, net);
-virDomainNetReleaseActualDevice(vm->def, net);
+if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK)
+virDomainNetReleaseActualDevice(vm->def, net);
 }
 }
 
@@ -1055,7 +1056,8 @@ libxlNetworkPrepareDevices(virDomainDefPtr def)
  * network's pool of devices, or resolve bridge device name
  * to the one defined in the network definition.
  */
-if (virDomainNetAllocateActualDevice(def, net) < 0)
+if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+virDomainNetAllocateActualDevice(def, net) < 0)
 return -1;
 
 actualType = virDomainNetGetActualType(net);
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 3d03e7320a..d702873892 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -3396,7 +3396,8 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
  * network's pool of devices, or resolve bridge device name
  * to the one defined in the network definition.
  */
-if (virDomainNetAllocateActualDevice(vm->def, net) < 0)
+if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+virDomainNetAllocateActualDevice(vm->def, net) < 0)
 goto cleanup;
 
 actualType = virDomainNetGetActualType(net);
@@ -3446,7 +3447,8 @@ libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
 vm->def->nets[vm->def->nnets++] = net;
 } else {
 virDomainNetRemoveHostdev(vm->def, net);
-virDomainNetReleaseActualDevice(vm->def, net);
+if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK)
+virDomainNetReleaseActualDevice(vm->def, net);
 }
 virObjectUnref(cfg);
 return ret;
@@ -3869,7 +3871,8 @@ libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
  cleanup:
 libxl_device_nic_dispose();
 if (!ret) {
-virDomainNetReleaseActualDevice(vm->def, detach);
+if (detach->type == VIR_DOMAIN_NET_TYPE_NETWORK)
+virDomainNetReleaseActualDevice(vm->def, detach);
 virDomainNetRemove(vm->def, detachidx);
 }
 virObjectUnref(cfg);
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index de045c80bb..a5eaf12ce1 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -3867,7 +3867,8 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
  * network's pool of devices, or resolve bridge device name
  * to the one defined in the network definition.
  */
-if (virDomainNetAllocateActualDevice(vm->def, net) < 0)
+if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+virDomainNetAllocateActualDevice(vm->def, net) < 0)
 return -1;
 
 actualType = virDomainNetGetActualType(net);
@@ -4421,7 +4422,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
 ret = 0;
  cleanup:
 if (!ret) {
-

[libvirt] [PATCH 05/27] network: add missing bandwidth limits for bridge forward type

2018-12-24 Thread Daniel P . Berrangé
In the case of a network with forward=bridge, which has a bridge device
listed, we are capable of setting bandwidth limits but fail to call the
function to register them.

Signed-off-by: Daniel P. Berrangé 
---
 src/network/bridge_driver.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index b5aac9350b..2639b5ce61 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -3374,7 +3374,13 @@ networkValidate(virNetworkDriverStatePtr driver,
virNetworkForwardTypeToString(def->forward.type));
 return -1;
 }
-if (def->bandwidth) {
+
+bandwidthAllowed = (
+def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
+def->bridge != NULL);
+
+if (def->bandwidth &&
+!bandwidthAllowed) {
 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported network-wide  element "
  "in network %s with forward mode='%s'"),
@@ -3382,7 +3388,6 @@ networkValidate(virNetworkDriverStatePtr driver,
virNetworkForwardTypeToString(def->forward.type));
 return -1;
 }
-bandwidthAllowed = false;
 break;
 
 case VIR_NETWORK_FORWARD_LAST:
@@ -4659,6 +4664,9 @@ networkAllocateActualDevice(virNetworkPtr net,
 goto error;
 }
 }
+
+if (networkPlugBandwidth(obj, iface) < 0)
+goto error;
 break;
 }
 
@@ -5133,6 +5141,11 @@ networkReleaseActualDevice(virNetworkPtr net,
 break;
 
 case VIR_NETWORK_FORWARD_BRIDGE:
+if (iface->data.network.actual &&
+actualType == VIR_DOMAIN_NET_TYPE_BRIDGE &&
+networkUnplugBandwidth(obj, iface) < 0)
+goto error;
+break;
 case VIR_NETWORK_FORWARD_PRIVATE:
 case VIR_NETWORK_FORWARD_VEPA:
 case VIR_NETWORK_FORWARD_PASSTHROUGH:
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH 00/27] network: refactor to decouple virt drivers from network driver

2018-12-24 Thread Daniel P . Berrangé
Currently the network driver registers a set of callbacks with the virt
driver in order to handle allocating/releasing network ports associated
with guest NICs.

This series introduces a virNetworkPortPtr object and associated XML
that describes a network port. The virt drivers now call public APIs
associated with this new object to create/delete ports for guest NICs.

There are some parts that are not yet addressed by this series

 - The live updating of bandwidth limits on network ports
 - The old code would re-connect VIFs to bridges, and/or change
   bridges during startup. This code is deleted right now as it
   doesn't belong in the network driver. It needs to move to the
   virt drivers in some (to be determined) manner.

Daniel P. Berrangé (27):
  conf: make virPCIDeviceAddressFormat void
  network: restrict usage of port management APIs
  network: pass a virNetworkPtr to port management APIs
  conf: simplify link from hostdev back to network device
  network: add missing bandwidth limits for bridge forward type
  network: use 'bridge' as actual type instead of 'network'
  virt drivers: don't handle type=network after resolving actual network
type
  network: unconditionally merge port profiles
  conf: introduce virNetworkPortDefPtr struct and XML support
  network: stop passing virDomainNetDefPtr into bandwidth functions
  network: make networkLogAllocation independent of domain conf
  util: add API for copying virtual port profile data
  conf: add APIs to convert virDomainNetDef to virNetworkPortDef
  network: convert networkAllocateActualDevice to virNetworkPortDef
  network: convert networkNotifyActualDevice to virNetworkPortDef
  network: convert networkReleaseActualDevice to virNetworkPortDef
  network: convert hook script to take a network port XML
  network: introduce networkAllocatePort
  network: introduce networkNotifyPort
  network: introduce networkReleasePort
  network: add public APIs for network port object
  access: add permissions for network port objects
  remote: add support for new network port APIs
  virsh: add support for network port APIs
  conf: support recording ports against virNetworkObjPtr
  network: add implementation of network port APIs
  conf: switch over to use network port APIs for virt drivers

 include/libvirt/libvirt-network.h |   49 +
 include/libvirt/virterror.h   |3 +
 src/access/genpolkit.pl   |2 +-
 src/access/viraccessdriver.h  |6 +
 src/access/viraccessdrivernop.c   |   11 +
 src/access/viraccessdriverpolkit.c|   26 +
 src/access/viraccessdriverstack.c |   25 +
 src/access/viraccessmanager.c |   16 +
 src/access/viraccessmanager.h |6 +
 src/access/viraccessperm.c|8 +-
 src/access/viraccessperm.h|   38 +
 src/conf/Makefile.inc.am  |2 +
 src/conf/device_conf.c|3 +-
 src/conf/device_conf.h|6 +-
 src/conf/domain_conf.c|  413 ++-
 src/conf/domain_conf.h|   46 +-
 src/conf/network_conf.c   |7 +-
 src/conf/storage_adapter_conf.c   |4 +-
 src/conf/virnetworkobj.c  |  303 +
 src/conf/virnetworkobj.h  |   30 +
 src/conf/virnetworkportdef.c  |  497 
 src/conf/virnetworkportdef.h  |  112 ++
 src/datatypes.c   |   60 +
 src/datatypes.h   |   41 +
 src/driver-network.h  |   27 +
 src/libvirt-network.c |  351 ++
 src/libvirt_private.syms  |   21 +
 src/libvirt_public.syms   |   14 +
 src/libxl/libxl_conf.c|   21 +-
 src/libxl/libxl_domain.c  |   28 +-
 src/libxl/libxl_driver.c  |   27 +-
 src/lxc/lxc_driver.c  |   37 +-
 src/lxc/lxc_process.c |   21 +-
 src/network/bridge_driver.c   | 1069 +
 src/qemu/qemu_command.c   |   11 +-
 src/qemu/qemu_domain_address.c|4 +-
 src/qemu/qemu_driver.c|2 +-
 src/qemu/qemu_hotplug.c   |   84 +-
 src/qemu/qemu_hotplug.h   |2 +-
 src/qemu/qemu_interface.c |   12 +-
 src/qemu/qemu_process.c   |   32 +-
 src/remote/remote_daemon_dispatch.c   |   25 +
 src/remote/remote_driver.c|   28 +
 src/remote/remote_protocol.x  |   89 +-
 src/remote_protocol-structs   |   47 +
 src/rpc/gendispatch.pl|   18 +-
 src/util/virerror.c   |9 +
 src/util/virhook.c   

[libvirt] [PATCH 01/27] conf: make virPCIDeviceAddressFormat void

2018-12-24 Thread Daniel P . Berrangé
Only one of the three callers of virPCIDeviceAddressFormat correctly
handles an error return status. Fortunately it can't fail so can be
made void.

Signed-off-by: Daniel P. Berrangé 
---
 src/conf/device_conf.c  | 3 +--
 src/conf/device_conf.h  | 6 +++---
 src/conf/domain_conf.c  | 6 ++
 src/conf/network_conf.c | 7 +++
 src/conf/storage_adapter_conf.c | 4 ++--
 5 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index 32628c6448..cd994057c5 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -308,7 +308,7 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
 return ret;
 }
 
-int
+void
 virPCIDeviceAddressFormat(virBufferPtr buf,
   virPCIDeviceAddress addr,
   bool includeTypeInAddr)
@@ -320,7 +320,6 @@ virPCIDeviceAddressFormat(virBufferPtr buf,
   addr.bus,
   addr.slot,
   addr.function);
-return 0;
 }
 
 bool
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 56745707d9..7a3455f99f 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -202,9 +202,9 @@ bool virDeviceInfoPCIAddressExtensionIsPresent(const 
virDomainDeviceInfo *info);
 int virPCIDeviceAddressParseXML(xmlNodePtr node,
 virPCIDeviceAddressPtr addr);
 
-int virPCIDeviceAddressFormat(virBufferPtr buf,
-  virPCIDeviceAddress addr,
-  bool includeTypeInAddr);
+void virPCIDeviceAddressFormat(virBufferPtr buf,
+   virPCIDeviceAddress addr,
+   bool includeTypeInAddr);
 
 bool virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr);
 int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d8dfd1656f..706ee361ff 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -24809,10 +24809,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
 }
 break;
 case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
-if (virPCIDeviceAddressFormat(buf, pcisrc->addr,
-  includeTypeInAddr) != 0)
-virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-   _("PCI address Formatting failed"));
+virPCIDeviceAddressFormat(buf, pcisrc->addr,
+  includeTypeInAddr);
 
 if ((flags & VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES) &&
 (def->origstates.states.pci.unbind_from_stub ||
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index e035d8aba7..3e2d6dc756 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2471,10 +2471,9 @@ virNetworkDefFormatBuf(virBufferPtr buf,
 virBufferAddLit(buf, "/>\n");
 } else {
 if (def->forward.ifs[i].type ==  
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
-if (virPCIDeviceAddressFormat(buf,
-  
def->forward.ifs[i].device.pci,
-  true) < 0)
-goto error;
+virPCIDeviceAddressFormat(buf,
+  
def->forward.ifs[i].device.pci,
+  true);
 }
 }
 }
diff --git a/src/conf/storage_adapter_conf.c b/src/conf/storage_adapter_conf.c
index f333ae16ff..65d664b89b 100644
--- a/src/conf/storage_adapter_conf.c
+++ b/src/conf/storage_adapter_conf.c
@@ -325,8 +325,8 @@ virStorageAdapterFormatSCSIHost(virBufferPtr buf,
 virBufferAsprintf(buf, "\n",
   scsi_host->unique_id);
 virBufferAdjustIndent(buf, 2);
-ignore_value(virPCIDeviceAddressFormat(buf, scsi_host->parentaddr,
-   false));
+virPCIDeviceAddressFormat(buf, scsi_host->parentaddr,
+  false);
 virBufferAdjustIndent(buf, -2);
 virBufferAddLit(buf, "\n");
 virBufferAdjustIndent(buf, -2);
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v3 RESEND] qemu: Process RDMA GID state change event

2018-12-24 Thread Yuval Shaia
This event is emitted on the monitor when a GID table in pvrdma device
is modified and the change needs to be propagate to the backend RDMA
device's GID table.

The control over the RDMA device's GID table is done by updating the
device's Ethernet function addresses.
Usually the first GID entry is determine by the MAC address, the second
by the first IPv6 address and the third by the IPv4 address. Other
entries can be added by adding more IP addresses. The opposite is the
same, i.e. whenever an address is removed, the corresponding GID entry
is removed.

The process is done by the network and RDMA stacks. Whenever an address
is added the ib_core driver is notified and calls the device driver's
add_gid function which in turn update the device.

To support this in pvrdma device we need to hook into the create_bind
and destroy_bind HW commands triggered by pvrdma driver in guest.
Whenever a changed is made to the pvrdma device's GID table a special
QMP messages is sent to be processed by libvirt to update the address of
the backend Ethernet device.

Signed-off-by: Yuval Shaia 
---
(fixing mail subject from v2 to v3, rest is the same)
Hi,

Corresponding qemu commit was merged to master as part of the following
patch-set:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg583387.html

Appreciate if this patch can be reviewed and merged as well.

Thanks,
Yuval

v1 -> v2:
* Address all comments from Michal Privoznik

v2 -> v3:
* Remove static initialization in processRdmaGidStatusChangedEvent
---
 src/qemu/qemu_domain.c   |  3 +++
 src/qemu/qemu_domain.h   |  1 +
 src/qemu/qemu_driver.c   | 44 ++
 src/qemu/qemu_monitor.c  | 27 +++
 src/qemu/qemu_monitor.h  | 27 +++
 src/qemu/qemu_monitor_json.c | 36 +
 src/qemu/qemu_process.c  | 52 
 7 files changed, 190 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ba3fff607a..8da54c7ee9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13479,6 +13479,9 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
 case QEMU_PROCESS_EVENT_GUESTPANIC:
 qemuMonitorEventPanicInfoFree(event->data);
 break;
+case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+qemuMonitorEventRdmaGidStatusFree(event->data);
+break;
 case QEMU_PROCESS_EVENT_WATCHDOG:
 case QEMU_PROCESS_EVENT_DEVICE_DELETED:
 case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 80bd4bde91..64bceb9a98 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -487,6 +487,7 @@ typedef enum {
 QEMU_PROCESS_EVENT_BLOCK_JOB,
 QEMU_PROCESS_EVENT_MONITOR_EOF,
 QEMU_PROCESS_EVENT_PR_DISCONNECT,
+QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
 
 QEMU_PROCESS_EVENT_LAST
 } qemuProcessEventType;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a52e2495d5..5c6ab3c0ea 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4788,6 +4788,47 @@ processPRDisconnectEvent(virDomainObjPtr vm)
 }
 
 
+static void
+processRdmaGidStatusChangedEvent(virDomainObjPtr vm,
+ qemuMonitorRdmaGidStatusChangedPrivatePtr 
info)
+{
+unsigned int prefix_len;
+virSocketAddr addr;
+int rc;
+
+if (!virDomainObjIsActive(vm))
+return;
+
+
VIR_DEBUG("netdev=%s,gid_status=%d,subnet_prefix=0x%llx,interface_id=0x%llx",
+  info->netdev, info->gid_status, info->subnet_prefix,
+  info->interface_id);
+
+if (info->subnet_prefix) {
+prefix_len = 64;
+uint32_t ipv6[4];
+memcpy([0], >subnet_prefix, sizeof(info->subnet_prefix));
+memcpy([2], >interface_id, sizeof(info->interface_id));
+virSocketAddrSetIPv6AddrNetOrder(, ipv6);
+} else {
+prefix_len = 24;
+virSocketAddrSetIPv4AddrNetOrder(, info->interface_id >> 32);
+}
+
+if (info->gid_status) {
+VIR_DEBUG("Adding %s to %s", virSocketAddrFormat(), info->netdev);
+rc = virNetDevIPAddrAdd(info->netdev, , NULL, prefix_len);
+} else {
+VIR_DEBUG("Removing %s from %s", virSocketAddrFormat(),
+  info->netdev);
+rc = virNetDevIPAddrDel(info->netdev, , prefix_len);
+}
+
+if (rc < 0)
+VIR_WARN("Fail to update address %s to %s", virSocketAddrFormat(),
+ info->netdev);
+}
+
+
 static void qemuProcessEventHandler(void *data, void *opaque)
 {
 struct qemuProcessEvent *processEvent = data;
@@ -4828,6 +4869,9 @@ static void qemuProcessEventHandler(void *data, void 
*opaque)
 case QEMU_PROCESS_EVENT_PR_DISCONNECT:
 processPRDisconnectEvent(vm);
 break;
+case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+processRdmaGidStatusChangedEvent(vm, processEvent->data);
+break;
 case 

[libvirt] [PATCH v2 RESEND] qemu: Process RDMA GID state change event

2018-12-24 Thread Yuval Shaia
This event is emitted on the monitor when a GID table in pvrdma device
is modified and the change needs to be propagate to the backend RDMA
device's GID table.

The control over the RDMA device's GID table is done by updating the
device's Ethernet function addresses.
Usually the first GID entry is determine by the MAC address, the second
by the first IPv6 address and the third by the IPv4 address. Other
entries can be added by adding more IP addresses. The opposite is the
same, i.e. whenever an address is removed, the corresponding GID entry
is removed.

The process is done by the network and RDMA stacks. Whenever an address
is added the ib_core driver is notified and calls the device driver's
add_gid function which in turn update the device.

To support this in pvrdma device we need to hook into the create_bind
and destroy_bind HW commands triggered by pvrdma driver in guest.
Whenever a changed is made to the pvrdma device's GID table a special
QMP messages is sent to be processed by libvirt to update the address of
the backend Ethernet device.

Signed-off-by: Yuval Shaia 
---
Hi,
Corresponding qemu commit was merged to master as part of the following
patch-set:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg583387.html

Appreciate if this patch can be reviewed and merged as well.

Thanks,
Yuval

v1 -> v2:
* Address all comments from Michal Privoznik

v2 -> v3:
* Remove static initialization in processRdmaGidStatusChangedEvent
---
 src/qemu/qemu_domain.c   |  3 +++
 src/qemu/qemu_domain.h   |  1 +
 src/qemu/qemu_driver.c   | 44 ++
 src/qemu/qemu_monitor.c  | 27 +++
 src/qemu/qemu_monitor.h  | 27 +++
 src/qemu/qemu_monitor_json.c | 36 +
 src/qemu/qemu_process.c  | 52 
 7 files changed, 190 insertions(+)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index ba3fff607a..8da54c7ee9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13479,6 +13479,9 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
 case QEMU_PROCESS_EVENT_GUESTPANIC:
 qemuMonitorEventPanicInfoFree(event->data);
 break;
+case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+qemuMonitorEventRdmaGidStatusFree(event->data);
+break;
 case QEMU_PROCESS_EVENT_WATCHDOG:
 case QEMU_PROCESS_EVENT_DEVICE_DELETED:
 case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 80bd4bde91..64bceb9a98 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -487,6 +487,7 @@ typedef enum {
 QEMU_PROCESS_EVENT_BLOCK_JOB,
 QEMU_PROCESS_EVENT_MONITOR_EOF,
 QEMU_PROCESS_EVENT_PR_DISCONNECT,
+QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
 
 QEMU_PROCESS_EVENT_LAST
 } qemuProcessEventType;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a52e2495d5..5c6ab3c0ea 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4788,6 +4788,47 @@ processPRDisconnectEvent(virDomainObjPtr vm)
 }
 
 
+static void
+processRdmaGidStatusChangedEvent(virDomainObjPtr vm,
+ qemuMonitorRdmaGidStatusChangedPrivatePtr 
info)
+{
+unsigned int prefix_len;
+virSocketAddr addr;
+int rc;
+
+if (!virDomainObjIsActive(vm))
+return;
+
+
VIR_DEBUG("netdev=%s,gid_status=%d,subnet_prefix=0x%llx,interface_id=0x%llx",
+  info->netdev, info->gid_status, info->subnet_prefix,
+  info->interface_id);
+
+if (info->subnet_prefix) {
+prefix_len = 64;
+uint32_t ipv6[4];
+memcpy([0], >subnet_prefix, sizeof(info->subnet_prefix));
+memcpy([2], >interface_id, sizeof(info->interface_id));
+virSocketAddrSetIPv6AddrNetOrder(, ipv6);
+} else {
+prefix_len = 24;
+virSocketAddrSetIPv4AddrNetOrder(, info->interface_id >> 32);
+}
+
+if (info->gid_status) {
+VIR_DEBUG("Adding %s to %s", virSocketAddrFormat(), info->netdev);
+rc = virNetDevIPAddrAdd(info->netdev, , NULL, prefix_len);
+} else {
+VIR_DEBUG("Removing %s from %s", virSocketAddrFormat(),
+  info->netdev);
+rc = virNetDevIPAddrDel(info->netdev, , prefix_len);
+}
+
+if (rc < 0)
+VIR_WARN("Fail to update address %s to %s", virSocketAddrFormat(),
+ info->netdev);
+}
+
+
 static void qemuProcessEventHandler(void *data, void *opaque)
 {
 struct qemuProcessEvent *processEvent = data;
@@ -4828,6 +4869,9 @@ static void qemuProcessEventHandler(void *data, void 
*opaque)
 case QEMU_PROCESS_EVENT_PR_DISCONNECT:
 processPRDisconnectEvent(vm);
 break;
+case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+processRdmaGidStatusChangedEvent(vm, processEvent->data);
+break;
 case QEMU_PROCESS_EVENT_LAST:
 break;
 }
diff --git