wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_handle_bss_lost.cpp
changeset 0 c40eb8fe8501
child 17 a828660c511c
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Statemachine for handling BSS lost notification from drivers.
       
    15 *
       
    16 */
       
    17 
       
    18 /*
       
    19 * %version: 33 %
       
    20 */
       
    21 
       
    22 #include "core_operation_handle_bss_lost.h"
       
    23 #include "core_operation_roam.h"
       
    24 #include "core_operation_release.h"
       
    25 #include "core_sub_operation_roam_scan.h"
       
    26 #include "core_server.h"
       
    27 #include "core_tools.h"
       
    28 #include "core_am_tools.h"
       
    29 #include "core_scan_list.h"
       
    30 #include "am_debug.h"
       
    31 
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // ---------------------------------------------------------------------------
       
    37 //
       
    38 core_operation_handle_bss_lost_c::core_operation_handle_bss_lost_c(
       
    39     u32_t request_id,
       
    40     core_server_c* server,
       
    41     abs_core_driverif_c* drivers,
       
    42     abs_core_server_callback_c* adaptation,
       
    43     core_bss_lost_reason_e reason,
       
    44     u32_t reason_data ) :
       
    45     core_operation_base_c( core_operation_handle_bss_lost, request_id, server, drivers, adaptation,
       
    46         core_base_flag_drivers_needed | core_base_flag_connection_needed | core_base_flag_roam_operation ),
       
    47     reason_m( reason ),
       
    48     reason_data_m( reason_data ),
       
    49     failure_count_m( 0 ),
       
    50     is_connected_m( false_t ),
       
    51     scan_channels_m(),
       
    52     is_scan_channels_inverted_m( false_t ),
       
    53     release_reason_m( core_release_reason_max_roam_attempts_exceeded ),
       
    54     scan_interval_count_m( 0 ),
       
    55     scan_interval_m( 0 ),
       
    56     is_first_scan_m( true_t )
       
    57     {
       
    58     DEBUG( "core_operation_handle_bss_lost_c::core_operation_handle_bss_lost_c()" );
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // ---------------------------------------------------------------------------
       
    63 //
       
    64 core_operation_handle_bss_lost_c::~core_operation_handle_bss_lost_c()
       
    65     {
       
    66     DEBUG( "core_operation_handle_bss_lost_c::~core_operation_handle_bss_lost_c()" );
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // ---------------------------------------------------------------------------
       
    71 //
       
    72 core_error_e core_operation_handle_bss_lost_c::next_state()
       
    73     {
       
    74     DEBUG( "core_operation_handle_bss_lost_c::next_state()" );
       
    75 
       
    76     switch ( operation_state_m )
       
    77         {
       
    78         case core_state_init:
       
    79             {
       
    80             core_mac_address_s bssid =
       
    81                 server_m->get_connection_data()->current_ap_data()->bssid();
       
    82 
       
    83             /**
       
    84              * Update the reason for roaming.
       
    85              *
       
    86              * If the operation has been started because of a failed RCPI roam,
       
    87              * the original roam reason must not be changed.
       
    88              */
       
    89             if ( reason_m != core_bss_lost_reason_failed_rcpi_roam )
       
    90                 {
       
    91                 server_m->get_connection_data()->set_last_roam_failed_reason(
       
    92                     core_roam_failed_reason_none );
       
    93 
       
    94                 switch ( reason_m )
       
    95                     {
       
    96                     case core_bss_lost_reason_media_disconnect:
       
    97                         server_m->get_connection_data()->set_last_roam_reason(
       
    98                             core_roam_reason_media_disconnect );
       
    99                         break;
       
   100                     case core_bss_lost_reason_failed_reauthentication:
       
   101                         server_m->get_connection_data()->set_last_roam_reason(
       
   102                             core_roam_reason_failed_reauthentication );
       
   103                         break;
       
   104                     case core_bss_lost_reason_bss_lost:
       
   105                         /** Falls through on purpose. */
       
   106                     default:
       
   107                         server_m->get_connection_data()->set_last_roam_reason(
       
   108                             core_roam_reason_bss_lost );                   
       
   109                         break;
       
   110                     }
       
   111                 }
       
   112 
       
   113             /**
       
   114              * If the AP has deauthenticated us soon after a successful association
       
   115              * and EAPOL authentication, increase the deauthentication count. 
       
   116              * 
       
   117              * This check is done to detect APs that do MAC filtering after a
       
   118              * successful association. 
       
   119              */
       
   120             if ( reason_m == core_bss_lost_reason_media_disconnect &&
       
   121                  !server_m->get_connection_data()->is_eapol_authenticating() )
       
   122                 {
       
   123                 u64_t time = static_cast<u64_t>(
       
   124                     core_am_tools_c::timestamp() -
       
   125                     server_m->get_core_settings().roam_metrics().roam_ts_userdata_enabled() );
       
   126 
       
   127                 DEBUG1( "core_operation_handle_bss_lost_c::next_state() - deauthenticated after being connected for %u second(s)",
       
   128                     static_cast<u32_t>( time / SECONDS_FROM_MICROSECONDS ) );
       
   129 
       
   130                 if ( server_m->get_device_settings().max_ap_deauthentication_count &&
       
   131                      server_m->get_device_settings().ap_deauthentication_timeout &&
       
   132                      time <= server_m->get_device_settings().ap_deauthentication_timeout )
       
   133                     {
       
   134                     u8_t count( server_m->get_connection_data()->ap_deauthentication_count( bssid ) );
       
   135                     DEBUG1( "core_operation_handle_bss_lost_c::next_state() - AP deauthentication count was %u earlier",
       
   136                         count );
       
   137 
       
   138                     if ( count >= server_m->get_device_settings().max_ap_deauthentication_count - 1 )
       
   139                         {
       
   140                         DEBUG1( "core_operation_handle_bss_lost_c::next_state() - deauthentication count (%u) exceeded, blacklisting the AP",
       
   141                             server_m->get_device_settings().max_ap_deauthentication_count );
       
   142                         server_m->get_connection_data()->add_mac_to_temporary_blacklist(
       
   143                             bssid, core_ap_blacklist_reason_max_deauthentication_count );
       
   144                         }
       
   145                     else
       
   146                         {
       
   147                         DEBUG( "core_operation_handle_bss_lost_c::next_state() - increasing AP deauthentication count" );
       
   148                         server_m->get_connection_data()->increase_ap_deauthentication_count( bssid );
       
   149                         }
       
   150                     }
       
   151                 }
       
   152 
       
   153             /**
       
   154              * If the connection is lost when EAPOL is doing (re-)authentication,
       
   155              * EAPOL must be notified.
       
   156              */
       
   157             if ( server_m->get_connection_data()->is_eapol_authenticating() &&
       
   158                  ( server_m->get_connection_data()->iap_data().is_eap_used() ||
       
   159                    server_m->get_connection_data()->iap_data().is_wapi_used() ) )
       
   160                 {
       
   161                 network_id_c network_id(
       
   162                     &bssid.addr[0],
       
   163                     MAC_ADDR_LEN,
       
   164                     &server_m->own_mac_addr().addr[0],
       
   165                     MAC_ADDR_LEN,
       
   166                     server_m->get_eapol_instance().ethernet_type() );
       
   167 
       
   168                 DEBUG( "core_operation_handle_bss_lost_c::next_state() - marking is_eapol_authenticating as false" );
       
   169                 server_m->get_connection_data()->set_eapol_authenticating(
       
   170                     false_t );
       
   171 
       
   172                 DEBUG6( "core_operation_handle_bss_lost_c::next_state() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X",
       
   173                     bssid.addr[0], bssid.addr[1], bssid.addr[2],
       
   174                     bssid.addr[3], bssid.addr[4], bssid.addr[5] );
       
   175 
       
   176                 server_m->get_eapol_instance().disassociation( &network_id );
       
   177                 }
       
   178 
       
   179             operation_state_m = core_state_set_tx_level;            
       
   180 
       
   181             /**
       
   182              * Check the channels that were previously reported to be active.
       
   183              */
       
   184             server_m->get_scan_list().get_channels_by_ssid(
       
   185                 scan_channels_m,
       
   186                 server_m->get_connection_data()->ssid() );
       
   187 
       
   188             scan_channels_m.add(
       
   189                 server_m->get_connection_data()->current_ap_data()->band(),
       
   190                 server_m->get_connection_data()->current_ap_data()->channel() );
       
   191 
       
   192             scan_channels_m.merge(
       
   193                 server_m->get_connection_data()->adjacent_ap_channels() );
       
   194 
       
   195             scan_channels_m.merge(
       
   196                 server_m->get_connection_data()->current_ap_data()->ap_channel_report() );
       
   197 
       
   198             server_m->cancel_roam_timer();
       
   199 
       
   200             DEBUG( "core_operation_handle_bss_lost_c::next_state() - removing current AP entries from scan list" );
       
   201             server_m->get_scan_list().remove_entries_by_bssid(
       
   202                 bssid );
       
   203 
       
   204             server_m->get_core_settings().roam_metrics().set_roam_ts_userdata_disabled();
       
   205 
       
   206             drivers_m->disable_user_data(
       
   207                 request_id_m );
       
   208 
       
   209             break;
       
   210             }
       
   211         case core_state_set_tx_level:
       
   212             {
       
   213             operation_state_m = core_state_set_tx_level_success;
       
   214 
       
   215             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - setting tx power (%u)",
       
   216                 server_m->get_device_settings().tx_power_level );
       
   217 
       
   218             drivers_m->set_tx_power_level(
       
   219                 request_id_m,
       
   220                 server_m->get_device_settings().tx_power_level );
       
   221 
       
   222             break;
       
   223             }
       
   224         case core_state_set_tx_level_success:
       
   225             {
       
   226             u32_t tx_level = server_m->get_device_settings().tx_power_level;
       
   227             if ( server_m->get_connection_data()->last_tx_level() != tx_level )
       
   228                 {
       
   229                 DEBUG( "core_operation_handle_bss_lost_c::next_state() - TX level has changed, notifying change" );
       
   230 
       
   231                 adaptation_m->notify(
       
   232                     core_notification_tx_power_level_changed,
       
   233                     sizeof( tx_level ),
       
   234                     reinterpret_cast<u8_t*>(&tx_level) );
       
   235 
       
   236                 server_m->get_connection_data()->set_last_tx_level( tx_level );
       
   237                 }
       
   238 
       
   239             return goto_state( core_state_scan_start );
       
   240             }
       
   241         case core_state_scan_start:
       
   242             {
       
   243             operation_state_m = core_state_scan_complete;
       
   244 
       
   245             server_m->get_scan_list().set_tag(
       
   246                 core_scan_list_tag_roam_scan );
       
   247 
       
   248             core_operation_base_c* operation = new core_sub_operation_roam_scan_c(
       
   249                 request_id_m,
       
   250                 server_m,
       
   251                 drivers_m,
       
   252                 adaptation_m,
       
   253                 server_m->get_connection_data()->ssid(),
       
   254                 scan_channels_m.channels(),
       
   255                 false_t,
       
   256                 true_t );                
       
   257 
       
   258             return run_sub_operation( operation );            
       
   259             }
       
   260         case core_state_scan_complete:
       
   261             {
       
   262             operation_state_m = core_state_connect_success;
       
   263 
       
   264             DEBUG( "core_operation_handle_bss_lost_c::next_state() - trying to connect" );
       
   265 
       
   266             core_operation_base_c* operation = new core_operation_roam_c(
       
   267                 request_id_m,
       
   268                 server_m,
       
   269                 drivers_m,
       
   270                 adaptation_m,
       
   271                 is_connected_m,
       
   272                 core_scan_list_tag_roam_scan,
       
   273                 RCPI_VALUE_NONE,
       
   274                 MEDIUM_TIME_NOT_DEFINED,
       
   275                 server_m->get_connection_data()->ssid(),
       
   276                 BROADCAST_MAC_ADDR );
       
   277 
       
   278             return run_sub_operation( operation );
       
   279             }                        
       
   280         case core_state_connect_success:
       
   281             {
       
   282             operation_state_m = core_state_connect_set_rcpi_trigger;
       
   283 
       
   284             DEBUG( "core_operation_handle_bss_lost_c::next_state() - roamed successfully" );
       
   285 
       
   286             DEBUG( "core_operation_handle_bss_lost_c::next_state() - reseting RCPI roam check interval" );
       
   287             server_m->get_connection_data()->reset_rcpi_roam_interval();
       
   288 
       
   289             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - internal RCPI threshold level is %u",
       
   290                 server_m->get_device_settings().rcpi_trigger );
       
   291             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - external RCPI threshold level is %u",
       
   292                 server_m->get_core_settings().rcp_decline_boundary() );
       
   293 
       
   294             u8_t trigger_level = server_m->get_core_settings().rcp_decline_boundary();
       
   295             if ( trigger_level < server_m->get_device_settings().rcpi_trigger )
       
   296                 {
       
   297                 trigger_level = server_m->get_device_settings().rcpi_trigger;
       
   298                 }
       
   299             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - arming RCPI roam trigger (%u)",
       
   300                 trigger_level );
       
   301 
       
   302             drivers_m->set_rcpi_trigger_level(
       
   303                 request_id_m,
       
   304                 trigger_level );
       
   305 
       
   306             break;
       
   307             }
       
   308         case core_state_connect_set_rcpi_trigger:
       
   309             {
       
   310             return core_error_ok;
       
   311             }
       
   312         case core_state_connect_failure:
       
   313             {
       
   314             if( failure_reason_m == core_error_not_found )
       
   315                 {
       
   316                 if( is_first_scan_m )
       
   317                     {
       
   318                     /**
       
   319                      * This scan is part of the scans done in the beginning
       
   320                      * using partial channel masks.
       
   321                      */
       
   322 
       
   323                     if( !is_scan_channels_inverted_m )
       
   324                         {
       
   325                         /**
       
   326                          * If no suitable APs were found on the first scan, we scan
       
   327                          * immediately the remaining channels.
       
   328                          */
       
   329                         DEBUG( "core_operation_handle_bss_lost_c::next_state() - inverting channel mask" );
       
   330     
       
   331                         is_scan_channels_inverted_m = true_t;                    
       
   332                         scan_channels_m.invert_channels();
       
   333     
       
   334                         core_scan_channels_s filtered_channels(
       
   335                             server_m->get_core_settings().valid_scan_channels( scan_channels_m.channels() ) );
       
   336     
       
   337                         if( !filtered_channels.channels2dot4ghz[0] &&
       
   338                             !filtered_channels.channels2dot4ghz[1] )
       
   339                             {
       
   340                             DEBUG( "core_operation_handle_bss_lost_c::next_state() - inverted channel mask is zero, using full channel mask" );
       
   341     
       
   342                             scan_channels_m.set(
       
   343                                 SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
   344                             }
       
   345                         }
       
   346                     else
       
   347                         {
       
   348                         /**
       
   349                          * We start scanning using the normal algorithm and
       
   350                          * a full channel mask.
       
   351                          */
       
   352                         is_first_scan_m = false_t;
       
   353                         scan_interval_m =
       
   354                             server_m->get_device_settings().bss_lost_roam_min_interval;
       
   355                         scan_channels_m.set(
       
   356                             SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
   357                         }
       
   358                     }
       
   359                 else
       
   360                     {
       
   361                     scan_channels_m.set(
       
   362                         SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
   363 
       
   364                     ++failure_count_m;
       
   365                     ++scan_interval_count_m;
       
   366                     if( scan_interval_m < server_m->get_device_settings().bss_lost_roam_max_interval &&
       
   367                         scan_interval_count_m >= server_m->get_device_settings().bss_lost_roam_attempts_per_interval )
       
   368                         {
       
   369                         DEBUG1( "core_operation_handle_bss_lost_c::next_state() - maximum interval attempts (%u) exceeded, increasing interval",
       
   370                             server_m->get_device_settings().bss_lost_roam_attempts_per_interval );
       
   371                         scan_interval_count_m = 0;
       
   372                         scan_interval_m *= server_m->get_device_settings().bss_lost_roam_next_interval_factor;
       
   373                         scan_interval_m += server_m->get_device_settings().bss_lost_roam_next_interval_addition;                        
       
   374 
       
   375                         if( scan_interval_m > server_m->get_device_settings().bss_lost_roam_max_interval )
       
   376                             {
       
   377                             scan_interval_m = server_m->get_device_settings().bss_lost_roam_max_interval;
       
   378 
       
   379                             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - interval value set to maximum (%u)",
       
   380                                 scan_interval_m );                            
       
   381                             }
       
   382                         }
       
   383                     }
       
   384                 }
       
   385             else
       
   386                 {
       
   387                 /**
       
   388                  * The roaming failed because of some other reason than not
       
   389                  * finding a suitable AP.
       
   390                  */
       
   391                 is_first_scan_m = false_t;
       
   392                 failure_count_m = 0;
       
   393                 scan_interval_count_m = 0;
       
   394                 scan_interval_m =
       
   395                     server_m->get_device_settings().bss_lost_roam_min_interval;
       
   396 
       
   397                 scan_channels_m.set(
       
   398                     SCAN_CHANNELS_2DOT4GHZ_ETSI );
       
   399                 }
       
   400 
       
   401             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - roaming has failed %u time(s)",
       
   402                 failure_count_m );
       
   403             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - failure_reason_m is %u",
       
   404                 failure_reason_m );
       
   405             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - connect_status is %u",
       
   406                 server_m->get_connection_data()->connect_status() );
       
   407 
       
   408             /**
       
   409              * If EAPOL has notified about a total failure or we have tried too many times,
       
   410              * close down the connection. Otherwise, try again.
       
   411              */
       
   412             if ( failure_reason_m == core_error_eapol_total_failure ||
       
   413                  failure_reason_m == core_error_eapol_canceled_by_user ||
       
   414                  failure_count_m >= server_m->get_device_settings().bss_lost_roam_max_tries_to_find_nw )
       
   415                 {
       
   416                 return goto_state( core_state_connect_total_failure );
       
   417                 }
       
   418 
       
   419             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - next scan in %u microsecond(s)",
       
   420                 scan_interval_m );
       
   421 
       
   422             return asynch_goto(
       
   423                 core_state_scan_start,
       
   424                 scan_interval_m );
       
   425             }
       
   426         case core_state_connect_total_failure:
       
   427             {
       
   428             operation_state_m = core_state_connect_disconnect;
       
   429 
       
   430             DEBUG1( "core_operation_handle_bss_lost_c::next_state() - gave up roaming after %u tries",
       
   431                 failure_count_m );
       
   432 
       
   433             core_operation_base_c* operation = new core_operation_release_c(
       
   434                 request_id_m,
       
   435                 server_m,
       
   436                 drivers_m,
       
   437                 adaptation_m,
       
   438                 release_reason_m );
       
   439                         
       
   440             return run_sub_operation( operation );
       
   441             }
       
   442         case core_state_connect_disconnect:
       
   443             {
       
   444             DEBUG( "core_operation_handle_bss_lost_c::next_state() - connection closed successfully" );
       
   445 
       
   446             return core_error_ok;
       
   447             }
       
   448         default:
       
   449             {
       
   450             ASSERT( false_t );
       
   451             }
       
   452         }
       
   453 
       
   454     return core_error_request_pending;
       
   455     }
       
   456 
       
   457 // ---------------------------------------------------------------------------
       
   458 // ---------------------------------------------------------------------------
       
   459 //
       
   460 void core_operation_handle_bss_lost_c::user_cancel(
       
   461     bool_t /* do_graceful_cancel */ )
       
   462     {
       
   463     DEBUG( "core_operation_handle_bss_lost_c::user_cancel()" );
       
   464 
       
   465     release_reason_m = core_release_reason_external_request;
       
   466 
       
   467     operation_state_m = core_state_connect_total_failure;
       
   468     }
       
   469 
       
   470 // ---------------------------------------------------------------------------
       
   471 // ---------------------------------------------------------------------------
       
   472 //
       
   473 core_error_e core_operation_handle_bss_lost_c::cancel()
       
   474     {
       
   475     DEBUG( "core_operation_handle_bss_lost_c::cancel() " );    
       
   476 
       
   477     switch ( operation_state_m )
       
   478         {              
       
   479         case core_state_connect_success:
       
   480             {
       
   481             return goto_state( core_state_connect_failure );
       
   482             }
       
   483         default:
       
   484             {
       
   485             return failure_reason_m;
       
   486             }
       
   487         }
       
   488     }