PERFORCE change 42879 for review
Sam Leffler
sam at FreeBSD.org
Thu Nov 20 21:32:07 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=42879
Change 42879 by sam at sam_ebb on 2003/11/20 21:32:03
o expand fragment reassembly support handle 3 concurrent
frames per the spec
o make caller verify reassembly is needed before calling
the reassembler since the caller has enough state sitting
around to make this worthwhile
o fix cleanup code to not double-free the frag queues for
the bss node
Affected files ...
.. //depot/projects/netperf/sys/net80211/ieee80211_input.c#16 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.c#18 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.h#13 edit
Differences ...
==== //depot/projects/netperf/sys/net80211/ieee80211_input.c#16 (text+ko) ====
@@ -301,9 +301,18 @@
if (ic->ic_rawbpf)
bpf_mtap(ic->ic_rawbpf, m);
#endif
- m = ieee80211_reass(ic, ni, m);
- if (m == NULL)
- goto out;
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ /*
+ * Check for and reassemble fragmented frames.
+ */
+ if ((wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) ||
+ (le16toh(*(u_int16_t *)wh->i_seq) &
+ IEEE80211_SEQ_FRAG_MASK) != 0) {
+ m = ieee80211_reass(ic, ni, m);
+ if (m == NULL)
+ goto out;
+ }
+ }
m = ieee80211_decap(ifp, m);
if (m == NULL) {
ic->ic_stats.is_rx_decap++;
@@ -413,6 +422,19 @@
if (ic->ic_rawbpf)
bpf_mtap(ic->ic_rawbpf, m);
#endif
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ /*
+ * Check for and reassemble fragmented frames.
+ * XXX are management frames fragmented?
+ */
+ if ((wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) ||
+ (le16toh(*(u_int16_t *)wh->i_seq) &
+ IEEE80211_SEQ_FRAG_MASK) != 0) {
+ m = ieee80211_reass(ic, ni, m);
+ if (m == NULL)
+ goto out;
+ }
+ }
m = ieee80211_reass(ic, ni, m);
if (m == NULL)
goto out;
@@ -452,43 +474,81 @@
}
/*
- * Reassemble fragments as necessary.
+ * Reassemble fragments. The caller is required to check
+ * reassembly is needed before calling.
*/
static struct mbuf *
ieee80211_reass(struct ieee80211com *ic, struct ieee80211_node *ni, struct mbuf *m)
{
- struct ieee80211_frame *wh, *lwh;
+#define N(a) (sizeof(a)/sizeof(a[0]))
+ struct ieee80211_frame *wh;
+ struct ieee80211_frame *lwh = NULL; /* XXX silence compiler */
u_int16_t rxseq, lseq;
u_int8_t fragno, more;
+ int i, slot;
wh = mtod(m, struct ieee80211_frame *);
- if (IEEE80211_IS_MULTICAST(wh->i_addr1))
- return m; /* no mcast frames */
-
+ KASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1),
+ ("multicast frame sent for reassembly"));
more = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
rxseq = le16toh(*(u_int16_t *)wh->i_seq);
fragno = rxseq & IEEE80211_SEQ_FRAG_MASK;
- if (!more && fragno == 0)
- return m; /* not fragmented */
+ KASSERT(more || fragno != 0,
+ ("unexpected frame sent for reassembly, more %u fragno %u",
+ more, fragno));
+ /*
+ * Locate previously received data.
+ */
+ slot = -1;
+ for (i = N(ni->ni_rxfrag)-1; i >= 0; i--) {
+ if (ni->ni_rxfrag[i] != NULL) {
+ /*
+ * Slot is in use. If the data is from the same
+ * sender then use the slot. We check the sequence
+ * number below to decide if the existing data
+ * should be used or discarded.
+ */
+ lwh = mtod(ni->ni_rxfrag[i], struct ieee80211_frame *);
+ if (!IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
+ !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2))
+ continue;
+ slot = i;
+ break;
+ }
+ slot = i; /* record unused slot */
+ }
+ if (slot < 0) {
+ /*
+ * No free slot found, discard the oldest one.
+ */
+ /* XXX track age to identify oldest one */
+ /* XXX stat */
+ slot = 0;
+ m_freem(ni->ni_rxfrag[slot]);
+ ni->ni_rxfrag[slot] = NULL;
+ }
/*
* Validate that fragment is in order and
* related to the previous ones.
*/
- if (ni->ni_rxfrag != NULL) {
- lwh = mtod(ni->ni_rxfrag, struct ieee80211_frame *);
+ KASSERT(0 <= slot && slot < N(ni->ni_rxfrag),
+ ("fragment reassembly slot %d out of bounds", slot));
+ if (ni->ni_rxfrag[slot] != NULL) {
+ KASSERT(lwh == mtod(ni->ni_rxfrag[slot],
+ struct ieee80211_frame *),
+ ("fragment header pointer not setup"));
lseq = le16toh(*(u_int16_t *)lwh->i_seq);
/* NB: this checks seq#'s and frag number together */
- if (rxseq != lseq+1 ||
- !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
- !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
+ if (rxseq != lseq+1) {
/* Unrelated fragment, clear existing data */
/* XXX stat */
- m_freem(ni->ni_rxfrag);
- ni->ni_rxfrag = NULL;
+ m_freem(ni->ni_rxfrag[slot]);
+ ni->ni_rxfrag[slot] = NULL;
}
} else {
if (fragno != 0) { /* out of order fragment */
+ /* XXX maybe move this up so we don't reclaim a slot */
/* XXX stat */
m_freem(m);
return NULL;
@@ -497,25 +557,28 @@
/*
* Add new fragment to existing data, if any.
*/
- if (ni->ni_rxfrag != NULL) {
+ if (ni->ni_rxfrag[slot] != NULL) {
/*
* We know this is the next sequential fragment
* because of the check done above; append the data.
*/
- lwh = mtod(ni->ni_rxfrag, struct ieee80211_frame *);
- m_cat(ni->ni_rxfrag, m);
+ KASSERT(lwh == mtod(ni->ni_rxfrag[slot],
+ struct ieee80211_frame *),
+ ("fragment header pointer not setup"));
+ m_cat(ni->ni_rxfrag[slot], m);
/* record last sequence and fragno */
- *(u_int16_t *) lwh->i_seq = rxseq;
+ *(u_int16_t *)lwh->i_seq = rxseq;
if (!more) { /* reassembly complete */
- m = ni->ni_rxfrag;
- ni->ni_rxfrag = NULL;
+ m = ni->ni_rxfrag[slot];
+ ni->ni_rxfrag[slot] = NULL;
} else /* frame incomplete */
m = NULL;
} else {
- ni->ni_rxfrag = m;
+ ni->ni_rxfrag[slot] = m;
m = NULL;
}
return m;
+#undef N
}
struct mbuf *
==== //depot/projects/netperf/sys/net80211/ieee80211_node.c#18 (text+ko) ====
@@ -111,11 +111,8 @@
{
struct ieee80211com *ic = (void *)ifp;
- if (ic->ic_bss != NULL) {
- if (ic->ic_bss->ni_rxfrag != NULL)
- m_freem(ic->ic_bss->ni_rxfrag);
+ if (ic->ic_bss != NULL)
(*ic->ic_node_free)(ic, ic->ic_bss);
- }
ieee80211_free_allnodes(ic);
IEEE80211_NODE_LOCK_DESTROY(ic);
}
@@ -530,6 +527,9 @@
static void
_ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+ int i;
+
KASSERT(ni != ic->ic_bss, ("freeing bss node"));
IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
@@ -542,9 +542,11 @@
}
if (TAILQ_EMPTY(&ic->ic_node))
ic->ic_inact_timer = 0;
- if (ni->ni_rxfrag != NULL)
- m_freem(ni->ni_rxfrag);
+ for (i = 0; i < N(ni->ni_rxfrag); i++)
+ if (ni->ni_rxfrag[i] != NULL)
+ m_freem(ni->ni_rxfrag[i]);
(*ic->ic_node_free)(ic, ni);
+#undef N
}
void
==== //depot/projects/netperf/sys/net80211/ieee80211_node.h#13 (text+ko) ====
@@ -108,7 +108,7 @@
int ni_inact; /* inactivity mark count */
int ni_txrate; /* index to ni_rates[] */
u_int32_t *ni_challenge; /* shared-key challenge */
- struct mbuf *ni_rxfrag; /* rx frag reassembly */
+ struct mbuf *ni_rxfrag[3]; /* rx frag reassembly */
};
static __inline struct ieee80211_node *
More information about the p4-projects
mailing list