[libvirt] [PATCH 0/4] enable s390 support for crypto key mgmt operations

2015-04-27 Thread akrowiak
From: Tony Krowiak 

The IBM System z Central Processor Assist for Cryptographic Functions (CPACF)
hardware provides a set of CPU instructions for use in clear-key encryption,
pseudo random number generation, hash functions, and protected-key encryption.
The CPACF protected key cryptographic functions operate with a protected key
that is encrypted under a unique wrapping key stored in the Hardware
System Area (HSA) of the machine and can only be accessed by firmware. The
wrapping key cannot be accessed by the operating system or application
programs. There are two wrapping keys: One for wrapping AES keys and one for
wrapping DEA/TDEA (DES/TDES) keys. This patch set enables the support for 
encrypting clear keys under the AES or DEA/TDEA wrapping key on a guest VM 
running on an s390 host that supports key wrapping.  

Tony Krowiak (4):
  libvirt: docs: XML to enable/disable protected key mgmt ops
  libvirt: conf: parse XML for protected key management ops
  libvirt: qemu: enable/disable protected key management ops
  libvirt: tests: test protected key mgmt ops support

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


[libvirt] [PATCH 4/4] libvirt: tests: test protected key mgmt ops support

2015-04-27 Thread akrowiak
From: Tony Krowiak 

Test the support for enabling/disabling CPACF protected key management
operations for a guest.

Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Reviewed-by: Boris Fiuczynski 
---
 src/qemu/qemu_capabilities.c   |9 ++
 src/qemu/qemu_capabilities.h   |2 +
 tests/qemuargv2xmltest.c   |6 +
 .../qemuxml2argv-machine-aeskeywrap-off-argv.args  |6 +
 .../qemuxml2argv-machine-aeskeywrap-off-argv.xml   |   27 
 .../qemuxml2argv-machine-aeskeywrap-off-cap.args   |7 +
 .../qemuxml2argv-machine-aeskeywrap-off-cap.xml|   28 +
 .../qemuxml2argv-machine-aeskeywrap-off-caps.args  |7 +
 .../qemuxml2argv-machine-aeskeywrap-off-caps.xml   |   28 +
 .../qemuxml2argv-machine-aeskeywrap-on-argv.args   |6 +
 .../qemuxml2argv-machine-aeskeywrap-on-argv.xml|   27 
 .../qemuxml2argv-machine-aeskeywrap-on-cap.args|7 +
 .../qemuxml2argv-machine-aeskeywrap-on-cap.xml |   28 +
 .../qemuxml2argv-machine-aeskeywrap-on-caps.args   |7 +
 .../qemuxml2argv-machine-aeskeywrap-on-caps.xml|   27 
 .../qemuxml2argv-machine-deakeywrap-off-argv.args  |6 +
 .../qemuxml2argv-machine-deakeywrap-off-argv.xml   |   27 
 .../qemuxml2argv-machine-deakeywrap-off-cap.args   |7 +
 .../qemuxml2argv-machine-deakeywrap-off-cap.xml|   28 +
 .../qemuxml2argv-machine-deakeywrap-off-caps.args  |7 +
 .../qemuxml2argv-machine-deakeywrap-off-caps.xml   |   28 +
 .../qemuxml2argv-machine-deakeywrap-on-argv.args   |6 +
 .../qemuxml2argv-machine-deakeywrap-on-argv.xml|   27 
 .../qemuxml2argv-machine-deakeywrap-on-cap.args|7 +
 .../qemuxml2argv-machine-deakeywrap-on-cap.xml |   28 +
 .../qemuxml2argv-machine-deakeywrap-on-caps.args   |7 +
 .../qemuxml2argv-machine-deakeywrap-on-caps.xml|   28 +
 .../qemuxml2argv-machine-keywrap-none-argv.args|6 +
 .../qemuxml2argv-machine-keywrap-none-argv.xml |   24 
 .../qemuxml2argv-machine-keywrap-none-caps.args|7 +
 .../qemuxml2argv-machine-keywrap-none-caps.xml |   25 
 .../qemuxml2argv-machine-keywrap-none.args |7 +
 .../qemuxml2argv-machine-keywrap-none.xml  |   25 
 tests/qemuxml2argvtest.c   |  127 ++--
 34 files changed, 637 insertions(+), 12 deletions(-)
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none.args
 create mode 100644 te

[libvirt] [PATCH 3/4] libvirt: qemu: enable/disable protected key management ops

2015-04-27 Thread akrowiak
From: Tony Krowiak 

Introduces two new -machine option parameters to the QEMU command to
enable/disable the CPACF protected key management operations for a guest:

aes-key-wrap='on|off'
dea-key-wrap='on|off'

The QEMU code maps the corresponding domain configuration elements to the
QEMU -machine option parameters to create the QEMU command:

   --> aes-key-wrap=on
  --> aes-key-wrap=off
   --> dea-key-wrap=on
  --> dea-key-wrap=off

Signed-off-by: Tony Krowiak 
Signed-off-by: Daniel Hansel 
Signed-off-by: Boris Fiuczynski 
Reviewed-by: Boris Fiuczynski 
---
 src/qemu/qemu_capabilities.c |5 +++
 src/qemu/qemu_capabilities.h |2 +
 src/qemu/qemu_command.c  |   72 ++
 src/qemu/qemu_domain.c   |   39 ++-
 4 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a458611..d1b9f6f 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -279,6 +279,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   "qxl.vgamem_mb",
   "qxl-vga.vgamem_mb",
   "pc-dimm",
+
+  "aes-key-wrap", /* 185 */
+  "dea-key-wrap",
 );
 
 
@@ -2518,6 +2521,8 @@ static struct virQEMUCapsCommandLineProps 
virQEMUCapsCommandLine[] = {
 { "msg", "timestamp", QEMU_CAPS_MSG_TIMESTAMP },
 { "numa", NULL, QEMU_CAPS_NUMA },
 { "drive", "throttling.bps-total-max", QEMU_CAPS_DRIVE_IOTUNE_MAX},
+{ "machine", "aes-key-wrap", QEMU_CAPS_AES_KEY_WRAP },
+{ "machine", "dea-key-wrap", QEMU_CAPS_DEA_KEY_WRAP },
 };
 
 static int
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index c7b1ac7..31e0494 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -224,6 +224,8 @@ typedef enum {
 QEMU_CAPS_QXL_VGAMEM = 182, /* -device qxl.vgamem_mb */
 QEMU_CAPS_QXL_VGA_VGAMEM = 183, /* -device qxl-vga.vgamem_mb */
 QEMU_CAPS_DEVICE_PC_DIMM = 184, /* pc-dimm device */
+QEMU_CAPS_AES_KEY_WRAP   = 185, /* -machine aes_key_wrap */
+QEMU_CAPS_DEA_KEY_WRAP   = 186, /* -machine dea_key_wrap */
 
 QEMU_CAPS_LAST,   /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 247954f..8ff1d88 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -38,6 +38,7 @@
 #include "virnetdevbridge.h"
 #include "virstring.h"
 #include "virtime.h"
+#include "virutil.h"
 #include "viruuid.h"
 #include "c-ctype.h"
 #include "domain_nwfilter.h"
@@ -7295,6 +7296,39 @@ qemuBuildObsoleteAccelArg(virCommandPtr cmd,
 return 0;
 }
 
+static bool
+qemuAppendKeyWrapMachineParm(virBuffer *buf, virQEMUCapsPtr qemuCaps,
+ int flag, const char *pname, int pstate)
+{
+if (pstate != VIR_TRISTATE_SWITCH_ABSENT) {
+if (!virQEMUCapsGet(qemuCaps, flag)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("%s is not available with this QEMU binary"), 
pname);
+return false;
+}
+
+virBufferAsprintf(buf, ",%s=%s", pname,
+  virTristateSwitchTypeToString(pstate));
+}
+
+return true;
+}
+
+static bool
+qemuAppendKeyWrapMachineParms(virBuffer *buf, virQEMUCapsPtr qemuCaps,
+  const virDomainDef *def)
+{
+if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_AES_KEY_WRAP,
+  "aes-key-wrap", def->keywrap.aes))
+return false;
+
+if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_DEA_KEY_WRAP,
+  "dea-key-wrap", def->keywrap.dea))
+return false;
+
+return true;
+}
+
 static int
 qemuBuildMachineArgStr(virCommandPtr cmd,
const virDomainDef *def,
@@ -7329,6 +7363,14 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
 }
 
 obsoleteAccel = true;
+
+if ((def->keywrap.aes != VIR_TRISTATE_SWITCH_ABSENT) ||
+(def->keywrap.dea != VIR_TRISTATE_SWITCH_ABSENT)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("key wrap support is not available "
+ "with this QEMU binary"));
+return -1;
+}
 } else {
 virBuffer buf = VIR_BUFFER_INITIALIZER;
 
@@ -7373,6 +7415,11 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
 }
 }
 
+if (!qemuAppendKeyWrapMachineParms(&buf, qemuCaps, def)) {
+virBufferFreeAndReset(&buf);
+return -1;
+}
+
 virCommandAddArgBuffer(cmd, &buf);
 }
 
@@ -12772,6 +12819,9 @@ qemuParseCommandLine(virCapsPtr qemuCaps,
 }
 
 /* handle all remaining "-machine" parameters */
+def->keywrap.aes = VIR_TRISTATE_SWITCH_ABSENT;
+

[libvirt] [PATCH 0/4] Enable support for s390 crypto key mgmt operations

2015-04-27 Thread akrowiak
From: Tony Krowiak 

The IBM System z Central Processor Assist for Cryptographic Functions (CPACF)
hardware provides a set of CPU instructions for use in clear-key encryption,
pseudo random number generation, hash functions, and protected-key encryption.
The CPACF protected key cryptographic functions operate with a protected key
which is encrypted under a unique wrapping key that is stored in the Hardware
System Area (HSA) of the machine and can only be accessed by firmware. The
wrapping key cannot be accessed by the operating system or application
programs. There are two wrapping keys: One for wrapping AES keys and one for
wrapping DES/TDES keys. This patch set enables the support for encrypting  
clear keys under the AES and DES/TDES wrapping keys for guests started on hosts 
running on s390 hardware that supports key wrapping.

Tony Krowiak (4):
  libvirt: docs: XML to enable/disable protected key mgmt ops
  libvirt: conf: parse XML for protected key management ops
  libvirt: qemu: enable/disable protected key management ops
  libvirt: tests: test protected key mgmt ops support

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


[libvirt] [PATCH 2/4] libvirt: conf: parse XML for protected key management ops

2015-04-27 Thread akrowiak
From: Tony Krowiak 

Parse the domain configuration XML elements that enable/disable access to
the protected key management operations for a guest:


  ...
  

  
  ...


Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Signed-off-by: Daniel Hansel 
Reviewed-by: Boris Fiuczynski 
---
 src/conf/domain_conf.c   |  189 ++
 src/conf/domain_conf.h   |   20 +
 src/libvirt_private.syms |2 +
 3 files changed, 211 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0b18720..4c8d934 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -476,6 +476,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, 
VIR_DOMAIN_SOUND_MODEL_LAST,
   "ich9",
   "usb")
 
