* Handle 11n/11ac channel switch. * * Use the received HT/VHT ie's to identify the right channel to use. * If we cannot locate it in the channel table then fallback to * legacy operation. * * Note that we use this information to identify the node's * channel only; the caller is responsible for insuring any * required channel change is done (e.g. in sta mode when * parsing the contents of
| 1729 | * parsing the contents of a beacon frame). |
| 1730 | */ |
| 1731 | static int |
| 1732 | htinfo_update_chw(struct ieee80211_node *ni, int htflags, int vhtflags) |
| 1733 | { |
| 1734 | struct ieee80211com *ic = ni->ni_ic; |
| 1735 | struct ieee80211_channel *c; |
| 1736 | int chanflags; |
| 1737 | int ret = 0; |
| 1738 | |
| 1739 | /* |
| 1740 | * First step - do HT/VHT only channel lookup based on operating mode |
| 1741 | * flags. This involves masking out the VHT flags as well. |
| 1742 | * Otherwise we end up doing the full channel walk each time |
| 1743 | * we trigger this, which is expensive. |
| 1744 | */ |
| 1745 | chanflags = (ni->ni_chan->ic_flags &~ |
| 1746 | (IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT)) | htflags | vhtflags; |
| 1747 | |
| 1748 | if (chanflags == ni->ni_chan->ic_flags) |
| 1749 | goto done; |
| 1750 | |
| 1751 | /* |
| 1752 | * If HT /or/ VHT flags have changed then check both. |
| 1753 | * We need to start by picking a HT channel anyway. |
| 1754 | */ |
| 1755 | |
| 1756 | c = NULL; |
| 1757 | chanflags = (ni->ni_chan->ic_flags &~ |
| 1758 | (IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT)) | htflags; |
| 1759 | /* XXX not right for ht40- */ |
| 1760 | c = ieee80211_find_channel(ic, ni->ni_chan->ic_freq, chanflags); |
| 1761 | if (c == NULL && (htflags & IEEE80211_CHAN_HT40)) { |
| 1762 | /* |
| 1763 | * No HT40 channel entry in our table; fall back |
| 1764 | * to HT20 operation. This should not happen. |
| 1765 | */ |
| 1766 | c = findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT20); |
| 1767 | #if 0 |
| 1768 | IEEE80211_NOTE(ni->ni_vap, |
| 1769 | IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni, |
| 1770 | "no HT40 channel (freq %u), falling back to HT20", |
| 1771 | ni->ni_chan->ic_freq); |
| 1772 | #endif |
| 1773 | /* XXX stat */ |
| 1774 | } |
| 1775 | |
| 1776 | /* Nothing found - leave it alone; move onto VHT */ |
| 1777 | if (c == NULL) |
| 1778 | c = ni->ni_chan; |
| 1779 | |
| 1780 | /* |
| 1781 | * If it's non-HT, then bail out now. |
| 1782 | */ |
| 1783 | if (! IEEE80211_IS_CHAN_HT(c)) { |
| 1784 | IEEE80211_NOTE(ni->ni_vap, |
| 1785 | IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni, |
| 1786 | "not HT; skipping VHT check (%u/0x%x)", |
| 1787 | c->ic_freq, c->ic_flags); |
| 1788 | goto done; |
no test coverage detected