[libvirt] [PATCH 0/5] Boot options cleanup
by Ján Tomko
Remove the -bootloader option from the QEMU driver, for
https://bugzilla.redhat.com/show_bug.cgi?id=1176050
as it was only supported by xenner.
Remove the -domid option, also xenner-only.
Cleanup -boot command line generation.
Ján Tomko (5):
Remove bootloader option from QEMU
Remove code handling the QEMU_CAPS_DOMID capability
Make -boot arg generation more readable
Rename boot_buf to boot_opts
Use virBufferTrim when generating boot options
src/qemu/qemu_command.c | 240 ++++++++++-----------
src/qemu/qemu_domain.c | 6 +
.../qemuxml2argvdata/qemuxml2argv-bootloader.args | 5 -
tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml | 27 ---
tests/qemuxml2argvdata/qemuxml2argv-input-xen.args | 5 -
tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml | 34 ---
tests/qemuxml2argvtest.c | 7 +-
tests/qemuxml2xmltest.c | 2 -
tests/qemuxmlnstest.c | 5 +-
9 files changed, 122 insertions(+), 209 deletions(-)
delete mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bootloader.args
delete mode 100644 tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml
delete mode 100644 tests/qemuxml2argvdata/qemuxml2argv-input-xen.args
delete mode 100644 tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml
--
2.0.5
9 years, 9 months
[libvirt] SR-IOV with libvirt
by Florin Stingaciu
Hello,
For the last little while I've been trying to configure a VM with a
passthrough interface using SR-IOV. I've managed to configure SR-IOV on the
hypervisor correctly. I'm working with a Mellanox ConnectX3 card with two
infiniband ports and hypervisors running Centos 7. I can see the PCI
devices (ie. virtual functions) using the `virsh nodedev-list` command.
The majority of tutorials online (including the tutorials on the libvirt
site), suggest one configures an SR-IOV passthrough interface in the
following manner in the VM definition file:
<interface type='hostdev' managed='yes'>
<mac address='52:54:00:d7:cd:aa'/>
<source>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00'
function='0x2'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</interface>
For example the above configuration should configure the second VF as a
passthrough interface for this VM. When I try to launch the VM, I get the
following error:
error: Failed to start domain test
error: internal error: missing IFLA_VF_INFO in netlink response
I've done research on this error quite extensively. This used to be a very
popular error a while back for scenarios where the total number of VFs is >
64. This is not the case here as I only have 8.
I've was never able to overcome this error but I did manage to get this
working another way. The VM will boot just fine and detect a new interface
if you define one of the VFs as a PCI in the following manner within the VM
definition file:
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x01' slot='0x00' function='0x2'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06'
function='0x0'/>
</hostdev>
As you can see the from the source bus and function, it's the same VF I was
trying with the definition above. I'm wondering if there is any particular
reason for this or how could I get around this error. Normally, I would
just use the second configuration, however I'm about to begin work within
an openstack environment where the sriovnicswitch ml2 plugin will be used
for networking. This plugin, when configuring passthrough interfaces uses
the first definition that does not work and spits out that error.
Considering even the official libvirt tutorials suggest the first way, I
feel like I must be missing something, or something broke and noone noticed
in one of the latest updates. Any help would be greatly appreciated.
Thanks,
-F
9 years, 9 months
[libvirt] [PATCHv2] Clarify behavior or virDomainDetachDevice
by Ján Tomko
Document that a complete device definition should be used
and a partial match can lead to the device being detached.
https://bugzilla.redhat.com/show_bug.cgi?id=872028
---
src/libvirt-domain.c | 14 ++++++++++++++
tools/virsh.pod | 9 ++++++---
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 492e90a..fb85a28 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -8266,6 +8266,13 @@ virDomainAttachDeviceFlags(virDomainPtr domain,
* into S4 state (also known as hibernation) unless you also modify the
* persistent domain definition.
*
+ * The supplied XML description of the device should be as specific
+ * as its definition in the domain XML. The set of attributes used
+ * to match the device are internal to the drivers. Using a partial definition,
+ * or attempting to detach a device that is not present in the domain XML,
+ * but shares some specific attributes with one that is present
+ * may lead to unexpected results.
+ *
* Returns 0 in case of success, -1 in case of failure.
*/
int
@@ -8341,6 +8348,13 @@ virDomainDetachDevice(virDomainPtr domain, const char *xml)
* into S4 state (also known as hibernation) unless you also modify the
* persistent domain definition.
*
+ * The supplied XML description of the device should be as specific
+ * as its definition in the domain XML. The set of attributes used
+ * to match the device are internal to the drivers. Using a partial definition,
+ * or attempting to detach a device that is not present in the domain XML,
+ * but shares some specific attributes with one that is present
+ * may lead to unexpected results.
+ *
* Returns 0 in case of success, -1 in case of failure.
*/
int
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 50de32c..09663f5 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2439,9 +2439,12 @@ as command B<attach-device>.
For passthrough host devices, see also B<nodedev-reattach>, needed if
the device does not use managed mode.
-B<Note>: using of partial device definition XML files may lead to unexpected
-results as some fields may be autogenerated and thus match devices other than
-expected.
+B<Note>: The supplied XML description of the device should be as specific
+as its definition in the domain XML. The set of attributes used
+to match the device are internal to the drivers. Using a partial definition,
+or attempting to detach a device that is not present in the domain XML,
+but shares some specific attributes with one that is present
+may lead to unexpected results.
If I<--live> is specified, affect a running domain.
If I<--config> is specified, affect the next startup of a persistent domain.
--
2.0.5
9 years, 9 months
[libvirt] [PATCH] Clarify behavior or virDomainDetachDevice
by Ján Tomko
Doucment that not all attributes are used for matching.
https://bugzilla.redhat.com/show_bug.cgi?id=872028
---
src/libvirt-domain.c | 5 +++++
tools/virsh.pod | 4 +++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 492e90a..a95c096 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -8341,6 +8341,11 @@ virDomainDetachDevice(virDomainPtr domain, const char *xml)
* into S4 state (also known as hibernation) unless you also modify the
* persistent domain definition.
*
+ * Note that not all attributes from the XML definition are checked.
+ * For example, if the mac address and the pci address specified in the XML
+ * match an existing interface, but source and interface type do not,
+ * the existing interface will be detached.
+ *
* Returns 0 in case of success, -1 in case of failure.
*/
int
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 50de32c..2c584d3 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2441,7 +2441,9 @@ the device does not use managed mode.
B<Note>: using of partial device definition XML files may lead to unexpected
results as some fields may be autogenerated and thus match devices other than
-expected.
+expected. Not every device attribute is checked when matching the device.
+For example a network interface can be detatched if the mac and PCI addresses
+match, even if the type does not.
If I<--live> is specified, affect a running domain.
If I<--config> is specified, affect the next startup of a persistent domain.
--
2.0.5
9 years, 9 months
[libvirt] [PATCH] qemu: Allow spaces in disk serial
by Michal Privoznik
There's been a bug report appearing on the qemu-devel list, that
libvirt is unable to pass spaces in disk serial number [1]. Not only
our RNG schema forbids that, the code is not prepared either. However,
with a bit of escaping (if needed) we can allow spaces there.
1: https://lists.gnu.org/archive/html/qemu-devel/2015-02/msg04041.html
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/schemas/domaincommon.rng | 2 +-
src/qemu/qemu_command.c | 5 ++--
.../qemuxml2argvdata/qemuxml2argv-disk-serial.args | 6 +++++
.../qemuxml2argvdata/qemuxml2argv-disk-serial.xml | 27 ++++++++++++++++++++++
tests/qemuxml2argvtest.c | 5 ++++
5 files changed, 42 insertions(+), 3 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-serial.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-serial.xml
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f41ca43..09bd921 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5067,7 +5067,7 @@
</define>
<define name="diskSerial">
<data type="string">
- <param name="pattern">[A-Za-z0-9_\.\+\-]+</param>
+ <param name="pattern">[A-Za-z0-9_\.\+\- ]+</param>
</data>
</define>
<define name="bridgeMode">
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7853125..b9adef6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2633,7 +2633,7 @@ qemuBuildIoEventFdStr(virBufferPtr buf,
}
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ "
static int
qemuSafeSerialParamValue(const char *value)
@@ -3616,7 +3616,8 @@ qemuBuildDriveStr(virConnectPtr conn,
virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_SERIAL)) {
if (qemuSafeSerialParamValue(disk->serial) < 0)
goto error;
- virBufferAsprintf(&opt, ",serial=%s", disk->serial);
+ virBufferAddLit(&opt, ",serial=");
+ virBufferEscapeShell(&opt, disk->serial);
}
if (disk->cachemode) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.args
new file mode 100644
index 0000000..8b08cfb
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.args
@@ -0,0 +1,6 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/libexec/qemu-kvm -S -M pc -cpu qemu32 -m 214 -smp 1 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb \
+-drive 'file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-1,serial='\'' WD-WMAP9A966149'\''' \
+-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.xml
new file mode 100644
index 0000000..0fe75f3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-serial.xml
@@ -0,0 +1,27 @@
+<domain type='kvm'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/libexec/qemu-kvm</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <serial> WD-WMAP9A966149</serial>
+ <address type='drive' controller='0' bus='0' target='0' unit='1'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 16f325e..3032d1b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -904,6 +904,11 @@ mymain(void)
QEMU_CAPS_DEVICE,
QEMU_CAPS_SCSI_BLOCK, QEMU_CAPS_VIRTIO_BLK_SG_IO,
QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI);
+ DO_TEST("disk-serial",
+ QEMU_CAPS_KVM,
+ QEMU_CAPS_DEVICE,
+ QEMU_CAPS_DRIVE,
+ QEMU_CAPS_DRIVE_SERIAL);
DO_TEST("graphics-vnc", QEMU_CAPS_VNC);
DO_TEST("graphics-vnc-socket", QEMU_CAPS_VNC);
--
2.0.5
9 years, 9 months
[libvirt] [PATCH 0/3] s390: rework and prevent default usb controller
by Stefan Zimmermann
Stefan Zimmermann (3):
Prevent default creation of usb controller on s390 and s390x
Adjust s390 test cases by removing usb device instances
Rework s390 architecture checking
src/qemu/qemu_command.c | 4 +++-
src/qemu/qemu_domain.c | 13 +++++++++----
tests/qemuxml2argvdata/qemuxml2argv-minimal-s390.args | 2 +-
.../qemuxml2argv-s390-piix-controllers.args | 2 +-
.../qemuxml2xmlout-s390-defaultconsole.xml | 1 -
5 files changed, 14 insertions(+), 8 deletions(-)
--
2.1.4
9 years, 9 months
[libvirt] [PATCH] Assign default SCSI controller model before checking attribute validity
by Ján Tomko
If the qemu binary on x86 does not support lsi SCSI controller,
but it supports virtio-scsi, we reject the virtio-specific attributes
for no reason.
Move the default controller assignment before the check.
https://bugzilla.redhat.com/show_bug.cgi?id=1168849
---
src/qemu/qemu_command.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 743d6f0..882a97c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4353,10 +4353,15 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
int *nusbcontroller)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
- int model;
+ int model = def->model;
+
+ if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
+ if ((qemuSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0)
+ return NULL;
+ }
if (!(def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI &&
- def->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI)) {
+ model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI)) {
if (def->queues) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("'queues' is only supported by virtio-scsi controller"));
@@ -4376,10 +4381,6 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
switch (def->type) {
case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
- model = def->model;
- if ((qemuSetSCSIControllerModel(domainDef, qemuCaps, &model)) < 0)
- return NULL;
-
switch (model) {
case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
--
2.0.5
9 years, 9 months
[libvirt] [PATCH] man: moved virsh command cpu-models
by Daniel Hansel
The description of the virsh command 'cpu-models' was written in the
wrong context (i.e. beside the domain states).
This patch moves the command description just to the cpu related
commands like 'cpu-baseline' and 'cpu-compare'.
Signed-off-by: Daniel Hansel <daniel.hansel(a)linux.vnet.ibm.com>
---
tools/virsh.pod | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 50de32c..b86c415 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -422,10 +422,6 @@ current domain is in.
=over 4
-=item B<cpu-models> I<arch>
-
-Print the list of CPU models known for the specified architecture.
-
=item B<running>
The domain is currently running on a CPU
@@ -573,6 +569,10 @@ I<cellno> modifier can be used to narrow the modification down to
a single host NUMA cell. On the other end of spectrum lies
I<--all> which executes the modification on all NUMA cells.
+=item B<cpu-models> I<arch>
+
+Print the list of CPU models known for the specified architecture.
+
=item B<cpu-baseline> I<FILE> [I<--features>]
Compute baseline CPU which will be supported by all host CPUs given in <file>.
--
1.9.3
9 years, 9 months
[libvirt] [PATCH] SRIOV NIC offload feature discovery
by James Chapman
Adding functionality to libvirt that will allow it
query the ethtool interface for the availability
of certain NIC HW offload features
---
src/conf/device_conf.h | 6 ++
src/conf/node_device_conf.c | 7 ++
src/conf/node_device_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/node_device/node_device_udev.c | 4 ++
src/util/virnetdev.c | 134 +++++++++++++++++++++++++++++++++++++
src/util/virnetdev.h | 12 +++-
7 files changed, 165 insertions(+), 1 deletion(-)
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 7256cdc..091f2f0 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -62,6 +62,12 @@ struct _virInterfaceLink {
unsigned int speed; /* link speed in Mbits per second */
};
+typedef struct _virDevFeature virDevFeature;
+typedef virDevFeature *virDevFeaturePtr;
+struct _virDevFeature {
+ char *name; /* device feature */
+};
+
int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr);
int virDevicePCIAddressParseXML(xmlNodePtr node,
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index a728a00..7f4dbfe 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -437,6 +437,12 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferEscapeString(&buf, "<address>%s</address>\n",
data->net.address);
virInterfaceLinkFormat(&buf, &data->net.lnk);
+ if (data->net.features) {
+ for (i = 0; i < data->net.nfeatures; i++) {
+ virBufferAsprintf(&buf, "<feature name='%s'/>\n",
+ data->net.features[i].name);
+ }
+ }
if (data->net.subtype != VIR_NODE_DEV_CAP_NET_LAST) {
const char *subtyp =
virNodeDevNetCapTypeToString(data->net.subtype);
@@ -1679,6 +1685,7 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
case VIR_NODE_DEV_CAP_NET:
VIR_FREE(data->net.ifname);
VIR_FREE(data->net.address);
+ VIR_FREE(data->net.features);
break;
case VIR_NODE_DEV_CAP_SCSI_HOST:
VIR_FREE(data->scsi_host.wwnn);
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index fd5d179..918523a 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -141,6 +141,8 @@ struct _virNodeDevCapsDef {
char *ifname;
virInterfaceLink lnk;
virNodeDevNetCapType subtype; /* LAST -> no subtype */
+ size_t nfeatures;
+ virDevFeaturePtr features;
} net;
struct {
unsigned int host;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c07a561..1d165a9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1659,6 +1659,7 @@ virNetDevAddRoute;
virNetDevClearIPAddress;
virNetDevDelMulti;
virNetDevExists;
+virNetDevGetFeatures;
virNetDevGetIndex;
virNetDevGetIPv4Address;
virNetDevGetLinkInfo;
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 03c7a0b..349733f 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -719,6 +719,10 @@ static int udevProcessNetworkInterface(struct udev_device *device,
if (virNetDevGetLinkInfo(data->net.ifname, &data->net.lnk) < 0)
goto out;
+ if (virNetDevGetFeatures(data->net.ifname, &data->net.features,
+ &data->net.nfeatures) < 0)
+ goto out;
+
ret = 0;
out:
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 2a0eb43..e513c85 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -2728,3 +2728,137 @@ int virNetDevGetRxFilter(const char *ifname,
*filter = fil;
return ret;
}
+
+#if defined(SIOCETHTOOL) && defined(HAVE_STRUCT_IFREQ)
+
+/**
+ * _virNetDevFeatureAvailable
+ * This function checks for the availability of a network device feature
+ *
+ * @ifname: name of the interface
+ * @cmd: reference to an ethtool command structure
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+_virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
+{
+ int ret = -1;
+ int sock = -1;
+ virIfreq ifr;
+
+ sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ virReportSystemError(errno, "%s", _("Cannot open control socket"));
+ goto cleanup;
+ }
+
+ strcpy(ifr.ifr_name, ifname);
+ ifr.ifr_data = (void*) cmd;
+
+ if (ioctl(sock, SIOCETHTOOL, &ifr) != 0) {
+ /* Privileged command, no error */
+ if (errno == EPERM || errno == EINVAL) {
+ virReportSystemError(errno, "%s", _("ioctl"));
+ /* Some kernels dont support named feature, no error */
+ } else if (errno == EOPNOTSUPP) {
+ virReportSystemError(errno, "%s", _("Warning"));
+ } else {
+ virReportSystemError(errno, "%s", _("Error"));
+ goto cleanup;
+ }
+ }
+
+ ret = cmd->data > 0 ? 1: 0;
+ cleanup:
+ if (sock)
+ VIR_FORCE_CLOSE(sock);
+
+ return ret;
+}
+
+
+/**
+ * virNetDevGetFeatures:
+ * This function gets the nic offloads features available for ifname
+ *
+ * @ifname: name of the interface
+ * @features: network device feature structures
+ * @nfeatures: number of features available
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+virNetDevGetFeatures(const char *ifname,
+ virDevFeaturePtr *features,
+ size_t *nfeatures)
+{
+ int ret = -1;
+ size_t i = -1;
+ size_t j = -1;
+ struct ethtool_value cmd;
+
+ struct elem{
+ const char *name;
+ const int cmd;
+ };
+ /* legacy ethtool getters */
+ struct elem cmds[] = {
+ {"rx", ETHTOOL_GRXCSUM},
+ {"tx", ETHTOOL_GTXCSUM },
+ {"sg", ETHTOOL_GSG},
+ {"tso", ETHTOOL_GTSO},
+ {"gso", ETHTOOL_GGSO},
+ {"gro", ETHTOOL_GGRO},
+ };
+ /* ethtool masks */
+ struct elem flags[] = {
+ {"lro", ETH_FLAG_LRO},
+ {"rxvlan", ETH_FLAG_RXVLAN},
+ {"txvlan", ETH_FLAG_TXVLAN},
+ {"ntuple", ETH_FLAG_NTUPLE},
+ {"rxhash", ETH_FLAG_RXHASH},
+ };
+
+ for (i = 0; i < (sizeof(cmds)/sizeof(struct elem)); i++) {
+ cmd.cmd = cmds[i].cmd;
+ if (_virNetDevFeatureAvailable(ifname, &cmd)) {
+ if (VIR_EXPAND_N(*features, *nfeatures, 1) < 0)
+ goto cleanup;
+ if ((ret = VIR_STRDUP((*features)[i].name, cmds[i].name)) != 1)
+ goto cleanup;
+ }
+ }
+
+ cmd.cmd = ETHTOOL_GFLAGS;
+ for (j = 0; j < (sizeof(flags)/sizeof(struct elem)); j++) {
+ if (_virNetDevFeatureAvailable(ifname, &cmd)) {
+ if (cmd.data & (flags[j].cmd)) {
+ if (VIR_EXPAND_N(*features, *nfeatures, 1) < 0)
+ goto cleanup;
+ if ((ret = VIR_STRDUP((*features)[i++].name, flags[j].name)) != 1)
+ goto cleanup;
+ }
+ }
+ }
+
+ ret = 0;
+ cleanup:
+
+ return ret;
+
+}
+#else
+int
+virNetDevGetFeatures(const char *ifname,
+ virDevFeaturePtr *features,
+ size_t *nfeatures)
+{
+ VIR_DEBUG("Getting network device features on %s is not implemented on this platform",
+ ifname);
+ *features = NULL;
+ *nfeatures = 0;
+
+ return 0;
+}
+#endif
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index de8b480..3847c68 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -31,6 +31,8 @@
# include "virpci.h"
# include "device_conf.h"
+# include <linux/ethtool.h>
+typedef struct ethtool_cmd virEthCmd;
# ifdef HAVE_STRUCT_IFREQ
typedef struct ifreq virIfreq;
# else
@@ -182,9 +184,17 @@ int virNetDevGetVirtualFunctionInfo(const char *vfname, char **pfname,
int *vf)
ATTRIBUTE_NONNULL(1);
+int virNetDevGetFeatures(const char *ifname,
+ virDevFeaturePtr *features,
+ size_t *nfeatures)
+ ATTRIBUTE_NONNULL(1);
+
+int _virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
int virNetDevGetLinkInfo(const char *ifname,
virInterfaceLinkPtr lnk)
- ATTRIBUTE_NONNULL(1);
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
virNetDevRxFilterPtr virNetDevRxFilterNew(void)
ATTRIBUTE_RETURN_CHECK;
--
2.1.0
9 years, 9 months
[libvirt] Exact meaning of "nativeMode" attribute in vlan tags
by Laine Stump
You'd think that I would know this, since I'm the person who reviewed
jrobson's patch adding support for the nativeMode attribute to the vlan
tag element. But you'd be wrong. Here is what the config looks like:
<vlan trunk='yes'>
<tag id='42' nativeMode='untagged'/>
<tag id='47'/>
</vlan>
I understand that trunk='yes' means that packets with any of the tags
listed in a <tag> subelement can be sent out this port (and the tag will
*not* be removed), and likewise packets arriving into the bridge from
the port are allowed to have any of the listed tags (and, again, no tag
will be removed). But what exactly do nativeMode='untagged' and
nativeMode='tagged' mean?
As I understand it, (nativeMode='untagged'|nativeMode='tagged') means
that packets (arriving from|sent to) the port (without a tag/with that
tag) will be (tagged|untagged). Can someone who fully understands this
please select A or B for each of the 4 parenthesized items (in as many
permutations as make sense).
I guess that in one of the modes, untagged packets going in one
direction or the other will be tagged, and vice versa, I just don't know
which direction does which, and for which mode, and don't want to guess.
(I'm asking this because I want to implement identical functionality for
standard Linux host bridges - I want to make sure there are no surprises
for people switching between OVS and Linux host bridge implementations).
9 years, 9 months