+VIR_ENUM_IMPL(virDomainKeyWrapCipherName,
+  VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST,
+  "aes",
+  "dea")
+
 VIR_ENUM_IMPL(virDomainMemballoonModel, VIR_DOMAIN_MEMBALLOON_MODEL_LAST,
   "virtio",
   "xen",
@@ -835,6 +840,124 @@ virDomainXMLOptionClassDispose(void *obj)
 
 
 /**
+ * virDomainKeyWrapCipherDefParseXML:
+ *
+ * @def  Domain definition
+ * @node An XML cipher node
+ * @ctxt The XML context
+ *
+ * Parse the attributes from the cipher node and store the state attribute in
+ * @def
+ *
+ * A cipher node has the form of
+ *
+ *   
+ *
+ * Returns 0 if the parse succeeded, otherwise; returns -1
+ */
+static int
+virDomainKeyWrapCipherDefParseXML(virDomainDefPtr def, xmlNodePtr node,
+  xmlXPathContextPtr ctxt)
+{
+
+char *name = NULL;
+char *state = NULL;
+int state_type;
+int name_type;
+int rc = -1;
+xmlNodePtr oldnode = ctxt->node;
+ctxt->node = node;
+name = virXPathString("string(./@name)", ctxt);
+
+if (name == NULL) {
+virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+   _("missing name for cipher"));
+goto error;
+}
+
+if ((name_type = virDomainKeyWrapCipherNameTypeFromString(name)) < 0) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher name"), name);
+goto error;
+}
+
+state = virXPathString("string(./@state)", ctxt);
+
+if (state == NULL) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("missing state for cipher named %s"), name);
+goto error;
+}
+
+if ((state_type = virTristateSwitchTypeFromString(state)) < 0) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher state"), state);
+goto error;
+}
+
+switch (name_type) {
+case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES:
+if (def->keywrap.aes != VIR_TRISTATE_SWITCH_ABSENT) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("A domain definition can have no more than "
+ "one cipher node with name %s"),
+   
virDomainKeyWrapCipherNameTypeToString(name_type));
+
+goto error;
+}
+def->keywrap.aes = state_type;
+break;
+case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA:
+if (def->keywrap.dea != VIR_TRISTATE_SWITCH_ABSENT) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("A domain definition can have no more than "
+ "one cipher node with name %s"),
+   
virDomainKeyWrapCipherNameTypeToString(name_type));
+
+goto error;
+}
+def->keywrap.dea = state_type;
+break;
+default:
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher name"), name);
+goto error;
+}
+
+ctxt->node = oldnode;
+rc = 0;
+
+ error:
+VIR_FREE(name);
+VIR_FREE(state);
+return rc;
+}
+
+static int
+virDomainKeyWrapDefParseXML(virDomainDefPtr def, xmlXPathContextPtr ctxt)
+{
+size_t i;
+int rc = -1;
+xmlNodePtr *nodes = NULL;
+int n = virXPathNodeSet("./keywrap/cipher", ctxt, &nodes);
+def->keywrap.aes = VIR_TRISTATE_SWITCH_ABSENT;
+def->keywrap.dea = VIR_TRISTATE_SWITCH_ABSENT;
+
+for (i = 0; i < n; i++) {
+if (virDomainKeyWrapCipherDefParseXML(def, nodes[i], ctxt) < 0)
+goto error;
+}
+
+rc = 0;
+
+ error:
+VIR_FREE(nodes);
+
+return rc;
+}
+
+
+/**
  * virDomainXMLOptionNew:
  *
  * Allocate a new domain XML configuration
@@ -15558,6 +15681,9 @@ virDomainDefParseXML(xmlDocPtr xml,
 VIR_FREE(tmp);
 }
 
+if (virDomainKeyWrapDefParseXML(def, ctxt) < 0)
+goto error;
+
 /* Extract custom metadata */
 if ((node = virXPathNode("./metadata[1]", ctxt)) != NULL)
 def->metadata = xmlCopyNode(node, 1);
@@ -20598,6 +20724,66 @@ 

[libvirt] [PATCH 1/4] libvirt: docs: XML to enable/disable protected key mgmt ops

2015-04-27 Thread akrowiak
From: Tony Krowiak 

Two new domain configuration XML elements have been added to enable/disable
the protected key management operations for a guest:


  ...
  

  
  ...


Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Reviewed-by: Boris Fiuczynski 
---
 docs/formatdomain.html.in |   37 +
 docs/schemas/domaincommon.rng |   24 
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0767a2a..0553a79 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6211,6 +6211,43 @@ qemu-kvm -net nic,model=? /dev/null
   being on a file system that lacks security labeling.
 
 
+Key Wrap
+
+   The content of the optional keywrap element specifies
+whether the guest will be allowed to perform the S390 cryptographic key
+management operations. A clear key can be protected by encrypting it
+under a unique wrapping key that is generated for each guest VM running
+on the host. Two variations of wrapping keys are generated: one version
+for encrypting protected keys using the DEA/TDEA algorithm, and another
+version for keys encrypted using the AES algorithm. If a
+keywrap element is not included, the guest will be granted
+access to both AES and DEA/TDEA key wrapping by default.
+
+
+
+  ...
+  
+
+  
+  ...
+
+
+At least one cipher element must be nested within the
+keywrap element.
+cipher
+The name attribute identifies the algorithm
+for encrypting a protected key. The values supported for this attribute
+are aes for encryption under the AES wrapping key, or
+dea for encryption under the DEA/TDEA wrapping key. The
+state attribute indicates whether the cryptographic key
+management operations should be turned on for the specified encryption
+algorithm. The value can be set to on or off.
+A default state of on will be assumed if a
+cipher element is not included for the AES or DEA/TDEA
+encryption algorithm.
+
+
+Note: DEA/TDEA is synonymous with DES/TDES.
 Example configs
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 7072954..71d9681 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -67,6 +67,9 @@
 
   
 
+
+  
+
   
 
   
@@ -382,6 +385,27 @@
 
   
 
+  
+
+  
+
+  
+
+  aes
+  dea
+
+  
+  
+
+on
+off
+
+  
+
+  
+
+  
+
   

[libvirt] [PATCH 0/4] Enable support for s390 crypto key mgmt operations

2015-05-07 Thread akrowiak
From: Tony Krowiak 

The IBM System z Central Processor Assist for Cryptographic Functions (CPACF)
hardware provides a set of CPU instructions for use in clear-key encryption,
pseudo random number generation, hash functions, and protected-key encryption.
The CPACF protected key cryptographic functions operate with a protected key
which is encrypted under a unique wrapping key that is stored in the Hardware
System Area (HSA) of the machine and can only be accessed by firmware. The
wrapping key cannot be accessed by the operating system or application
programs. There are two wrapping keys: One for wrapping AES keys and one for
wrapping DES/TDES keys. This patch set enables the support for encrypting  
clear keys under the AES and DES/TDES wrapping keys for guests started on hosts 
running on s390 hardware that supports key wrapping.

Tony Krowiak (4):
  libvirt: docs: XML to enable/disable protected key mgmt ops
  libvirt: conf: parse XML for protected key management ops
  libvirt: qemu: enable/disable protected key management ops
  libvirt: tests: test protected key mgmt ops support

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


[libvirt] [PATCH 3/4] libvirt: qemu: enable/disable protected key management ops

2015-05-07 Thread akrowiak
From: Tony Krowiak 

Introduces two new -machine option parameters to the QEMU command to
enable/disable the CPACF protected key management operations for a guest:

aes-key-wrap='on|off'
dea-key-wrap='on|off'

The QEMU code maps the corresponding domain configuration elements to the
QEMU -machine option parameters to create the QEMU command:

   --> aes-key-wrap=on
  --> aes-key-wrap=off
   --> dea-key-wrap=on
  --> dea-key-wrap=off

Signed-off-by: Tony Krowiak 
Signed-off-by: Daniel Hansel 
Signed-off-by: Boris Fiuczynski 
Reviewed-by: Boris Fiuczynski 
---
 src/qemu/qemu_capabilities.c |5 +++
 src/qemu/qemu_capabilities.h |2 +
 src/qemu/qemu_command.c  |   72 ++
 src/qemu/qemu_domain.c   |   39 ++-
 4 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a458611..d1b9f6f 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -279,6 +279,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   "qxl.vgamem_mb",
   "qxl-vga.vgamem_mb",
   "pc-dimm",
+
+  "aes-key-wrap", /* 185 */
+  "dea-key-wrap",
 );
 
 
@@ -2518,6 +2521,8 @@ static struct virQEMUCapsCommandLineProps 
virQEMUCapsCommandLine[] = {
 { "msg", "timestamp", QEMU_CAPS_MSG_TIMESTAMP },
 { "numa", NULL, QEMU_CAPS_NUMA },
 { "drive", "throttling.bps-total-max", QEMU_CAPS_DRIVE_IOTUNE_MAX},
+{ "machine", "aes-key-wrap", QEMU_CAPS_AES_KEY_WRAP },
+{ "machine", "dea-key-wrap", QEMU_CAPS_DEA_KEY_WRAP },
 };
 
 static int
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index c7b1ac7..31e0494 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -224,6 +224,8 @@ typedef enum {
 QEMU_CAPS_QXL_VGAMEM = 182, /* -device qxl.vgamem_mb */
 QEMU_CAPS_QXL_VGA_VGAMEM = 183, /* -device qxl-vga.vgamem_mb */
 QEMU_CAPS_DEVICE_PC_DIMM = 184, /* pc-dimm device */
+QEMU_CAPS_AES_KEY_WRAP   = 185, /* -machine aes_key_wrap */
+QEMU_CAPS_DEA_KEY_WRAP   = 186, /* -machine dea_key_wrap */
 
 QEMU_CAPS_LAST,   /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 247954f..8ff1d88 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -38,6 +38,7 @@
 #include "virnetdevbridge.h"
 #include "virstring.h"
 #include "virtime.h"
+#include "virutil.h"
 #include "viruuid.h"
 #include "c-ctype.h"
 #include "domain_nwfilter.h"
@@ -7295,6 +7296,39 @@ qemuBuildObsoleteAccelArg(virCommandPtr cmd,
 return 0;
 }
 
+static bool
+qemuAppendKeyWrapMachineParm(virBuffer *buf, virQEMUCapsPtr qemuCaps,
+ int flag, const char *pname, int pstate)
+{
+if (pstate != VIR_TRISTATE_SWITCH_ABSENT) {
+if (!virQEMUCapsGet(qemuCaps, flag)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+   _("%s is not available with this QEMU binary"), 
pname);
+return false;
+}
+
+virBufferAsprintf(buf, ",%s=%s", pname,
+  virTristateSwitchTypeToString(pstate));
+}
+
+return true;
+}
+
+static bool
+qemuAppendKeyWrapMachineParms(virBuffer *buf, virQEMUCapsPtr qemuCaps,
+  const virDomainDef *def)
+{
+if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_AES_KEY_WRAP,
+  "aes-key-wrap", def->keywrap.aes))
+return false;
+
+if (!qemuAppendKeyWrapMachineParm(buf, qemuCaps, QEMU_CAPS_DEA_KEY_WRAP,
+  "dea-key-wrap", def->keywrap.dea))
+return false;
+
+return true;
+}
+
 static int
 qemuBuildMachineArgStr(virCommandPtr cmd,
const virDomainDef *def,
@@ -7329,6 +7363,14 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
 }
 
 obsoleteAccel = true;
+
+if ((def->keywrap.aes != VIR_TRISTATE_SWITCH_ABSENT) ||
+(def->keywrap.dea != VIR_TRISTATE_SWITCH_ABSENT)) {
+virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+   _("key wrap support is not available "
+ "with this QEMU binary"));
+return -1;
+}
 } else {
 virBuffer buf = VIR_BUFFER_INITIALIZER;
 
@@ -7373,6 +7415,11 @@ qemuBuildMachineArgStr(virCommandPtr cmd,
 }
 }
 
