wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_create_ts.cpp
changeset 0 c40eb8fe8501
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2006-2010 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 creating a traffic stream.
       
    15 *
       
    16 */
       
    17 
       
    18 /*
       
    19 * %version: 6 %
       
    20 */
       
    21 
       
    22 #include "core_operation_create_ts.h"
       
    23 #include "core_operation_delete_ts.h"
       
    24 #include "core_traffic_stream.h"
       
    25 #include "core_sub_operation_create_ts.h"
       
    26 #include "core_frame_wmm_ie.h"
       
    27 #include "core_server.h"
       
    28 #include "core_tools.h"
       
    29 #include "core_traffic_stream_list_iter.h"
       
    30 #include "core_virtual_traffic_stream_list_iter.h"
       
    31 #include "am_debug.h"
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // ---------------------------------------------------------------------------
       
    37 //
       
    38 core_operation_create_ts_c::core_operation_create_ts_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     u8_t tid,
       
    44     u8_t user_priority,
       
    45     bool_t is_automatic_stream,
       
    46     const core_traffic_stream_params_s& params,
       
    47     u32_t& stream_id,
       
    48     core_traffic_stream_status_e& stream_status ) :
       
    49     core_operation_base_c( core_operation_create_ts, request_id, server, drivers, adaptation,
       
    50         core_base_flag_none ),
       
    51     requested_tid_m( tid ),
       
    52     tid_m( tid ),
       
    53     user_priority_m( user_priority ),
       
    54     access_class_m( core_access_class_best_effort ),
       
    55     is_automatic_stream_m( is_automatic_stream ),
       
    56     requested_params_m( params ),
       
    57     params_m( params ),
       
    58     stream_id_m( stream_id ),
       
    59     stream_status_m( stream_status ),
       
    60     stream_m( NULL )
       
    61     {
       
    62     DEBUG( "core_operation_create_ts_c::core_operation_create_ts_c()" );
       
    63     }
       
    64 
       
    65 // ---------------------------------------------------------------------------
       
    66 // ---------------------------------------------------------------------------
       
    67 //
       
    68 core_operation_create_ts_c::~core_operation_create_ts_c()
       
    69     {
       
    70     DEBUG( "core_operation_create_ts_c::~core_operation_create_ts_c()" );
       
    71 
       
    72     delete stream_m;
       
    73     }
       
    74 
       
    75 // ---------------------------------------------------------------------------
       
    76 // ---------------------------------------------------------------------------
       
    77 //
       
    78 core_error_e core_operation_create_ts_c::next_state()
       
    79     {
       
    80     DEBUG( "core_operation_create_ts_c::next_state()" );
       
    81 
       
    82     switch ( operation_state_m )
       
    83         {              
       
    84         case core_state_init:
       
    85             {
       
    86             if( !server_m->get_core_settings().is_connected() )
       
    87                 {
       
    88                 DEBUG( "core_operation_create_ts_c::next_state() - not connected, nothing to do" );
       
    89 
       
    90                 return core_error_general;
       
    91                 }
       
    92             if( !is_valid_params() )
       
    93                 {
       
    94                 DEBUG( "core_operation_create_ts_c::next_state() - invalid traffic stream parameters" );
       
    95 
       
    96                 return core_error_illegal_argument;                
       
    97                 }
       
    98             access_class_m = core_tools_c::convert_user_priority_to_ac( user_priority_m );
       
    99 
       
   100             core_traffic_stream_list_c& ts_list(
       
   101                 server_m->get_connection_data()->traffic_stream_list() );
       
   102             core_virtual_traffic_stream_list_c& virtual_ts_list(
       
   103                 server_m->get_connection_data()->virtual_traffic_stream_list() );
       
   104             core_traffic_stream_list_iter_c ts_iter( ts_list );
       
   105             core_virtual_traffic_stream_list_iter_c virtual_ts_iter( virtual_ts_list );
       
   106 
       
   107             DEBUG( "core_operation_create_ts_c::next_state() - current traffic streams:" );
       
   108             virtual_ts_list.print_contents();
       
   109             ts_list.print_contents();
       
   110 
       
   111             if( tid_m != TRAFFIC_STREAM_TID_NONE )
       
   112                 {
       
   113                 /**
       
   114                  * If TID has been specified for the virtual traffic stream, check
       
   115                  * whether it clashes with an existing traffic stream.
       
   116                  */
       
   117                 if( ts_list.is_traffic_stream_for_tid( tid_m ) )
       
   118                     {
       
   119                     DEBUG1( "core_operation_create_ts_c::next_state() - stream already exists for TID %u",
       
   120                         tid_m );
       
   121 
       
   122                     return core_error_already_exists;
       
   123                     }
       
   124                 }
       
   125             else
       
   126                 {
       
   127                 /**
       
   128                  * If TID has been left unspecified, select the next free
       
   129                  * TID.
       
   130                  *
       
   131                  * First try to select the next free TID from virtual traffic
       
   132                  * stream list. In the unlikely scenario where all TIDs are
       
   133                  * in use, try the traffic stream list next.
       
   134                  */
       
   135                 tid_m = virtual_ts_list.next_tid();
       
   136                 if( tid_m == MAX_TRAFFIC_STREAM_TID )
       
   137                     {
       
   138                     tid_m = ts_list.next_tid();
       
   139                     if( tid_m == MAX_TRAFFIC_STREAM_TID )
       
   140                         {                    
       
   141                         DEBUG( "core_operation_create_ts_c::next_state() - no free TIDs" );
       
   142 
       
   143                         return core_error_general;
       
   144                         }
       
   145                     }
       
   146                 }
       
   147 
       
   148 #ifdef _DEBUG
       
   149             DEBUG2( "core_operation_create_ts_c::next_state() - Traffic Stream TID is %u, UP is %u",
       
   150                 tid_m, user_priority_m );
       
   151 
       
   152             DEBUG( "core_operation_create_ts_c::next_state() - trying to create a traffic stream with values:" );
       
   153             if( params_m.is_periodic_traffic )
       
   154                 {
       
   155                 DEBUG( "core_operation_create_ts_c::next_state() - Traffic pattern:              periodic" );
       
   156                 }
       
   157             else
       
   158                 {
       
   159                 DEBUG( "core_operation_create_ts_c::next_state() - Traffic pattern:              aperiodic" );
       
   160                 }            
       
   161             if( params_m.direction == core_traffic_stream_direction_uplink )
       
   162                 {
       
   163                 DEBUG( "core_operation_create_ts_c::next_state() - Direction:                    uplink" );
       
   164                 }
       
   165             else if( params_m.direction == core_traffic_stream_direction_downlink )
       
   166                 {
       
   167                 DEBUG( "core_operation_create_ts_c::next_state() - Direction:                    downlink" );
       
   168                 }
       
   169             else
       
   170                 {
       
   171                 DEBUG( "core_operation_create_ts_c::next_state() - Direction:                    bi-directional" );
       
   172                 }                
       
   173             DEBUG2( "core_operation_create_ts_c::next_state() - Nominal MSDU Size:            %u (0x%04X)",
       
   174                 params_m.nominal_msdu_size, params_m.nominal_msdu_size );                
       
   175             DEBUG2( "core_operation_create_ts_c::next_state() - Maximum MSDU Size:            %u (0x%04X)",
       
   176                 params_m.maximum_msdu_size, params_m.maximum_msdu_size );
       
   177             DEBUG2( "core_operation_create_ts_c::next_state() - Minimum Service Interval:     %u (0x%08X)",
       
   178                 params_m.minimum_service_interval, params_m.minimum_service_interval );
       
   179             DEBUG2( "core_operation_create_ts_c::next_state() - Maximum Service Interval:     %u (0x%08X)",
       
   180                 params_m.maximum_service_interval, params_m.maximum_service_interval );
       
   181             DEBUG2( "core_operation_create_ts_c::next_state() - Inactivity Interval:          %u (0x%08X)",
       
   182                 params_m.inactivity_interval, params_m.inactivity_interval );
       
   183             DEBUG2( "core_operation_create_ts_c::next_state() - Suspension Interval:          %u (0x%08X)",
       
   184                 params_m.suspension_interval, params_m.suspension_interval );
       
   185             DEBUG2( "core_operation_create_ts_c::next_state() - Service Start Time:           %u (0x%08X)",
       
   186                 params_m.service_start_time, params_m.service_start_time );
       
   187             DEBUG2( "core_operation_create_ts_c::next_state() - Minimum Data Rate:            %u (0x%08X)",
       
   188                 params_m.minimum_data_rate, params_m.minimum_data_rate );        
       
   189             DEBUG2( "core_operation_create_ts_c::next_state() - Mean Data Rate:               %u (0x%08X)",
       
   190                 params_m.mean_data_rate, params_m.mean_data_rate );
       
   191             DEBUG2( "core_operation_create_ts_c::next_state() - Peak Data Rate:               %u (0x%08X)",
       
   192                 params_m.peak_data_rate, params_m.peak_data_rate );
       
   193             DEBUG2( "core_operation_create_ts_c::next_state() - Maximum Burst Size:           %u (0x%08X)",
       
   194                 params_m.maximum_burst_size, params_m.maximum_burst_size );
       
   195             DEBUG2( "core_operation_create_ts_c::next_state() - Delay Bound:                  %u (0x%08X)",
       
   196                 params_m.delay_bound, params_m.delay_bound );
       
   197             DEBUG2( "core_operation_create_ts_c::next_state() - Minimum PHY Rate:             %u (0x%08X)",
       
   198                 params_m.minimum_phy_rate, params_m.minimum_phy_rate );
       
   199             DEBUG2( "core_operation_create_ts_c::next_state() - Nominal PHY Rate:             %u (0x%04X)",
       
   200                 params_m.nominal_phy_rate, params_m.nominal_phy_rate );
       
   201             DEBUG2( "core_operation_create_ts_c::next_state() - Surplus Bandwidth Allowance:  %u (0x%04X)",
       
   202                 params_m.surplus_bandwidth_allowance, params_m.surplus_bandwidth_allowance );
       
   203 #endif // _DEBUG
       
   204 
       
   205             stream_m = new core_traffic_stream_c(
       
   206                 tid_m,
       
   207                 user_priority_m );
       
   208             if( !stream_m )
       
   209                 {
       
   210                 DEBUG( "core_operation_create_ts_c::next_state() - unable to allocate a traffic stream instance" );
       
   211 
       
   212                 return core_error_no_memory;
       
   213                 }
       
   214 
       
   215             /**
       
   216              * If the Max Tx MSDU Lifetime is not overridden, use the default value.             
       
   217              */
       
   218             if( !params_m.override_max_tx_msdu_lifetime )
       
   219                 {
       
   220                 params_m.override_max_tx_msdu_lifetime = server_m->get_device_settings().max_tx_msdu_life_time;
       
   221                 }
       
   222 
       
   223             stream_m->set_default_traffic_values( params_m );            
       
   224             stream_m->reset_to_default_values();            
       
   225 
       
   226             /**
       
   227              * If this is a manual traffic stream, all automatic streams
       
   228              * need to be deleted before continuing.
       
   229              */
       
   230             if( !is_automatic_stream_m )
       
   231                 {
       
   232                 server_m->get_connection_data()->set_ac_traffic_mode(
       
   233                     access_class_m,
       
   234                     core_access_class_traffic_mode_manual );
       
   235 
       
   236                 /**
       
   237                  * Send an indication to notify clients that traffic mode
       
   238                  * is now set to manual.
       
   239                  */
       
   240                 u8_t buf[5];
       
   241                 buf[0] = static_cast<u8_t>( 
       
   242                     access_class_m );
       
   243                 buf[1] = static_cast<u8_t>(
       
   244                     core_access_class_traffic_mode_manual );
       
   245                 adaptation_m->notify(
       
   246                     core_notification_ac_traffic_mode_changed,
       
   247                     sizeof( buf ),
       
   248                     buf );
       
   249 
       
   250                 return goto_state( core_state_delete_streams );
       
   251                 }
       
   252 
       
   253             /**
       
   254              * Otherwise proceed with stream creation.
       
   255              */            
       
   256             return goto_state( core_state_create_stream );
       
   257             }
       
   258         case core_state_delete_streams:
       
   259             {
       
   260             core_virtual_traffic_stream_list_iter_c virtual_ts_iter(
       
   261                 server_m->get_connection_data()->virtual_traffic_stream_list() );
       
   262             for( core_virtual_traffic_stream_c* iter = virtual_ts_iter.first(); iter; iter = virtual_ts_iter.next() )
       
   263                 {
       
   264                 if( iter->access_class() == access_class_m &&
       
   265                     iter->is_automatic_stream() )
       
   266                     {
       
   267                     core_operation_base_c* operation = new core_operation_delete_ts_c(
       
   268                         request_id_m,
       
   269                         server_m,
       
   270                         drivers_m,
       
   271                         adaptation_m,
       
   272                         iter->id() );
       
   273 
       
   274                     return run_sub_operation( operation, core_state_delete_streams );                    
       
   275                     }
       
   276                 }
       
   277 
       
   278             return asynch_goto( core_state_create_stream );
       
   279             }            
       
   280         case core_state_create_stream:
       
   281             {
       
   282             core_ap_data_c* current_ap = server_m->get_connection_data()->current_ap_data();
       
   283             if( !current_ap->is_wmm_ie_present() ||
       
   284                 !current_ap->is_admission_control_required( access_class_m ) )
       
   285                 {
       
   286                 DEBUG1( "core_operation_create_ts_c::next_state() - AP doesn't require admission control on AC %u",
       
   287                     access_class_m );
       
   288                 
       
   289                 /**
       
   290                  * An actual traffic stream is not needed but the virtual traffic
       
   291                  * stream is still created.
       
   292                  */                
       
   293                 server_m->get_connection_data()->virtual_traffic_stream_list().add_traffic_stream(
       
   294                     requested_tid_m,
       
   295                     TRAFFIC_STREAM_TID_NONE,
       
   296                     user_priority_m,
       
   297                     is_automatic_stream_m,
       
   298                     requested_params_m,
       
   299                     stream_id_m,
       
   300                     core_traffic_stream_status_inactive_not_required );
       
   301 
       
   302                 return core_error_ok;
       
   303                 }
       
   304 
       
   305             /**
       
   306              * Try to create the actual traffic stream.
       
   307              */
       
   308             core_operation_base_c* operation = new core_sub_operation_create_ts_c(
       
   309                 request_id_m,
       
   310                 server_m,
       
   311                 drivers_m,
       
   312                 adaptation_m,
       
   313                 *server_m->get_connection_data()->current_ap_data(),
       
   314                 tid_m,
       
   315                 user_priority_m,
       
   316                 params_m,
       
   317                 stream_status_m );
       
   318 
       
   319             return run_sub_operation( operation, core_state_create_stream_success );
       
   320             }
       
   321         case core_state_create_stream_failed:
       
   322             {
       
   323             DEBUG( "core_operation_create_ts_c::next_state() - traffic stream creation failed" );
       
   324 
       
   325             /**
       
   326              * Eventhough the actual traffic stream couldn't be created, the virtual traffic
       
   327              * stream is still created.
       
   328              */            
       
   329             server_m->get_connection_data()->virtual_traffic_stream_list().add_traffic_stream(
       
   330                 requested_tid_m,
       
   331                 TRAFFIC_STREAM_TID_NONE,
       
   332                 user_priority_m,
       
   333                 is_automatic_stream_m,
       
   334                 requested_params_m,
       
   335                 stream_id_m,
       
   336                 stream_status_m );
       
   337 
       
   338             return core_error_ok;
       
   339             }
       
   340         case core_state_create_stream_success:
       
   341             {
       
   342             operation_state_m = core_state_parameters_set;
       
   343 
       
   344             DEBUG( "core_operation_create_ts_c::next_state() - traffic stream created successfully" );
       
   345 
       
   346             server_m->get_connection_data()->virtual_traffic_stream_list().add_traffic_stream(
       
   347                 requested_tid_m,
       
   348                 tid_m,
       
   349                 user_priority_m,
       
   350                 is_automatic_stream_m,
       
   351                 requested_params_m,
       
   352                 stream_id_m,
       
   353                 core_traffic_stream_status_active );
       
   354 
       
   355             /**
       
   356              * Store the new traffic stream parameters.
       
   357              */
       
   358             stream_m->set_status( core_traffic_stream_status_active );
       
   359             stream_m->set_traffic_values( params_m );            
       
   360             server_m->get_connection_data()->traffic_stream_list().update_traffic_stream(
       
   361                 *stream_m );
       
   362 
       
   363             if( params_m.direction == core_traffic_stream_direction_uplink ||
       
   364                 params_m.direction == core_traffic_stream_direction_bidirectional )
       
   365                 {
       
   366                 server_m->get_connection_data()->set_ac_traffic_status(
       
   367                     access_class_m,
       
   368                     core_access_class_traffic_status_admitted );
       
   369 
       
   370                 /**
       
   371                  * Send an indication to notify clients that this access class
       
   372                  * is now admitted. 
       
   373                  */
       
   374                 u8_t buf[5];
       
   375                 buf[0] = static_cast<u8_t>( 
       
   376                     access_class_m );
       
   377                 buf[1] = static_cast<u8_t>(
       
   378                     core_access_class_traffic_status_admitted );
       
   379                 adaptation_m->notify(
       
   380                     core_notification_ac_traffic_status_changed,
       
   381                     sizeof( buf ),
       
   382                     buf );
       
   383 
       
   384                 /**
       
   385                  * Set the parameters to the drivers based on the created
       
   386                  * traffic stream.
       
   387                  */
       
   388                 DEBUG( "core_operation_create_ts_c::next_state() - setting tx queue parameters" );
       
   389     
       
   390                 drivers_m->set_tx_queue_parameters(
       
   391                     request_id_m,
       
   392                     stream_m->access_class(),
       
   393                     stream_m->medium_time(),
       
   394                     stream_m->max_tx_msdu_lifetime() );
       
   395                 }
       
   396             else
       
   397                 {
       
   398                 /**
       
   399                  * Since TX queue parameters apply only to uplink, there is nothing
       
   400                  * more to do on downlink streams.
       
   401                  */
       
   402                 return core_error_ok;                
       
   403                 }
       
   404 
       
   405             break;
       
   406             }
       
   407         case core_state_parameters_set:
       
   408             {
       
   409             DEBUG( "core_operation_create_ts_c::next_state() - tx queue parameters set" );
       
   410 
       
   411             return core_error_ok;
       
   412             } 
       
   413         default:
       
   414             {
       
   415             ASSERT( false_t );
       
   416             }
       
   417         }
       
   418 
       
   419     return core_error_request_pending;
       
   420     }
       
   421 
       
   422 
       
   423 // ---------------------------------------------------------------------------
       
   424 // ---------------------------------------------------------------------------
       
   425 //
       
   426 core_error_e core_operation_create_ts_c::cancel()
       
   427     {
       
   428     DEBUG( "core_operation_create_ts_c::cancel() " );    
       
   429 
       
   430     switch( operation_state_m )
       
   431         {              
       
   432         case core_state_create_stream_success:
       
   433             {
       
   434             return goto_state( core_state_create_stream_failed );
       
   435             }
       
   436         default:
       
   437             {
       
   438             return failure_reason_m;
       
   439             }
       
   440         }
       
   441     }
       
   442 
       
   443 // ---------------------------------------------------------------------------
       
   444 // ---------------------------------------------------------------------------
       
   445 //
       
   446 bool_t core_operation_create_ts_c::is_valid_params()
       
   447     {
       
   448     if( tid_m >= MAX_TRAFFIC_STREAM_TID && tid_m != TRAFFIC_STREAM_TID_NONE )
       
   449         {
       
   450         DEBUG1( "core_operation_create_ts_c::is_valid_params() - invalid TID value: %u",
       
   451             tid_m );
       
   452 
       
   453         return false_t;
       
   454         }
       
   455     if( user_priority_m >= MAX_QOS_USER_PRIORITY )
       
   456         {
       
   457         DEBUG1( "core_operation_create_ts_c::is_valid_params() - invalid user priority value: %u",
       
   458             user_priority_m );        
       
   459 
       
   460         return false_t;
       
   461         }
       
   462 
       
   463     return true_t;
       
   464     }
       
   465