28c28
< __FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 190094 2009-03-19 18:45:37Z rpaulo $");
---
> __FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 190391 2009-03-24 20:39:08Z sam $");
49a50,52
> #ifdef IEEE80211_SUPPORT_SUPERG
> #include <net80211/ieee80211_superg.h>
> #endif
65,67d67
< static struct mbuf *ieee80211_encap_fastframe(struct ieee80211vap *,
< struct mbuf *m1, const struct ether_header *eh1,
< struct mbuf *m2, const struct ether_header *eh2);
734c734
< static struct mbuf *
---
> struct mbuf *
864c864
< int hdrsize, hdrspace, datalen, addqos, txfrag, isff, is4addr;
---
> int hdrsize, hdrspace, datalen, addqos, txfrag, is4addr;
938,941c938
< if ((isff = m->m_flags & M_FF) != 0) {
< struct mbuf *m2;
< struct ether_header eh2;
<
---
> if (__predict_true((m->m_flags & M_FF) == 0)) {
943,988d939
< * Fast frame encapsulation. There must be two packets
< * chained with m_nextpkt. We do header adjustment for
< * each, add the tunnel encapsulation, and then concatenate
< * the mbuf chains to form a single frame for transmission.
< */
< m2 = m->m_nextpkt;
< if (m2 == NULL) {
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: only one frame\n", __func__);
< goto bad;
< }
< m->m_nextpkt = NULL;
< /*
< * Include fast frame headers in adjusting header
< * layout; this allocates space according to what
< * ieee80211_encap_fastframe will do.
< */
< m = ieee80211_mbuf_adjust(vap,
< hdrspace + sizeof(struct llc) + sizeof(uint32_t) + 2 +
< sizeof(struct ether_header),
< key, m);
< if (m == NULL) {
< /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
< m_freem(m2);
< goto bad;
< }
< /*
< * Copy second frame's Ethernet header out of line
< * and adjust for encapsulation headers. Note that
< * we make room for padding in case there isn't room
< * at the end of first frame.
< */
< KASSERT(m2->m_len >= sizeof(eh2), ("no ethernet header!"));
< ETHER_HEADER_COPY(&eh2, mtod(m2, caddr_t));
< m2 = ieee80211_mbuf_adjust(vap,
< ATH_FF_MAX_HDR_PAD + sizeof(struct ether_header),
< NULL, m2);
< if (m2 == NULL) {
< /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
< goto bad;
< }
< m = ieee80211_encap_fastframe(vap, m, &eh, m2, &eh2);
< if (m == NULL)
< goto bad;
< } else {
< /*
1004a956,961
> } else {
> #ifdef IEEE80211_SUPPORT_SUPERG
> m = ieee80211_ff_encap(vap, m, hdrspace, key);
> if (m == NULL)
> #endif
> goto bad;
1050c1007
< if (m->m_flags & M_MORE_DATA)
---
> if (m->m_flags & M_MORE_DATA)
1131c1088
< !isff); /* NB: don't fragment ff's */
---
> (m->m_flags & M_FF) == 0); /* NB: don't fragment ff's */
1178,1306d1134
< * Do Ethernet-LLC encapsulation for each payload in a fast frame
< * tunnel encapsulation. The frame is assumed to have an Ethernet
< * header at the front that must be stripped before prepending the
< * LLC followed by the Ethernet header passed in (with an Ethernet
< * type that specifies the payload size).
< */
< static struct mbuf *
< ieee80211_encap1(struct ieee80211vap *vap, struct mbuf *m,
< const struct ether_header *eh)
< {
< struct llc *llc;
< uint16_t payload;
<
< /* XXX optimize by combining m_adj+M_PREPEND */
< m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
< llc = mtod(m, struct llc *);
< llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
< llc->llc_control = LLC_UI;
< llc->llc_snap.org_code[0] = 0;
< llc->llc_snap.org_code[1] = 0;
< llc->llc_snap.org_code[2] = 0;
< llc->llc_snap.ether_type = eh->ether_type;
< payload = m->m_pkthdr.len; /* NB: w/o Ethernet header */
<
< M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
< if (m == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for ether_header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< ETHER_HEADER_COPY(mtod(m, void *), eh);
< mtod(m, struct ether_header *)->ether_type = htons(payload);
< return m;
< }
<
< /*
< * Do fast frame tunnel encapsulation. The two frames and
< * Ethernet headers are supplied. The caller is assumed to
< * have arrange for space in the mbuf chains for encapsulating
< * headers (to avoid major mbuf fragmentation).
< *
< * The encapsulated frame is returned or NULL if there is a
< * problem (should not happen).
< */
< static struct mbuf *
< ieee80211_encap_fastframe(struct ieee80211vap *vap,
< struct mbuf *m1, const struct ether_header *eh1,
< struct mbuf *m2, const struct ether_header *eh2)
< {
< struct llc *llc;
< struct mbuf *m;
< int pad;
<
< /*
< * First, each frame gets a standard encapsulation.
< */
< m1 = ieee80211_encap1(vap, m1, eh1);
< if (m1 == NULL) {
< m_freem(m2);
< return NULL;
< }
< m2 = ieee80211_encap1(vap, m2, eh2);
< if (m2 == NULL) {
< m_freem(m1);
< return NULL;
< }
<
< /*
< * Pad leading frame to a 4-byte boundary. If there
< * is space at the end of the first frame, put it
< * there; otherwise prepend to the front of the second
< * frame. We know doing the second will always work
< * because we reserve space above. We prefer appending
< * as this typically has better DMA alignment properties.
< */
< for (m = m1; m->m_next != NULL; m = m->m_next)
< ;
< pad = roundup2(m1->m_pkthdr.len, 4) - m1->m_pkthdr.len;
< if (pad) {
< if (M_TRAILINGSPACE(m) < pad) { /* prepend to second */
< m2->m_data -= pad;
< m2->m_len += pad;
< m2->m_pkthdr.len += pad;
< } else { /* append to first */
< m->m_len += pad;
< m1->m_pkthdr.len += pad;
< }
< }
<
< /*
< * Now, stick 'em together and prepend the tunnel headers;
< * first the Atheros tunnel header (all zero for now) and
< * then a special fast frame LLC.
< *
< * XXX optimize by prepending together
< */
< m->m_next = m2; /* NB: last mbuf from above */
< m1->m_pkthdr.len += m2->m_pkthdr.len;
< M_PREPEND(m1, sizeof(uint32_t)+2, M_DONTWAIT);
< if (m1 == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for tunnel header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< memset(mtod(m1, void *), 0, sizeof(uint32_t)+2);
<
< M_PREPEND(m1, sizeof(struct llc), M_DONTWAIT);
< if (m1 == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for llc header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< llc = mtod(m1, struct llc *);
< llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
< llc->llc_control = LLC_UI;
< llc->llc_snap.org_code[0] = ATH_FF_SNAP_ORGCODE_0;
< llc->llc_snap.org_code[1] = ATH_FF_SNAP_ORGCODE_1;
< llc->llc_snap.org_code[2] = ATH_FF_SNAP_ORGCODE_2;
< llc->llc_snap.ether_type = htons(ATH_FF_ETH_TYPE);
<
< vap->iv_stats.is_ff_encap++;
<
< return m1;
< }
<
< /*
1571d1398
< #define ATH_OUI_BYTES 0x00, 0x03, 0x7f
1573,1596d1399
< * Add a WME information element to a frame.
< */
< static uint8_t *
< ieee80211_add_ath(uint8_t *frm, uint8_t caps, uint16_t defkeyix)
< {
< static const struct ieee80211_ath_ie info = {
< .ath_id = IEEE80211_ELEMID_VENDOR,
< .ath_len = sizeof(struct ieee80211_ath_ie) - 2,
< .ath_oui = { ATH_OUI_BYTES },
< .ath_oui_type = ATH_OUI_TYPE,
< .ath_oui_subtype= ATH_OUI_SUBTYPE,
< .ath_version = ATH_OUI_VERSION,
< };
< struct ieee80211_ath_ie *ath = (struct ieee80211_ath_ie *) frm;
<
< memcpy(frm, &info, sizeof(info));
< ath->ath_capability = caps;
< ath->ath_defkeyix[0] = (defkeyix & 0xff);
< ath->ath_defkeyix[1] = ((defkeyix >> 8) & 0xff);
< return frm + sizeof(info);
< }
< #undef ATH_OUI_BYTES
<
< /*
1979a1783
> #ifdef IEEE80211_SUPPORT_SUPERG
1980a1785
> #endif
2048a1854
> #ifdef IEEE80211_SUPPORT_SUPERG
2055a1862
> #endif /* IEEE80211_SUPPORT_SUPERG */
2090a1898
> #ifdef IEEE80211_SUPPORT_SUPERG
2091a1900
> #endif
2125a1935
> #ifdef IEEE80211_SUPPORT_SUPERG
2129a1940
> #endif /* IEEE80211_SUPPORT_SUPERG */
2229a2041
> #ifdef IEEE80211_SUPPORT_SUPERG
2230a2043
> #endif
2312a2126
> #ifdef IEEE80211_SUPPORT_SUPERG
2315a2130
> #endif
< __FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 190094 2009-03-19 18:45:37Z rpaulo $");
---
> __FBSDID("$FreeBSD: head/sys/net80211/ieee80211_output.c 190391 2009-03-24 20:39:08Z sam $");
49a50,52
> #ifdef IEEE80211_SUPPORT_SUPERG
> #include <net80211/ieee80211_superg.h>
> #endif
65,67d67
< static struct mbuf *ieee80211_encap_fastframe(struct ieee80211vap *,
< struct mbuf *m1, const struct ether_header *eh1,
< struct mbuf *m2, const struct ether_header *eh2);
734c734
< static struct mbuf *
---
> struct mbuf *
864c864
< int hdrsize, hdrspace, datalen, addqos, txfrag, isff, is4addr;
---
> int hdrsize, hdrspace, datalen, addqos, txfrag, is4addr;
938,941c938
< if ((isff = m->m_flags & M_FF) != 0) {
< struct mbuf *m2;
< struct ether_header eh2;
<
---
> if (__predict_true((m->m_flags & M_FF) == 0)) {
943,988d939
< * Fast frame encapsulation. There must be two packets
< * chained with m_nextpkt. We do header adjustment for
< * each, add the tunnel encapsulation, and then concatenate
< * the mbuf chains to form a single frame for transmission.
< */
< m2 = m->m_nextpkt;
< if (m2 == NULL) {
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: only one frame\n", __func__);
< goto bad;
< }
< m->m_nextpkt = NULL;
< /*
< * Include fast frame headers in adjusting header
< * layout; this allocates space according to what
< * ieee80211_encap_fastframe will do.
< */
< m = ieee80211_mbuf_adjust(vap,
< hdrspace + sizeof(struct llc) + sizeof(uint32_t) + 2 +
< sizeof(struct ether_header),
< key, m);
< if (m == NULL) {
< /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
< m_freem(m2);
< goto bad;
< }
< /*
< * Copy second frame's Ethernet header out of line
< * and adjust for encapsulation headers. Note that
< * we make room for padding in case there isn't room
< * at the end of first frame.
< */
< KASSERT(m2->m_len >= sizeof(eh2), ("no ethernet header!"));
< ETHER_HEADER_COPY(&eh2, mtod(m2, caddr_t));
< m2 = ieee80211_mbuf_adjust(vap,
< ATH_FF_MAX_HDR_PAD + sizeof(struct ether_header),
< NULL, m2);
< if (m2 == NULL) {
< /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
< goto bad;
< }
< m = ieee80211_encap_fastframe(vap, m, &eh, m2, &eh2);
< if (m == NULL)
< goto bad;
< } else {
< /*
1004a956,961
> } else {
> #ifdef IEEE80211_SUPPORT_SUPERG
> m = ieee80211_ff_encap(vap, m, hdrspace, key);
> if (m == NULL)
> #endif
> goto bad;
1050c1007
< if (m->m_flags & M_MORE_DATA)
---
> if (m->m_flags & M_MORE_DATA)
1131c1088
< !isff); /* NB: don't fragment ff's */
---
> (m->m_flags & M_FF) == 0); /* NB: don't fragment ff's */
1178,1306d1134
< * Do Ethernet-LLC encapsulation for each payload in a fast frame
< * tunnel encapsulation. The frame is assumed to have an Ethernet
< * header at the front that must be stripped before prepending the
< * LLC followed by the Ethernet header passed in (with an Ethernet
< * type that specifies the payload size).
< */
< static struct mbuf *
< ieee80211_encap1(struct ieee80211vap *vap, struct mbuf *m,
< const struct ether_header *eh)
< {
< struct llc *llc;
< uint16_t payload;
<
< /* XXX optimize by combining m_adj+M_PREPEND */
< m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
< llc = mtod(m, struct llc *);
< llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
< llc->llc_control = LLC_UI;
< llc->llc_snap.org_code[0] = 0;
< llc->llc_snap.org_code[1] = 0;
< llc->llc_snap.org_code[2] = 0;
< llc->llc_snap.ether_type = eh->ether_type;
< payload = m->m_pkthdr.len; /* NB: w/o Ethernet header */
<
< M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
< if (m == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for ether_header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< ETHER_HEADER_COPY(mtod(m, void *), eh);
< mtod(m, struct ether_header *)->ether_type = htons(payload);
< return m;
< }
<
< /*
< * Do fast frame tunnel encapsulation. The two frames and
< * Ethernet headers are supplied. The caller is assumed to
< * have arrange for space in the mbuf chains for encapsulating
< * headers (to avoid major mbuf fragmentation).
< *
< * The encapsulated frame is returned or NULL if there is a
< * problem (should not happen).
< */
< static struct mbuf *
< ieee80211_encap_fastframe(struct ieee80211vap *vap,
< struct mbuf *m1, const struct ether_header *eh1,
< struct mbuf *m2, const struct ether_header *eh2)
< {
< struct llc *llc;
< struct mbuf *m;
< int pad;
<
< /*
< * First, each frame gets a standard encapsulation.
< */
< m1 = ieee80211_encap1(vap, m1, eh1);
< if (m1 == NULL) {
< m_freem(m2);
< return NULL;
< }
< m2 = ieee80211_encap1(vap, m2, eh2);
< if (m2 == NULL) {
< m_freem(m1);
< return NULL;
< }
<
< /*
< * Pad leading frame to a 4-byte boundary. If there
< * is space at the end of the first frame, put it
< * there; otherwise prepend to the front of the second
< * frame. We know doing the second will always work
< * because we reserve space above. We prefer appending
< * as this typically has better DMA alignment properties.
< */
< for (m = m1; m->m_next != NULL; m = m->m_next)
< ;
< pad = roundup2(m1->m_pkthdr.len, 4) - m1->m_pkthdr.len;
< if (pad) {
< if (M_TRAILINGSPACE(m) < pad) { /* prepend to second */
< m2->m_data -= pad;
< m2->m_len += pad;
< m2->m_pkthdr.len += pad;
< } else { /* append to first */
< m->m_len += pad;
< m1->m_pkthdr.len += pad;
< }
< }
<
< /*
< * Now, stick 'em together and prepend the tunnel headers;
< * first the Atheros tunnel header (all zero for now) and
< * then a special fast frame LLC.
< *
< * XXX optimize by prepending together
< */
< m->m_next = m2; /* NB: last mbuf from above */
< m1->m_pkthdr.len += m2->m_pkthdr.len;
< M_PREPEND(m1, sizeof(uint32_t)+2, M_DONTWAIT);
< if (m1 == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for tunnel header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< memset(mtod(m1, void *), 0, sizeof(uint32_t)+2);
<
< M_PREPEND(m1, sizeof(struct llc), M_DONTWAIT);
< if (m1 == NULL) { /* XXX cannot happen */
< IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
< "%s: no space for llc header\n", __func__);
< vap->iv_stats.is_tx_nobuf++;
< return NULL;
< }
< llc = mtod(m1, struct llc *);
< llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
< llc->llc_control = LLC_UI;
< llc->llc_snap.org_code[0] = ATH_FF_SNAP_ORGCODE_0;
< llc->llc_snap.org_code[1] = ATH_FF_SNAP_ORGCODE_1;
< llc->llc_snap.org_code[2] = ATH_FF_SNAP_ORGCODE_2;
< llc->llc_snap.ether_type = htons(ATH_FF_ETH_TYPE);
<
< vap->iv_stats.is_ff_encap++;
<
< return m1;
< }
<
< /*
1571d1398
< #define ATH_OUI_BYTES 0x00, 0x03, 0x7f
1573,1596d1399
< * Add a WME information element to a frame.
< */
< static uint8_t *
< ieee80211_add_ath(uint8_t *frm, uint8_t caps, uint16_t defkeyix)
< {
< static const struct ieee80211_ath_ie info = {
< .ath_id = IEEE80211_ELEMID_VENDOR,
< .ath_len = sizeof(struct ieee80211_ath_ie) - 2,
< .ath_oui = { ATH_OUI_BYTES },
< .ath_oui_type = ATH_OUI_TYPE,
< .ath_oui_subtype= ATH_OUI_SUBTYPE,
< .ath_version = ATH_OUI_VERSION,
< };
< struct ieee80211_ath_ie *ath = (struct ieee80211_ath_ie *) frm;
<
< memcpy(frm, &info, sizeof(info));
< ath->ath_capability = caps;
< ath->ath_defkeyix[0] = (defkeyix & 0xff);
< ath->ath_defkeyix[1] = ((defkeyix >> 8) & 0xff);
< return frm + sizeof(info);
< }
< #undef ATH_OUI_BYTES
<
< /*
1979a1783
> #ifdef IEEE80211_SUPPORT_SUPERG
1980a1785
> #endif
2048a1854
> #ifdef IEEE80211_SUPPORT_SUPERG
2055a1862
> #endif /* IEEE80211_SUPPORT_SUPERG */
2090a1898
> #ifdef IEEE80211_SUPPORT_SUPERG
2091a1900
> #endif
2125a1935
> #ifdef IEEE80211_SUPPORT_SUPERG
2129a1940
> #endif /* IEEE80211_SUPPORT_SUPERG */
2229a2041
> #ifdef IEEE80211_SUPPORT_SUPERG
2230a2043
> #endif
2312a2126
> #ifdef IEEE80211_SUPPORT_SUPERG
2315a2130
> #endif