+if (!qemuAppendKeyWrapMachineParms(&buf, qemuCaps, def)) {
+virBufferFreeAndReset(&buf);
+return -1;
+}
+
 virCommandAddArgBuffer(cmd, &buf);
 }
 
@@ -12772,6 +12819,9 @@ qemuParseCommandLine(virCapsPtr qemuCaps,
 }
 
 /* handle all remaining "-machine" parameters */
+def->keywrap.aes = VIR_TRISTATE_SWITCH_ABSENT;
+

[libvirt] [PATCH 4/4] libvirt: tests: test protected key mgmt ops support

2015-05-07 Thread akrowiak
From: Tony Krowiak 

Test the support for enabling/disabling CPACF protected key management
operations for a guest.

Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Reviewed-by: Boris Fiuczynski 
---
 src/qemu/qemu_capabilities.c   |9 ++
 src/qemu/qemu_capabilities.h   |2 +
 tests/qemuargv2xmltest.c   |6 +
 .../qemuxml2argv-machine-aeskeywrap-off-argv.args  |6 +
 .../qemuxml2argv-machine-aeskeywrap-off-argv.xml   |   27 
 .../qemuxml2argv-machine-aeskeywrap-off-cap.args   |7 +
 .../qemuxml2argv-machine-aeskeywrap-off-cap.xml|   28 +
 .../qemuxml2argv-machine-aeskeywrap-off-caps.args  |7 +
 .../qemuxml2argv-machine-aeskeywrap-off-caps.xml   |   28 +
 .../qemuxml2argv-machine-aeskeywrap-on-argv.args   |6 +
 .../qemuxml2argv-machine-aeskeywrap-on-argv.xml|   27 
 .../qemuxml2argv-machine-aeskeywrap-on-cap.args|7 +
 .../qemuxml2argv-machine-aeskeywrap-on-cap.xml |   28 +
 .../qemuxml2argv-machine-aeskeywrap-on-caps.args   |7 +
 .../qemuxml2argv-machine-aeskeywrap-on-caps.xml|   27 
 .../qemuxml2argv-machine-deakeywrap-off-argv.args  |6 +
 .../qemuxml2argv-machine-deakeywrap-off-argv.xml   |   27 
 .../qemuxml2argv-machine-deakeywrap-off-cap.args   |7 +
 .../qemuxml2argv-machine-deakeywrap-off-cap.xml|   28 +
 .../qemuxml2argv-machine-deakeywrap-off-caps.args  |7 +
 .../qemuxml2argv-machine-deakeywrap-off-caps.xml   |   28 +
 .../qemuxml2argv-machine-deakeywrap-on-argv.args   |6 +
 .../qemuxml2argv-machine-deakeywrap-on-argv.xml|   27 
 .../qemuxml2argv-machine-deakeywrap-on-cap.args|7 +
 .../qemuxml2argv-machine-deakeywrap-on-cap.xml |   28 +
 .../qemuxml2argv-machine-deakeywrap-on-caps.args   |7 +
 .../qemuxml2argv-machine-deakeywrap-on-caps.xml|   28 +
 .../qemuxml2argv-machine-keywrap-none-argv.args|6 +
 .../qemuxml2argv-machine-keywrap-none-argv.xml |   24 
 .../qemuxml2argv-machine-keywrap-none-caps.args|7 +
 .../qemuxml2argv-machine-keywrap-none-caps.xml |   25 
 .../qemuxml2argv-machine-keywrap-none.args |7 +
 .../qemuxml2argv-machine-keywrap-none.xml  |   25 
 tests/qemuxml2argvtest.c   |  127 ++--
 34 files changed, 637 insertions(+), 12 deletions(-)
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-off-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-aeskeywrap-on-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-off-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-cap.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-cap.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-deakeywrap-on-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-argv.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-argv.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-caps.args
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none-caps.xml
 create mode 100644 
tests/qemuxml2argvdata/qemuxml2argv-machine-keywrap-none.args
 create mode 100644 te

[libvirt] [PATCH 1/4] libvirt: docs: XML to enable/disable protected key mgmt ops

2015-05-07 Thread akrowiak
From: Tony Krowiak 

Two new domain configuration XML elements have been added to enable/disable
the protected key management operations for a guest:


  ...
  

  
  ...


Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Reviewed-by: Boris Fiuczynski 
---
 docs/formatdomain.html.in |   37 +
 docs/schemas/domaincommon.rng |   24 
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0767a2a..0553a79 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -6211,6 +6211,43 @@ qemu-kvm -net nic,model=? /dev/null
   being on a file system that lacks security labeling.
 
 
+Key Wrap
+
+   The content of the optional keywrap element specifies
+whether the guest will be allowed to perform the S390 cryptographic key
+management operations. A clear key can be protected by encrypting it
+under a unique wrapping key that is generated for each guest VM running
+on the host. Two variations of wrapping keys are generated: one version
+for encrypting protected keys using the DEA/TDEA algorithm, and another
+version for keys encrypted using the AES algorithm. If a
+keywrap element is not included, the guest will be granted
+access to both AES and DEA/TDEA key wrapping by default.
+
+
+
+  ...
+  
+
+  
+  ...
+
+
+At least one cipher element must be nested within the
+keywrap element.
+cipher
+The name attribute identifies the algorithm
+for encrypting a protected key. The values supported for this attribute
+are aes for encryption under the AES wrapping key, or
+dea for encryption under the DEA/TDEA wrapping key. The
+state attribute indicates whether the cryptographic key
+management operations should be turned on for the specified encryption
+algorithm. The value can be set to on or off.
+A default state of on will be assumed if a
+cipher element is not included for the AES or DEA/TDEA
+encryption algorithm.
+
+
+Note: DEA/TDEA is synonymous with DES/TDES.
 Example configs
 
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 7072954..71d9681 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -67,6 +67,9 @@
 
   
 
+
+  
+
   
 
   
@@ -382,6 +385,27 @@
 
   
 
+  
+
+  
+
+  
+
+  aes
+  dea
+
+  
+  
+
+on
+off
+
+  
+
+  
+
+  
+
   

[libvirt] [PATCH 2/4] libvirt: conf: parse XML for protected key management ops

2015-05-07 Thread akrowiak
From: Tony Krowiak 

Parse the domain configuration XML elements that enable/disable access to
the protected key management operations for a guest:


  ...
  

  
  ...


Signed-off-by: Tony Krowiak 
Signed-off-by: Viktor Mihajlovski 
Signed-off-by: Daniel Hansel 
Reviewed-by: Boris Fiuczynski 
---
 src/conf/domain_conf.c   |  189 ++
 src/conf/domain_conf.h   |   20 +
 src/libvirt_private.syms |2 +
 3 files changed, 211 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0b18720..4c8d934 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -476,6 +476,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, 
VIR_DOMAIN_SOUND_MODEL_LAST,
   "ich9",
   "usb")
 
+VIR_ENUM_IMPL(virDomainKeyWrapCipherName,
+  VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST,
+  "aes",
+  "dea")
+
 VIR_ENUM_IMPL(virDomainMemballoonModel, VIR_DOMAIN_MEMBALLOON_MODEL_LAST,
   "virtio",
   "xen",
@@ -835,6 +840,124 @@ virDomainXMLOptionClassDispose(void *obj)
 
 
 /**
+ * virDomainKeyWrapCipherDefParseXML:
+ *
+ * @def  Domain definition
+ * @node An XML cipher node
+ * @ctxt The XML context
+ *
+ * Parse the attributes from the cipher node and store the state attribute in
+ * @def
+ *
+ * A cipher node has the form of
+ *
+ *   
+ *
+ * Returns 0 if the parse succeeded, otherwise; returns -1
+ */
+static int
+virDomainKeyWrapCipherDefParseXML(virDomainDefPtr def, xmlNodePtr node,
+  xmlXPathContextPtr ctxt)
+{
+
+char *name = NULL;
+char *state = NULL;
+int state_type;
+int name_type;
+int rc = -1;
+xmlNodePtr oldnode = ctxt->node;
+ctxt->node = node;
+name = virXPathString("string(./@name)", ctxt);
+
+if (name == NULL) {
+virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+   _("missing name for cipher"));
+goto error;
+}
+
+if ((name_type = virDomainKeyWrapCipherNameTypeFromString(name)) < 0) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher name"), name);
+goto error;
+}
+
+state = virXPathString("string(./@state)", ctxt);
+
+if (state == NULL) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("missing state for cipher named %s"), name);
+goto error;
+}
+
+if ((state_type = virTristateSwitchTypeFromString(state)) < 0) {
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher state"), state);
+goto error;
+}
+
+switch (name_type) {
+case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES:
+if (def->keywrap.aes != VIR_TRISTATE_SWITCH_ABSENT) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("A domain definition can have no more than "
+ "one cipher node with name %s"),
+   
virDomainKeyWrapCipherNameTypeToString(name_type));
+
+goto error;
+}
+def->keywrap.aes = state_type;
+break;
+case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA:
+if (def->keywrap.dea != VIR_TRISTATE_SWITCH_ABSENT) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("A domain definition can have no more than "
+ "one cipher node with name %s"),
+   
virDomainKeyWrapCipherNameTypeToString(name_type));
+
+goto error;
+}
+def->keywrap.dea = state_type;
+break;
+default:
+virReportError(VIR_ERR_CONF_SYNTAX,
+   _("%s is not a supported cipher name"), name);
+goto error;
+}
+
+ctxt->node = oldnode;
+rc = 0;
+
+ error:
+VIR_FREE(name);
+VIR_FREE(state);
+return rc;
+}
+
+static int
+virDomainKeyWrapDefParseXML(virDomainDefPtr def, xmlXPathContextPtr ctxt)
+{
+size_t i;
+int rc = -1;
+xmlNodePtr *nodes = NULL;
+int n = virXPathNodeSet("./keywrap/cipher", ctxt, &nodes);
+def->keywrap.aes = VIR_TRISTATE_SWITCH_ABSENT;
+def->keywrap.dea = VIR_TRISTATE_SWITCH_ABSENT;
+
+for (i = 0; i < n; i++) {
+if (virDomainKeyWrapCipherDefParseXML(def, nodes[i], ctxt) < 0)
+goto error;
+}
+
+rc = 0;
+
+ error:
+VIR_FREE(nodes);
+
+return rc;
+}
+
+
+/**
  * virDomainXMLOptionNew:
  *
  * Allocate a new domain XML configuration
@@ -15558,6 +15681,9 @@ virDomainDefParseXML(xmlDocPtr xml,
 VIR_FREE(tmp);
 }
 
+if (virDomainKeyWrapDefParseXML(def, ctxt) < 0)
+goto error;
+
 /* Extract custom metadata */
 if ((node = virXPathNode("./metadata[1]", ctxt)) != NULL)
 def->metadata = xmlCopyNode(node, 1);
@@ -20598,6 +20724,66 @@ 

[libvirt] [PATCH 0/2] Extend NIC_RX_FILTER_CHANGED event handler to process multicast list

2014-10-06 Thread akrowiak
From: Tony Krowiak 

This patch set extends the handler for qemu's NIC_RX_FILTER_CHANGED event. It 
adds 
code to compare the old and new multicast MAC address lists and programs the 
macvtap filters to match the guest.

