summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-05-25 06:28:30 +0000
committeradrian <adrian@FreeBSD.org>2013-05-25 06:28:30 +0000
commit58d0c29676a96ac1c8c14b4717051336c64a04ec (patch)
tree88538a90b3a9413450673c455cec15993ec239e7 /sys/net80211
parenteded42d0e523cfa40d1c00d1d1a01eb15f4a48cf (diff)
downloadFreeBSD-src-58d0c29676a96ac1c8c14b4717051336c64a04ec.zip
FreeBSD-src-58d0c29676a96ac1c8c14b4717051336c64a04ec.tar.gz
Fix net80211 fragment creation.
When creating fragment frames, the header length should honour the DATAPAD flag. This fixes the fragments that are queued to the ath(4) driver but it doesn't yet fix fragment transmission. That requires further changes to the ath(4) transmit path. Well, strictly speaking, it requires further changes to _all_ wifi driver transmit paths, but this is at least a start. Tested: * AR5416, STA mode, w/ fragthreshold set to 256.
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_output.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index e9ba167..2fff3ae 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1495,18 +1495,28 @@ static int
ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,
u_int hdrsize, u_int ciphdrsize, u_int mtu)
{
+ struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_frame *wh, *whf;
struct mbuf *m, *prev, *next;
u_int totalhdrsize, fragno, fragsize, off, remainder, payload;
+ u_int hdrspace;
KASSERT(m0->m_nextpkt == NULL, ("mbuf already chained?"));
KASSERT(m0->m_pkthdr.len > mtu,
("pktlen %u mtu %u", m0->m_pkthdr.len, mtu));
+ /*
+ * Honor driver DATAPAD requirement.
+ */
+ if (ic->ic_flags & IEEE80211_F_DATAPAD)
+ hdrspace = roundup(hdrsize, sizeof(uint32_t));
+ else
+ hdrspace = hdrsize;
+
wh = mtod(m0, struct ieee80211_frame *);
/* NB: mark the first frag; it will be propagated below */
wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
- totalhdrsize = hdrsize + ciphdrsize;
+ totalhdrsize = hdrspace + ciphdrsize;
fragno = 1;
off = mtu - ciphdrsize;
remainder = m0->m_pkthdr.len - off;
@@ -1553,9 +1563,10 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,
payload = fragsize - totalhdrsize;
/* NB: destination is known to be contiguous */
- m_copydata(m0, off, payload, mtod(m, uint8_t *) + hdrsize);
- m->m_len = hdrsize + payload;
- m->m_pkthdr.len = hdrsize + payload;
+
+ m_copydata(m0, off, payload, mtod(m, uint8_t *) + hdrspace);
+ m->m_len = hdrspace + payload;
+ m->m_pkthdr.len = hdrspace + payload;
m->m_flags |= M_FRAG;
/* chain up the fragment */
OpenPOWER on IntegriCloud