summaryrefslogtreecommitdiffstats
path: root/sys/net80211/ieee80211_mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211/ieee80211_mesh.c')
-rw-r--r--sys/net80211/ieee80211_mesh.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c
index 9750a4a..7f1ba21 100644
--- a/sys/net80211/ieee80211_mesh.c
+++ b/sys/net80211/ieee80211_mesh.c
@@ -1041,11 +1041,12 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m,
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *parent = ic->ic_ifp;
struct ieee80211_node *ni;
struct ether_header *eh;
int error;
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
+
eh = mtod(m, struct ether_header *);
ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest);
if (ni == NULL) {
@@ -1132,6 +1133,8 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m,
}
}
#endif /* IEEE80211_SUPPORT_SUPERG */
+
+ IEEE80211_TX_LOCK(ic);
if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) {
/*
* Encapsulate the packet in prep for transmission.
@@ -1143,9 +1146,9 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m,
return;
}
}
- error = parent->if_transmit(parent, m);
+ error = ieee80211_parent_transmit(ic, m);
+ IEEE80211_TX_UNLOCK(ic);
if (error != 0) {
- m_freem(m);
ieee80211_free_node(ni);
} else {
ifp->if_opackets++;
@@ -1171,6 +1174,8 @@ ieee80211_mesh_forward_to_gates(struct ieee80211vap *vap,
struct ieee80211_mesh_gate_route *gr = NULL, *gr_next;
struct mbuf *m, *mcopy, *next;
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
+
KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER,
("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER"));
@@ -1240,7 +1245,6 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ifnet *ifp = vap->iv_ifp;
- struct ifnet *parent = ic->ic_ifp;
const struct ieee80211_frame *wh =
mtod(m, const struct ieee80211_frame *);
struct mbuf *mcopy;
@@ -1249,6 +1253,9 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
struct ieee80211_node *ni;
int err;
+ /* This is called from the RX path - don't hold this lock */
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
+
/*
* mesh ttl of 1 means we are the last one receving it,
* according to amendment we decrement and then check if
@@ -1320,7 +1327,20 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m,
/* XXX do we know m_nextpkt is NULL? */
mcopy->m_pkthdr.rcvif = (void *) ni;
- err = parent->if_transmit(parent, mcopy);
+
+ /*
+ * XXX this bypasses all of the VAP TX handling; it passes frames
+ * directly to the parent interface.
+ *
+ * Because of this, there's no TX lock being held as there's no
+ * encaps state being used.
+ *
+ * Doing a direct parent transmit may not be the correct thing
+ * to do here; we'll have to re-think this soon.
+ */
+ IEEE80211_TX_LOCK(ic);
+ err = ieee80211_parent_transmit(ic, mcopy);
+ IEEE80211_TX_UNLOCK(ic);
if (err != 0) {
/* NB: IFQ_HANDOFF reclaims mbuf */
ieee80211_free_node(ni);
@@ -1457,6 +1477,10 @@ mesh_recv_indiv_data_to_fwrd(struct ieee80211vap *vap, struct mbuf *m,
struct ieee80211_qosframe_addr4 *qwh;
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt_meshda, *rt_meshsa;
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /* This is called from the RX path - don't hold this lock */
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
qwh = (struct ieee80211_qosframe_addr4 *)wh;
@@ -1512,8 +1536,12 @@ mesh_recv_indiv_data_to_me(struct ieee80211vap *vap, struct mbuf *m,
const struct ieee80211_meshcntl_ae10 *mc10;
struct ieee80211_mesh_state *ms = vap->iv_mesh;
struct ieee80211_mesh_route *rt;
+ struct ieee80211com *ic = vap->iv_ic;
int ae;
+ /* This is called from the RX path - don't hold this lock */
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
+
qwh = (struct ieee80211_qosframe_addr4 *)wh;
mc10 = (const struct ieee80211_meshcntl_ae10 *)mc;
@@ -1575,6 +1603,10 @@ mesh_recv_group_data(struct ieee80211vap *vap, struct mbuf *m,
{
#define MC01(mc) ((const struct ieee80211_meshcntl_ae01 *)mc)
struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct ieee80211com *ic = vap->iv_ic;
+
+ /* This is called from the RX path - don't hold this lock */
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
mesh_forward(vap, m, mc);
@@ -1621,6 +1653,9 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
need_tap = 1; /* mbuf need to be tapped. */
type = -1; /* undefined */
+ /* This is called from the RX path - don't hold this lock */
+ IEEE80211_TX_UNLOCK_ASSERT(ic);
+
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
ni->ni_macaddr, NULL,
@@ -2743,6 +2778,7 @@ mesh_send_action(struct ieee80211_node *ni,
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_bpf_params params;
struct ieee80211_frame *wh;
+ int ret;
KASSERT(ni != NULL, ("null node"));
@@ -2761,6 +2797,7 @@ mesh_send_action(struct ieee80211_node *ni,
return ENOMEM;
}
+ IEEE80211_TX_LOCK(ic);
wh = mtod(m, struct ieee80211_frame *);
ieee80211_send_setup(ni, m,
IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
@@ -2778,7 +2815,9 @@ mesh_send_action(struct ieee80211_node *ni,
IEEE80211_NODE_STAT(ni, tx_mgmt);
- return ic->ic_raw_xmit(ni, m, &params);
+ ret = ieee80211_raw_output(vap, ni, m, &params);
+ IEEE80211_TX_UNLOCK(ic);
+ return (ret);
}
#define ADDSHORT(frm, v) do { \
OpenPOWER on IntegriCloud