Tony Krowiak (2):
  util: Functions to update host network device's multicast filter
  qemu: change macvtap multicast list in response to
NIC_RX_FILTER_CHANGED

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


[libvirt] [PATCH 1/2] util: Functions to update host network device's multicast filter

2014-10-06 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions to needed to synchronize the
changes made to a guest domain network device's multicast filter
with the corresponding macvtap device's filter on the host:

* Get/add/remove multicast MAC addresses
* Get the macvtap device's RX filter list

Signed-off-by: Tony Krowiak 
---
 src/libvirt_private.syms |4 +
 src/util/virmacaddr.c|   37 +
 src/util/virmacaddr.h|4 +
 src/util/virnetdev.c |  360 ++
 src/util/virnetdev.h |   11 ++
 5 files changed, 416 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d6265ac..6d06a2c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1590,13 +1590,16 @@ virMacAddrIsBroadcastRaw;
 virMacAddrIsMulticast;
 virMacAddrIsUnicast;
 virMacAddrParse;
+virMacAddrParseHex;
 virMacAddrSet;
 virMacAddrSetRaw;
 
 
 # util/virnetdev.h
+virNetDevAddMulti;
 virNetDevAddRoute;
 virNetDevClearIPv4Address;
+virNetDevDelMulti;
 virNetDevExists;
 virNetDevGetIndex;
 virNetDevGetIPv4Address;
@@ -1604,6 +1607,7 @@ virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
 virNetDevGetPhysicalFunction;
+virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c
index ebd1182..ae5e5d2 100644
--- a/src/util/virmacaddr.c
+++ b/src/util/virmacaddr.c
@@ -198,6 +198,43 @@ virMacAddrFormat(const virMacAddr *addr,
 return str;
 }
 
+/**
+ * virMacAddrParseHex:
+ * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB"
+ * @addr: 6-byte MAC address
+ *
+ * Parse the hexadecimal representation of a MAC address
+ *
+ * Return 0 upon success, or -1 in case of error.
+ */
+int
+virMacAddrParseHex(const char* str, virMacAddrPtr addr)
+{
+if (strlen(str) != VIR_MAC_HEXLEN)
+return -1;
+
+size_t iaddr;
+size_t istr;
+
+
+for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) {
+unsigned int hex;
+
+if (sscanf(&str[istr], "%02x", &hex) != 1)
+break;
+
+if (hex > UCHAR_MAX)
+break;
+
+addr->addr[iaddr] = hex;
+}
+
+if (istr == VIR_MAC_HEXLEN)
+return 0;
+
+return -1;
+}
+
 void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr)
 {
diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h
index 49efc36..72a285a 100644
--- a/src/util/virmacaddr.h
+++ b/src/util/virmacaddr.h
@@ -27,6 +27,7 @@
 # include "internal.h"
 
 # define VIR_MAC_BUFLEN 6
+#define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2)
 # define VIR_MAC_PREFIX_BUFLEN 3
 # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3)
 
@@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char 
prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr);
 int virMacAddrParse(const char* str,
 virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK;
+int virMacAddrParseHex(const char* str,
+   virMacAddrPtr addr)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 bool virMacAddrIsUnicast(const virMacAddr *addr);
 bool virMacAddrIsMulticast(const virMacAddr *addr);
 bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]);
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index db5623a..5e53f5f 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -56,6 +56,33 @@
 
 VIR_LOG_INIT("util.netdev");
 
+# define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1)
+# define VIR_MCAST_INDEX_TOKEN_IDX 0
+# define VIR_MCAST_NAME_TOKEN_IDX 1
+# define VIR_MCAST_USERS_TOKEN_IDX 2
+# define VIR_MCAST_GLOBAL_TOKEN_IDX 3
+# define VIR_MCAST_ADDR_TOKEN_IDX 4
+# define VIR_MCAST_NUM_TOKENS 5
+# define VIR_MCAST_TOKEN_DELIMS " \n"
+# define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1)
+
+typedef struct _virNetDevMcastEntry virNetDevMcastEntry;
+typedef virNetDevMcastEntry *virNetDevMcastEntryPtr;
+struct _virNetDevMcastEntry  {
+int index;
+char name[VIR_MCAST_NAME_LEN];
+int users;
+bool global;
+virMacAddr macaddr;
+};
+
+typedef struct _virNetDevMcast virNetDevMcast;
+typedef virNetDevMcast *virNetDevMcastPtr;
+struct _virNetDevMcast {
+size_t nentries;
+virNetDevMcastEntryPtr *entries;
+};
+
 #if defined(HAVE_STRUCT_IFREQ)
 static int virNetDevSetupControlFull(const char *ifname,
  struct ifreq *ifr,
@@ -1934,6 +1961,266 @@ virNetDevGetLinkInfo(const char *ifname,
 #endif /* defined(__linux__) */
 
 
+#if defined(SIOCADDMULTI) && defined(HAVE_STRUCT_IFREQ)
+/**
+ * virNetDevAddMulti:
+ * @ifname: interface name to which to add multicast MAC address
+ * @macaddr: MAC address
+ *
+ * This function adds the @macaddr to the multicast list for a given interface
+ * @ifname.
+ *
+ * Returns 0 in case of success or -1 on failure

[libvirt] [PATCH 2/2] qemu: change macvtap multicast list in response to NIC_RX_FILTER_CHANGED

2014-10-06 Thread akrowiak
From: Tony Krowiak 

This patch adds functionality to processNicRxFilterChangedEvent().
The old and new multicast lists are compared and the filters in
the macvtap are programmed to match the guest's filters.

Signed-off-by: Tony Krowiak 
---
 src/qemu/qemu_driver.c |  138 +++
 1 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4e2b356..7ff9c38 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4147,6 +4147,106 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
 
 
 static void
+syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+char newMacStr[VIR_MAC_STRING_BUFLEN];
+
+if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
+virMacAddrFormat(&guestFilter->mac, newMacStr);
+
+/* set new MAC address from guest to associated macvtap device */
+if (virNetDevSetMAC(ifname, &guestFilter->mac)) {
+VIR_WARN("Couldn't set new MAC address %s to device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ newMacStr, ifname);
+} else {
+VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
+}
+}
+}
+
+
+static void
+syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+  virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < guestFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < hostFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&guestFilter->multicast.table[i],
+  &hostFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
+
+if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i])) {
+VIR_WARN("Couldn't add new multicast MAC address %s to "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Added multicast MAC %s to %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < hostFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < guestFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&hostFilter->multicast.table[i],
+  &guestFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
+
+if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i])) {
+VIR_WARN("Couldn't delete multicast MAC address %s from "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Deleted multicast MAC %s from %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterMulticast(char *ifname,
+ virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
+syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
+}
+
+static void
 processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
virDomainObjPtr vm,
char *devAlias)
@@ -4155,9 +4255,8 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
 qemuDomainObjPrivatePtr priv = vm->privateData;
 virDomainDeviceDef dev;
 virDomainNetDefPtr def;
-virNetDevRxFilterPtr filter = NULL;
-virMacAddr oldMAC;
-char newMacStr[VIR_MAC_STRING_BUFLEN];
+virNetDevRxFilterPtr guestFilter = NULL;
+virNetDevRxFilterPtr hostFilter = NULL;
 int ret;
 
 VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
@@ -4202,37 +4301,27 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
   "device %s in domain %s", def->info.alias, vm->def->name);
 
 qemuDomainObjEnterMonitor(driver, vm);
-ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &filter);
+ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
 qemuDomainObjExitMonitor(driver,

[libvirt] [PATCHv2 0/2] Extend NIC_RX_FILTER_CHANGED event handler to process multicast list

2014-10-10 Thread akrowiak
From: Tony Krowiak 

This patch set extends the handler for qemu's NIC_RX_FILTER_CHANGED event. It 
adds 
code to compare the old and new multicast MAC address lists and programs the 
macvtap filters to match the guest.

Changes from V1:

Responded to review comments from Laine Stump and Eric Blake

Tony Krowiak (2):
  util: Functions to update host network device's multicast filter
  qemu: change macvtap multicast list in response to
NIC_RX_FILTER_CHANGED

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


[libvirt] [PATCHv2 1/2] util: Functions to update host network device's multicast filter

2014-10-10 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions to needed to synchronize the
changes made to a guest domain network device's multicast filter
with the corresponding macvtap device's filter on the host:

* Get/add/remove multicast MAC addresses
* Get the macvtap device's RX filter list

changes from v1:
* Using virHexToBin function to parse HEX MAC address instead of
  sscanf in virMacAddrParseHex function
* Using ENOSYS in error messages for empty functions
* Reading entire file with virFileReadAll function when
  parsing /proc/net/dev_mcast file
* Using VIR_APPEND_ELEMENT macro when appending array of
  /proc/net/dev_mcast file objects
* Misc. formatting changes

Signed-off-by: Tony Krowiak 
---
 src/libvirt_private.syms |4 +
 src/util/virmacaddr.c|   25 
 src/util/virmacaddr.h|4 +
 src/util/virnetdev.c |  358 ++
 src/util/virnetdev.h |   10 ++
 5 files changed, 401 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d6265ac..6d06a2c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1590,13 +1590,16 @@ virMacAddrIsBroadcastRaw;
 virMacAddrIsMulticast;
 virMacAddrIsUnicast;
 virMacAddrParse;
+virMacAddrParseHex;
 virMacAddrSet;
 virMacAddrSetRaw;
 
 
 # util/virnetdev.h
+virNetDevAddMulti;
 virNetDevAddRoute;
 virNetDevClearIPv4Address;
+virNetDevDelMulti;
 virNetDevExists;
 virNetDevGetIndex;
 virNetDevGetIPv4Address;
@@ -1604,6 +1607,7 @@ virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
 virNetDevGetPhysicalFunction;
+virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c
index ebd1182..612a409 100644
--- a/src/util/virmacaddr.c
+++ b/src/util/virmacaddr.c
@@ -29,6 +29,7 @@
 #include "c-ctype.h"
 #include "virmacaddr.h"
 #include "virrandom.h"
+#include "virutil.h"
 
 static const unsigned char virMacAddrBroadcastAddrRaw[VIR_MAC_BUFLEN] =
 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -198,6 +199,30 @@ virMacAddrFormat(const virMacAddr *addr,
 return str;
 }
 
+/**
+ * virMacAddrParseHex:
+ * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB"
+ * @addr: 6-byte MAC address
+ *
+ * Parse the hexadecimal representation of a MAC address
+ *
+ * Return 0 upon success, or -1 in case of error.
+ */
+int
+virMacAddrParseHex(const char *str, virMacAddrPtr addr)
+{
+size_t i;
+
+if (strspn(str, "0123456789abcdefABCDEF") != VIR_MAC_HEXLEN ||
+str[VIR_MAC_HEXLEN])
+return -1;
+
+for (i = 0; i < VIR_MAC_BUFLEN; i++)
+addr->addr[i] = (virHexToBin(str[2 * i]) << 4 |
+ virHexToBin(str[2 * i + 1]));
+return 0;
+}
+
 void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr)
 {
diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h
index 49efc36..72a285a 100644
--- a/src/util/virmacaddr.h
+++ b/src/util/virmacaddr.h
@@ -27,6 +27,7 @@
 # include "internal.h"
 
 # define VIR_MAC_BUFLEN 6
+#define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2)
 # define VIR_MAC_PREFIX_BUFLEN 3
 # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3)
 
@@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char 
prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr);
 int virMacAddrParse(const char* str,
 virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK;
+int virMacAddrParseHex(const char* str,
+   virMacAddrPtr addr)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 bool virMacAddrIsUnicast(const virMacAddr *addr);
 bool virMacAddrIsMulticast(const virMacAddr *addr);
 bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]);
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index db5623a..1410cfe 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -56,6 +56,35 @@
 
 VIR_LOG_INIT("util.netdev");
 
