/*****************************************************************************

 @(#) $Id: mtp_trcc.h,v 0.7.2.1 2001/02/03 05:48:42 brian Test $

 -----------------------------------------------------------------------------

 Copyright (C) 1997-2001  Brian Bidulock <bidulock@dallas.net>

 All Rights Reserved.

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 Ave, Cambridge, MA 02139, USA.

 -----------------------------------------------------------------------------

 Last Modified $Date: 2001/02/03 05:48:42 $ by $Author: brian $

 *****************************************************************************/

#ifndef __SLS_TRCC_H__
#define __SLS_TRCC_H__

/*
 *  Referenced functions.
 */

static inline void rs_rcat_start_congestion_test(rs_t *rs);
static inline void rs_rcat_stop_congestion_test(rs_t *rs);

static inline void rs_tsfc_destination_congestion_status(rs_t *rs, int cong);

static inline void rs_tsrc_accessibility_data_request(rs_t *rs);

/*
 *  Forward declarations.
 */

static inline void rs_t15_timeout(rs_t *rs);

static inline void rs_trcc_(rs_t *rs);
static inline void rs_trcc_accessibility_data(rs_t *rs);
static inline void rs_trcc_decrement_destination_congestion_status(rs_t *rs);
static inline void rs_trcc_destination_congestion_status(rs_t *rs, int cong);
static inline void rs_trcc_destination_inaccessible(rs_t *rs);

/*
 *  Signalling Traffic Management (STM)
 *  Signalling Route Set Congestion Control (TRCC)
 *  Figure 29a/Q.704
 */

static inline void rs_t15_timeout(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_WAIT02:
            rs_rcat_start_congestion_test(rs);
            rs->statem.trcc_state = RS_STATE_WAIT03;
            break;
    }
}

static inline void rs_trcc_destination_congestion_status(rs_t *rs, int cong)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
            /* Store destination congestion status */
            rs->statem.cong_status = cong;
            rs_tsrc_accessibility_data_request(rs);
            rs->statem.trcc_state = RS_STATE_WAIT01;
            break;
        case RS_STATE_WAIT01:
            if ( cong > rs->statem.cong_status ) rs->statem.cong_status = cong_status;
            break;
        case RS_STATE_WAIT02:
            if ( cong != rs->statem.cong_status ) {
                rs->statem.cong_status = cong;
                rs_tsfc_destination_congestion_status(rs, cong);
                rs_timer_stop(t15);
                rs_timer_start(t15);
            }
            break;
        case RS_STATE_WAIT03:
            rs_rcat_stop_congestion_test(rs);
            if ( cong != rs->statem.cong_status ) {
                rs->statem.cong_status = cong;
                rs_tsfc_destination_congestion_status(rs, cong);
                rs_timer_start(t15);
                rs->statem.trcc_state = RS_STATE_WAIT02;
            }
            break;
    }
}

static inline void rs_trcc_decrement_destination_congestion_status(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
        case RS_STATE_WAIT01:
        case RS_STATE_WAIT02:
            break;
        case RS_STATE_WAIT03:
            rs->statem.cong_status--;
            rs_tsfc_destination_congestion_status(rs, rs->statem.cong_status);
            if ( rs->statem.cong_status )
                rs_rcat_start_congestion_test(rs);
            else
                rs->statem.trcc_state = RS_STATE_IDLE;
            break;
    }
}

static inline void rs_trcc_accessibility_data(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
            break;
        case RS_STATE_WAIT01:
            if ( rs->statem.destination_accessible ) {
                /* Update destination congestion status */
                rs_tsfc_destination_congestion_status(rs, rs->statem.cong_status);
                rs_timer_start(t15);
                rs->statem.trcc_state = RS_STATE_WAIT02;
            } else {
                rs->statem.trcc_state = RS_STATE_IDLE;
            }
            break;
        case RS_STATE_WAIT02:
            break;
    }
}

static inline void rs_trcc_destination_inaccessible(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
            break;
        case RS_STATE_WAIT01:
            rs->statem.trcc_state = RS_STATE_IDLE;
            break;
        case RS_STATE_WAIT02:
            rs->statem.cong_status = 0;
            rs_timer_stop(t15);
            rs->statem.trcc_state = RS_STATE_IDLE;
            break;
        case RS_STATE_WAIT03:
            rs->statem.cong_status = 0;
            rs_rcat_stop_congestion_test(rs);
            rs->statem.trcc_state = RS_STATE_IDLE;
            break;
    }
}

static inline void rs_trcc_(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
            break;
        case RS_STATE_WAIT01:
            break;
        case RS_STATE_WAIT02:
            break;
    }
}

static inline void rs_trcc_(rs_t *rs)
{
    switch ( rs->statem.trcc_state ) {
        case RS_STATE_IDLE:
            break;
        case RS_STATE_WAIT01:
            break;
        case RS_STATE_WAIT02:
            break;
    }
}

#endif  __SLS_TRCC_H__

