Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202816
b: refs/heads/master
c: 2b2c009
h: refs/heads/master
v: v3
  • Loading branch information
Juuso Oikarinen authored and John W. Linville committed Jun 3, 2010
1 parent 8f036d8 commit b53bb23
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 095dfdb0c479661f437b24b85e31f0d0b841eab6
refs/heads/master: 2b2c009ecf71f4c66ff8420b63dddbc9737e04e3
14 changes: 14 additions & 0 deletions trunk/include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/wireless.h>
#include <linux/device.h>
#include <linux/ieee80211.h>
#include <linux/inetdevice.h>
#include <net/cfg80211.h>

/**
Expand Down Expand Up @@ -1532,6 +1533,16 @@ enum ieee80211_ampdu_mlme_action {
* of the bss parameters has changed when a call is made. The callback
* can sleep.
*
* @configure_arp_filter: Configuration function for hardware ARP query filter.
* This function is called with all the IP addresses configured to the
* interface as argument - all ARP queries targeted to any of these
* addresses must pass through. If the hardware filter does not support
* enought addresses, hardware filtering must be disabled. The ifa_list
* argument may be NULL, indicating that filtering must be disabled.
* This function is called upon association complete with current
* address(es), and while associated whenever the IP address(es) change.
* The callback can sleep.
*
* @prepare_multicast: Prepare for multicast filter configuration.
* This callback is optional, and its return value is passed
* to configure_filter(). This callback must be atomic.
Expand Down Expand Up @@ -1671,6 +1682,9 @@ struct ieee80211_ops {
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *info,
u32 changed);
int (*configure_arp_filter)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct in_ifaddr *ifa_list);
u64 (*prepare_multicast)(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list);
void (*configure_filter)(struct ieee80211_hw *hw,
Expand Down
17 changes: 17 additions & 0 deletions trunk/net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
trace_drv_bss_info_changed(local, sdata, info, changed);
}

struct in_ifaddr;
static inline int drv_configure_arp_filter(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct in_ifaddr *ifa_list)
{
int ret = 0;

might_sleep();

if (local->ops->configure_arp_filter)
ret = local->ops->configure_arp_filter(&local->hw, vif,
ifa_list);

trace_drv_configure_arp_filter(local, vif_to_sdata(vif), ifa_list, ret);
return ret;
}

static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
struct netdev_hw_addr_list *mc_list)
{
Expand Down
25 changes: 25 additions & 0 deletions trunk/net/mac80211/driver-trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,31 @@ TRACE_EVENT(drv_bss_info_changed,
)
);

TRACE_EVENT(drv_configure_arp_filter,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct in_ifaddr *ifa_list, int ret),

TP_ARGS(local, sdata, ifa_list, ret),

TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
__field(int, ret)
),

TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
__entry->ret = ret;
),

TP_printk(
VIF_PR_FMT LOCAL_PR_FMT " ret:%d",
VIF_PR_ARG, LOCAL_PR_ARG, __entry->ret
)
);

TRACE_EVENT(drv_prepare_multicast,
TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret),

Expand Down
2 changes: 2 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ struct ieee80211_local {
struct work_struct dynamic_ps_disable_work;
struct timer_list dynamic_ps_timer;
struct notifier_block network_latency_notifier;
struct notifier_block ifa_notifier;

int user_power_level; /* in dBm */
int power_constr_level; /* in dBm */
Expand Down Expand Up @@ -997,6 +998,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_sw_ie *sw_elem,
struct ieee80211_bss *bss,
Expand Down
63 changes: 62 additions & 1 deletion trunk/net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,58 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
mutex_unlock(&local->iflist_mtx);
}

int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata)
{
struct in_device *idev;
int ret = 0;

BUG_ON(!sdata);
ASSERT_RTNL();

idev = sdata->dev->ip_ptr;
if (!idev)
return 0;

ret = drv_configure_arp_filter(sdata->local, &sdata->vif,
idev->ifa_list);
return ret;
}

static int ieee80211_ifa_changed(struct notifier_block *nb,
unsigned long data, void *arg)
{
struct in_ifaddr *ifa = arg;
struct ieee80211_local *local =
container_of(nb, struct ieee80211_local,
ifa_notifier);
struct net_device *ndev = ifa->ifa_dev->dev;
struct wireless_dev *wdev = ndev->ieee80211_ptr;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_if_managed *ifmgd;

/* Make sure it's our interface that got changed */
if (!wdev)
return NOTIFY_DONE;

if (wdev->wiphy != local->hw.wiphy)
return NOTIFY_DONE;

/* We are concerned about IP addresses only when associated */
sdata = IEEE80211_DEV_TO_SUB_IF(ndev);

/* ARP filtering is only supported in managed mode */
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return NOTIFY_DONE;

ifmgd = &sdata->u.mgd;
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated)
ieee80211_set_arp_filter(sdata);
mutex_unlock(&ifmgd->mtx);

return NOTIFY_DONE;
}

struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops)
{
Expand Down Expand Up @@ -612,14 +664,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
ieee80211_max_network_latency;
result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
&local->network_latency_notifier);

if (result) {
rtnl_lock();
goto fail_pm_qos;
}

local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
result = register_inetaddr_notifier(&local->ifa_notifier);
if (result)
goto fail_ifa;

return 0;

fail_ifa:
pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
&local->network_latency_notifier);
rtnl_lock();
fail_pm_qos:
ieee80211_led_exit(local);
ieee80211_remove_interfaces(local);
Expand Down Expand Up @@ -647,6 +707,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)

pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
&local->network_latency_notifier);
unregister_inetaddr_notifier(&local->ifa_notifier);

rtnl_lock();

Expand Down
11 changes: 10 additions & 1 deletion trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -2078,8 +2078,17 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
cfg80211_send_assoc_timeout(wk->sdata->dev,
wk->filter_ta);
return WORK_DONE_DESTROY;
} else {
mutex_unlock(&wk->sdata->u.mgd.mtx);

/*
* configure ARP filter IP addresses to the driver,
* intentionally outside the mgd mutex.
*/
rtnl_lock();
ieee80211_set_arp_filter(wk->sdata);
rtnl_unlock();
}
mutex_unlock(&wk->sdata->u.mgd.mtx);
}

cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
Expand Down

0 comments on commit b53bb23

Please sign in to comment.