Date: Thu, 20 Nov 2003 21:32:04 -0800 (PST) From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 42879 for review Message-ID: <200311210532.hAL5W446045901@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=42879 Change 42879 by sam@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 *
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200311210532.hAL5W446045901>