+# define PROC_NET_DEV_MCAST "/proc/net/dev_mcast"
+# define MAX_MCAST_SIZE 50*14336
+# define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1)
+# define VIR_MCAST_INDEX_TOKEN_IDX 0
+# define VIR_MCAST_NAME_TOKEN_IDX 1
+# define VIR_MCAST_USERS_TOKEN_IDX 2
+# define VIR_MCAST_GLOBAL_TOKEN_IDX 3
+# define VIR_MCAST_ADDR_TOKEN_IDX 4
+# define VIR_MCAST_NUM_TOKENS 5
+# define VIR_MCAST_TOKEN_DELIMS " \n"
+# define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1)
+
+typedef struct _virNetDevMcastEntry virNetDevMcastEntry;
+typedef virNetDevMcastEntry *virNetDevMcastEntryPtr;
+struct _virNetDevMcastEntry  {
+int index;
+char name[VIR_MCAST_NAME_LEN];
+int users;
+bool global;
+virMacAddr macaddr;
+};
+
+typedef struct _virNetDevMcast virNetDevMcast;
+typedef virNetDevMcast *virNetDevMcastPtr;
+struct _virNetDevMcast {
+size_t nentries;
+virNetDevMcastEntryPtr *entries;
+};
+
 #if defined(HAV

[libvirt] [PATCHv2 2/2] qemu: change macvtap multicast list in response to NIC_RX_FILTER_CHANGED

2014-10-10 Thread akrowiak
From: Tony Krowiak 

This patch adds functionality to processNicRxFilterChangedEvent().
The old and new multicast lists are compared and the filters in
the macvtap are programmed to match the guest's filters.

Signed-off-by: Tony Krowiak 
---
 src/qemu/qemu_driver.c |  138 +++
 1 files changed, 114 insertions(+), 24 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4e2b356..7ff9c38 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4147,6 +4147,106 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
 
 
 static void
+syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+char newMacStr[VIR_MAC_STRING_BUFLEN];
+
+if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
+virMacAddrFormat(&guestFilter->mac, newMacStr);
+
+/* set new MAC address from guest to associated macvtap device */
+if (virNetDevSetMAC(ifname, &guestFilter->mac)) {
+VIR_WARN("Couldn't set new MAC address %s to device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ newMacStr, ifname);
+} else {
+VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
+}
+}
+}
+
+
+static void
+syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+  virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < guestFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < hostFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&guestFilter->multicast.table[i],
+  &hostFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
+
+if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i])) {
+VIR_WARN("Couldn't add new multicast MAC address %s to "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Added multicast MAC %s to %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < hostFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < guestFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&hostFilter->multicast.table[i],
+  &guestFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
+
+if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i])) {
+VIR_WARN("Couldn't delete multicast MAC address %s from "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Deleted multicast MAC %s from %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterMulticast(char *ifname,
+ virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
+syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
+}
+
+static void
 processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
virDomainObjPtr vm,
char *devAlias)
@@ -4155,9 +4255,8 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
 qemuDomainObjPrivatePtr priv = vm->privateData;
 virDomainDeviceDef dev;
 virDomainNetDefPtr def;
-virNetDevRxFilterPtr filter = NULL;
-virMacAddr oldMAC;
-char newMacStr[VIR_MAC_STRING_BUFLEN];
+virNetDevRxFilterPtr guestFilter = NULL;
+virNetDevRxFilterPtr hostFilter = NULL;
 int ret;
 
 VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
@@ -4202,37 +4301,27 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
   "device %s in domain %s", def->info.alias, vm->def->name);
 
 qemuDomainObjEnterMonitor(driver, vm);
-ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &filter);
+ret = qemuMonitorQueryRxFilter(priv->mon, devAlias, &guestFilter);
 qemuDomainObjExitMonitor(driver,

[libvirt] [PATCHv2 1/2] util: Functions to update host network device's multicast filter

2014-10-13 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions to needed to synchronize the
changes made to a guest domain network device's multicast filter
with the corresponding macvtap device's filter on the host:

* Get/add/remove multicast MAC addresses
* Get the macvtap device's RX filter list

Signed-off-by: Tony Krowiak 
---

Changes from V1:

* Using virHexToBin function to parse HEX MAC address instead of
  sscanf in virMacAddrParseHex function
* Using ENOSYS in error messages for empty functions
* Reading entire file with virFileReadAll function when
  parsing /proc/net/dev_mcast file
* Using VIR_APPEND_ELEMENT macro when appending array of
  /proc/net/dev_mcast file objects
* Misc. formatting changes

 src/libvirt_private.syms |4 +
 src/util/virmacaddr.c|   37 +
 src/util/virmacaddr.h|4 +
 src/util/virnetdev.c |  360 ++
 src/util/virnetdev.h |   11 ++
 5 files changed, 416 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d6265ac..6d06a2c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1590,13 +1590,16 @@ virMacAddrIsBroadcastRaw;
 virMacAddrIsMulticast;
 virMacAddrIsUnicast;
 virMacAddrParse;
+virMacAddrParseHex;
 virMacAddrSet;
 virMacAddrSetRaw;
 
 
 # util/virnetdev.h
+virNetDevAddMulti;
 virNetDevAddRoute;
 virNetDevClearIPv4Address;
+virNetDevDelMulti;
 virNetDevExists;
 virNetDevGetIndex;
 virNetDevGetIPv4Address;
@@ -1604,6 +1607,7 @@ virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
 virNetDevGetPhysicalFunction;
+virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c
index ebd1182..ae5e5d2 100644
--- a/src/util/virmacaddr.c
+++ b/src/util/virmacaddr.c
@@ -198,6 +198,43 @@ virMacAddrFormat(const virMacAddr *addr,
 return str;
 }
 
+/**
+ * virMacAddrParseHex:
+ * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB"
+ * @addr: 6-byte MAC address
+ *
+ * Parse the hexadecimal representation of a MAC address
+ *
+ * Return 0 upon success, or -1 in case of error.
+ */
+int
+virMacAddrParseHex(const char* str, virMacAddrPtr addr)
+{
+if (strlen(str) != VIR_MAC_HEXLEN)
+return -1;
+
+size_t iaddr;
+size_t istr;
+
+
+for (istr = 0, iaddr = 0; iaddr < VIR_MAC_BUFLEN; istr += 2, iaddr++) {
+unsigned int hex;
+
+if (sscanf(&str[istr], "%02x", &hex) != 1)
+break;
+
+if (hex > UCHAR_MAX)
+break;
+
+addr->addr[iaddr] = hex;
+}
+
+if (istr == VIR_MAC_HEXLEN)
+return 0;
+
+return -1;
+}
+
 void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr)
 {
diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h
index 49efc36..72a285a 100644
--- a/src/util/virmacaddr.h
+++ b/src/util/virmacaddr.h
@@ -27,6 +27,7 @@
 # include "internal.h"
 
 # define VIR_MAC_BUFLEN 6
+#define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2)
 # define VIR_MAC_PREFIX_BUFLEN 3
 # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3)
 
@@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char 
prefix[VIR_MAC_PREFIX_BUFLEN],
 virMacAddrPtr addr);
 int virMacAddrParse(const char* str,
 virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK;
+int virMacAddrParseHex(const char* str,
+   virMacAddrPtr addr)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 bool virMacAddrIsUnicast(const virMacAddr *addr);
 bool virMacAddrIsMulticast(const virMacAddr *addr);
 bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]);
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index db5623a..5e53f5f 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -56,6 +56,33 @@
 
 VIR_LOG_INIT("util.netdev");
 
