On Mon, Feb 23, 2015 at 03:38:29PM +0000, James Chapman wrote:
Adding functionality to libvirt that will allow it
query the ethtool interface for the availability
of certain NIC HW offload features
Here is an example of the feature XML definition:
<device>
<name>net_eth4_90_e2_ba_5e_a5_45</name>
<path>/sys/devices/pci0000:00/0000:00:03.0/0000:08:00.1/net/eth4</path>
<parent>pci_0000_08_00_1</parent>
<capability type='net'>
<interface>eth4</interface>
<address>90:e2:ba:5e:a5:45</address>
<link speed='10000' state='up'/>
<feature name='rx'/>
<feature name='tx'/>
<feature name='sg'/>
<feature name='tso'/>
<feature name='gso'/>
<feature name='gro'/>
<feature name='rxvlan'/>
<feature name='txvlan'/>
<feature name='rxhash'/>
<capability type='80203'/>
</capability>
</device>
---
docs/formatnode.html.in | 18 +++
docs/schemas/nodedev.rng | 14 +++
src/conf/device_conf.h | 6 +
src/conf/node_device_conf.c | 45 ++++++-
src/conf/node_device_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/node_device/node_device_udev.c | 4 +
src/util/virnetdev.c | 143 ++++++++++++++++++++++
src/util/virnetdev.h | 7 ++
tests/nodedevschemadata/net_00_13_02_b9_f9_d3.xml | 9 ++
tests/nodedevschemadata/net_00_15_58_2f_e9_55.xml | 9 ++
11 files changed, 257 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 */
+};
+
This would be much nicer stored in a bitmap.
I added an enum type for all the features, fixed the nits below and
pushed the patch.
+/**
+ * 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;
+ virDevFeaturePtr tmpfeature = NULL;
+
+ 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 < ARRAY_CARDINALITY(cmds); i++) {
+ cmd.cmd = cmds[i].cmd;
+ if (virNetDevFeatureAvailable(ifname, &cmd)) {
+ if (VIR_ALLOC(tmpfeature) < 0)
+ goto cleanup;
+ if ((ret = VIR_STRDUP(tmpfeature->name, cmds[i].name)) != 1)
+ goto cleanup;
+ if (VIR_APPEND_ELEMENT(*features, *nfeatures, *tmpfeature) < 0)
+ goto cleanup;
+ }
+ }
+
+ cmd.cmd = ETHTOOL_GFLAGS;
+ for (j = 0; j < ARRAY_CARDINALITY(flags); j++) {
+ if (virNetDevFeatureAvailable(ifname, &cmd)) {
These two lines can be exchanged to reduce number of ioctl calls.
+ if (cmd.data & (flags[j].cmd)) {
+ if (VIR_ALLOC(tmpfeature) < 0)
+ goto cleanup;
+ if ((ret = VIR_STRDUP(tmpfeature->name, flags[j].name)) != 1)
+ goto cleanup;
+ if (VIR_APPEND_ELEMENT(*features, *nfeatures, *tmpfeature) < 0)
+ goto cleanup;
+ }
+ }
+ }
+
+ ret = 0;
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index de8b480..22ef1a2 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;
Unused type.
Jan