Changeset 2463

Show
Ignore:
Timestamp:
06/16/07 00:32:08 (2 years ago)
Author:
mtaylor
Message:

Ticket 1388:

When a user explicitly changes the channel on an access point VAP, the behavior is currently to record the desired channel, which would ONLY take effect on bringing down the interface and bringing it back up.

Oddly enough, the only path through this code for master mode VAPs looks at the roaming mode and determines whether it is set to auto. If so, it puts us into 'scan' mode which causes channel change to occur (in the case of station, it will no scan if a channel change is pending and will jus switch).

The correct behavior should be as follows:

If interface is down, set desired channel and do no further action. If interface is running and up, use the channel change IE on beacon to update the channel. If interface is running and not up we set the channel directly.

The current behavior of not changing channels has two unpleasant side effects:

1. Because the channel change has not taken effect, the txpower list is not updated and invalid power levels are seen and entered in startup scripts. Setting channel + power will often fail if the old channel had a lower power level restriction.

2. Because the channel change does not take effect until an explicit restart, assigning the channel after bringing up an interface in a ifup type script would fail.

3. You should not have to use iwpriv doth_chanswitch in order to change the channel of an AP explicitly.

4. You should be able to change channels on an AP without dropping associations.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/madwifi-dfs/net80211/ieee80211_wireless.c

    r2445 r2463  
    7272         (_vap)->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO) 
    7373#define RESCAN  1 
     74 
     75static void 
     76pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt); 
    7477 
    7578static int 
     
    748751            vap->iv_opmode == IEEE80211_M_WDS) && 
    749752            vap->iv_des_chan != IEEE80211_CHAN_ANYC) { 
    750                 /* 
    751                  * Monitor and wds modes can switch directly. 
    752                  */ 
     753                /* Monitor and wds modes can switch directly. */ 
    753754                ic->ic_curchan = vap->iv_des_chan; 
    754755                if (vap->iv_state == IEEE80211_S_RUN) { 
    755756                        ic->ic_set_channel(ic); 
    756757                } 
     758        } else if(vap->iv_opmode == IEEE80211_M_HOSTAP) { 
     759                /* Need to use channel switch announcement on beacon if we are  
     760                 * up and running.  We use ic_set_channel directly if we are  
     761                 * "running" but not "up".  Otherwise, iv_des_chan will take 
     762                 * effect when we are transitioned to RUN state later. */ 
     763                if(IS_UP(vap->iv_dev)) { 
     764                        pre_announced_chanswitch(dev, ieee80211_chan2ieee(ic, vap->iv_des_chan), IEEE80211_DEFAULT_CHANCHANGE_TBTT_COUNT); 
     765                } 
     766                else if (vap->iv_state == IEEE80211_S_RUN) { 
     767                        ic->ic_curchan = vap->iv_des_chan; 
     768                        ic->ic_set_channel(ic); 
     769                } 
    757770        } else { 
    758                 /* 
    759                  * Need to go through the state machine in case we need 
     771                /* Need to go through the state machine in case we need 
    760772                 * to reassociate or the like.  The state machine will 
    761                  * pickup the desired channel and avoid scanning. 
    762                  */ 
     773                 * pickup the desired channel and avoid scanning. */ 
    763774                if (IS_UP_AUTO(vap)) 
    764775                        ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 
     
    43104321} 
    43114322 
     4323static void 
     4324pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) { 
     4325        struct ieee80211vap *vap = dev->priv; 
     4326        struct ieee80211com *ic = vap->iv_ic; 
     4327        /* now flag the beacon update to include the channel switch IE */ 
     4328        ic->ic_flags |= IEEE80211_F_CHANSWITCH; 
     4329        ic->ic_chanchange_chan = channel; 
     4330        ic->ic_chanchange_tbtt = tbtt; 
     4331} 
     4332 
    43124333static int 
    43134334ieee80211_ioctl_chanswitch(struct net_device *dev, struct iw_request_info *info, 
     
    43214342                return 0; 
    43224343 
    4323         /* now flag the beacon update to include the channel switch IE */ 
    4324         ic->ic_flags |= IEEE80211_F_CHANSWITCH; 
    4325         ic->ic_chanchange_chan = param[0]; 
    4326         ic->ic_chanchange_tbtt = param[1]; 
     4344        pre_announced_chanswitch(dev, param[0], param[1]); 
    43274345 
    43284346        return 0;