Skip to content

Commit 7044cc5

Browse files
Kalle Valolinvjw
authored andcommitted
mac80211: add functions to create PS Poll and Nullfunc templates
Some hardware, for example wl1251 and wl1271, handle the transmission of power save related frames in hardware, but the driver is responsible for creating the templates. It's better to create the templates in mac80211, that way all drivers can benefit from this. Add two new functions, ieee80211_pspoll_get() and ieee80211_nullfunc_get() which drivers need to call to get the frame. Drivers are also responsible for updating the templates after each association. Also new struct ieee80211_hdr_3addr is added to ieee80211.h to make it easy to calculate length of the Nullfunc frame. Signed-off-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent b3579d6 commit 7044cc5

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

include/linux/ieee80211.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ struct ieee80211_hdr {
130130
u8 addr4[6];
131131
} __attribute__ ((packed));
132132

133+
struct ieee80211_hdr_3addr {
134+
__le16 frame_control;
135+
__le16 duration_id;
136+
u8 addr1[6];
137+
u8 addr2[6];
138+
u8 addr3[6];
139+
__le16 seq_ctrl;
140+
} __attribute__ ((packed));
141+
133142
/**
134143
* ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
135144
* @fc: frame control bytes in little-endian byteorder

include/net/mac80211.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,36 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
18741874
return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
18751875
}
18761876

1877+
/**
1878+
* ieee80211_pspoll_get - retrieve a PS Poll template
1879+
* @hw: pointer obtained from ieee80211_alloc_hw().
1880+
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
1881+
*
1882+
* Creates a PS Poll a template which can, for example, uploaded to
1883+
* hardware. The template must be updated after association so that correct
1884+
* AID, BSSID and MAC address is used.
1885+
*
1886+
* Note: Caller (or hardware) is responsible for setting the
1887+
* &IEEE80211_FCTL_PM bit.
1888+
*/
1889+
struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
1890+
struct ieee80211_vif *vif);
1891+
1892+
/**
1893+
* ieee80211_nullfunc_get - retrieve a nullfunc template
1894+
* @hw: pointer obtained from ieee80211_alloc_hw().
1895+
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
1896+
*
1897+
* Creates a Nullfunc template which can, for example, uploaded to
1898+
* hardware. The template must be updated after association so that correct
1899+
* BSSID and address is used.
1900+
*
1901+
* Note: Caller (or hardware) is responsible for setting the
1902+
* &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
1903+
*/
1904+
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
1905+
struct ieee80211_vif *vif);
1906+
18771907
/**
18781908
* ieee80211_rts_get - RTS frame generation function
18791909
* @hw: pointer obtained from ieee80211_alloc_hw().

net/mac80211/tx.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,84 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
22002200
}
22012201
EXPORT_SYMBOL(ieee80211_beacon_get_tim);
22022202

2203+
struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
2204+
struct ieee80211_vif *vif)
2205+
{
2206+
struct ieee80211_sub_if_data *sdata;
2207+
struct ieee80211_if_managed *ifmgd;
2208+
struct ieee80211_pspoll *pspoll;
2209+
struct ieee80211_local *local;
2210+
struct sk_buff *skb;
2211+
2212+
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
2213+
return NULL;
2214+
2215+
sdata = vif_to_sdata(vif);
2216+
ifmgd = &sdata->u.mgd;
2217+
local = sdata->local;
2218+
2219+
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
2220+
if (!skb) {
2221+
printk(KERN_DEBUG "%s: failed to allocate buffer for "
2222+
"pspoll template\n", sdata->name);
2223+
return NULL;
2224+
}
2225+
skb_reserve(skb, local->hw.extra_tx_headroom);
2226+
2227+
pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
2228+
memset(pspoll, 0, sizeof(*pspoll));
2229+
pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
2230+
IEEE80211_STYPE_PSPOLL);
2231+
pspoll->aid = cpu_to_le16(ifmgd->aid);
2232+
2233+
/* aid in PS-Poll has its two MSBs each set to 1 */
2234+
pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);
2235+
2236+
memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
2237+
memcpy(pspoll->ta, vif->addr, ETH_ALEN);
2238+
2239+
return skb;
2240+
}
2241+
EXPORT_SYMBOL(ieee80211_pspoll_get);
2242+
2243+
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
2244+
struct ieee80211_vif *vif)
2245+
{
2246+
struct ieee80211_hdr_3addr *nullfunc;
2247+
struct ieee80211_sub_if_data *sdata;
2248+
struct ieee80211_if_managed *ifmgd;
2249+
struct ieee80211_local *local;
2250+
struct sk_buff *skb;
2251+
2252+
if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
2253+
return NULL;
2254+
2255+
sdata = vif_to_sdata(vif);
2256+
ifmgd = &sdata->u.mgd;
2257+
local = sdata->local;
2258+
2259+
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
2260+
if (!skb) {
2261+
printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
2262+
"template\n", sdata->name);
2263+
return NULL;
2264+
}
2265+
skb_reserve(skb, local->hw.extra_tx_headroom);
2266+
2267+
nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb,
2268+
sizeof(*nullfunc));
2269+
memset(nullfunc, 0, sizeof(*nullfunc));
2270+
nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
2271+
IEEE80211_STYPE_NULLFUNC |
2272+
IEEE80211_FCTL_TODS);
2273+
memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
2274+
memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
2275+
memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
2276+
2277+
return skb;
2278+
}
2279+
EXPORT_SYMBOL(ieee80211_nullfunc_get);
2280+
22032281
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
22042282
const void *frame, size_t frame_len,
22052283
const struct ieee80211_tx_info *frame_txctl,

0 commit comments

Comments
 (0)