mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
Reuse the socket in virNetDevGetFeatures
This speeds up node_device_udev driver startup 11x.
This commit is contained in:
parent
d59ca0b05f
commit
0a9bbe748a
@ -3200,26 +3200,17 @@ virNetDevRDMAFeature(const char *ifname,
|
|||||||
* virNetDevSendEthtoolIoctl
|
* virNetDevSendEthtoolIoctl
|
||||||
* This function sends ethtool ioctl request
|
* This function sends ethtool ioctl request
|
||||||
*
|
*
|
||||||
* @ifname: name of the interface
|
* @fd: socket to operate on
|
||||||
* @cmd: reference to an ethtool command structure
|
* @ifr: struct ifreq with the command
|
||||||
*
|
*
|
||||||
* Returns 0 on success, -1 on failure.
|
* Returns 0 on success, -1 on failure.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
virNetDevSendEthtoolIoctl(const char *ifname, void *cmd)
|
virNetDevSendEthtoolIoctl(int fd, struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int fd = -1;
|
|
||||||
struct ifreq ifr;
|
|
||||||
|
|
||||||
/* Ultimately uses AF_PACKET for socket which requires privileged
|
ret = ioctl(fd, SIOCETHTOOL, ifr);
|
||||||
* daemon support.
|
|
||||||
*/
|
|
||||||
if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ifr.ifr_data = cmd;
|
|
||||||
ret = ioctl(fd, SIOCETHTOOL, &ifr);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
case EINVAL: /* kernel doesn't support SIOCETHTOOL */
|
case EINVAL: /* kernel doesn't support SIOCETHTOOL */
|
||||||
@ -3230,12 +3221,10 @@ virNetDevSendEthtoolIoctl(const char *ifname, void *cmd)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
virReportSystemError(errno, "%s", _("ethtool ioctl error"));
|
virReportSystemError(errno, "%s", _("ethtool ioctl error"));
|
||||||
goto cleanup;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
|
||||||
VIR_FORCE_CLOSE(fd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3249,16 +3238,17 @@ struct virNetDevEthtoolFeatureCmd {
|
|||||||
* virNetDevFeatureAvailable
|
* virNetDevFeatureAvailable
|
||||||
* This function checks for the availability of a network device feature
|
* This function checks for the availability of a network device feature
|
||||||
*
|
*
|
||||||
* @ifname: name of the interface
|
* @fd: socket to operate on
|
||||||
|
* @ifr: struct ifreq with the command
|
||||||
* @cmd: reference to an ethtool command structure
|
* @cmd: reference to an ethtool command structure
|
||||||
*
|
*
|
||||||
* Returns true if the feature is available, false otherwise.
|
* Returns true if the feature is available, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
|
virNetDevFeatureAvailable(int fd, struct ifreq *ifr, struct ethtool_value *cmd)
|
||||||
{
|
{
|
||||||
cmd = (void*)cmd;
|
ifr->ifr_data = (void*)cmd;
|
||||||
if (virNetDevSendEthtoolIoctl(ifname, cmd) == 0 &&
|
if (virNetDevSendEthtoolIoctl(fd, ifr) == 0 &&
|
||||||
cmd->data > 0)
|
cmd->data > 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
@ -3267,7 +3257,8 @@ virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
|
virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
|
||||||
const char *ifname)
|
int fd,
|
||||||
|
struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
struct ethtool_value cmd = { 0 };
|
struct ethtool_value cmd = { 0 };
|
||||||
@ -3307,13 +3298,13 @@ virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_CARDINALITY(ethtool_cmds); i++) {
|
for (i = 0; i < ARRAY_CARDINALITY(ethtool_cmds); i++) {
|
||||||
cmd.cmd = ethtool_cmds[i].cmd;
|
cmd.cmd = ethtool_cmds[i].cmd;
|
||||||
if (virNetDevFeatureAvailable(ifname, &cmd))
|
if (virNetDevFeatureAvailable(fd, ifr, &cmd))
|
||||||
ignore_value(virBitmapSetBit(bitmap, ethtool_cmds[i].feat));
|
ignore_value(virBitmapSetBit(bitmap, ethtool_cmds[i].feat));
|
||||||
}
|
}
|
||||||
|
|
||||||
# if HAVE_DECL_ETHTOOL_GFLAGS
|
# if HAVE_DECL_ETHTOOL_GFLAGS
|
||||||
cmd.cmd = ETHTOOL_GFLAGS;
|
cmd.cmd = ETHTOOL_GFLAGS;
|
||||||
if (virNetDevFeatureAvailable(ifname, &cmd)) {
|
if (virNetDevFeatureAvailable(fd, ifr, &cmd)) {
|
||||||
for (i = 0; i < ARRAY_CARDINALITY(flags); i++) {
|
for (i = 0; i < ARRAY_CARDINALITY(flags); i++) {
|
||||||
if (cmd.data & flags[i].cmd)
|
if (cmd.data & flags[i].cmd)
|
||||||
ignore_value(virBitmapSetBit(bitmap, flags[i].feat));
|
ignore_value(virBitmapSetBit(bitmap, flags[i].feat));
|
||||||
@ -3328,16 +3319,19 @@ virNetDevGetEthtoolFeatures(virBitmapPtr bitmap,
|
|||||||
* virNetDevGFeatureAvailable
|
* virNetDevGFeatureAvailable
|
||||||
* This function checks for the availability of a network device gfeature
|
* This function checks for the availability of a network device gfeature
|
||||||
*
|
*
|
||||||
* @ifname: name of the interface
|
* @fd: socket to operate on
|
||||||
* @cmd: reference to a gfeatures ethtool command structure
|
* @ifr: struct ifreq with the command
|
||||||
|
* @cmd: reference to an ethtool command structure
|
||||||
*
|
*
|
||||||
* Returns true if the feature is available, false otherwise.
|
* Returns true if the feature is available, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
virNetDevGFeatureAvailable(const char *ifname, struct ethtool_gfeatures *cmd)
|
virNetDevGFeatureAvailable(int fd,
|
||||||
|
struct ifreq *ifr,
|
||||||
|
struct ethtool_gfeatures *cmd)
|
||||||
{
|
{
|
||||||
cmd = (void*)cmd;
|
ifr->ifr_data = (void*)cmd;
|
||||||
if (virNetDevSendEthtoolIoctl(ifname, cmd) == 0)
|
if (virNetDevSendEthtoolIoctl(fd, ifr) == 0)
|
||||||
return !!FEATURE_BIT_IS_SET(cmd->features, TX_UDP_TNL, active);
|
return !!FEATURE_BIT_IS_SET(cmd->features, TX_UDP_TNL, active);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3345,7 +3339,8 @@ virNetDevGFeatureAvailable(const char *ifname, struct ethtool_gfeatures *cmd)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
|
virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
|
||||||
const char *ifname)
|
int fd,
|
||||||
|
struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
struct ethtool_gfeatures *g_cmd;
|
struct ethtool_gfeatures *g_cmd;
|
||||||
|
|
||||||
@ -3355,7 +3350,7 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
|
|||||||
|
|
||||||
g_cmd->cmd = ETHTOOL_GFEATURES;
|
g_cmd->cmd = ETHTOOL_GFEATURES;
|
||||||
g_cmd->size = GFEATURES_SIZE;
|
g_cmd->size = GFEATURES_SIZE;
|
||||||
if (virNetDevGFeatureAvailable(ifname, g_cmd))
|
if (virNetDevGFeatureAvailable(fd, ifr, g_cmd))
|
||||||
ignore_value(virBitmapSetBit(bitmap, VIR_NET_DEV_FEAT_TXUDPTNL));
|
ignore_value(virBitmapSetBit(bitmap, VIR_NET_DEV_FEAT_TXUDPTNL));
|
||||||
VIR_FREE(g_cmd);
|
VIR_FREE(g_cmd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -3363,7 +3358,8 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap,
|
|||||||
# else
|
# else
|
||||||
static int
|
static int
|
||||||
virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap ATTRIBUTE_UNUSED,
|
virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap ATTRIBUTE_UNUSED,
|
||||||
const char *ifname ATTRIBUTE_UNUSED)
|
int fd ATTRIBUTE_UNUSED,
|
||||||
|
struct ifreq *ifr ATTRIBUGE_UNUSED)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3384,6 +3380,10 @@ int
|
|||||||
virNetDevGetFeatures(const char *ifname,
|
virNetDevGetFeatures(const char *ifname,
|
||||||
virBitmapPtr *out)
|
virBitmapPtr *out)
|
||||||
{
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
int ret = -1;
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
if (!(*out = virBitmapNew(VIR_NET_DEV_FEAT_LAST)))
|
if (!(*out = virBitmapNew(VIR_NET_DEV_FEAT_LAST)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -3393,14 +3393,24 @@ virNetDevGetFeatures(const char *ifname,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virNetDevGetEthtoolFeatures(*out, ifname);
|
/* Ultimately uses AF_PACKET for socket which requires privileged
|
||||||
|
* daemon support.
|
||||||
|
*/
|
||||||
|
if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (virNetDevGetEthtoolGFeatures(*out, ifname) < 0)
|
virNetDevGetEthtoolFeatures(*out, fd, &ifr);
|
||||||
return -1;
|
|
||||||
|
if (virNetDevGetEthtoolGFeatures(*out, fd, &ifr) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (virNetDevRDMAFeature(ifname, out) < 0)
|
if (virNetDevRDMAFeature(ifname, out) < 0)
|
||||||
return -1;
|
goto cleanup;
|
||||||
return 0;
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FORCE_CLOSE(fd);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int
|
int
|
||||||
|
Loading…
Reference in New Issue
Block a user