Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Jan 2013 04:38:32 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r245097 - head/sys/net80211
Message-ID:  <201301060438.r064cW9U098424@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sun Jan  6 04:38:31 2013
New Revision: 245097
URL: http://svnweb.freebsd.org/changeset/base/245097

Log:
  Handle HWMP if_transmit() failure gracefully.
  
  If if_transmit() fails, the node ref may need freeing.
  
  This is based on the same logic used by the ageq, which the mesh code
  (re) uses for frames which need to be staged before transmitting.
  It also does the same thing - if M_ENCAP is set on the mbuf, it treats
  the recvif pointer as a node reference and derefs it.

Modified:
  head/sys/net80211/ieee80211_hwmp.c

Modified: head/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- head/sys/net80211/ieee80211_hwmp.c	Sun Jan  6 03:51:44 2013	(r245096)
+++ head/sys/net80211/ieee80211_hwmp.c	Sun Jan  6 04:38:31 2013	(r245097)
@@ -1227,6 +1227,8 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	struct mbuf *m, *next;
 	uint32_t metric = 0;
 	const uint8_t *addr;
+	int is_encap;
+	struct ieee80211_node *ni_encap;
 
 	if (ni == vap->iv_bss ||
 	    ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED)
@@ -1403,11 +1405,21 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	    (struct ieee80211_node *)(uintptr_t)
 	    ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
 	for (; m != NULL; m = next) {
+		is_encap = !! (m->m_flags & M_ENCAP);
+		ni_encap = (struct ieee80211_node *) m->m_pkthdr.rcvif;
 		next = m->m_nextpkt;
 		m->m_nextpkt = NULL;
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 		    "flush queued frame %p len %d", m, m->m_pkthdr.len);
-		ifp->if_transmit(ifp, m);
+
+		/*
+		 * If the mbuf has M_ENCAP set, ensure we free it.
+		 * Note that after if_transmit() is called, m is invalid.
+		 */
+		if (ifp->if_transmit(ifp, m) != 0) {
+			if (is_encap)
+				ieee80211_free_node(ni_encap);
+		}
 	}
 #undef	IS_PROXY
 #undef	PROXIED_BY_US



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301060438.r064cW9U098424>