PERFORCE change 149552 for review
Sam Leffler
sam at FreeBSD.org
Wed Sep 10 17:58:49 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=149552
Change 149552 by sam at sam_ebb on 2008/09/10 17:57:49
Checkpoint support for sending BAR:
o set the start seq# from ni_txseqs
o add callback for response processing for driver to override
o don't commit the new seq# until we believe the BAR has been
delivered; this is problematic for drivers that don't give
back ACK status (so they'll just have to assume it goes through)
NB: there is no locking and we should allocate tap struct's
on demand instead of statically allocating them in the node
NB: we are super aggressive sending BAR as it's delivery is
critical; this may need to be rethought
NB: we reuse the addba request state which is a hack
done w/ the assumption there should never be an
addba request pending at the same time we send BAR
Affected files ...
.. //depot/projects/vap/sys/net80211/ieee80211_ht.c#48 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ht.h#21 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#52 edit
Differences ...
==== //depot/projects/vap/sys/net80211/ieee80211_ht.c#48 (text+ko) ====
@@ -86,6 +86,8 @@
int ieee80211_addba_timeout = -1; /* timeout waiting for ADDBA response */
int ieee80211_addba_backoff = -1; /* backoff after max ADDBA requests */
int ieee80211_addba_maxtries = 3; /* max ADDBA requests before backoff */
+int ieee80211_bar_timeout = -1; /* timeout waiting for BAR response */
+int ieee80211_bar_maxtries = 50; /* max BAR requests before DELBA */
/*
* Setup HT parameters that depends on the clock frequency.
@@ -98,6 +100,7 @@
#endif
ieee80211_addba_timeout = msecs_to_ticks(250);
ieee80211_addba_backoff = msecs_to_ticks(10*1000);
+ ieee80211_bar_timeout = msecs_to_ticks(250);
}
SYSINIT(wlan_ht, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_ht_setup, NULL);
@@ -113,6 +116,8 @@
struct ieee80211_tx_ampdu *tap);
static void ieee80211_aggr_recv_action(struct ieee80211_node *ni,
const uint8_t *frm, const uint8_t *efrm);
+static void ieee80211_bar_response(struct ieee80211_node *ni,
+ struct ieee80211_tx_ampdu *tap, int status);
void
ieee80211_ht_attach(struct ieee80211com *ic)
@@ -124,6 +129,7 @@
ic->ic_addba_request = ieee80211_addba_request;
ic->ic_addba_response = ieee80211_addba_response;
ic->ic_addba_stop = ieee80211_addba_stop;
+ ic->ic_bar_response = ieee80211_bar_response;
ic->ic_htprotmode = IEEE80211_PROT_RTSCTS;
ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE;
@@ -802,6 +808,7 @@
for (ac = 0; ac < WME_NUM_AC; ac++) {
tap = &ni->ni_tx_ampdu[ac];
tap->txa_ac = ac;
+ tap->txa_ni = ni;
/* NB: further initialization deferred */
}
ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
@@ -1485,7 +1492,7 @@
struct ieee80211_tx_ampdu *tap,
int status, int baparamset, int batimeout)
{
- int bufsiz;
+ int bufsiz, tid;
/* XXX locking */
addba_stop_timeout(tap);
@@ -1494,7 +1501,11 @@
/* XXX override our request? */
tap->txa_wnd = (bufsiz == 0) ?
IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
+ /* XXX AC/TID */
+ tid = MS(baparamset, IEEE80211_BAPS_TID);
+ tap->txa_seqstart = tap->txa_start = ni->ni_txseqs[tid];
tap->txa_flags |= IEEE80211_AGGR_RUNNING;
+ tap->txa_attempts = 0;
} else {
/* mark tid so we don't try again */
tap->txa_flags |= IEEE80211_AGGR_NAK;
@@ -1868,6 +1879,7 @@
uint16_t args[4];
/* XXX locking */
+ tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
if (IEEE80211_AMPDU_RUNNING(tap)) {
IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
ni, "%s: stop BA stream for AC %d (reason %d)",
@@ -1888,6 +1900,83 @@
}
}
+static void
+bar_timeout(void *arg)
+{
+ struct ieee80211_tx_ampdu *tap = arg;
+ struct ieee80211_node *ni = tap->txa_ni;
+
+ KASSERT((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0,
+ ("bar/addba collision, flags 0x%x", tap->txa_flags));
+
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
+ ni, "%s: tid %u flags 0x%x attempts %d", __func__,
+ tap->txa_ac, tap->txa_flags, tap->txa_attempts);
+
+ /* guard against race with bar_tx_complete */
+ if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
+ return;
+ /* XXX ? */
+ if (tap->txa_attempts >= ieee80211_bar_maxtries)
+ ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
+ else
+ ieee80211_send_bar(ni, tap, tap->txa_seqpending);
+}
+
+static void
+bar_start_timer(struct ieee80211_tx_ampdu *tap)
+{
+ callout_reset(&tap->txa_timer, ieee80211_bar_timeout, bar_timeout, tap);
+}
+
+static void
+bar_stop_timer(struct ieee80211_tx_ampdu *tap)
+{
+ callout_stop(&tap->txa_timer);
+}
+
+static void
+bar_tx_complete(struct ieee80211_node *ni, void *arg, int status)
+{
+ struct ieee80211_tx_ampdu *tap = arg;
+
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
+ ni, "%s: tid %u flags 0x%x pending %d status %d",
+ __func__, tap->txa_ac, tap->txa_flags,
+ callout_pending(&tap->txa_timer), status);
+
+ /* XXX locking */
+ if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) &&
+ callout_pending(&tap->txa_timer)) {
+ struct ieee80211com *ic = ni->ni_ic;
+
+ if (status) /* ACK'd */
+ bar_stop_timer(tap);
+ ic->ic_bar_response(ni, tap, status);
+ } else {
+ /* NB: just let timer expire so we pace requests */
+ }
+}
+
+static void
+ieee80211_bar_response(struct ieee80211_node *ni,
+ struct ieee80211_tx_ampdu *tap, int status)
+{
+
+ if (status != 0) { /* got ACK */
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
+ ni, "BAR moves BA win <%u:%u> (%u frames) txseq %u tid %u",
+ tap->txa_start,
+ IEEE80211_SEQ_ADD(tap->txa_start, tap->txa_wnd-1),
+ tap->txa_qframes, tap->txa_seqpending,
+ WME_AC_TO_TID(tap->txa_ac));
+
+ /* NB: timer already stopped in bar_tx_complete */
+ tap->txa_start = tap->txa_seqpending;
+ tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
+ }
+}
+
/*
* Transmit a BAR frame to the specified node. The
* BAR contents are drawn from the supplied aggregation
@@ -1904,17 +1993,30 @@
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_frame_bar *bar;
struct mbuf *m;
+ uint16_t barctl, barseqctl;
uint8_t *frm;
- uint16_t barctl, barseqctl;
int tid, ret;
+ if ((tap->txa_flags & IEEE80211_AGGR_RUNNING) == 0) {
+ /* no ADDBA response, should not happen */
+ /* XXX stat+msg */
+ return EINVAL;
+ }
+ /* XXX locking */
+ bar_stop_timer(tap);
+
ieee80211_ref_node(ni);
- m = ieee80211_getmgtframe(&frm, ic->ic_headroom,
- sizeof(struct ieee80211_frame_bar));
+ m = ieee80211_getmgtframe(&frm, ic->ic_headroom, sizeof(*bar));
if (m == NULL)
senderr(ENOMEM, is_tx_nobuf);
+ if (!ieee80211_add_callback(m, bar_tx_complete, tap)) {
+ m_freem(m);
+ senderr(ENOMEM, is_tx_nobuf); /* XXX */
+ /* NOTREACHED */
+ }
+
bar = mtod(m, struct ieee80211_frame_bar *);
bar->i_fc[0] = IEEE80211_FC0_VERSION_0 |
IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_BAR;
@@ -1938,11 +2040,29 @@
IEEE80211_NODE_STAT(ni, tx_mgmt); /* XXX tx_ctl? */
+ /* XXX locking */
+ /* init/bump attempts counter */
+ if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
+ tap->txa_attempts = 1;
+ else
+ tap->txa_attempts++;
+ tap->txa_seqpending = seq;
+ tap->txa_flags |= IEEE80211_AGGR_BARPEND;
+
IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
ni, "send BAR: tid %u ctl 0x%x start %u (attempt %d)",
tid, barctl, seq, tap->txa_attempts);
- return ic->ic_raw_xmit(ni, m, NULL);
+ ret = ic->ic_raw_xmit(ni, m, NULL);
+ if (ret != 0) {
+ /* xmit failed, clear state flag */
+ tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
+ goto bad;
+ }
+ /* XXX hack against tx complete happening before timer is started */
+ if (tap->txa_flags & IEEE80211_AGGR_BARPEND)
+ bar_start_timer(tap);
+ return 0;
bad:
ieee80211_free_node(ni);
return ret;
==== //depot/projects/vap/sys/net80211/ieee80211_ht.h#21 (text+ko) ====
@@ -38,12 +38,14 @@
typedef uint16_t ieee80211_seq;
struct ieee80211_tx_ampdu {
+ struct ieee80211_node *txa_ni; /* back pointer */
u_short txa_flags;
#define IEEE80211_AGGR_IMMEDIATE 0x0001 /* BA policy */
#define IEEE80211_AGGR_XCHGPEND 0x0002 /* ADDBA response pending */
#define IEEE80211_AGGR_RUNNING 0x0004 /* ADDBA response received */
#define IEEE80211_AGGR_SETUP 0x0008 /* deferred state setup */
#define IEEE80211_AGGR_NAK 0x0010 /* peer NAK'd ADDBA request */
+#define IEEE80211_AGGR_BARPEND 0x0020 /* BAR response pending */
uint8_t txa_ac;
uint8_t txa_token; /* dialog token */
int txa_lastsample; /* ticks @ last traffic sample */
@@ -53,9 +55,10 @@
short txa_qframes; /* data queued (frames) */
ieee80211_seq txa_seqstart;
ieee80211_seq txa_start;
+ ieee80211_seq txa_seqpending; /* new start pending BAR response */
uint16_t txa_wnd; /* BA window size */
- uint8_t txa_attempts; /* # ADDBA requests w/o a response */
- int txa_nextrequest;/* soonest to make next ADDBA request */
+ uint8_t txa_attempts; /* # ADDBA/BAR requests w/o a response*/
+ int txa_nextrequest;/* soonest to make next request */
struct callout txa_timer;
void *txa_private; /* driver-private storage */
};
@@ -187,8 +190,8 @@
struct ieee80211_tx_ampdu *);
void ieee80211_ampdu_stop(struct ieee80211_node *,
struct ieee80211_tx_ampdu *, int);
-int ieee80211_send_bar(struct ieee80211_node *,
- struct ieee80211_tx_ampdu *tap, ieee80211_seq seq);
+int ieee80211_send_bar(struct ieee80211_node *, struct ieee80211_tx_ampdu *,
+ ieee80211_seq);
int ieee80211_send_action(struct ieee80211_node *,
int, int, uint16_t [4]);
uint8_t *ieee80211_add_htcap(uint8_t *, struct ieee80211_node *);
==== //depot/projects/vap/sys/net80211/ieee80211_var.h#52 (text+ko) ====
@@ -273,6 +273,9 @@
int status, int baparamset, int batimeout);
void (*ic_addba_stop)(struct ieee80211_node *,
struct ieee80211_tx_ampdu *);
+ /* BAR response received */
+ void (*ic_bar_response)(struct ieee80211_node *,
+ struct ieee80211_tx_ampdu *, int status);
};
struct ieee80211_aclator;
More information about the p4-projects
mailing list