[802.11] Add high-level support for CTS protection
authorJoshua Oreman <oremanj@xenon.get-linux.org>
Sat, 13 Jun 2009 02:01:23 +0000 (19:01 -0700)
committerJoshua Oreman <oremanj@xenon.get-linux.org>
Sat, 13 Jun 2009 02:01:23 +0000 (19:01 -0700)
This involves calculating the rate to use for RTS/CTS packets
whenever we change the basic data rate. From there it's up to
the driver to program the card to use the CTS if phy_flags
has the NET80211_PHY_USE_PROTECTION bit set.

src/include/gpxe/net80211.h
src/net/net80211.c

index 8144463..a99b955 100644 (file)
@@ -664,6 +664,13 @@ struct net80211_device
        /** The rate currently in use, as an index into the rates array */
        u8 rate;
 
+       /** The rate to use for RTS/CTS transmissions
+        *
+        * This is always the fastest basic rate that is not faster
+        * than the data rate in use. Also an index into the rates array.
+        */
+       u8 rtscts_rate;
+
        /** Bitmask of basic rates
         *
         * If bit N is set in this value, with the LSB bit 0, then
index 13ef3c2..f378410 100644 (file)
@@ -130,6 +130,7 @@ net80211_marshal_request_info ( struct net80211_device *dev,
                                struct ieee80211_ie *ie );
 
 static void net80211_step_associate ( struct process *proc );
+static void net80211_set_rtscts_rate ( struct net80211_device *dev );
 static void net80211_set_rate_intelligently ( struct net80211_device *dev );
 static void net80211_handle_auth ( struct net80211_device *dev,
                                   struct io_buffer *iob );
@@ -961,6 +962,8 @@ static int net80211_process_ie ( struct net80211_device *dev,
 
                dev->nr_rates -= delta;
 
+               net80211_set_rtscts_rate ( dev );
+
                if ( dev->rates[dev->rate] != old_rate )
                        changed |= NET80211_CFG_RATE;
        }
@@ -1411,6 +1414,41 @@ void net80211_autoassociate ( struct net80211_device *dev )
        dev->associating = NULL;
 }
 
+/**
+ * Pick TX rate for RTS/CTS packets based on data rate
+ *
+ * @v dev      802.11 device
+ *
+ * The RTS/CTS rate is the fastest TX rate marked as "basic" that is
+ * not faster than the data rate.
+ */
+static void net80211_set_rtscts_rate ( struct net80211_device *dev )
+{
+       u16 datarate = NET80211_RATE_VALUE ( dev->rates[dev->rate] );
+       u16 rtsrate = 0;
+       int rts_idx = -1;
+       int i;
+
+       for ( i = 0; i < dev->nr_rates; i++ ) {
+               u16 rate = NET80211_RATE_VALUE ( dev->rates[i] );
+
+               if ( ! ( dev->basic_rates & ( 1 << i ) ) || rate > datarate )
+                       continue;
+
+               if ( rate > rtsrate ) {
+                       rtsrate = rate;
+                       rts_idx = i;
+               }
+       }
+
+       /* If this is in initialization, we might not have any basic
+          rates; just use the first data rate in that case. */
+       if ( rts_idx < 0 )
+               rts_idx = 0;
+
+       dev->rtscts_rate = rts_idx;
+}
+
 /**
  * Pick TX rate from the rate list we have
  *