+# define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1)
+# define VIR_MCAST_INDEX_TOKEN_IDX 0
+# define VIR_MCAST_NAME_TOKEN_IDX 1
+# define VIR_MCAST_USERS_TOKEN_IDX 2
+# define VIR_MCAST_GLOBAL_TOKEN_IDX 3
+# define VIR_MCAST_ADDR_TOKEN_IDX 4
+# define VIR_MCAST_NUM_TOKENS 5
+# define VIR_MCAST_TOKEN_DELIMS " \n"
+# define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1)
+
+typedef struct _virNetDevMcastEntry virNetDevMcastEntry;
+typedef virNetDevMcastEntry *virNetDevMcastEntryPtr;
+struct _virNetDevMcastEntry  {
+int index;
+char name[VIR_MCAST_NAME_LEN];
+int users;
+bool global;
+virMacAddr macaddr;
+};
+
+typedef struct _virNetDevMcast virNetDevMcast;
+typedef virNetDevMcast *virNetDevMcastPtr;
+struct _virNetDevMcast {
+size_t nentries;
+virNetDevMcastEntryPtr *entries;
+};
+
 #if defined(HAVE_STRUCT_IFREQ)
 static int virNetDevSetupControlFull(const char *ifname,
  struct ifreq *ifr,
@@ -1934,6 +1961,266 @@ virNetDevGetLinkI

[libvirt] [PATCHv2 2/2] qemu: change macvtap multicast list in response to NIC_RX_FILTER_CHANGED

2014-10-13 Thread akrowiak
From: Tony Krowiak 

This patch adds functionality to processNicRxFilterChangedEvent().
The old and new multicast lists are compared and the filters in
the macvtap are programmed to match the guest's filters.

Signed-off-by: Tony Krowiak 
---
 src/qemu/qemu_driver.c |  150 
 src/util/virmacaddr.c  |   32 +++---
 src/util/virnetdev.c   |  149 ++-
 3 files changed, 218 insertions(+), 113 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7c9b1ab..cf1ae9c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4147,6 +4147,118 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
 
 
 static void
+syncNicRxFilterMacAddr(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+char newMacStr[VIR_MAC_STRING_BUFLEN];
+
+if (virMacAddrCmp(&hostFilter->mac, &guestFilter->mac)) {
+virMacAddrFormat(&guestFilter->mac, newMacStr);
+
+/* set new MAC address from guest to associated macvtap device */
+if (virNetDevSetMAC(ifname, &guestFilter->mac)) {
+VIR_WARN("Couldn't set new MAC address %s to device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ newMacStr, ifname);
+} else {
+VIR_DEBUG("device %s MAC address set to %s", ifname, newMacStr);
+}
+}
+}
+
+
+static void
+syncNicRxFilterGuestMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+  virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < guestFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < hostFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&guestFilter->multicast.table[i],
+  &hostFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&guestFilter->multicast.table[i], macstr);
+
+if (virNetDevAddMulti(ifname, &guestFilter->multicast.table[i])) {
+VIR_WARN("Couldn't add new multicast MAC address %s to "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Added multicast MAC %s to %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterHostMulticast(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+size_t i, j;
+bool found;
+char macstr[VIR_MAC_STRING_BUFLEN];
+
+for (i = 0; i < hostFilter->multicast.nTable; i++) {
+found = false;
+
+for (j = 0; j < guestFilter->multicast.nTable; j++) {
+if (virMacAddrCmp(&hostFilter->multicast.table[i],
+  &guestFilter->multicast.table[j]) == 0) {
+found = true;
+break;
+}
+}
+
+if (!found) {
+virMacAddrFormat(&hostFilter->multicast.table[i], macstr);
+
+if (virNetDevDelMulti(ifname, &hostFilter->multicast.table[i])) {
+VIR_WARN("Couldn't delete multicast MAC address %s from "
+ "device %s while responding to NIC_RX_FILTER_CHANGED",
+ macstr, ifname);
+} else {
+VIR_DEBUG("Deleted multicast MAC %s from %s interface",
+  macstr, ifname);
+}
+}
+}
+}
+
+
+static void
+syncNicRxFilterMulticast(char *ifname,
+ virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+VIR_DEBUG("RXFILTER: guest multicast list:");
+if (guestFilter->multicast.nTable) {
+char addr[VIR_MAC_STRING_BUFLEN];
+for (size_t i = 0; i < guestFilter->multicast.nTable; i++) {
+VIR_DEBUG("RXFILTER:%s", 
virMacAddrFormat(&guestFilter->multicast.table[i], addr));
+}
+if (hostFilter->multicast.nTable) {
+char addr[VIR_MAC_STRING_BUFLEN];
+for (size_t i = 0; i < hostFilter->multicast.nTable; i++) {
+VIR_DEBUG("RXFILTER:%s", virMacAddrFormat(&hostFilter->multicast.table[i], 
addr));
+}
+}
+syncNicRxFilterGuestMulticast(ifname, guestFilter, hostFilter);
+syncNicRxFilterHostMulticast(ifname, guestFilter, hostFilter);
+}
+
+static void
 processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
virDomainObjPtr vm,
char *devAlias)
@@ -4155,9 +4267,8 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
 qemuDomainObjPrivatePtr priv = vm->privateData;
 virDomainDeviceDef dev;
 virDomainNetDefPtr def;
-virNetDevRxFilterPtr filter = 

[libvirt] [PATCH 0/2] Sync macvtap device modes when guest rxfilter changes

2015-01-19 Thread akrowiak
From: Tony Krowiak 

This patch set provides the code to synchonize some macvtap device 
modes when the values are changed on the guest's network device.  The 
following modes will by synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

Tony Krowiak (2):
  util: Functions for getting/setting device options
  qemu: change macvtap device options in response to
NIC_RX_FILTER_CHANGED

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


[libvirt] [PATCH 2/2] qemu: change macvtap device options in response to NIC_RX_FILTER_CHANGED

2015-01-19 Thread akrowiak
From: Tony Krowiak 

This patch supplies the funtionality of synchronizing the host macvtap
device options with the guest device's in response to the
NIC_RX_FILTER_CHANGED event.

The following device options will be synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

Signed-off-by: Tony Krowiak 
---
 src/qemu/qemu_driver.c |   92 
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5994558..141f91a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4168,6 +4168,93 @@ syncNicRxFilterHostMulticast(char *ifname, 
virNetDevRxFilterPtr guestFilter,
 
 
 static void
+syncNicRxFilterPromiscMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+bool promisc;
+bool setpromisc = false;
+
+/* Set macvtap promisc mode to true if the guest has vlans defined */
+/* or synchronize the macvtap promisc mode if different from guest */
+if (guestFilter->vlan.nTable > 0) {
+if (!hostFilter->promiscuous) {
+setpromisc = true;
+promisc = true;
+}
+} else if (hostFilter->promiscuous != guestFilter->promiscuous) {
+setpromisc = true;
+promisc = guestFilter->promiscuous;
+}
+
+if (setpromisc) {
+if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
+VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ promisc ? "true" : "false", ifname);
+}
+}
+}
+
+
+static void
+syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+if (hostFilter->multicast.mode != guestFilter->multicast.mode) {
+switch (guestFilter->multicast.mode) {
+case VIR_NETDEV_RX_FILTER_MODE_ALL:
+if (virNetDevSetRcvAllMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set allmulticast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
+if (virNetDevSetRcvMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set multicast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+default:
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvMulti(ifname, false)) {
+VIR_WARN("Couldn't set multicast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED",
+ ifname);
+}
+break;
+}
+}
+}
+
+
+static void
+syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
+syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
+}
+
+
+static void
 syncNicRxFilterMulticast(char *ifname,
  virNetDevRxFilterPtr guestFilter,
  virNetDevRxFilterPtr hostFilter)
@@ -4250,9 +4337,14 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
  * attributes to match those of the guest network device:
  * - MAC address
  * - Multicast MAC address table
+ * - Device options:
+ *   - PROMISC
+ *   - MULTICAST
+ *   - ALLMULTI
  */
 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
+syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
 }
 
  endjob:
-- 
1.7.1

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


[libvirt] [PATCH 1/2] util: Functions for getting/setting device options

2015-01-19 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions needed to synchronize
the rxfilter changes made to a guest domain with the corresponding
macvtap devices on the host:

* Get/set PROMISC flag
* Get/set ALLMULTI, MULTICAST

Signed-off-by: Tony Krowiak 
---
 src/libvirt_private.syms |6 +
 src/util/virnetdev.c |  346 ++
 src/util/virnetdev.h |   14 ++
 3 files changed, 366 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a2eec83..6b49b08 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1646,6 +1646,9 @@ virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
 virNetDevGetVLanID;
 virNetDevIsOnline;
+virNetDevIsPromiscuous;
+virNetDevIsRcvAllMulti;
+virNetDevIsRcvMulti;
 virNetDevIsVirtualFunction;
 virNetDevLinkDump;
 virNetDevReplaceMacAddress;
@@ -1663,6 +1666,9 @@ virNetDevSetMTUFromDevice;
 virNetDevSetName;
 virNetDevSetNamespace;
 virNetDevSetOnline;
+virNetDevSetPromiscuous;
+virNetDevSetRcvAllMulti;
+virNetDevSetRcvMulti;
 virNetDevSetupControl;
 virNetDevValidateConfig;
 
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ef96b2b..c610f5b 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -2337,6 +2337,333 @@ int virNetDevDelMulti(const char *ifname 
ATTRIBUTE_UNUSED,
 }
 #endif
 
