[libvirt] [PATCH] nodedev: Fix gfeature size to be according to running kernel

Moshe Levi moshele at mellanox.com
Tue Aug 11 07:28:58 UTC 2015



> -----Original Message-----
> From: sendmail [mailto:justsendmailnothingelse at gmail.com] On Behalf Of
> Laine Stump
> Sent: Tuesday, August 11, 2015 9:27 AM
> To: libvir-list at redhat.com
> Cc: Moshe Levi
> Subject: Re: [libvirt] [PATCH] nodedev: Fix gfeature size to be according to
> running kernel
> 
> On 08/08/2015 05:34 AM, Moshe Levi wrote:
> > This patch add virNetDevGetGFeaturesSize to get the supported gfeature
> > size from the kernel
> > ---
> 
> This is interesting/possibly useful, but it doesn't fix the crash that users are
> experiencing. Here is a patch that should fix the crash:
> 
> https://www.redhat.com/archives/libvir-list/2015-August/msg00382.html
> 
> I would rather have that patch pushed before this one (which will mean
> rebasing and resolving some merge conflicts).

Ok I will rebase once you patch is merged. 
> 
> 
> >  src/util/virnetdev.c |   60
> ++++++++++++++++++++++++++++++++++++++++++++++---
> >  1 files changed, 56 insertions(+), 4 deletions(-)
> >
> > diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index
> > 1e20789..3fdf4bb 100644
> > --- a/src/util/virnetdev.c
> > +++ b/src/util/virnetdev.c
> > @@ -89,8 +89,10 @@ VIR_LOG_INIT("util.netdev");
> >
> >  #define RESOURCE_FILE_LEN 4096
> >  #if HAVE_DECL_ETHTOOL_GFEATURES
> > +#define ETH_GSTRING_LEN 32
> 
> Where does the "32" come from? Is it from ETH_GSTRING_LEN (defined in
> ethtool.h)? If so, why not just use that directly instead of #defining a new
> one?

It is define in ethtool-copy.h 
> 
> 
> >  # define TX_UDP_TNL 25
> 
> I'll keep asking this every time I encounter it until I get a response - when I
> look at the ethtool source files in the kernel, it looks to me like the index for
> this capability should be 26 and not 25. Where/how did you arrive at the
> value of 25?
I printed the value when I run ethtool command 
moshe index 25
tx-udp_tnl-segmentation: on
moshe index 26
tx-mpls-segmentation: off [fixed]

ethtool modified code 
static void dump_one_feature(const char *indent, const char *name,
                             const struct feature_state *state,
                             const struct feature_state *ref_state,
                             u32 index)
{
        if (ref_state &&
            !(FEATURE_BIT_IS_SET(state->features.features, index, active) ^
              FEATURE_BIT_IS_SET(ref_state->features.features, index, active)))
                return;
        printf("moshe index %d\n",index);
        printf("%s%s: %s%s\n",
               indent, name,
               FEATURE_BIT_IS_SET(state->features.features, index, active) ?
               "on" : "off",
               (!FEATURE_BIT_IS_SET(state->features.features, index, available)
                || FEATURE_BIT_IS_SET(state->features.features, index,
                                      never_changed))
               ? " [fixed]"
               : (FEATURE_BIT_IS_SET(state->features.features, index, requested)
                  ^ FEATURE_BIT_IS_SET(state->features.features, index, active))
               ? (FEATURE_BIT_IS_SET(state->features.features, index, requested)
                  ? " [requested on]" : " [requested off]")
               : "");
}

Also this how I got the GFEATURES_SIZE 2



> 
> 
> > -# define GFEATURES_SIZE 2
> > +# define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
> > +# define FEATURE_BITS_TO_BLOCKS(n_bits)      DIV_ROUND_UP(n_bits,
> 32U)
> >  # 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)        \
> > @@ -3110,6 +3112,53 @@ virNetDevGFeatureAvailable(const char
> *ifname, struct ethtool_gfeatures *cmd)
> >          ret = FEATURE_BIT_IS_SET(cmd->features, TX_UDP_TNL, active);
> >      return ret;
> >  }
> > +/**
> > + * virNetDevGetGFeaturesSize
> > + * This function return the number of gfeatures supported in
> > + * the kernel
> > + *
> > + * @ifname: name of the interface
> > + *
> > + * Returns gfeature size on success, and 0 on failure or not supported.
> > + */
> > + static int
> > +virNetDevGetGFeaturesSize(const char *ifname) {
> > +    struct {
> > +        struct ethtool_sset_info hdr;
> > +        uint32_t buf[1];
> > +    } sset_info;
> > +    struct ethtool_gstrings *strings;
> > +    uint32_t size = 0;
> > +
> > +    sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
> > +    sset_info.hdr.reserved = 0;
> > +    sset_info.hdr.sset_mask = 1ULL << ETH_SS_FEATURES;
> > +
> > +    if (virNetDevSendEthtoolIoctl(ifname, &sset_info) == -1)
> > +        return size;
> 
> virNetDevSendEthtoolIoctl() logs an error message, but it looks like you want
> for an error to be swallowed here (just returning size = 0). If that's the case
> then virNetDevSendEthtoolIoctl() needs to be reworked to not log errors,
> then every caller to it needs to log the error.
This was comment by John Ferlan he preferred the method will return size 0 if not supported 
or error. My previous patch which I send to him directly and not the ML return -1 on failure. 
But thinking about this again I don't want to swallow if error occur. 
What do you think? 

> 
> 
> > +    size = sset_info.hdr.sset_mask ? sset_info.hdr.data[0] : 0;
> > +
> > +    if (VIR_ALLOC_VAR(strings, struct ethtool_gstrings, sizeof(*strings) +
> size * ETH_GSTRING_LEN)) {
> > +        size = 0;
> > +        return size;
> > +    }
> > +
> > +    strings->cmd = ETHTOOL_GSTRINGS;
> > +    strings->string_set = ETH_SS_FEATURES;
> > +    strings->len = size;
> > +    if (size != 0 && virNetDevSendEthtoolIoctl(ifname, strings) == -1) {
> > +        size = 0;
> > +        goto cleanup;
> > +    }
> > +
> > +    size = FEATURE_BITS_TO_BLOCKS(size);
> > +
> > + cleanup:
> > +    VIR_FREE(strings);
> > +    return size;
> > +}
> > +
> >  # endif
> >
> >
> > @@ -3189,9 +3238,12 @@ virNetDevGetFeatures(const char *ifname,
> >
> >  # 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));
> > +    g_cmd.size = virNetDevGetGFeaturesSize(ifname);
> > +    if (g_cmd.size == 0)
> > +        VIR_DEBUG("GFeatures unsupported or failure in getting
> > + GFeatures size on ifname %s", ifname);
> 
> Should this failure really be ignored? Or should it lead to failure of the entire
> operation?
So I guess only if I will return -1 on failure we should not ignore it (like I mention  in the comment above ) and  the unsupported will be size 0 
And that can be ignored.
> 
> 
> > +    else
> > +        if (virNetDevGFeatureAvailable(ifname, &g_cmd))
> > +            ignore_value(virBitmapSetBit(*out,
> > + VIR_NET_DEV_FEAT_TXUDPTNL));
> >  # endif
> >
> >      if (virNetDevRDMAFeature(ifname, out) < 0)





More information about the libvir-list mailing list