mac80211: Split sending tx'ed frames to monitor interfaces into its own function
This allows ieee80211_tx_monitor to be used directly for sending 802.11 frames to all monitor interfaces. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
d55d0d598e
commit
4dc792b8f0
@ -1635,6 +1635,9 @@ void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
|
|||||||
struct sk_buff *
|
struct sk_buff *
|
||||||
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb, u32 info_flags);
|
struct sk_buff *skb, u32 info_flags);
|
||||||
|
void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
|
||||||
|
struct ieee80211_supported_band *sband,
|
||||||
|
int retry_count, int shift, bool send_to_cooked);
|
||||||
|
|
||||||
void ieee80211_check_fast_xmit(struct sta_info *sta);
|
void ieee80211_check_fast_xmit(struct sta_info *sta);
|
||||||
void ieee80211_check_fast_xmit_all(struct ieee80211_local *local);
|
void ieee80211_check_fast_xmit_all(struct ieee80211_local *local);
|
||||||
|
@ -668,16 +668,70 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_tx_status_noskb);
|
EXPORT_SYMBOL(ieee80211_tx_status_noskb);
|
||||||
|
|
||||||
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
|
||||||
|
struct ieee80211_supported_band *sband,
|
||||||
|
int retry_count, int shift, bool send_to_cooked)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
struct net_device *prev_dev = NULL;
|
||||||
|
int rtap_len;
|
||||||
|
|
||||||
|
/* send frame to monitor interfaces now */
|
||||||
|
rtap_len = ieee80211_tx_radiotap_len(info);
|
||||||
|
if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
|
||||||
|
pr_err("ieee80211_tx_status: headroom too small\n");
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
|
||||||
|
rtap_len, shift);
|
||||||
|
|
||||||
|
/* XXX: is this sufficient for BPF? */
|
||||||
|
skb_set_mac_header(skb, 0);
|
||||||
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
skb->pkt_type = PACKET_OTHERHOST;
|
||||||
|
skb->protocol = htons(ETH_P_802_2);
|
||||||
|
memset(skb->cb, 0, sizeof(skb->cb));
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||||
|
if (!ieee80211_sdata_running(sdata))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
|
||||||
|
!send_to_cooked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (prev_dev) {
|
||||||
|
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
if (skb2) {
|
||||||
|
skb2->dev = prev_dev;
|
||||||
|
netif_rx(skb2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_dev = sdata->dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prev_dev) {
|
||||||
|
skb->dev = prev_dev;
|
||||||
|
netif_rx(skb);
|
||||||
|
skb = NULL;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||||
|
{
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
struct ieee80211_local *local = hw_to_local(hw);
|
struct ieee80211_local *local = hw_to_local(hw);
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
__le16 fc;
|
__le16 fc;
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
|
||||||
struct net_device *prev_dev = NULL;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
struct rhash_head *tmp;
|
struct rhash_head *tmp;
|
||||||
int retry_count;
|
int retry_count;
|
||||||
@ -685,7 +739,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||||||
bool send_to_cooked;
|
bool send_to_cooked;
|
||||||
bool acked;
|
bool acked;
|
||||||
struct ieee80211_bar *bar;
|
struct ieee80211_bar *bar;
|
||||||
int rtap_len;
|
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
int tid = IEEE80211_NUM_TIDS;
|
int tid = IEEE80211_NUM_TIDS;
|
||||||
const struct bucket_table *tbl;
|
const struct bucket_table *tbl;
|
||||||
@ -878,51 +931,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send frame to monitor interfaces now */
|
/* send to monitor interfaces */
|
||||||
rtap_len = ieee80211_tx_radiotap_len(info);
|
ieee80211_tx_monitor(local, skb, sband, retry_count, shift, send_to_cooked);
|
||||||
if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
|
|
||||||
pr_err("ieee80211_tx_status: headroom too small\n");
|
|
||||||
dev_kfree_skb(skb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
|
|
||||||
rtap_len, shift);
|
|
||||||
|
|
||||||
/* XXX: is this sufficient for BPF? */
|
|
||||||
skb_set_mac_header(skb, 0);
|
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
||||||
skb->pkt_type = PACKET_OTHERHOST;
|
|
||||||
skb->protocol = htons(ETH_P_802_2);
|
|
||||||
memset(skb->cb, 0, sizeof(skb->cb));
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
|
||||||
if (!ieee80211_sdata_running(sdata))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
|
|
||||||
!send_to_cooked)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (prev_dev) {
|
|
||||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
|
||||||
if (skb2) {
|
|
||||||
skb2->dev = prev_dev;
|
|
||||||
netif_rx(skb2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_dev = sdata->dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prev_dev) {
|
|
||||||
skb->dev = prev_dev;
|
|
||||||
netif_rx(skb);
|
|
||||||
skb = NULL;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
|
||||||
dev_kfree_skb(skb);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_tx_status);
|
EXPORT_SYMBOL(ieee80211_tx_status);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user