+#if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+/**
+ * virNetDevSetPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: true for receive all packets, false for do not receive
+ *   all packets
+ *
+ * Function to control if an interface is to receive all
+ * packets (receive all, true) or not (do not receive all, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetPromiscuous(const char *ifname,
+bool promiscuous)
+{
+int fd = -1;
+int ret = -1;
+struct ifreq ifr;
+int ifflags;
+
+if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+return -1;
+
+if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+virReportSystemError(errno,
+ _("Cannot get interface flags on '%s'"),
+ ifname);
+goto cleanup;
+}
+
+if (promiscuous)
+ifflags = ifr.ifr_flags | IFF_PROMISC;
+else
+ifflags = ifr.ifr_flags & ~IFF_PROMISC;
+
+if (ifr.ifr_flags != ifflags) {
+ifr.ifr_flags = ifflags;
+if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+virReportSystemError(errno,
+ _("Cannot set interface flags on '%s'"),
+ ifname);
+goto cleanup;
+}
+}
+
+ret = 0;
+
+ cleanup:
+VIR_FORCE_CLOSE(fd);
+return ret;
+}
+#else
+int virNetDevSetPromiscuous(const char *ifname,
+bool promiscuous ATTRIBUTE_UNUSED)
+{
+virReportSystemError(ENOSYS, "%s",
+ _("Unable to set device flags for interfaces "
+   "on this platform"));
+return -1;
+}
+#endif
+
+#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+/**
+ * virNetDevIsPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: where to store the status
+ *
+ * Function to query if an interface is receiving all packets (true) or
+ * not (false)
+ *
+ * Returns 0 in case of success or an errno code in case of failure.
+ */
+int virNetDevIsPromiscuous(const char *ifname,
+   bool *promiscuous)
+{
+int fd = -1;
+int ret = -1;
+struct ifreq ifr;
+
+if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
+return -1;
+
+if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+virReportSystemError(errno,
+ _("Cannot get interface flags on '%s'"),
+ ifname);
+goto cleanup;
+}
+
+*promiscuous = (ifr.ifr_flags & IFF_PROMISC) ? true : false;
+ret = 0;
+
+ cleanup:
+VIR_FORCE_CLOSE(fd);
+return ret;
+}
+#else
+int virNetDevIsPromiscuous(const char *ifname ATTRIBUTE_UNUSED,
+bool *promiscuous ATTRIBUTE_UNUSED)
+{
+virReportSystemError(ENOSYS, "%s",
+ _("Unable to retrieve device flags for interfaces "
+   "on this platform"));
+return -1;
+}
+#endif
+
+#if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+/**
+ * virNetDevSetRcvMulti:
+ * @ifname: the interface name
+ * @:receive true for receive multicast packets, false for do not receive
+ *   multicast packets
+ *
+ * Function to control if an interface is to receive multicast
+ * packets in which it is interested (receive, true)
+ * or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvMulti(const char *ifname,
+ bool receive)
+{
+int fd = -1;
+int ret = -1;
+struct ifreq ifr;
+  

[libvirt] (no subject)

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch set provides the code to synchonize some macvtap device 
modes when the values are changed on the guest's network device.  The 
following modes will by synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

I noticed something while testing this patch set that did not occur prior 
to installing more recent kernel and Qemu distributions.  It seems that 
the VLAN table always has an entry for VLAN ID 0 when the rxfilter is 
queried during processing of the NIC_RX_FILTER_CHANGED event.  That means
that the PROMISC flag for macvtap0 will be set.  I don't know if this 
will cause problems, but I thought I'd make note of it in case anybody
wants to comment on that.  

Tony Krowiak (2):
  util: Functions for getting/setting device options
  qemu: change macvtap device options in response to
NIC_RX_FILTER_CHANGED

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


[libvirt] [PATCH v2 1/2] util: Functions for getting/setting device options

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions needed to synchronize
the rxfilter changes made to a guest domain with the corresponding
macvtap devices on the host:

* Get/set PROMISC flag
* Get/set ALLMULTI, MULTICAST

Signed-off-by: Tony Krowiak 
---
Changes for v2 (response to review comments for v1):
* Changed names of virNetDevIs... functions
* Consolidated code for getting/setting of device option flags

 src/libvirt_private.syms |8 ++-
 src/util/virnetdev.c |  186 +++---
 src/util/virnetdev.h |   24 ++-
 3 files changed, 190 insertions(+), 28 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a2eec83..8d76f9b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1639,13 +1639,16 @@ virNetDevGetIPv4Address;
 virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
+virNetDevGetOnline;
 virNetDevGetPhysicalFunction;
+virNetDevGetPromiscuous;
+virNetDevGetRcvAllMulti;
+virNetDevGetRcvMulti;
 virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
 virNetDevGetVLanID;
-virNetDevIsOnline;
 virNetDevIsVirtualFunction;
 virNetDevLinkDump;
 virNetDevReplaceMacAddress;
@@ -1663,6 +1666,9 @@ virNetDevSetMTUFromDevice;
 virNetDevSetName;
 virNetDevSetNamespace;
 virNetDevSetOnline;
+virNetDevSetPromiscuous;
+virNetDevSetRcvAllMulti;
+virNetDevSetRcvMulti;
 virNetDevSetupControl;
 virNetDevValidateConfig;
 
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ef96b2b..2bc1b93 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -610,17 +610,7 @@ int virNetDevSetName(const char* ifname, const char 
*newifname)
 
 
 #if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
-/**
- * virNetDevSetOnline:
- * @ifname: the interface name
- * @online: true for up, false for down
- *
- * Function to control if an interface is activated (up, true) or not (down, 
false)
- *
- * Returns 0 in case of success or -1 on error.
- */
-int virNetDevSetOnline(const char *ifname,
-   bool online)
+int virNetDevSetIFFlag(const char *ifname, int flag, bool val)
 {
 int fd = -1;
 int ret = -1;
@@ -637,10 +627,10 @@ int virNetDevSetOnline(const char *ifname,
 goto cleanup;
 }
 
-if (online)
-ifflags = ifr.ifr_flags | IFF_UP;
+if (val)
+ifflags = ifr.ifr_flags | flag;
 else
-ifflags = ifr.ifr_flags & ~IFF_UP;
+ifflags = ifr.ifr_flags & ~flag;
 
 if (ifr.ifr_flags != ifflags) {
 ifr.ifr_flags = ifflags;
@@ -659,8 +649,9 @@ int virNetDevSetOnline(const char *ifname,
 return ret;
 }
 #else
-int virNetDevSetOnline(const char *ifname,
-   bool online ATTRIBUTE_UNUSED)
+int virNetDevSetIFFlag(const char *ifname,
+   int flag ATTRIBUTE_UNUSED,
+   bool val ATTRIBUTE_UNUSED)
 {
 virReportSystemError(ENOSYS,
  _("Cannot set interface flags on '%s'"),
@@ -670,18 +661,77 @@ int virNetDevSetOnline(const char *ifname,
 #endif
 
 
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+
 /**
- * virNetDevIsOnline:
+ * virNetDevSetOnline:
  * @ifname: the interface name
- * @online: where to store the status
+ * @online: true for up, false for down
  *
- * Function to query if an interface is activated (true) or not (false)
+ * Function to control if an interface is activated (up, true) or not (down, 
false)
  *
- * Returns 0 in case of success or an errno code in case of failure.
+ * Returns 0 in case of success or -1 on error.
  */
-int virNetDevIsOnline(const char *ifname,
-  bool *online)
+int virNetDevSetOnline(const char *ifname,
+   bool online)
+{
+
+return virNetDevSetIFFlag(ifname, IFF_UP, online);
+}
+
+/**
+ * virNetDevSetPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: true for receive all packets, false for do not receive
+ *   all packets
+ *
+ * Function to control if an interface is to receive all
+ * packets (receive all, true) or not (do not receive all, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetPromiscuous(const char *ifname,
+bool promiscuous)
+{
+return virNetDevSetIFFlag(ifname, IFF_PROMISC, promiscuous);
+}
+
+/**
+ * virNetDevSetRcvMulti:
+ * @ifname: the interface name
+ * @:receive true for receive multicast packets, false for do not receive
+ *   multicast packets
+ *
+ * Function to control if an interface is to receive multicast
+ * packets in which it is interested (receive, true)
+ * or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvMulti(const char *ifname,
+ bool receive)
+{
+return virNetDevSetIFFlag(ifname, IFF_MULTICAST, receive);
+}
+
+/**
+ * virNetDevSetRcvAllMulti:
+ * @ifname: the int

[libvirt] [PATCH 2/2] qemu: change macvtap device options in response to NIC_RX_FILTER_CHANGED

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch enables synchronization of the host macvtap
device options with the guest device's in response to the
NIC_RX_FILTER_CHANGED event.

The following device options will be synchronized:
* PROMISC
* MULTICAST
* ALLMULTI
---
 src/qemu/qemu_driver.c |   92 
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bc6aae4..47c1b5e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4168,6 +4168,93 @@ syncNicRxFilterHostMulticast(char *ifname, 
virNetDevRxFilterPtr guestFilter,
 
 
 static void
+syncNicRxFilterPromiscMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+bool promisc;
+bool setpromisc = false;
+
+/* Set macvtap promisc mode to true if the guest has vlans defined */
+/* or synchronize the macvtap promisc mode if different from guest */
+if (guestFilter->vlan.nTable > 0) {
+if (!hostFilter->promiscuous) {
+setpromisc = true;
+promisc = true;
+}
+} else if (hostFilter->promiscuous != guestFilter->promiscuous) {
+setpromisc = true;
+promisc = guestFilter->promiscuous;
+}
+
+if (setpromisc) {
+if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
+VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ promisc ? "true" : "false", ifname);
+}
+}
+}
+
+
+static void
+syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+if (hostFilter->multicast.mode != guestFilter->multicast.mode) {
+switch (guestFilter->multicast.mode) {
+case VIR_NETDEV_RX_FILTER_MODE_ALL:
+if (virNetDevSetRcvAllMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set allmulticast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
+if (virNetDevSetRcvMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set multicast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NONE:
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvMulti(ifname, false)) {
+VIR_WARN("Couldn't set multicast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED",
+ ifname);
+}
+break;
+}
+}
+}
+
+
+static void
+syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
+syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
+}
+
+
+static void
 syncNicRxFilterMulticast(char *ifname,
  virNetDevRxFilterPtr guestFilter,
  virNetDevRxFilterPtr hostFilter)
@@ -4250,9 +4337,14 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
  * attributes to match those of the guest network device:
  * - MAC address
  * - Multicast MAC address table
+ * - Device options:
+ *   - PROMISC
+ *   - MULTICAST
+ *   - ALLMULTI
  */
 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
+syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
 }
 
  endjob:
-- 
1.7.1

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


[libvirt] [PATCH 1/2] util: Functions for getting/setting device options

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions needed to synchronize
the rxfilter changes made to a guest domain with the corresponding
macvtap devices on the host:

* Get/set PROMISC flag
* Get/set ALLMULTI, MULTICAST
---
 src/libvirt_private.syms |8 ++-
 src/util/virnetdev.c |  186 +++---
 src/util/virnetdev.h |   24 ++-
 3 files changed, 190 insertions(+), 28 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a2eec83..8d76f9b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1639,13 +1639,16 @@ virNetDevGetIPv4Address;
 virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
+virNetDevGetOnline;
 virNetDevGetPhysicalFunction;
+virNetDevGetPromiscuous;
+virNetDevGetRcvAllMulti;
+virNetDevGetRcvMulti;
 virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
 virNetDevGetVLanID;
-virNetDevIsOnline;
 virNetDevIsVirtualFunction;
 virNetDevLinkDump;
 virNetDevReplaceMacAddress;
@@ -1663,6 +1666,9 @@ virNetDevSetMTUFromDevice;
 virNetDevSetName;
 virNetDevSetNamespace;
 virNetDevSetOnline;
+virNetDevSetPromiscuous;
+virNetDevSetRcvAllMulti;
+virNetDevSetRcvMulti;
 virNetDevSetupControl;
 virNetDevValidateConfig;
 
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ef96b2b..2bc1b93 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -610,17 +610,7 @@ int virNetDevSetName(const char* ifname, const char 
*newifname)
 
 
 #if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
-/**
- * virNetDevSetOnline:
- * @ifname: the interface name
- * @online: true for up, false for down
- *
- * Function to control if an interface is activated (up, true) or not (down, 
false)
- *
- * Returns 0 in case of success or -1 on error.
- */
-int virNetDevSetOnline(const char *ifname,
-   bool online)
+int virNetDevSetIFFlag(const char *ifname, int flag, bool val)
 {
 int fd = -1;
 int ret = -1;
@@ -637,10 +627,10 @@ int virNetDevSetOnline(const char *ifname,
 goto cleanup;
 }
 
-if (online)
-ifflags = ifr.ifr_flags | IFF_UP;
+if (val)
+ifflags = ifr.ifr_flags | flag;
 else
-ifflags = ifr.ifr_flags & ~IFF_UP;
+ifflags = ifr.ifr_flags & ~flag;
 
 if (ifr.ifr_flags != ifflags) {
 ifr.ifr_flags = ifflags;
@@ -659,8 +649,9 @@ int virNetDevSetOnline(const char *ifname,
 return ret;
 }
 #else
-int virNetDevSetOnline(const char *ifname,
-   bool online ATTRIBUTE_UNUSED)
+int virNetDevSetIFFlag(const char *ifname,
+   int flag ATTRIBUTE_UNUSED,
+   bool val ATTRIBUTE_UNUSED)
 {
 virReportSystemError(ENOSYS,
  _("Cannot set interface flags on '%s'"),
@@ -670,18 +661,77 @@ int virNetDevSetOnline(const char *ifname,
 #endif
 
 
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+
 /**
- * virNetDevIsOnline:
+ * virNetDevSetOnline:
  * @ifname: the interface name
- * @online: where to store the status
+ * @online: true for up, false for down
  *
- * Function to query if an interface is activated (true) or not (false)
+ * Function to control if an interface is activated (up, true) or not (down, 
false)
  *
- * Returns 0 in case of success or an errno code in case of failure.
+ * Returns 0 in case of success or -1 on error.
  */
-int virNetDevIsOnline(const char *ifname,
-  bool *online)
+int virNetDevSetOnline(const char *ifname,
+   bool online)
+{
+
+return virNetDevSetIFFlag(ifname, IFF_UP, online);
+}
+
+/**
+ * virNetDevSetPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: true for receive all packets, false for do not receive
+ *   all packets
+ *
+ * Function to control if an interface is to receive all
+ * packets (receive all, true) or not (do not receive all, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetPromiscuous(const char *ifname,
+bool promiscuous)
+{
+return virNetDevSetIFFlag(ifname, IFF_PROMISC, promiscuous);
+}
+
+/**
+ * virNetDevSetRcvMulti:
+ * @ifname: the interface name
+ * @:receive true for receive multicast packets, false for do not receive
+ *   multicast packets
+ *
+ * Function to control if an interface is to receive multicast
+ * packets in which it is interested (receive, true)
+ * or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvMulti(const char *ifname,
+ bool receive)
+{
+return virNetDevSetIFFlag(ifname, IFF_MULTICAST, receive);
+}
+
+/**
+ * virNetDevSetRcvAllMulti:
+ * @ifname: the interface name
+ * @:receive true for receive all packets, false for do not receive all packets
+ *
+ * Function to control if an interface is to receive all multicast
+ * packets (receive, true

[libvirt] [PATCH v2 2/2] qemu: change macvtap device options in response to NIC_RX_FILTER_CHANGED

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch enables synchronization of the host macvtap
device options with the guest device's in response to the
NIC_RX_FILTER_CHANGED event.

The following device options will be synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

Signed-off-by: Tony Krowiak 
---
Changes for v2 (response to v1 review comments):
* Replaced "default" case in syncNicRxFilterMultiMode function with 
  VIR_NETDEV_RX_FILTER_MODE_NONE

 src/qemu/qemu_driver.c |   92 
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bc6aae4..47c1b5e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4168,6 +4168,93 @@ syncNicRxFilterHostMulticast(char *ifname, 
virNetDevRxFilterPtr guestFilter,
 
 
 static void
+syncNicRxFilterPromiscMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+bool promisc;
+bool setpromisc = false;
+
+/* Set macvtap promisc mode to true if the guest has vlans defined */
+/* or synchronize the macvtap promisc mode if different from guest */
+if (guestFilter->vlan.nTable > 0) {
+if (!hostFilter->promiscuous) {
+setpromisc = true;
+promisc = true;
+}
+} else if (hostFilter->promiscuous != guestFilter->promiscuous) {
+setpromisc = true;
+promisc = guestFilter->promiscuous;
+}
+
+if (setpromisc) {
+if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
+VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ promisc ? "true" : "false", ifname);
+}
+}
+}
+
+
+static void
+syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+if (hostFilter->multicast.mode != guestFilter->multicast.mode) {
+switch (guestFilter->multicast.mode) {
+case VIR_NETDEV_RX_FILTER_MODE_ALL:
+if (virNetDevSetRcvAllMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set allmulticast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
+if (virNetDevSetRcvMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set multicast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NONE:
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvMulti(ifname, false)) {
+VIR_WARN("Couldn't set multicast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED",
+ ifname);
+}
+break;
+}
+}
+}
+
+
+static void
+syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
+syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
+}
+
+
+static void
 syncNicRxFilterMulticast(char *ifname,
  virNetDevRxFilterPtr guestFilter,
  virNetDevRxFilterPtr hostFilter)
@@ -4250,9 +4337,14 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
  * attributes to match those of the guest network device:
  * - MAC address
  * - Multicast MAC address table
+ * - Device options:
+ *   - PROMISC
+ *   - MULTICAST
+ *   - ALLMULTI
  */
 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
+syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
 }
 
  endjob:
-- 
1.7.1

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


[libvirt] [PATCH v3 1/2] util: Functions for getting/setting device options

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch provides the utility functions needed to synchronize
the rxfilter changes made to a guest domain with the corresponding
macvtap devices on the host:

* Get/set PROMISC flag
* Get/set ALLMULTI, MULTICAST

Signed-off-by: Tony Krowiak 
---
Changes for v3:
* Fixed a syntax-check error in virNetDevGetRxFilter function

 src/libvirt_private.syms |8 ++-
 src/util/virnetdev.c |  186 +++---
 src/util/virnetdev.h |   24 ++-
 3 files changed, 190 insertions(+), 28 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a2eec83..8d76f9b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1639,13 +1639,16 @@ virNetDevGetIPv4Address;
 virNetDevGetLinkInfo;
 virNetDevGetMAC;
 virNetDevGetMTU;
+virNetDevGetOnline;
 virNetDevGetPhysicalFunction;
+virNetDevGetPromiscuous;
+virNetDevGetRcvAllMulti;
+virNetDevGetRcvMulti;
 virNetDevGetRxFilter;
 virNetDevGetVirtualFunctionIndex;
 virNetDevGetVirtualFunctionInfo;
 virNetDevGetVirtualFunctions;
 virNetDevGetVLanID;
-virNetDevIsOnline;
 virNetDevIsVirtualFunction;
 virNetDevLinkDump;
 virNetDevReplaceMacAddress;
@@ -1663,6 +1666,9 @@ virNetDevSetMTUFromDevice;
 virNetDevSetName;
 virNetDevSetNamespace;
 virNetDevSetOnline;
+virNetDevSetPromiscuous;
+virNetDevSetRcvAllMulti;
+virNetDevSetRcvMulti;
 virNetDevSetupControl;
 virNetDevValidateConfig;
 
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index ef96b2b..5d330ce 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -610,17 +610,7 @@ int virNetDevSetName(const char* ifname, const char 
*newifname)
 
 
 #if defined(SIOCSIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
-/**
- * virNetDevSetOnline:
- * @ifname: the interface name
- * @online: true for up, false for down
- *
- * Function to control if an interface is activated (up, true) or not (down, 
false)
- *
- * Returns 0 in case of success or -1 on error.
- */
-int virNetDevSetOnline(const char *ifname,
-   bool online)
+int virNetDevSetIFFlag(const char *ifname, int flag, bool val)
 {
 int fd = -1;
 int ret = -1;
@@ -637,10 +627,10 @@ int virNetDevSetOnline(const char *ifname,
 goto cleanup;
 }
 
-if (online)
-ifflags = ifr.ifr_flags | IFF_UP;
+if (val)
+ifflags = ifr.ifr_flags | flag;
 else
-ifflags = ifr.ifr_flags & ~IFF_UP;
+ifflags = ifr.ifr_flags & ~flag;
 
 if (ifr.ifr_flags != ifflags) {
 ifr.ifr_flags = ifflags;
@@ -659,8 +649,9 @@ int virNetDevSetOnline(const char *ifname,
 return ret;
 }
 #else
-int virNetDevSetOnline(const char *ifname,
-   bool online ATTRIBUTE_UNUSED)
+int virNetDevSetIFFlag(const char *ifname,
+   int flag ATTRIBUTE_UNUSED,
+   bool val ATTRIBUTE_UNUSED)
 {
 virReportSystemError(ENOSYS,
  _("Cannot set interface flags on '%s'"),
@@ -670,18 +661,77 @@ int virNetDevSetOnline(const char *ifname,
 #endif
 
 
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ)
+
 /**
- * virNetDevIsOnline:
+ * virNetDevSetOnline:
  * @ifname: the interface name
- * @online: where to store the status
+ * @online: true for up, false for down
  *
- * Function to query if an interface is activated (true) or not (false)
+ * Function to control if an interface is activated (up, true) or not (down, 
false)
  *
- * Returns 0 in case of success or an errno code in case of failure.
+ * Returns 0 in case of success or -1 on error.
  */
-int virNetDevIsOnline(const char *ifname,
-  bool *online)
+int virNetDevSetOnline(const char *ifname,
+   bool online)
+{
+
+return virNetDevSetIFFlag(ifname, IFF_UP, online);
+}
+
+/**
+ * virNetDevSetPromiscuous:
+ * @ifname: the interface name
+ * @promiscuous: true for receive all packets, false for do not receive
+ *   all packets
+ *
+ * Function to control if an interface is to receive all
+ * packets (receive all, true) or not (do not receive all, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetPromiscuous(const char *ifname,
+bool promiscuous)
+{
+return virNetDevSetIFFlag(ifname, IFF_PROMISC, promiscuous);
+}
+
+/**
+ * virNetDevSetRcvMulti:
+ * @ifname: the interface name
+ * @:receive true for receive multicast packets, false for do not receive
+ *   multicast packets
+ *
+ * Function to control if an interface is to receive multicast
+ * packets in which it is interested (receive, true)
+ * or not (do not receive, false)
+ *
+ * Returns 0 in case of success or -1 on error.
+ */
+int virNetDevSetRcvMulti(const char *ifname,
+ bool receive)
+{
+return virNetDevSetIFFlag(ifname, IFF_MULTICAST, receive);
+}
+
+/**
+ * virNetDevSetRcvAllMulti:
+ * @ifname: the interface name
+ * @:receive true for receive all packets, false for do not receive a

[libvirt] [PATCH v3 2/2] qemu: change macvtap device options in response to NIC_RX_FILTER_CHANGED

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch enables synchronization of the host macvtap
device options with the guest device's in response to the
NIC_RX_FILTER_CHANGED event.

The following device options will be synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

Signed-off-by: Tony Krowiak 
---
No changes for v3
 src/qemu/qemu_driver.c |   92 
 1 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index bc6aae4..47c1b5e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4168,6 +4168,93 @@ syncNicRxFilterHostMulticast(char *ifname, 
virNetDevRxFilterPtr guestFilter,
 
 
 static void
+syncNicRxFilterPromiscMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+bool promisc;
+bool setpromisc = false;
+
+/* Set macvtap promisc mode to true if the guest has vlans defined */
+/* or synchronize the macvtap promisc mode if different from guest */
+if (guestFilter->vlan.nTable > 0) {
+if (!hostFilter->promiscuous) {
+setpromisc = true;
+promisc = true;
+}
+} else if (hostFilter->promiscuous != guestFilter->promiscuous) {
+setpromisc = true;
+promisc = guestFilter->promiscuous;
+}
+
+if (setpromisc) {
+if (virNetDevSetPromiscuous(ifname, promisc) < 0) {
+VIR_WARN("Couldn't set PROMISC flag to %s for device %s "
+ "while responding to NIC_RX_FILTER_CHANGED",
+ promisc ? "true" : "false", ifname);
+}
+}
+}
+
+
+static void
+syncNicRxFilterMultiMode(char *ifname, virNetDevRxFilterPtr guestFilter,
+ virNetDevRxFilterPtr hostFilter)
+{
+if (hostFilter->multicast.mode != guestFilter->multicast.mode) {
+switch (guestFilter->multicast.mode) {
+case VIR_NETDEV_RX_FILTER_MODE_ALL:
+if (virNetDevSetRcvAllMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set allmulticast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NORMAL:
+if (virNetDevSetRcvMulti(ifname, true)) {
+
+VIR_WARN("Couldn't set multicast flag to 'on' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+break;
+
+case VIR_NETDEV_RX_FILTER_MODE_NONE:
+if (virNetDevSetRcvAllMulti(ifname, false)) {
+VIR_WARN("Couldn't set allmulticast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED", ifname);
+}
+
+if (virNetDevSetRcvMulti(ifname, false)) {
+VIR_WARN("Couldn't set multicast flag to 'off' for "
+ "device %s while responding to "
+ "NIC_RX_FILTER_CHANGED",
+ ifname);
+}
+break;
+}
+}
+}
+
+
+static void
+syncNicRxFilterDeviceOptions(char *ifname, virNetDevRxFilterPtr guestFilter,
+   virNetDevRxFilterPtr hostFilter)
+{
+syncNicRxFilterPromiscMode(ifname, guestFilter, hostFilter);
+syncNicRxFilterMultiMode(ifname, guestFilter, hostFilter);
+}
+
+
+static void
 syncNicRxFilterMulticast(char *ifname,
  virNetDevRxFilterPtr guestFilter,
  virNetDevRxFilterPtr hostFilter)
@@ -4250,9 +4337,14 @@ processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
  * attributes to match those of the guest network device:
  * - MAC address
  * - Multicast MAC address table
+ * - Device options:
+ *   - PROMISC
+ *   - MULTICAST
+ *   - ALLMULTI
  */
 syncNicRxFilterMacAddr(def->ifname, guestFilter, hostFilter);
 syncNicRxFilterMulticast(def->ifname, guestFilter, hostFilter);
+syncNicRxFilterDeviceOptions(def->ifname, guestFilter, hostFilter);
 }
 
  endjob:
-- 
1.7.1

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


[libvirt] [PATCH v3 0/2] Sync macvtap device modes when guest rxfilter changes

2015-01-22 Thread akrowiak
From: Tony Krowiak 

This patch set provides the code to synchonize some macvtap device 
modes when the values are changed on the guest's network device.  The 
following modes will by synchronized:
* PROMISC
* MULTICAST
* ALLMULTI

I noticed something while testing this patch set that did not occur prior 
to installing more recent kernel and Qemu distributions.  It seems that 
the VLAN table always has an entry for VLAN ID 0 when the rxfilter is 
queried during processing of the NIC_RX_FILTER_CHANGED event.  That means
that the PROMISC flag for macvtap0 will be set.  I don't know if this 
will cause problems, but I thought I'd make note of it in case anybody
wants to comment on that.

v2 changes:
* virnetdev.c
* Changed names of virNetDevIs... functions to virNetDevGet...
* Consolidated code for getting/setting of device option flags
* qemu_driver.c
* Replaced "default" case in syncNicRxFilterMultiMode function with 
  VIR_NETDEV_RX_FILTER_MODE_NONE

v3 changes:
* virnetdev.c
* Fixed a syntax-check error in virNetDevGetRxFilter function

Tony Krowiak (2):
  util: Functions for getting/setting device options
  qemu: change macvtap device options in response to
NIC_RX_FILTER_CHANGED

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