[libvirt] [PATCHv2] nodedev: add RDMA and tx-udp_tnl-segmentation NIC capabilities

John Ferlan jferlan at redhat.com
Tue Jul 21 11:14:12 UTC 2015



On 07/19/2015 06:11 AM, Moshe Levi wrote:
...

One more that just dawned on me while rereading...  Because
virNetDevGFeatureAvailable is only called when the conditional
HAVE_DECL_ETHTOOL_GFEATURES is set, there should be a couple of other
places to wrap...

> diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
> index 98808e2..e7b7957 100644
> --- a/src/conf/device_conf.c
> +++ b/src/conf/device_conf.c
> @@ -51,7 +51,9 @@ VIR_ENUM_IMPL(virNetDevFeature,
>                "rxvlan",
>                "txvlan",
>                "ntuple",
> -              "rxhash")
> +              "rxhash",
> +              "rdma",
> +              "txudptnl")
>  
>  int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
>  {
> diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
> index 7ea90f6..40a2b3d 100644
> --- a/src/conf/device_conf.h
> +++ b/src/conf/device_conf.h
> @@ -74,6 +74,8 @@ typedef enum {
>      VIR_NET_DEV_FEAT_TXVLAN,
>      VIR_NET_DEV_FEAT_NTUPLE,
>      VIR_NET_DEV_FEAT_RXHASH,
> +    VIR_NET_DEV_FEAT_RDMA,
> +    VIR_NET_DEV_FEAT_TXUDPTNL,
>      VIR_NET_DEV_FEAT_LAST
>  } virNetDevFeature;
>  
> diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
> index e4fcd81..0dcb42d 100644
> --- a/src/util/virnetdev.c
> +++ b/src/util/virnetdev.c
> @@ -87,6 +87,14 @@ VIR_LOG_INIT("util.netdev");
>  # define VIR_IFF_ALLMULTI 0
>  #endif
>  
> +#define RESOURCE_FILE_LEN 4096

The following are only used when HAVE_DECL_ETHTOOL_GFEATURES, I'll wrap
them (including the appropriate spaces on the # define

> +#define TX_UDP_TNL 25
> +#define GFEATURES_SIZE 2
> +#define FEATURE_WORD(blocks, index, field)  ((blocks)[(index) / 32U].field)
> +#define FEATURE_FIELD_FLAG(index)      (1U << (index) % 32U)
> +#define FEATURE_BIT_IS_SET(blocks, index, field)        \
> +    (FEATURE_WORD(blocks, index, field) & FEATURE_FIELD_FLAG(index))
> +
>  typedef enum {
>      VIR_MCAST_TYPE_INDEX_TOKEN,
>      VIR_MCAST_TYPE_NAME_TOKEN,
> @@ -1868,7 +1876,6 @@ virNetDevReplaceMacAddress(const char *linkdev,
>          goto cleanup;
>  
>      ret = 0;
> -
>   cleanup:
>      VIR_FREE(path);
>      return ret;
> @@ -2858,9 +2865,9 @@ static int virNetDevGetMulticastTable(const char *ifname,
>      }
>  
>      ret = 0;
> +
>   cleanup:
>      virNetDevMcastListClear(&mcast);
> -
>      return ret;
>  }
>  
> @@ -2943,11 +2950,76 @@ int virNetDevGetRxFilter(const char *ifname,
>      return ret;
>  }
>  
> +
> +/**
> + * virNetDevRDMAFeature
> + * This function checks for the availability of RDMA feature
> + * and add it to bitmap
> + *
> + * @ifname: name of the interface
> + * @out: add RDMA feature if exist to bitmap
> + *
> + * Returns 0 on success, -1 on failure.
> + */
> +static int
> +virNetDevRDMAFeature(const char *ifname,
> +                     virBitmapPtr *out)
> +{
> +    char *eth_devpath = NULL;
> +    char *ib_devpath = NULL;
> +    char *eth_res_buf = NULL;
> +    char *ib_res_buf = NULL;
> +    DIR *dirp = NULL;
> +    struct dirent *dp;
> +    int ret = -1;
> +
> +    if (!(dirp = opendir(SYSFS_INFINIBAND_DIR))) {
> +        virReportSystemError(errno,
> +                             _("Failed to opendir path '%s'"),
> +                             SYSFS_INFINIBAND_DIR);
> +        goto cleanup;
> +    }
> +
> +    if (virAsprintf(&eth_devpath, SYSFS_NET_DIR "%s/device/resource", ifname) < 0)
> +        goto cleanup;
> +    if (!virFileExists(eth_devpath))
> +        goto cleanup;
> +    if (virFileReadAll(eth_devpath, RESOURCE_FILE_LEN, &eth_res_buf) < 0)
> +        goto cleanup;
> +
> +    while (virDirRead(dirp, &dp, SYSFS_INFINIBAND_DIR) > 0) {
> +        if (dp->d_name[0] == '.')
> +            continue;
> +        if (virAsprintf(&ib_devpath, SYSFS_INFINIBAND_DIR "%s/device/resource", dp->d_name) < 0) {
> +            VIR_FREE(ib_devpath);
> +            continue;
> +        }
> +        if (virFileReadAll(ib_devpath, RESOURCE_FILE_LEN, &ib_res_buf) < 0) {
> +            VIR_FREE(ib_res_buf);
> +            continue;
> +        }
> +        if  (STREQ(eth_res_buf, ib_res_buf)) {
> +            ignore_value(virBitmapSetBit(*out, VIR_NET_DEV_FEAT_RDMA));
> +            break;
> +        }
> +        VIR_FREE(ib_res_buf);
> +    }
> +    ret = 0;
> +
> + cleanup:
> +    closedir(dirp);
> +    VIR_FREE(eth_devpath);
> +    VIR_FREE(ib_devpath);
> +    VIR_FREE(eth_res_buf);
> +    VIR_FREE(ib_res_buf);
> +    return ret;
> +}
> +
>  #if defined(SIOCETHTOOL) && defined(HAVE_STRUCT_IFREQ)
>  
>  /**
> - * virNetDevFeatureAvailable
> - * This function checks for the availability of a network device feature
> + * virNetDevSendEthtoolIoctl
> + * This function sends ethtool ioctl request
>   *
>   * @ifname: name of the interface
>   * @cmd: reference to an ethtool command structure
> @@ -2955,7 +3027,7 @@ int virNetDevGetRxFilter(const char *ifname,
>   * Returns 0 on success, -1 on failure.
>   */
>  static int
> -virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
> +virNetDevSendEthtoolIoctl(const char *ifname, void *cmd)
>  {
>      int ret = -1;
>      int sock = -1;
> @@ -2969,9 +3041,9 @@ virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
>  
>      memset(&ifr, 0, sizeof(ifr));
>      strcpy(ifr.ifr_name, ifname);
> -    ifr.ifr_data = (void*) cmd;
> -
> -    if (ioctl(sock, SIOCETHTOOL, &ifr) != 0) {
> +    ifr.ifr_data = cmd;
> +    ret = ioctl(sock, SIOCETHTOOL, &ifr);
> +    if (ret != 0) {
>          switch (errno) {
>              case EPERM:
>                  VIR_DEBUG("ethtool ioctl: permission denied");
> @@ -2988,11 +3060,51 @@ virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
>          }
>      }
>  
> -    ret = cmd->data > 0 ? 1: 0;
>   cleanup:
>      if (sock)
>          VIR_FORCE_CLOSE(sock);
> +    return ret;
> +}
>  
> +
> +/**
> +* 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 if not found, 1 on success, and -1 on failure.
> +*/
> +static int
> +virNetDevFeatureAvailable(const char *ifname, struct ethtool_value *cmd)
> +{
> +    int ret = -1;
> +
> +    cmd = (void*)cmd;
> +    if (!virNetDevSendEthtoolIoctl(ifname, cmd))
> +        ret = cmd->data > 0 ? 1: 0;
> +    return ret;
> +}
> +
> +

The following is only called when HAVE_DECL_ETHTOOL_GFEATURES.

If not wrapped in the #ifdef too, then on arches where it isn't true,
the compiler will probably complain about a static function that's
defined, but not used.

> +/**
> + * virNetDevGFeatureAvailable
> + * This function checks for the availability of a network device gfeature
> + *
> + * @ifname: name of the interface
> + * @cmd: reference to a gfeatures ethtool command structure
> + *
> + * Returns 0 if not found, 1 on success, and -1 on failure.
> + */
> +static int
> +virNetDevGFeatureAvailable(const char *ifname, struct ethtool_gfeatures *cmd)
> +{
> +    int ret = -1;
> +
> +    cmd = (void*)cmd;
> +    if (!virNetDevSendEthtoolIoctl(ifname, cmd))
> +        ret = FEATURE_BIT_IS_SET(cmd->features, TX_UDP_TNL, active);
>      return ret;
>  }
>  
> @@ -3013,7 +3125,7 @@ virNetDevGetFeatures(const char *ifname,
>  {
>      size_t i = -1;
>      struct ethtool_value cmd = { 0 };
> -
> +    struct ethtool_gfeatures g_cmd = { 0 };

Same for g_cmd needing the wrapping

I'll make those changes as well

John
>      struct elem{
>          const int cmd;
>          const virNetDevFeature feat;
> @@ -3069,6 +3181,15 @@ virNetDevGetFeatures(const char *ifname,
>      }
>  # endif
>  
> +#  if HAVE_DECL_ETHTOOL_GFEATURES
> +    g_cmd.cmd = ETHTOOL_GFEATURES;
> +    g_cmd.size = GFEATURES_SIZE;
> +    if (virNetDevGFeatureAvailable(ifname, &g_cmd))
> +        ignore_value(virBitmapSetBit(*out, VIR_NET_DEV_FEAT_TXUDPTNL));
> +# endif
> +
> +    if (virNetDevRDMAFeature(ifname, out))
> +        return -1;
>      return 0;
>  }
>  #else




More information about the libvir-list mailing list