
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