mac80211: add driver callback for per-interface multicast filter
Some devices have multicast filter capability for each individual virtual interface rather than just a global one. Add an interface specific driver callback allowing such drivers to configure this. Signed-off-by: Alexander Bondar <alexander.bondar@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
511044ea0b
commit
488b366a45
4 changed files with 58 additions and 0 deletions
|
@ -2259,6 +2259,9 @@ enum ieee80211_roc_type {
|
||||||
* See the section "Frame filtering" for more information.
|
* See the section "Frame filtering" for more information.
|
||||||
* This callback must be implemented and can sleep.
|
* This callback must be implemented and can sleep.
|
||||||
*
|
*
|
||||||
|
* @set_multicast_list: Configure the device's interface specific RX multicast
|
||||||
|
* filter. This callback is optional. This callback must be atomic.
|
||||||
|
*
|
||||||
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
* @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit
|
||||||
* must be set or cleared for a given STA. Must be atomic.
|
* must be set or cleared for a given STA. Must be atomic.
|
||||||
*
|
*
|
||||||
|
@ -2605,6 +2608,10 @@ struct ieee80211_ops {
|
||||||
unsigned int changed_flags,
|
unsigned int changed_flags,
|
||||||
unsigned int *total_flags,
|
unsigned int *total_flags,
|
||||||
u64 multicast);
|
u64 multicast);
|
||||||
|
void (*set_multicast_list)(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif, bool allmulti,
|
||||||
|
struct netdev_hw_addr_list *mc_list);
|
||||||
|
|
||||||
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
|
||||||
bool set);
|
bool set);
|
||||||
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||||
|
|
|
@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void drv_set_multicast_list(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct netdev_hw_addr_list *mc_list)
|
||||||
|
{
|
||||||
|
bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
|
||||||
|
|
||||||
|
trace_drv_set_multicast_list(local, sdata, mc_list->count);
|
||||||
|
|
||||||
|
check_sdata_in_driver(sdata);
|
||||||
|
|
||||||
|
if (local->ops->set_multicast_list)
|
||||||
|
local->ops->set_multicast_list(&local->hw, &sdata->vif,
|
||||||
|
allmulti, mc_list);
|
||||||
|
trace_drv_return_void(local);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void drv_configure_filter(struct ieee80211_local *local,
|
static inline void drv_configure_filter(struct ieee80211_local *local,
|
||||||
unsigned int changed_flags,
|
unsigned int changed_flags,
|
||||||
unsigned int *total_flags,
|
unsigned int *total_flags,
|
||||||
|
|
|
@ -919,6 +919,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
|
||||||
atomic_dec(&local->iff_promiscs);
|
atomic_dec(&local->iff_promiscs);
|
||||||
sdata->flags ^= IEEE80211_SDATA_PROMISC;
|
sdata->flags ^= IEEE80211_SDATA_PROMISC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: If somebody needs this on AP interfaces,
|
||||||
|
* it can be enabled easily but multicast
|
||||||
|
* addresses from VLANs need to be synced.
|
||||||
|
*/
|
||||||
|
if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
|
||||||
|
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
||||||
|
sdata->vif.type != NL80211_IFTYPE_AP)
|
||||||
|
drv_set_multicast_list(local, sdata, &dev->mc);
|
||||||
|
|
||||||
spin_lock_bh(&local->filter_lock);
|
spin_lock_bh(&local->filter_lock);
|
||||||
__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
|
__hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len);
|
||||||
spin_unlock_bh(&local->filter_lock);
|
spin_unlock_bh(&local->filter_lock);
|
||||||
|
|
|
@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(drv_set_multicast_list,
|
||||||
|
TP_PROTO(struct ieee80211_local *local,
|
||||||
|
struct ieee80211_sub_if_data *sdata, int mc_count),
|
||||||
|
|
||||||
|
TP_ARGS(local, sdata, mc_count),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
LOCAL_ENTRY
|
||||||
|
__field(bool, allmulti)
|
||||||
|
__field(int, mc_count)
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
LOCAL_ASSIGN;
|
||||||
|
__entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI;
|
||||||
|
__entry->mc_count = mc_count;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk(
|
||||||
|
LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d",
|
||||||
|
LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
TRACE_EVENT(drv_configure_filter,
|
TRACE_EVENT(drv_configure_filter,
|
||||||
TP_PROTO(struct ieee80211_local *local,
|
TP_PROTO(struct ieee80211_local *local,
|
||||||
unsigned int changed_flags,
|
unsigned int changed_flags,
|
||||||
|
|
Loading…
Add table
Reference in a new issue