From: Michael Buesch <mb@bu3sch.de>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org,
Jouni Malinen <jkmaline@cc.hut.fi>,
Johannes Berg <johannes@sipsolutions.net>
Subject: [PATCH #2] d80211: Add API to generate RTS and CTS-to-self frames
Date: Mon, 5 Feb 2007 17:26:09 +0100 [thread overview]
Message-ID: <200702051726.09556.mb@bu3sch.de> (raw)
This adds API calls to generate RTS and CTS-to-self frames.
To be called if the device firmware requires the host to
generate RTS/CTS frames.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Index: bu3sch-wireless-dev/include/linux/ieee80211.h
===================================================================
--- bu3sch-wireless-dev.orig/include/linux/ieee80211.h 2007-02-05 17:21:09.000000000 +0100
+++ bu3sch-wireless-dev/include/linux/ieee80211.h 2007-02-05 17:21:13.000000000 +0100
@@ -189,6 +189,21 @@ struct ieee80211_mgmt {
} __attribute__ ((packed));
+/* Control frames */
+struct ieee80211_rts {
+ __le16 frame_control;
+ __le16 duration;
+ __u8 ra[6];
+ __u8 ta[6];
+} __attribute__ ((packed));
+
+struct ieee80211_cts {
+ __le16 frame_control;
+ __le16 duration;
+ __u8 ra[6];
+} __attribute__ ((packed));
+
+
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
Index: bu3sch-wireless-dev/include/net/d80211.h
===================================================================
--- bu3sch-wireless-dev.orig/include/net/d80211.h 2007-02-05 17:21:09.000000000 +0100
+++ bu3sch-wireless-dev/include/net/d80211.h 2007-02-05 17:21:13.000000000 +0100
@@ -194,7 +194,6 @@ struct ieee80211_tx_control {
#define IEEE80211_TXCTL_TKIP_NEW_PHASE1_KEY (1<<9)
u32 flags; /* tx control flags defined
* above */
- u16 rts_cts_duration; /* duration field for RTS/CTS frame */
u8 retry_limit; /* 1 = only first attempt, 2 = one retry, .. */
u8 power_level; /* per-packet transmit power level, in dBm */
u8 antenna_sel; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
@@ -208,7 +207,8 @@ struct ieee80211_tx_control {
u8 sw_retry_attempt; /* number of times hw has tried to
* transmit frame (not incl. hw retries) */
- int rateidx; /* internal 80211.o rateidx */
+ int rateidx; /* internal 80211.o rateidx */
+ int rts_rateidx; /* internal 80211.o rateidx for RTS/CTS */
int alt_retry_rate; /* retry rate for the last retries, given as the
* hw specific value for the rate (from
* struct ieee80211_rate). To be used to limit
@@ -829,6 +829,70 @@ struct sk_buff *ieee80211_beacon_get(str
struct ieee80211_tx_control *control);
/**
+ * ieee80211_rts_get - RTS frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the RTS.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @rts: The buffer where to store the RTS frame.
+ *
+ * If the RTS frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next RTS frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and RTS frame is needed.
+ */
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl,
+ struct ieee80211_rts *rts);
+
+/**
+ * ieee80211_rts_duration - Get the duration field for an RTS frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the RTS.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the RTS is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+ size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl);
+
+/**
+ * ieee80211_ctstoself_get - CTS-to-self frame generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
+ * @frame_len: the frame length (in octets).
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ * @cts: The buffer where to store the CTS-to-self frame.
+ *
+ * If the CTS-to-self frames are generated by the host system (i.e., not in
+ * hardware/firmware), the low-level driver uses this function to receive
+ * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
+ * for calling this function before and CTS-to-self frame is needed.
+ */
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl,
+ struct ieee80211_cts *cts);
+
+/**
+ * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
+ * @frame_txctl: &struct ieee80211_tx_control of the frame.
+ *
+ * If the CTS-to-self is generated in firmware, but the host system must provide
+ * the duration field, the low-level driver uses this function to receive
+ * the duration field value in little-endian byteorder.
+ */
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl);
+
+/**
* ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
* @hw: pointer as obtained from ieee80211_alloc_hw().
* @if_id: interface ID from &struct ieee80211_if_init_conf.
Index: bu3sch-wireless-dev/net/d80211/ieee80211.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211.c 2007-02-05 17:21:09.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211.c 2007-02-05 17:21:13.000000000 +0100
@@ -802,7 +802,6 @@ ieee80211_tx_h_misc(struct ieee80211_txr
if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
(control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
struct ieee80211_rate *rate;
- int erp = tx->u.tx.rate->flags & IEEE80211_RATE_ERP;
/* Do not use multiple retry rates when using RTS/CTS */
control->alt_retry_rate = -1;
@@ -813,16 +812,8 @@ ieee80211_tx_h_misc(struct ieee80211_txr
!(rate->flags & IEEE80211_RATE_BASIC))
rate--;
- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
- dur += ieee80211_frame_duration(tx->local, 10,
- rate->rate, erp,
- tx->local->
- short_preamble);
- dur += ieee80211_frame_duration(tx->local, tx->skb->len,
- tx->u.tx.rate->rate, erp,
- tx->u.tx.short_preamble);
- control->rts_cts_duration = dur;
control->rts_cts_rate = rate->val;
+ control->rts_rateidx = (int)(rate - tx->local->curr_rates);
}
if (tx->sta) {
@@ -1781,7 +1772,6 @@ struct sk_buff * ieee80211_beacon_get(st
control->power_level = local->hw.conf.power_level;
control->flags |= IEEE80211_TXCTL_NO_ACK;
control->retry_limit = 1;
- control->rts_cts_duration = 0;
control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
}
@@ -1790,6 +1780,91 @@ struct sk_buff * ieee80211_beacon_get(st
}
EXPORT_SYMBOL(ieee80211_beacon_get);
+__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
+ size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_rate *rate;
+ int short_preamble = local->short_preamble;
+ int erp;
+ u16 dur;
+
+ rate = &(local->curr_rates[frame_txctl->rts_rateidx]);
+ erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+ /* CTS duration */
+ dur = ieee80211_frame_duration(local, 10, rate->rate,
+ erp, short_preamble);
+ /* Data frame duration */
+ dur += ieee80211_frame_duration(local, frame_len, rate->rate,
+ erp, short_preamble);
+ /* ACK duration */
+ dur += ieee80211_frame_duration(local, 10, rate->rate,
+ erp, short_preamble);
+
+ return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_rts_duration);
+
+
+__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
+ size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_rate *rate;
+ int short_preamble = local->short_preamble;
+ int erp;
+ u16 dur;
+
+ rate = &(local->curr_rates[frame_txctl->rts_rateidx]);
+ erp = !!(rate->flags & IEEE80211_RATE_ERP);
+
+ /* Data frame duration */
+ dur = ieee80211_frame_duration(local, frame_len, rate->rate,
+ erp, short_preamble);
+ if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
+ /* ACK duration */
+ dur += ieee80211_frame_duration(local, 10, rate->rate,
+ erp, short_preamble);
+ }
+
+ return cpu_to_le16(dur);
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_duration);
+
+void ieee80211_rts_get(struct ieee80211_hw *hw,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl,
+ struct ieee80211_rts *rts)
+{
+ const struct ieee80211_hdr *hdr = frame;
+ u16 fctl;
+
+ fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
+ rts->frame_control = cpu_to_le16(fctl);
+ rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl);
+ memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
+ memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
+}
+EXPORT_SYMBOL(ieee80211_rts_get);
+
+void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
+ const void *frame, size_t frame_len,
+ const struct ieee80211_tx_control *frame_txctl,
+ struct ieee80211_cts *cts)
+{
+ const struct ieee80211_hdr *hdr = frame;
+ u16 fctl;
+
+ fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
+ cts->frame_control = cpu_to_le16(fctl);
+ cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl);
+ memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
+}
+EXPORT_SYMBOL(ieee80211_ctstoself_get);
+
struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
struct ieee80211_tx_control *control)
Index: bu3sch-wireless-dev/net/d80211/ieee80211_sta.c
===================================================================
--- bu3sch-wireless-dev.orig/net/d80211/ieee80211_sta.c 2007-02-05 17:21:09.000000000 +0100
+++ bu3sch-wireless-dev/net/d80211/ieee80211_sta.c 2007-02-05 17:21:13.000000000 +0100
@@ -2068,7 +2068,6 @@ static int ieee80211_sta_join_ibss(struc
control.power_level = local->hw.conf.power_level;
control.flags |= IEEE80211_TXCTL_NO_ACK;
control.retry_limit = 1;
- control.rts_cts_duration = 0;
ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
if (ifsta->probe_resp) {
--
Greetings Michael.
next reply other threads:[~2007-02-05 16:27 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-05 16:26 Michael Buesch [this message]
2007-02-08 19:44 ` [PATCH #2] d80211: Add API to generate RTS and CTS-to-self frames Jiri Benc
2007-02-09 5:57 ` Michael Buesch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200702051726.09556.mb@bu3sch.de \
--to=mb@bu3sch.de \
--cc=jkmaline@cc.hut.fi \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).