Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net80211/ieee80211_output.c
Show First 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | |||||
* if appropriate.) | * if appropriate.) | ||||
*/ | */ | ||||
int | int | ||||
ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, | ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, | ||||
struct ieee80211_node *ni) | struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *ifp = vap->iv_ifp; | struct ifnet *ifp = vap->iv_ifp; | ||||
int error; | int error, len, mcast; | ||||
if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && | if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && | ||||
(m->m_flags & M_PWR_SAV) == 0) { | (m->m_flags & M_PWR_SAV) == 0) { | ||||
/* | /* | ||||
* Station in power save mode; pass the frame | * Station in power save mode; pass the frame | ||||
* to the 802.11 layer and continue. We'll get | * to the 802.11 layer and continue. We'll get | ||||
* the frame back when the time is right. | * the frame back when the time is right. | ||||
* XXX lose WDS vap linkage? | * XXX lose WDS vap linkage? | ||||
*/ | */ | ||||
(void) ieee80211_pwrsave(ni, m); | if (ieee80211_pwrsave(ni, m) != 0) | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
/* | /* | ||||
* We queued it fine, so tell the upper layer | * We queued it fine, so tell the upper layer | ||||
* that we consumed it. | * that we consumed it. | ||||
*/ | */ | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 12 Lines | ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, | ||||
} | } | ||||
/* | /* | ||||
* Stash the node pointer. Note that we do this after | * Stash the node pointer. Note that we do this after | ||||
* any call to ieee80211_dwds_mcast because that code | * any call to ieee80211_dwds_mcast because that code | ||||
* uses any existing value for rcvif to identify the | * uses any existing value for rcvif to identify the | ||||
* interface it (might have been) received on. | * interface it (might have been) received on. | ||||
*/ | */ | ||||
m->m_pkthdr.rcvif = (void *)ni; | m->m_pkthdr.rcvif = (void *)ni; | ||||
mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1: 0; | |||||
len = m->m_pkthdr.len; | |||||
BPF_MTAP(ifp, m); /* 802.3 tx */ | BPF_MTAP(ifp, m); /* 802.3 tx */ | ||||
/* | /* | ||||
* Check if A-MPDU tx aggregation is setup or if we | * Check if A-MPDU tx aggregation is setup or if we | ||||
* should try to enable it. The sta must be associated | * should try to enable it. The sta must be associated | ||||
* with HT and A-MPDU enabled for use. When the policy | * with HT and A-MPDU enabled for use. When the policy | ||||
* routine decides we should enable A-MPDU we issue an | * routine decides we should enable A-MPDU we issue an | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) { | ||||
/* | /* | ||||
* Encapsulate the packet in prep for transmission. | * Encapsulate the packet in prep for transmission. | ||||
*/ | */ | ||||
m = ieee80211_encap(vap, ni, m); | m = ieee80211_encap(vap, ni, m); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
/* NB: stat+msg handled in ieee80211_encap */ | /* NB: stat+msg handled in ieee80211_encap */ | ||||
IEEE80211_TX_UNLOCK(ic); | IEEE80211_TX_UNLOCK(ic); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
/* XXX better status? */ | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
} | } | ||||
error = ieee80211_parent_xmitpkt(ic, m); | error = ieee80211_parent_xmitpkt(ic, m); | ||||
/* | /* | ||||
* Unlock at this point - no need to hold it across | * Unlock at this point - no need to hold it across | ||||
* ieee80211_free_node() (ie, the comlock) | * ieee80211_free_node() (ie, the comlock) | ||||
*/ | */ | ||||
IEEE80211_TX_UNLOCK(ic); | IEEE80211_TX_UNLOCK(ic); | ||||
if (error != 0) { | if (error != 0) { | ||||
/* NB: IFQ_HANDOFF reclaims mbuf */ | /* NB: IFQ_HANDOFF reclaims mbuf */ | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
} else { | } else { | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | ||||
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast); | |||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, len); | |||||
} | } | ||||
ic->ic_lastdata = ticks; | ic->ic_lastdata = ticks; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (IS_DWDS(vap)) { | ||||
* DWDS vaps; multicast frames are handled by | * DWDS vaps; multicast frames are handled by | ||||
* dispatching the frame as it comes through | * dispatching the frame as it comes through | ||||
* the AP vap (see below). | * the AP vap (see below). | ||||
*/ | */ | ||||
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_WDS, | IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_WDS, | ||||
eh->ether_dhost, "mcast", "%s", "on DWDS"); | eh->ether_dhost, "mcast", "%s", "on DWDS"); | ||||
vap->iv_stats.is_dwds_mcast++; | vap->iv_stats.is_dwds_mcast++; | ||||
m_freem(m); | m_freem(m); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
/* XXX better status? */ | /* XXX better status? */ | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP) { | if (vap->iv_opmode == IEEE80211_M_HOSTAP) { | ||||
/* | /* | ||||
* Spam DWDS vap's w/ multicast traffic. | * Spam DWDS vap's w/ multicast traffic. | ||||
*/ | */ | ||||
/* XXX only if dwds in use? */ | /* XXX only if dwds in use? */ | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
if (vap->iv_state == IEEE80211_S_SLEEP) { | if (vap->iv_state == IEEE80211_S_SLEEP) { | ||||
/* | /* | ||||
* In power save; queue frame and then wakeup device | * In power save; queue frame and then wakeup device | ||||
* for transmit. | * for transmit. | ||||
*/ | */ | ||||
ic->ic_lastdata = ticks; | ic->ic_lastdata = ticks; | ||||
(void) ieee80211_pwrsave(ni, m); | if (ieee80211_pwrsave(ni, m) != 0) | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
ieee80211_new_state(vap, IEEE80211_S_RUN, 0); | ieee80211_new_state(vap, IEEE80211_S_RUN, 0); | ||||
return (0); | return (0); | ||||
} | } | ||||
if (ieee80211_vap_pkt_send_dest(vap, m, ni) != 0) | if (ieee80211_vap_pkt_send_dest(vap, m, ni) != 0) | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
return (0); | return (0); | ||||
Show All 15 Lines | ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m) | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *parent = ic->ic_ifp; | struct ifnet *parent = ic->ic_ifp; | ||||
/* NB: parent must be up and running */ | /* NB: parent must be up and running */ | ||||
if (!IFNET_IS_UP_RUNNING(parent)) { | if (!IFNET_IS_UP_RUNNING(parent)) { | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, | ||||
"%s: ignore queue, parent %s not up+running\n", | "%s: ignore queue, parent %s not up+running\n", | ||||
__func__, parent->if_xname); | __func__, parent->if_xname); | ||||
/* XXX stat */ | |||||
m_freem(m); | m_freem(m); | ||||
return (EINVAL); | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
return (ENETDOWN); | |||||
} | } | ||||
/* | /* | ||||
* No data frames go out unless we're running. | * No data frames go out unless we're running. | ||||
* Note in particular this covers CAC and CSA | * Note in particular this covers CAC and CSA | ||||
* states (though maybe we should check muting | * states (though maybe we should check muting | ||||
* for CSA). | * for CSA). | ||||
*/ | */ | ||||
if (vap->iv_state != IEEE80211_S_RUN && | if (vap->iv_state != IEEE80211_S_RUN && | ||||
vap->iv_state != IEEE80211_S_SLEEP) { | vap->iv_state != IEEE80211_S_SLEEP) { | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
/* re-check under the com lock to avoid races */ | /* re-check under the com lock to avoid races */ | ||||
if (vap->iv_state != IEEE80211_S_RUN && | if (vap->iv_state != IEEE80211_S_RUN && | ||||
vap->iv_state != IEEE80211_S_SLEEP) { | vap->iv_state != IEEE80211_S_SLEEP) { | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, | ||||
"%s: ignore queue, in %s state\n", | "%s: ignore queue, in %s state\n", | ||||
__func__, ieee80211_state_name[vap->iv_state]); | __func__, ieee80211_state_name[vap->iv_state]); | ||||
vap->iv_stats.is_tx_badstate++; | vap->iv_stats.is_tx_badstate++; | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | ifp->if_drv_flags |= IFF_DRV_OACTIVE; | ||||
m_freem(m); | m_freem(m); | ||||
return (EINVAL); | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
return (ENETDOWN); | |||||
} | } | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
} | } | ||||
/* | /* | ||||
* Sanitize mbuf flags for net80211 use. We cannot | * Sanitize mbuf flags for net80211 use. We cannot | ||||
* clear M_PWR_SAV or M_MORE_DATA because these may | * clear M_PWR_SAV or M_MORE_DATA because these may | ||||
* be set for frames that are re-submitted from the | * be set for frames that are re-submitted from the | ||||
▲ Show 20 Lines • Show All 2,978 Lines • Show Last 20 Lines |