From 32bfd35d4b63bd63de4bb0d791ef049c3c868726 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Dec 2007 01:31:26 +0100 Subject: mac80211: dont use interface indices in drivers This patch gets rid of the if_id stuff where possible in favour of a new per-virtual-interface structure "struct ieee80211_vif". This structure is located at the end of the per-interface structure and contains a variable length driver-use data area. This has two advantages: * removes the need to look up interfaces by if_id, this is better for working with network namespaces and performance * allows drivers to store and retrieve per-interface data without having to allocate own lists/hash tables Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211.c | 12 ++++++----- net/mac80211/ieee80211_i.h | 8 ++++++++ net/mac80211/ieee80211_iface.c | 2 +- net/mac80211/sta_info.c | 27 +++++++++++++++++++------ net/mac80211/tx.c | 46 +++++++++++++++++++----------------------- net/mac80211/util.c | 45 ++++++++++++++--------------------------- 6 files changed, 73 insertions(+), 67 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 4807e52..42c2708 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -243,7 +243,7 @@ static int ieee80211_open(struct net_device *dev) sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; /* fall through */ default: - conf.if_id = dev->ifindex; + conf.vif = &sdata->vif; conf.type = sdata->type; conf.mac_addr = dev->dev_addr; res = local->ops->add_interface(local_to_hw(local), &conf); @@ -378,7 +378,7 @@ static int ieee80211_stop(struct net_device *dev) sdata->u.sta.extra_ie_len = 0; /* fall through */ default: - conf.if_id = dev->ifindex; + conf.vif = &sdata->vif; conf.type = sdata->type; conf.mac_addr = dev->dev_addr; /* disable all keys for as long as this netdev is down */ @@ -515,7 +515,7 @@ static int __ieee80211_if_config(struct net_device *dev, conf.beacon_control = control; } return local->ops->config_interface(local_to_hw(local), - dev->ifindex, &conf); + &sdata->vif, &conf); } int ieee80211_if_config(struct net_device *dev) @@ -527,11 +527,13 @@ int ieee80211_if_config_beacon(struct net_device *dev) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_control control; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sk_buff *skb; if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) return 0; - skb = ieee80211_beacon_get(local_to_hw(local), dev->ifindex, &control); + skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif, + &control); if (!skb) return -ENOMEM; return __ieee80211_if_config(dev, skb, &control); @@ -736,7 +738,7 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, struct ieee80211_tx_packet_data *pkt_data; pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; - pkt_data->ifindex = control->ifindex; + pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex; pkt_data->flags = 0; if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS) pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b898b31..c551a7f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -387,8 +387,16 @@ struct ieee80211_sub_if_data { struct dentry *default_key; } debugfs; #endif + /* must be last, dynamically sized area in this! */ + struct ieee80211_vif vif; }; +static inline +struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) +{ + return container_of(p, struct ieee80211_sub_if_data, vif); +} + #define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev) enum { diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index 7cfd866..b720663 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c @@ -47,7 +47,7 @@ int ieee80211_if_add(struct net_device *dev, const char *name, int ret; ASSERT_RTNL(); - ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), + ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, ieee80211_if_setup); if (!ndev) return -ENOMEM; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 1257c7a..32e2417 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -177,9 +177,16 @@ struct sta_info * sta_info_add(struct ieee80211_local *local, list_add(&sta->list, &local->sta_list); local->num_sta++; sta_info_hash_add(local, sta); - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), dev->ifindex, - STA_NOTIFY_ADD, addr); + if (local->ops->sta_notify) { + struct ieee80211_sub_if_data *sdata; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + if (sdata->type == IEEE80211_IF_TYPE_VLAN) + sdata = sdata->u.vlan.ap; + + local->ops->sta_notify(local_to_hw(local), &sdata->vif, + STA_NOTIFY_ADD, addr); + } write_unlock_bh(&local->sta_lock); #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -247,9 +254,17 @@ void sta_info_free(struct sta_info *sta) ieee80211_key_free(sta->key); sta->key = NULL; - if (local->ops->sta_notify) - local->ops->sta_notify(local_to_hw(local), sta->dev->ifindex, - STA_NOTIFY_REMOVE, sta->addr); + if (local->ops->sta_notify) { + struct ieee80211_sub_if_data *sdata; + + sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); + + if (sdata->type == IEEE80211_IF_TYPE_VLAN) + sdata = sdata->u.vlan.ap; + + local->ops->sta_notify(local_to_hw(local), &sdata->vif, + STA_NOTIFY_REMOVE, sta->addr); + } rate_control_remove_sta_debugfs(sta); ieee80211_sta_debugfs_remove(sta); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f619416..1b772ee 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -999,9 +999,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, return TXRX_CONTINUE; } -/* Device in tx->dev has a reference added; use dev_put(tx->dev) when - * finished with it. - * +/* * NB: @tx is uninitialised when passed in here */ static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, @@ -1022,6 +1020,7 @@ static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx, return -ENODEV; /* initialises tx with control */ __ieee80211_tx_prepare(tx, skb, dev, control); + dev_put(dev); return 0; } @@ -1252,7 +1251,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, } } - control.ifindex = odev->ifindex; + control.vif = &osdata->vif; control.type = osdata->type; if (pkt_data->flags & IEEE80211_TXPD_REQ_TX_STATUS) control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS; @@ -1691,7 +1690,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local, read_unlock_bh(&local->sta_lock); } -struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, +struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_tx_control *control) { struct ieee80211_local *local = hw_to_local(hw); @@ -1703,19 +1703,16 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, u8 *b_head, *b_tail; int bh_len, bt_len; - bdev = dev_get_by_index(&init_net, if_id); - if (bdev) { - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); - ap = &sdata->u.ap; - dev_put(bdev); - } + sdata = vif_to_sdata(vif); + bdev = sdata->dev; + ap = &sdata->u.ap; if (!ap || sdata->type != IEEE80211_IF_TYPE_AP || !ap->beacon_head) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) - printk(KERN_DEBUG "no beacon data avail for idx=%d " - "(%s)\n", if_id, bdev ? bdev->name : "N/A"); + printk(KERN_DEBUG "no beacon data avail for %s\n", + bdev->name); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ return NULL; } @@ -1771,7 +1768,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, } EXPORT_SYMBOL(ieee80211_beacon_get); -void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id, +void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_control *frame_txctl, struct ieee80211_rts *rts) @@ -1781,13 +1778,14 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id, fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; rts->frame_control = cpu_to_le16(fctl); - rts->duration = ieee80211_rts_duration(hw, if_id, frame_len, frame_txctl); + rts->duration = ieee80211_rts_duration(hw, vif, frame_len, + frame_txctl); memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); } EXPORT_SYMBOL(ieee80211_rts_get); -void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id, +void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_control *frame_txctl, struct ieee80211_cts *cts) @@ -1797,13 +1795,15 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id, fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; cts->frame_control = cpu_to_le16(fctl); - cts->duration = ieee80211_ctstoself_duration(hw, if_id, frame_len, frame_txctl); + cts->duration = ieee80211_ctstoself_duration(hw, vif, + frame_len, frame_txctl); memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); } EXPORT_SYMBOL(ieee80211_ctstoself_get); struct sk_buff * -ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, +ieee80211_get_buffered_bc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct ieee80211_tx_control *control) { struct ieee80211_local *local = hw_to_local(hw); @@ -1816,12 +1816,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; - bdev = dev_get_by_index(&init_net, if_id); - if (bdev) { - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); - bss = &sdata->u.ap; - dev_put(bdev); - } + sdata = vif_to_sdata(vif); + bdev = sdata->dev; + if (!bss || sdata->type != IEEE80211_IF_TYPE_AP || !bss->beacon_head) return NULL; @@ -1857,7 +1854,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id, if (res == TXRX_DROP || res == TXRX_QUEUED) break; } - dev_put(tx.dev); skb = tx.skb; /* handlers are allowed to change skb */ if (res == TXRX_DROP) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index adb85dd..15503ca 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -302,44 +302,34 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, } /* Exported duration function for driver use */ -__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, int if_id, +__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, size_t frame_len, int rate) { struct ieee80211_local *local = hw_to_local(hw); - struct net_device *bdev = dev_get_by_index(&init_net, if_id); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); u16 dur; int erp; - if (unlikely(!bdev)) - return 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); erp = ieee80211_is_erp_rate(hw->conf.phymode, rate); dur = ieee80211_frame_duration(local, frame_len, rate, erp, sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE); - dev_put(bdev); return cpu_to_le16(dur); } EXPORT_SYMBOL(ieee80211_generic_frame_duration); -__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id, - size_t frame_len, +__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, size_t frame_len, const struct ieee80211_tx_control *frame_txctl) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; - struct net_device *bdev = dev_get_by_index(&init_net, if_id); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); int short_preamble; int erp; u16 dur; - if (unlikely(!bdev)) - return 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); short_preamble = sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE; rate = frame_txctl->rts_rate; @@ -355,27 +345,22 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id, dur += ieee80211_frame_duration(local, 10, rate->rate, erp, short_preamble); - dev_put(bdev); return cpu_to_le16(dur); } EXPORT_SYMBOL(ieee80211_rts_duration); -__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id, +__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, size_t frame_len, const struct ieee80211_tx_control *frame_txctl) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; - struct net_device *bdev = dev_get_by_index(&init_net, if_id); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); int short_preamble; int erp; u16 dur; - if (unlikely(!bdev)) - return 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(bdev); short_preamble = sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE; rate = frame_txctl->rts_rate; @@ -390,7 +375,6 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id, erp, short_preamble); } - dev_put(bdev); return cpu_to_le16(dur); } EXPORT_SYMBOL(ieee80211_ctstoself_duration); @@ -475,10 +459,11 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_wake_queues); -void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, - void (*iterator)(void *data, u8 *mac, - int if_id), - void *data) +void ieee80211_iterate_active_interfaces( + struct ieee80211_hw *hw, + void (*iterator)(void *data, u8 *mac, + struct ieee80211_vif *vif), + void *data) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; @@ -501,7 +486,7 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw, continue; if (netif_running(sdata->dev)) iterator(data, sdata->dev->dev_addr, - sdata->dev->ifindex); + &sdata->vif); } rcu_read_unlock(); -- cgit v1.1