wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_delete_ts.cpp
changeset 0 c40eb8fe8501
child 21 af3fb27c7511
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_operation_delete_ts.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,345 @@
+/*
+* Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Statemachine for deleting a traffic stream.
+*
+*/
+
+/*
+* %version: 8 %
+*/
+
+#include "core_operation_delete_ts.h"
+#include "core_traffic_stream.h"
+#include "core_frame_wmm_ie_tspec.h"
+#include "core_frame_action_wmm.h"
+#include "core_server.h"
+#include "core_tools.h"
+#include "core_traffic_stream_list_iter.h"
+#include "core_virtual_traffic_stream_list_iter.h"
+#include "am_debug.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_operation_delete_ts_c::core_operation_delete_ts_c(
+    u32_t request_id,
+    core_server_c* server,
+    abs_core_driverif_c* drivers,
+    abs_core_server_callback_c* adaptation,
+    u32_t stream_id ) :
+    core_operation_base_c( core_operation_delete_ts, request_id, server, drivers, adaptation,
+        core_base_flag_none ),
+    id_m( stream_id )
+    {
+    DEBUG( "core_operation_delete_ts_c::core_operation_delete_ts_c()" );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_operation_delete_ts_c::~core_operation_delete_ts_c()
+    {
+    DEBUG( "core_operation_delete_ts_c::~core_operation_delete_ts_c()" );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_operation_delete_ts_c::next_state()
+    {
+    DEBUG( "core_operation_delete_ts_c::next_state()" );
+
+    switch ( operation_state_m )
+        {              
+        case core_state_init:
+            {
+            operation_state_m = core_base_state_parameters_set;
+            
+            if( !server_m->get_core_settings().is_connected() )
+                {
+                DEBUG( "core_operation_delete_ts_c::next_state() - not connected, nothing to do" );
+
+                return core_error_general;
+                }
+
+            core_traffic_stream_list_c& ts_list(
+                server_m->get_connection_data()->traffic_stream_list() );
+            core_virtual_traffic_stream_list_c& virtual_ts_list(
+                server_m->get_connection_data()->virtual_traffic_stream_list() );
+            core_traffic_stream_list_iter_c ts_iter( ts_list );
+            core_virtual_traffic_stream_list_iter_c virtual_ts_iter( virtual_ts_list );
+
+            DEBUG( "core_operation_delete_ts_c::next_state() - current traffic streams:" );
+            virtual_ts_list.print_contents();
+            ts_list.print_contents();
+            
+            /**
+             * Find the virtual traffic stream to be deleted.
+             */
+            core_virtual_traffic_stream_c* virtual_stream = NULL;
+            core_virtual_traffic_stream_c* virtual_iter = virtual_ts_iter.first();
+            while( virtual_iter )
+                {
+                if( virtual_iter->id() == id_m )
+                    {
+                    virtual_stream = virtual_iter;
+                    virtual_iter = NULL;
+                    }
+                else
+                    {
+                    virtual_iter = virtual_ts_iter.next();
+                    }
+                }
+
+            if( !virtual_stream )
+                {
+                DEBUG1( "core_operation_delete_ts_c::next_state() - no virtual traffic stream with ID %u found",
+                    id_m );
+
+                return core_error_not_found;
+                }
+
+            u8_t tid = virtual_stream->tid();
+            
+            DEBUG3( "core_operation_delete_ts_c::next_state() - virtual traffic stream with ID %u found, TID: %u, UP: %u",
+                id_m, tid, virtual_stream->user_priority() );
+
+            /**
+             * Delete the virtual traffic stream.
+             */
+            virtual_ts_iter.remove();
+            
+            /**
+             * Locate the actual traffic stream based on the TID.
+             */
+            core_traffic_stream_c* stream = NULL;            
+            core_traffic_stream_c* iter = ts_iter.first();
+            while( iter )
+                {
+                if( iter->tid() == tid )
+                    {
+                    stream = iter;
+
+                    iter = NULL;
+                    }
+                else
+                    {
+                    iter = ts_iter.next();
+                    }
+                }
+
+            if( !stream )
+                {
+                DEBUG1( "core_operation_delete_ts_c::next_state() - no traffic stream with TID %u found",
+                    id_m );
+
+                /**
+                 * This is not an error since the virtual traffic streams can
+                 * exist eventhough the AP doesn't require admission control.
+                 */
+
+                return core_error_ok;
+                }
+
+            stream->dec_reference_count();
+            if( stream->reference_count() )
+                {
+                DEBUG1( "core_operation_delete_ts_c::next_state() - traffic stream reference count is %u, not deleting",
+                    stream->reference_count() );
+                
+                /**
+                 * If there are still other virtual traffic streams referencing
+                 * this traffic stream, do not delete it. 
+                 */
+
+                return core_error_ok;
+                }
+
+            u8_t user_priority = stream->user_priority();
+            core_traffic_stream_direction_e direction = stream->direction();
+            bool_t is_uapsd( true_t );
+            if( !server_m->get_connection_data()->current_ap_data()->is_uapsd_supported() ||
+                !server_m->get_core_settings().is_uapsd_enable_for_access_class(
+                    core_tools_c::convert_user_priority_to_ac( user_priority ) ) )
+                {
+                is_uapsd = false_t;
+                }
+            DEBUG1( "core_operation_delete_ts_c::next_state() - U-APSD %u",
+                is_uapsd );
+
+            core_frame_wmm_ie_tspec_c* tspec_ie = core_frame_wmm_ie_tspec_c::instance(
+                stream->tid(),
+                user_priority,
+                is_uapsd,
+                stream->is_periodic_traffic(),
+                stream->direction(),
+                stream->nominal_msdu_size(),
+                stream->maximum_msdu_size(),
+                stream->minimum_service_interval(),
+                stream->maximum_service_interval(),
+                stream->inactivity_interval(),
+                stream->suspension_interval(),
+                stream->service_start_time(),
+                stream->minimum_data_rate(),
+                stream->mean_data_rate(),
+                stream->peak_data_rate(),
+                stream->maximum_burst_size(),
+                stream->delay_bound(),
+                stream->minimum_phy_rate(),
+                stream->surplus_bandwidth_allowance(),
+                stream->medium_time() );
+            if( !tspec_ie )
+                {
+                DEBUG( "core_operation_delete_ts_c::next_state() - unable to allocate a WMM TSPEC IE" );
+                return core_error_no_memory;
+                }
+
+            DEBUG( "core_operation_delete_ts_c::next_state() - TSPEC IE:" );
+            DEBUG_BUFFER( tspec_ie->data_length(), tspec_ie->data() );
+
+            const core_mac_address_s dest(
+                server_m->get_connection_data()->current_ap_data()->bssid() );
+            const core_mac_address_s src(
+                server_m->own_mac_addr() );
+
+            core_frame_action_wmm_c* frame = core_frame_action_wmm_c::instance(
+                0,                  // Duration
+                dest,               // Destination
+                src,                // Source
+                dest,               // BSSID
+                0,                  // Sequence Control
+                core_frame_action_wmm_c::core_dot11_action_wmm_type_delts, // Action Type
+                0,                  // Dialog Token
+                core_frame_action_wmm_c::core_dot11_action_wmm_status_admission_accepted, // Status Code
+                tspec_ie );
+
+            delete tspec_ie;
+            tspec_ie = NULL;
+
+            if( !frame )
+                {
+                DEBUG( "core_operation_delete_ts_c::next_state() - unable to allocate an action frame" );
+                return core_error_no_memory;
+                }
+
+            DEBUG( "core_operation_delete_ts_c::next_state() - DELTS REQ:" );
+            DEBUG_BUFFER( frame->data_length(), frame->data() );
+
+            server_m->send_management_frame(
+                core_frame_type_dot11,
+                frame->data_length(),
+                frame->data(),
+                dest );
+
+            delete frame;
+            frame = NULL;
+
+            DEBUG( "core_operation_delete_ts_c::next_state() - DELTS request sent" );
+
+            server_m->get_wpx_adaptation_instance().handle_ts_delete(
+                tid, user_priority );
+
+            /**
+             * If there no more manual virtual traffic streams in this AC,
+             * switch the traffic mode back to automatic.
+             */
+            if( virtual_ts_list.traffic_mode_by_ac( stream->access_class() ) == core_access_class_traffic_mode_automatic )
+                {
+                server_m->get_connection_data()->set_ac_traffic_mode(
+                    stream->access_class(),
+                    core_access_class_traffic_mode_automatic );
+
+                DEBUG( "core_operation_delete_ts_c::next_state() - traffic mode set to automatic for this AC, notifying clients" );
+
+                u8_t buf[5];
+                buf[0] = static_cast<u8_t>( 
+                    stream->access_class() );
+                buf[1] = static_cast<u8_t>(
+                    core_access_class_traffic_mode_automatic );
+                adaptation_m->notify(
+                    core_notification_ac_traffic_mode_changed,
+                    sizeof( buf ),
+                    buf );                
+                }
+
+            /**
+             * Delete the actual traffic stream.
+             */
+            ts_iter.remove();
+
+            if( direction == core_traffic_stream_direction_uplink ||
+                direction == core_traffic_stream_direction_bidirectional )
+                {
+                server_m->get_connection_data()->set_ac_traffic_status(
+                    core_tools_c::convert_user_priority_to_ac( user_priority ),
+                    core_access_class_traffic_status_not_admitted );
+
+                /**
+                 * Send an indication to notify clients that this access class
+                 * is no longer admitted.
+                 * 
+                 * We don't have to the check the ACM bits since the traffic
+                 * stream wouldn't exist if the AP didn't require admission
+                 * control.  
+                 */
+                DEBUG( "core_operation_delete_ts_c::next_state() - traffic no longer admitted on this AC, notifying clients" );
+
+                u8_t buf[5];
+                buf[0] = static_cast<u8_t>( 
+                    core_tools_c::convert_user_priority_to_ac( user_priority ) );
+                buf[1] = static_cast<u8_t>(
+                    core_access_class_traffic_status_not_admitted );
+                adaptation_m->notify(
+                    core_notification_ac_traffic_status_changed,
+                    sizeof( buf ),
+                    buf );
+
+                /**
+                 * Reset TX queue parameters back to default values.
+                 */
+                DEBUG( "core_operation_delete_ts_c::next_state() - resetting tx queue parameters" ); 
+
+                drivers_m->set_tx_queue_parameters(
+                    request_id_m,
+                    core_tools_c::convert_user_priority_to_ac( user_priority ),
+                    0,
+                    server_m->get_device_settings().max_tx_msdu_life_time );
+                }
+            else
+                {
+                /**
+                 * Since TX queue parameters apply only to uplink, there is nothing
+                 * more to do on downlink streams.
+                 */
+                return core_error_ok; 
+                }
+
+            break;
+            }
+        case core_base_state_parameters_set:
+            {
+            DEBUG( "core_operation_delete_ts_c::next_state() - tx queue parameters reset" );
+            
+            return core_error_ok;
+            }
+        default:
+            {
+            ASSERT( false_t );
+            }
+        }
+
+    return core_error_request_pending;
+    }