<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body text="#000000" bgcolor="#ffffff">
    Normally wouldn't cross-post, but at first I thought this was a bug
    in the cfg80211 kernel module, but the more I thought about it the
    more it seemed to be a bug in the libnl API itself.<br>
    <br>
    Can someone who understands this better than me weigh in?<br>
    <br>
    Thanks.<br>
    <br>
    -Philip<br>
    <br>
    <br>
    -------- Original Message --------
    <table class="moz-email-headers-table" border="0" cellpadding="0"
      cellspacing="0">
      <tbody>
        <tr>
          <th nowrap="nowrap" valign="BASELINE" align="RIGHT">Subject: </th>
          <td>Re: [PATCH 3/3] nl80211: New command for setting TX rate
            mask for rate control</td>
        </tr>
        <tr>
          <th nowrap="nowrap" valign="BASELINE" align="RIGHT">Date: </th>
          <td>Thu, 19 Aug 2010 14:26:51 -0700</td>
        </tr>
        <tr>
          <th nowrap="nowrap" valign="BASELINE" align="RIGHT">From: </th>
          <td>Philip Prindeville
            <a class="moz-txt-link-rfc2396E" href="mailto:philipp_subx@redfish-solutions.com">&lt;philipp_subx@redfish-solutions.com&gt;</a></td>
        </tr>
        <tr>
          <th nowrap="nowrap" valign="BASELINE" align="RIGHT">To: </th>
          <td>Jouni Malinen <a class="moz-txt-link-rfc2396E" href="mailto:jouni.malinen@atheros.com">&lt;jouni.malinen@atheros.com&gt;</a></td>
        </tr>
        <tr>
          <th nowrap="nowrap" valign="BASELINE" align="RIGHT">CC: </th>
          <td>John W. Linville <a class="moz-txt-link-rfc2396E" href="mailto:linville@tuxdriver.com">&lt;linville@tuxdriver.com&gt;</a>, Johannes
            Berg <a class="moz-txt-link-rfc2396E" href="mailto:johannes@sipsolutions.net">&lt;johannes@sipsolutions.net&gt;</a>,
            <a class="moz-txt-link-abbreviated" href="mailto:linux-wireless@vger.kernel.org">linux-wireless@vger.kernel.org</a>, Jouni Malinen
            <a class="moz-txt-link-rfc2396E" href="mailto:j@w1.fi">&lt;j@w1.fi&gt;</a></td>
        </tr>
      </tbody>
    </table>
    <br>
    <br>
    <pre> On 12/29/09 2:59 AM, Jouni Malinen wrote:

&gt; Add a new NL80211_CMD_SET_TX_BITRATE_MASK command and related
&gt; attributes to provide support for setting TX rate mask for rate
&gt; control. This uses the existing cfg80211 set_bitrate_mask operation
&gt; that was previously used only with WEXT compat code (SIOCSIWRATE). The
&gt; nl80211 command allows more generic configuration of allowed rates as
&gt; a mask instead of fixed/max rate.
&gt;
&gt; Signed-off-by: Jouni Malinen<a class="moz-txt-link-rfc2396E" href="mailto:jouni.malinen@atheros.com">&lt;jouni.malinen@atheros.com&gt;</a>
&gt;
&gt; ---
&gt;   include/linux/nl80211.h |   44 +++++++++++++++++++
&gt;   include/net/cfg80211.h  |    4 -
&gt;   net/wireless/nl80211.c  |  111 ++++++++++++++++++++++++++++++++++++++++++++++++
&gt;   3 files changed, 157 insertions(+), 2 deletions(-)
&gt;
&gt; --- wireless-testing.orig/include/linux/nl80211.h        2009-12-29 10:50:56.000000000 +0200
&gt; +++ wireless-testing/include/linux/nl80211.h        2009-12-29 10:56:42.000000000 +0200
&gt; @@ -295,6 +295,10 @@
&gt;    *        This command is also used as an event to notify when a requested
&gt;    *        remain-on-channel duration has expired.
&gt;    *
&gt; + * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX
&gt; + *        rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
&gt; + *        and @NL80211_ATTR_TX_RATES the set of allowed rates.
&gt; + *
&gt;    * @NL80211_CMD_MAX: highest used command number
&gt;    * @__NL80211_CMD_AFTER_LAST: internal use
&gt;    */
&gt; @@ -381,6 +385,8 @@ enum nl80211_commands {
&gt;           NL80211_CMD_REMAIN_ON_CHANNEL,
&gt;           NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
&gt;
&gt; +        NL80211_CMD_SET_TX_BITRATE_MASK,
&gt; +
&gt;           /* add new commands above here */
&gt;
&gt;           /* used to define NL80211_CMD_MAX below */
&gt; @@ -638,6 +644,13 @@ enum nl80211_commands {
&gt;    *
&gt;    * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects.
&gt;    *
&gt; + * @NL80211_ATTR_TX_RATES: Nested set of attributes
&gt; + *        (enum nl80211_tx_rate_attributes) describing TX rates per band. The
&gt; + *        enum nl80211_band value is used as the index (nla_type() of the nested
&gt; + *        data. If a band is not included, it will be configured to allow all
&gt; + *        rates based on negotiated supported rates information. This attribute
&gt; + *        is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
&gt; + *
&gt;    * @NL80211_ATTR_MAX: highest attribute number currently defined
&gt;    * @__NL80211_ATTR_AFTER_LAST: internal use
&gt;    */
&gt; @@ -779,6 +792,8 @@ enum nl80211_attrs {
&gt;
&gt;           NL80211_ATTR_COOKIE,
&gt;
&gt; +        NL80211_ATTR_TX_RATES,
&gt; +
&gt;           /* add attributes here, update the policy in nl80211.c */
&gt;
&gt;           __NL80211_ATTR_AFTER_LAST,
&gt; @@ -1478,4 +1493,33 @@ enum nl80211_key_attributes {
&gt;           NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
&gt;   };
&gt;
&gt; +/**
&gt; + * enum nl80211_tx_rate_attributes - TX rate set attributes
&gt; + * @__NL80211_TXRATE_INVALID: invalid
&gt; + * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection
&gt; + *        in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
&gt; + *        1 = 500 kbps) but without the IE length restriction (at most
&gt; + *        %NL80211_MAX_SUPP_RATES in a single array).
&gt; + * @__NL80211_TXRATE_AFTER_LAST: internal
&gt; + * @NL80211_TXRATE_MAX: highest TX rate attribute
&gt; + */
&gt; +enum nl80211_tx_rate_attributes {
&gt; +        __NL80211_TXRATE_INVALID,
&gt; +        NL80211_TXRATE_LEGACY,
&gt; +
&gt; +        /* keep last */
&gt; +        __NL80211_TXRATE_AFTER_LAST,
&gt; +        NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
&gt; +};
&gt; +
&gt; +/**
&gt; + * enum nl80211_band - Frequency band
&gt; + * @NL80211_BAND_2GHZ - 2.4 GHz ISM band
&gt; + * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz)
&gt; + */
&gt; +enum nl80211_band {
&gt; +        NL80211_BAND_2GHZ,
&gt; +        NL80211_BAND_5GHZ,
&gt; +};
&gt; +
&gt;   #endif /* __LINUX_NL80211_H */
&gt; --- wireless-testing.orig/net/wireless/nl80211.c        2009-12-29 10:50:57.000000000 +0200
&gt; +++ wireless-testing/net/wireless/nl80211.c        2009-12-29 10:57:37.000000000 +0200
&gt; @@ -143,6 +143,7 @@ static struct nla_policy nl80211_policy[
&gt;                                    .len = WLAN_PMKID_LEN },
&gt;           [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
&gt;           [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
&gt; +        [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
&gt;   };
&gt;
&gt;   /* policy for the attributes */
&gt; @@ -572,6 +573,7 @@ static int nl80211_send_wiphy(struct sk_
&gt;           CMD(del_pmksa, DEL_PMKSA);
&gt;           CMD(flush_pmksa, FLUSH_PMKSA);
&gt;           CMD(remain_on_channel, REMAIN_ON_CHANNEL);
&gt; +        CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
&gt;           if (dev-&gt;wiphy.flags&amp;  WIPHY_FLAG_NETNS_OK) {
&gt;                   i++;
&gt;                   NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
&gt; @@ -4423,6 +4425,109 @@ static int nl80211_cancel_remain_on_chan
&gt;           return err;
&gt;   }
&gt;
&gt; +static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
&gt; +                           u8 *rates, u8 rates_len)
&gt; +{
&gt; +        u8 i;
&gt; +        u32 mask = 0;
&gt; +
&gt; +        for (i = 0; i&lt;  rates_len; i++) {
&gt; +                int rate = (rates[i]&amp;  0x7f) * 5;
&gt; +                int ridx;
&gt; +                for (ridx = 0; ridx&lt;  sband-&gt;n_bitrates; ridx++) {
&gt; +                        struct ieee80211_rate *srate =
&gt; +                                &amp;sband-&gt;bitrates[ridx];
&gt; +                        if (rate == srate-&gt;bitrate) {
&gt; +                                mask |= 1&lt;&lt;  ridx;
&gt; +                                break;
&gt; +                        }
&gt; +                }
&gt; +                if (ridx == sband-&gt;n_bitrates)
&gt; +                        return 0; /* rate not found */
&gt; +        }
&gt; +
&gt; +        return mask;
&gt; +}
&gt; +
&gt; +static struct nla_policy
&gt; +nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] __read_mostly = {
&gt; +        [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
&gt; +                                    .len = NL80211_MAX_SUPP_RATES },
&gt; +};
&gt; +
&gt; +static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
&gt; +                                       struct genl_info *info)
&gt; +{
&gt; +        struct nlattr *tb[NL80211_TXRATE_MAX + 1];
&gt; +        struct cfg80211_registered_device *rdev;
&gt; +        struct cfg80211_bitrate_mask mask;
&gt; +        int err, rem, i;
&gt; +        struct net_device *dev;
&gt; +        struct nlattr *tx_rates;
&gt; +        struct ieee80211_supported_band *sband;
&gt; +
&gt; +        if (info-&gt;attrs[NL80211_ATTR_TX_RATES] == NULL)
&gt; +                return -EINVAL;
&gt; +
&gt; +        rtnl_lock();
&gt; +
&gt; +        err = get_rdev_dev_by_info_ifindex(info,&amp;rdev,&amp;dev);
&gt; +        if (err)
&gt; +                goto unlock_rtnl;
&gt; +
&gt; +        if (!rdev-&gt;ops-&gt;set_bitrate_mask) {
&gt; +                err = -EOPNOTSUPP;
&gt; +                goto unlock;
&gt; +        }
&gt; +
&gt; +        memset(&amp;mask, 0, sizeof(mask));
&gt; +        /* Default to all rates enabled */
&gt; +        for (i = 0; i&lt;  IEEE80211_NUM_BANDS; i++) {
&gt; +                sband = rdev-&gt;wiphy.bands[i];
&gt; +                mask.control[i].legacy =
&gt; +                        sband ? (1&lt;&lt;  sband-&gt;n_bitrates) - 1 : 0;
&gt; +        }
&gt; +
&gt; +        /*
&gt; +         * The nested attribute uses enum nl80211_band as the index. This maps
&gt; +         * directly to the enum ieee80211_band values used in cfg80211.
&gt; +         */
&gt; +        nla_for_each_nested(tx_rates, info-&gt;attrs[NL80211_ATTR_TX_RATES], rem)
&gt; +        {
&gt; +                enum ieee80211_band band = nla_type(tx_rates);

Can this even work?  The first entry in nl80211_band is NL80211_BAND_2GHZ, i.e. zero.

Yet looking at libnl-1.1/lib/attr.c there's:

int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
              struct nla_policy *policy)
{
...
        nla_for_each_attr(nla, head, len, rem) {
                int type = nla_type(nla);

                if (type == 0) {
                        fprintf(stderr, "Illegal nla-&gt;nla_type == 0\n");
                        continue;
                }

so any time nla-&gt;nla_type is set to NL80211_BAND_2GHZ, isn't this going to be problematic?

Or am I misreading this code?

-Philip


&gt; +                if (band&lt;  0 || band&gt;= IEEE80211_NUM_BANDS) {
&gt; +                        err = -EINVAL;
&gt; +                        goto unlock;
&gt; +                }
&gt; +                sband = rdev-&gt;wiphy.bands[band];
&gt; +                if (sband == NULL) {
&gt; +                        err = -EINVAL;
&gt; +                        goto unlock;
&gt; +                }
&gt; +                nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
&gt; +                          nla_len(tx_rates), nl80211_txattr_policy);
&gt; +                if (tb[NL80211_TXRATE_LEGACY]) {
&gt; +                        mask.control[band].legacy = rateset_to_mask(
&gt; +                                sband,
&gt; +                                nla_data(tb[NL80211_TXRATE_LEGACY]),
&gt; +                                nla_len(tb[NL80211_TXRATE_LEGACY]));
&gt; +                        if (mask.control[band].legacy == 0) {
&gt; +                                err = -EINVAL;
&gt; +                                goto unlock;
&gt; +                        }
&gt; +                }
&gt; +        }
&gt; +
&gt; +        err = rdev-&gt;ops-&gt;set_bitrate_mask(&amp;rdev-&gt;wiphy, dev, NULL,&amp;mask);
&gt; +
&gt; + unlock:
&gt; +        dev_put(dev);
&gt; +        cfg80211_unlock_rdev(rdev);
&gt; + unlock_rtnl:
&gt; +        rtnl_unlock();
&gt; +        return err;
&gt; +}
&gt; +
&gt;   static struct genl_ops nl80211_ops[] = {
&gt;           {
&gt;                   .cmd = NL80211_CMD_GET_WIPHY,
&gt; @@ -4697,6 +4802,12 @@ static struct genl_ops nl80211_ops[] = {
&gt;                   .policy = nl80211_policy,
&gt;                   .flags = GENL_ADMIN_PERM,
&gt;           },
&gt; +        {
&gt; +                .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
&gt; +                .doit = nl80211_set_tx_bitrate_mask,
&gt; +                .policy = nl80211_policy,
&gt; +                .flags = GENL_ADMIN_PERM,
&gt; +        },
&gt;   };
&gt;
&gt;   static struct genl_multicast_group nl80211_mlme_mcgrp = {
&gt; --- wireless-testing.orig/include/net/cfg80211.h        2009-12-29 10:54:29.000000000 +0200
&gt; +++ wireless-testing/include/net/cfg80211.h        2009-12-29 10:55:52.000000000 +0200
&gt; @@ -39,8 +39,8 @@
&gt;    * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
&gt;    */
&gt;   enum ieee80211_band {
&gt; -        IEEE80211_BAND_2GHZ,
&gt; -        IEEE80211_BAND_5GHZ,
&gt; +        IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
&gt; +        IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
&gt;
&gt;           /* keep last */
&gt;           IEEE80211_NUM_BANDS
&gt;


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to <a class="moz-txt-link-abbreviated" href="mailto:majordomo@vger.kernel.org">majordomo@vger.kernel.org</a>
More majordomo info at  <a class="moz-txt-link-freetext" href="http://vger.kernel.org/majordomo-info.html">http://vger.kernel.org/majordomo-info.html</a>
</pre>
  </body>
</html>