Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Oct 2003 21:15:22 -0700 (PDT)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 39768 for review
Message-ID:  <200310160415.h9G4FMkQ045178@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=39768

Change 39768 by sam@sam_ebb on 2003/10/15 21:14:38

	support for fragment reassembly on receive

Affected files ...

.. //depot/projects/netperf/sys/net80211/ieee80211_input.c#9 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.c#12 edit
.. //depot/projects/netperf/sys/net80211/ieee80211_node.h#9 edit

Differences ...

==== //depot/projects/netperf/sys/net80211/ieee80211_input.c#9 (text+ko) ====

@@ -66,6 +66,9 @@
 #include <netinet/if_ether.h>
 #endif
 
+static	struct mbuf *ieee80211_reass(struct ieee80211com *,
+				     struct ieee80211_node *, struct mbuf *);
+
 /*
  * Process a received frame.  The node associated with the sender
  * should be supplied.  If nothing was found in the node table then
@@ -259,6 +262,9 @@
 		/* copy to listener after decrypt */
 		if (ic->ic_rawbpf)
 			bpf_mtap(ic->ic_rawbpf, m);
+		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++;
@@ -357,6 +363,9 @@
 		}
 		if (ic->ic_rawbpf)
 			bpf_mtap(ic->ic_rawbpf, m);
+		m = ieee80211_reass(ic, ni, m);
+		if (m == NULL)
+			goto out;
 		(*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
 		m_freem(m);
 		return;
@@ -379,6 +388,73 @@
 	}
 }
 
+/*
+ * Reassemble fragments as necessary.
+ */
+static struct mbuf *
+ieee80211_reass(struct ieee80211com *ic, struct ieee80211_node *ni, struct mbuf *m)
+{
+	struct ieee80211_frame *wh, *lwh;
+	u_int16_t rxseq, lseq;
+	u_int8_t fragno, more;
+
+	wh = mtod(m, struct ieee80211_frame *);
+	if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+		return m;			/* no mcast frames */
+
+	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 */
+
+	/*
+	 * 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 *);
+		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)) {
+			/* Unrelated fragment, clear existing data */
+			/* XXX stat */
+			m_freem(ni->ni_rxfrag);
+			ni->ni_rxfrag = NULL;
+		}
+	} else {
+		if (fragno != 0) {		/* out of order fragment */
+			/* XXX stat */
+			m_freem(m);
+			return NULL;
+		}
+	}
+	/*
+	 * Add new fragment to existing data, if any.
+	 */
+ 	if (ni->ni_rxfrag != 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);
+		/* record last sequence and fragno */
+		*(u_int16_t *) lwh->i_seq = rxseq;
+		if (!more) {			/* reassembly complete */
+			m = ni->ni_rxfrag;
+			ni->ni_rxfrag = NULL;
+		} else				/* frame incomplete */
+			m = NULL;
+	} else {
+		ni->ni_rxfrag = m;
+		m = NULL;
+	}
+	return m;
+}
+
 struct mbuf *
 ieee80211_decap(struct ifnet *ifp, struct mbuf *m)
 {

==== //depot/projects/netperf/sys/net80211/ieee80211_node.c#12 (text+ko) ====

@@ -110,8 +110,11 @@
 {
 	struct ieee80211com *ic = (void *)ifp;
 
-	if (ic->ic_bss != NULL)
+	if (ic->ic_bss != NULL) {
+		if (ic->ic_bss->ni_rxfrag != NULL)
+			m_freem(ic->ic_bss->ni_rxfrag);
 		(*ic->ic_node_free)(ic, ic->ic_bss);
+	}
 	ieee80211_free_allnodes(ic);
 	IEEE80211_NODE_LOCK_DESTROY(ic);
 }
@@ -517,6 +520,8 @@
 	LIST_REMOVE(ni, ni_hash);
 	if (TAILQ_EMPTY(&ic->ic_node))
 		ic->ic_inact_timer = 0;
+	if (ni->ni_rxfrag != NULL)
+		m_freem(ni->ni_rxfrag);
 	(*ic->ic_node_free)(ic, ni);
 }
 

==== //depot/projects/netperf/sys/net80211/ieee80211_node.h#9 (text+ko) ====

@@ -102,6 +102,7 @@
 	int			ni_fails;	/* failure count to associate */
 	int			ni_inact;	/* inactivity mark count */
 	int			ni_txrate;	/* index to ni_rates[] */
+	struct mbuf		*ni_rxfrag;	/* 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?200310160415.h9G4FMkQ045178>