On Wed, 15 Mar 2006 16:36:16 -0800, Jouni Malinen wrote: > In theory, the low-level driver can determine the needed mask itself. > However, it would need to be somehow notified of allowed BSSID values. > By removing this entry, this information would need to fetched from > somewhere else before interfaces are added. > > Most hardware implementations have storage for a single MAC address in > EEPROM (or something similar) and in some cases, no addresses are stored > with the card and some external store is needed for this. We have been > using this mechanism of passing the information from user space to avoid > problems in figuring out board specific mechanisms for storing extra > data. Do you have any ideas on what would be the best of getting this > information configured after this change?
See the patch below. Is it viable? > This and similar change for ieee80211_get_buffered_bc() add more > requirements for the low-level driver. It used to be enough to just know > that the low-level code should ask for up to N beacon frames. However, > with this change, the low-level driver would need to maintain a list of > ifindexes for the virtual interfaces. This is somewhat against the > original design of hiding all the virtual interfaces from low-level > code. I like the approach, but I'm afraid it's not generic enough. The new code should cover all possibilities (even such hypothetical case as a card capable of multiple APs in its firmware with host-buffering of frames for STAs in PS mode). In a typical case of only-one-AP capable card the code will be nearly the same. In your case it indeed means one extra list. > I think the ifindex values could be made available from add/remove > interface calls that you added. Was that what you had in mind or is > there another mechanism for getting the needed ifindexes down? Yes, I wanted to add ifindex into ieee80211_if_conf but apparently forgot to. See patch below. ---->8---- This patch fixes some problems in interface configuration. - Pass interface ID to add_interface and remove_interface callbacks. This ID is used by a driver when calling ieee80211_beacon_get and ieee80211_get_buffered_bc functions. - New configuration callback, config_interface, is introduced. - Allow BSSID to be set per-interface. Signed-off-by: Jiri Benc <[EMAIL PROTECTED]> Index: dscape/include/net/d80211.h =================================================================== --- dscape.orig/include/net/d80211.h 2006-03-06 16:23:57.000000000 +0100 +++ dscape/include/net/d80211.h 2006-03-16 16:10:08.000000000 +0100 @@ -286,8 +286,6 @@ struct ieee80211_conf { int atheros_xr; - u8 client_bssid[ETH_ALEN]; - /* Following five fields are used for IEEE 802.11H */ unsigned int radar_detect; unsigned int spect_mgmt; @@ -310,11 +308,18 @@ struct ieee80211_conf { #define IEEE80211_SUB_IF_TYPE_WDS 0x5A580211 #define IEEE80211_SUB_IF_TYPE_VLAN 0x00080211 -struct ieee80211_if_conf { +struct ieee80211_if_init_conf { + int if_id; /* not valid for monitor interface */ int type; void *mac_addr; }; +struct ieee80211_if_conf { + int type; /* just for convenience; doesn't change during + * the live of the interface */ + u8 *bssid; +}; + typedef enum { ALG_NONE, ALG_WEP, ALG_TKIP, ALG_CCMP, ALG_NULL } ieee80211_key_alg; @@ -476,17 +481,22 @@ struct ieee80211_hw { * of open() and add_interface() handler has to be non-NULL. If * add_interface() is NULL, one STA interface is permitted only. */ int (*add_interface)(struct net_device *dev, - struct ieee80211_if_conf *conf); + struct ieee80211_if_init_conf *conf); /* Notify a driver that interface is going down. The stop() handler * is called prior to this if this is a last interface. */ void (*remove_interface)(struct net_device *dev, - struct ieee80211_if_conf *conf); + struct ieee80211_if_init_conf *conf); /* Handler for configuration requests. IEEE 802.11 code calls this * function to change hardware configuration, e.g., channel. */ int (*config)(struct net_device *dev, struct ieee80211_conf *conf); + /* Handler for configuration requests related to interfaces (e.g. + * BSSID). */ + int (*config_interface)(struct net_device *dev, int if_id, + struct ieee80211_if_conf *conf); + /* ieee80211 drivers should use this and not the function in * net_device. dev->flags, dev->mc_count and dev->mc_list must not * be used; use passed parameters and ieee80211_get_mc_list_item @@ -674,7 +684,7 @@ void ieee80211_tx_status_irqsafe(struct * low-level is responsible for calling this function before beacon data is * needed (e.g., based on hardware interrupt). Returned skb is used only once * and low-level driver is responsible of freeing it. */ -struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx, +struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int if_id, struct ieee80211_tx_control *control); /* Function for accessing buffered broadcast and multicast frames. If @@ -692,7 +702,7 @@ struct sk_buff * ieee80211_beacon_get(st * does not need to check for DTIM beacons separately and should be able to * use common code for all beacons. */ struct sk_buff * -ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx, +ieee80211_get_buffered_bc(struct net_device *dev, int if_id, struct ieee80211_tx_control *control); /* Low level drivers that have their own MLME and MAC indicate Index: dscape/net/d80211/ieee80211.c =================================================================== --- dscape.orig/net/d80211/ieee80211.c 2006-03-15 19:09:06.000000000 +0100 +++ dscape/net/d80211/ieee80211.c 2006-03-16 16:10:38.000000000 +0100 @@ -1556,7 +1556,7 @@ static void ieee80211_beacon_add_tim(str } -struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int bss_idx, +struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int if_id, struct ieee80211_tx_control *control) { struct ieee80211_local *local = dev->priv; @@ -1569,18 +1569,19 @@ struct sk_buff * ieee80211_beacon_get(st u8 *b_head, *b_tail; int bh_len, bt_len; - bdev = dev_get_by_index(bss_idx); + bdev = dev_get_by_index(if_id); if (bdev) { sdata = IEEE80211_DEV_TO_SUB_IF(bdev); ap = &sdata->u.ap; dev_put(bdev); } - if (ap == NULL || ap->beacon_head == NULL) { + if (ap == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_AP || + ap->beacon_head == NULL) { #ifdef CONFIG_D80211_VERBOSE_DEBUG if (net_ratelimit()) printk(KERN_DEBUG "no beacon data avail for idx=%d " - "(%s)\n", bss_idx, bdev ? bdev->name : "N/A"); + "(%s)\n", if_id, bdev ? bdev->name : "N/A"); #endif /* CONFIG_D80211_VERBOSE_DEBUG */ return NULL; } @@ -1632,7 +1633,7 @@ struct sk_buff * ieee80211_beacon_get(st struct sk_buff * -ieee80211_get_buffered_bc(struct net_device *dev, int bss_idx, +ieee80211_get_buffered_bc(struct net_device *dev, int if_id, struct ieee80211_tx_control *control) { struct ieee80211_local *local = dev->priv; @@ -1645,13 +1646,14 @@ ieee80211_get_buffered_bc(struct net_dev struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; - bdev = dev_get_by_index(bss_idx); + bdev = dev_get_by_index(if_id); if (bdev) { sdata = IEEE80211_DEV_TO_SUB_IF(bdev); bss = &sdata->u.ap; dev_put(bdev); } - if (bss == NULL || bss->beacon_head == NULL) + if (bss == NULL || sdata->type != IEEE80211_SUB_IF_TYPE_AP || + bss->beacon_head == NULL) return NULL; if (bss->dtim_count != 0) @@ -1694,6 +1696,23 @@ ieee80211_get_buffered_bc(struct net_dev return skb; } +int ieee80211_if_config(struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = dev->priv; + struct ieee80211_if_conf conf; + + if (!local->hw->config_interface) + return 0; + + memset(&conf, 0, sizeof(conf)); + conf.type = sdata->type; + if (sdata->type == IEEE80211_SUB_IF_TYPE_STA || + sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) { + conf.bssid = sdata->u.sta.bssid; + } + return local->hw->config_interface(local->mdev, dev->ifindex, &conf); +} int ieee80211_hw_config(struct net_device *dev) { @@ -1914,10 +1933,11 @@ static int ieee80211_master_stop(struct * and switch them if necessary. */ static inline void ieee80211_start_soft_monitor(struct ieee80211_local *local) { - struct ieee80211_if_conf conf; + struct ieee80211_if_init_conf conf; if (local->open_count && local->open_count == local->monitors && !local->hw->monitor_during_oper && local->hw->remove_interface) { + conf.if_id = -1; conf.type = IEEE80211_SUB_IF_TYPE_MNTR; conf.mac_addr = NULL; local->hw->remove_interface(local->mdev, &conf); @@ -1928,10 +1948,11 @@ static inline void ieee80211_start_soft_ * and switch them if necessary. */ static void ieee80211_start_hard_monitor(struct ieee80211_local *local) { - struct ieee80211_if_conf conf; + struct ieee80211_if_init_conf conf; if (local->open_count && local->open_count == local->monitors && !local->hw->monitor_during_oper && local->hw->add_interface) { + conf.if_id = -1; conf.type = IEEE80211_SUB_IF_TYPE_MNTR; conf.mac_addr = NULL; local->hw->add_interface(local->mdev, &conf); @@ -1942,7 +1963,7 @@ static int ieee80211_open(struct net_dev { struct ieee80211_sub_if_data *sdata, *nsdata; struct ieee80211_local *local = dev->priv; - struct ieee80211_if_conf conf; + struct ieee80211_if_init_conf conf; int res; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -1971,6 +1992,7 @@ static int ieee80211_open(struct net_dev ieee80211_start_soft_monitor(local); if (local->hw->add_interface) { + conf.if_id = dev->ifindex; conf.type = sdata->type; conf.mac_addr = dev->dev_addr; res = local->hw->add_interface(sdata->master, &conf); @@ -2034,8 +2056,9 @@ static int ieee80211_stop(struct net_dev local->hw->stop(sdata->master); } if (local->hw->remove_interface) { - struct ieee80211_if_conf conf; + struct ieee80211_if_init_conf conf; + conf.if_id = dev->ifindex; conf.type = sdata->type; conf.mac_addr = dev->dev_addr; local->hw->remove_interface(sdata->master, &conf); Index: dscape/net/d80211/ieee80211_i.h =================================================================== --- dscape.orig/net/d80211/ieee80211_i.h 2006-03-15 19:09:06.000000000 +0100 +++ dscape/net/d80211/ieee80211_i.h 2006-03-16 15:54:06.000000000 +0100 @@ -493,6 +493,7 @@ struct ieee80211_local { /* ieee80211.c */ int ieee80211_hw_config(struct net_device *dev); +int ieee80211_if_config(struct net_device *dev); struct ieee80211_key_conf * ieee80211_key_data2conf(struct ieee80211_local *local, struct ieee80211_key *data); Index: dscape/net/d80211/ieee80211_ioctl.c =================================================================== --- dscape.orig/net/d80211/ieee80211_ioctl.c 2006-03-15 19:09:06.000000000 +0100 +++ dscape/net/d80211/ieee80211_ioctl.c 2006-03-16 16:03:46.000000000 +0100 @@ -1791,22 +1791,11 @@ static int ieee80211_ioctl_siwap(struct struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { - struct ieee80211_local *local = dev->priv; struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->type == IEEE80211_SUB_IF_TYPE_STA || sdata->type == IEEE80211_SUB_IF_TYPE_IBSS) { - int changed_bssid = 0; - if (memcmp(local->conf.client_bssid, (u8 *) &ap_addr->sa_data, - ETH_ALEN) != 0) - changed_bssid = 1; - memcpy(local->conf.client_bssid, (u8 *) &ap_addr->sa_data, - ETH_ALEN); - if (changed_bssid && ieee80211_hw_config(dev)) { - printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", dev->name); - } return ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); } else if (sdata->type == IEEE80211_SUB_IF_TYPE_WDS) { if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data, Index: dscape/net/d80211/ieee80211_sta.c =================================================================== --- dscape.orig/net/d80211/ieee80211_sta.c 2006-03-06 16:23:56.000000000 +0100 +++ dscape/net/d80211/ieee80211_sta.c 2006-03-16 16:07:45.000000000 +0100 @@ -1990,7 +1990,9 @@ static int ieee80211_sta_join_ibss(struc local->hw->reset_tsf(local->mdev); } memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); - memcpy(local->conf.client_bssid, bss->bssid, ETH_ALEN); + res = ieee80211_if_config(dev); + if (res) + return res; local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; @@ -2345,11 +2347,20 @@ int ieee80211_sta_set_bssid(struct net_d { struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; + int res; sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; - memcpy(ifsta->bssid, bssid, ETH_ALEN); + if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { + memcpy(ifsta->bssid, bssid, ETH_ALEN); + res = ieee80211_if_config(dev); + if (res) { + printk(KERN_DEBUG "%s: Failed to config new BSSID to " + "the low-level driver\n", dev->name); + return res; + } + } if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) ifsta->bssid_set = 0; -- Jiri Benc SUSE Labs - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html