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

 @(#) $Id: mtp_tprc.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 __MTP_TPRC_H__
#define __MTP_TPRC_H__

/*
 *  Referenced functions.
 */

static inline void rs_hmdc_restart_begins(rs_t *rs);
static inline void rs_hmdc_restart_ends(rs_t *rs);
static inline void rs_hmdc_stop_restart(rs_t *rs);

static inline void rs_hmdt_restart_begins(rs_t *rs);
static inline void rs_hmdt_restart_ends(rs_t *rs);
static inline void rs_hmdt_stop_restart(rs_t *rs);

static inline void rs_hmrt_restart_begins(rs_t *rs);
static inline void rs_hmrt_restart_ends(rs_t *rs);
static inline void rs_hmrt_stop_restart(rs_t *rs);

static inline void rs_llsc_restart_begins(rs_t *rs);
static inline void rs_llsc_restart_ends(rs_t *rs);
static inline void rs_llsc_stop_restart(rs_t *rs);

static inline void rs_rsrt_restart_begins(rs_t *rs);
static inline void rs_rsrt_restart_ends(rs_t *rs);
static inline void rs_rsrt_stop_restart(rs_t *rs);

static inline void rs_rtac_restart_begins(rs_t *rs);
static inline void rs_rtac_restart_ends(rs_t *rs);
static inline void rs_rtac_stop_restart(rs_t *rs);

static inline void rs_rtpc_restart_begins(rs_t *rs);
static inline void rs_rtpc_restart_ends(rs_t *rs);
static inline void rs_rtpc_stop_restart(rs_t *rs);

static inline void rs_rtrc_restart_begins(rs_t *rs);
static inline void rs_rtrc_restart_ends(rs_t *rs);
static inline void rs_rtrc_stop_restart(rs_t *rs);

static inline void rs_tlac_restart_begins(rs_t *rs);
static inline void rs_tlac_restart_ends(rs_t *rs);
static inline void rs_tlac_stop_restart(rs_t *rs);

static inline void rs_tsfc_stop_restart(rs_t *rs);

static inline void rs_tspc_restart_begins(rs_t *rs);
static inline void rs_tspc_restart_ends(rs_t *rs);
static inline void rs_tspc_stop_restart(rs_t *rs);

static inline void rs_tsrc_restart_ends(rs_t *rs);
static inline void rs_tsrc_send_status(rs_t *rs);
static inline void rs_tsrc_sending_status_phase(rs_t *rs);
static inline void rs_tsrc_t20_expired(rs_t *rs);
static inline void rs_tsrc_traffic_restart_allowed(rs_t *rs);

/*
 *  Forward declarations.
 */

static inline void rs_t18_timeout(rs_t *rs);
static inline void rs_t19_timeout(rs_t *rs);
static inline void rs_t20_timeout(rs_t *rs);

static inline void rs_tprc_adjacent_sp_restarting(rs_t *rs);
static inline void rs_tprc_signalling_link_available(rs_t *rs);
static inline void rs_tprc_signalling_link_unavailable(rs_t *rs);
static inline void rs_tprc_signalling_point_restart_indication(rs_t *rs);
static inline void rs_tprc_signalling_point_restart_indication_mgmt(rs_t *rs);
static inline void rs_tprc_status_sent(rs_t *rs);
static inline void rs_tprc_stop_restart(rs_t *rs);
static inline void rs_tprc_traffic_restart_allowed(rs_t *rs);

/*
 *  Signalling Traffic Management (STM)
 *  Signalling Point Restart Control (TPRC)
 *  Figure 34b/Q.704
 */

static inline void rs_t18_timeout(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT01:
            rs_llsc_restart_ends(rs);
            /* Any links still restoring are reported failed, but keep trying */
            rs_tsrc_sending_status_phase(rs);
            rs_tsrc_send_status(rs); /* The status infomction is sent after
                                        the linkset is available at level 3 */
            rs->statem.tprc_state = RS_STATE_WAIT02;
            break;
    }
}

static inline void rs_t19_timeout(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_IDLE:
            rs->statem.t19_running = 0; /* for that destination */
            break;
    }
}

static inline void rs_t20_timeout(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT02:
            rs_timer_stop(t20);
            rs_tsrc_t20_expired(rs);
            rs_tsrc_restart_ends(rs);
            rs_timer_start(t19); /* For all SPs to which a TRA message was sent */
            rs_llsc_restart_ends(rs);
            rs_tspc_restart_ends(rs);
            rs_tlac_restart_ends(rs);
            rs_rtrc_restart_ends(rs);
            rs_rtpc_restart_ends(rs);
            rs_rsrt_restart_ends(rs);
            rs_rtac_restart_ends(rs);
            rs_hmrt_restart_ends(rs);
            rs_hmdc_restart_ends(rs);
            rs_hmdt_restart_ends(rs);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
        case RS_STATE_WAIT03:
            rs_tsrc_t20_expired(rs);
            rs_tsrc_sending_status_phase(rs);   /*  Puts TSRC into "Wait 05"
                                                    so that TRA message is
                                                    sent. */
            rs_llsc_restart_ends(rs);
            rs_tsrc_restart_ends(rs);           /*  The status information is
                                                    sent after the linkset is
                                                    available at level 3. */
            rs_tspc_restart_ends(rs);
            rs_tlac_restart_ends(rs);
            rs_rtrc_restart_ends(rs);
            rs_rtpc_restart_ends(rs);
            rs_rsrt_restart_ends(rs);
            rs_rtac_restart_ends(rs);
            rs_hmrt_restart_ends(rs);
            rs_hmdc_restart_ends(rs);
            rs_hmdt_restart_ends(rs);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
    }
}

static inline void rs_tprc_adjacent_sp_restarting(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_IDLE:
            rs->statem.adjacent_sp_restarting = 1;
            break;
    }
}

static inline void rs_tprc_signalling_point_restart_indication_mgmt(rs_t *rs)
{
    /* This applies to system initialization */
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_IDLE:
            rs_llsc_restart_begins(rs);
            break;
    }
}

static inline void rs_tprc_traffic_restart_allowed(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_IDLE:
            if ( /* From an adjacent SP restarting? */ ) {
                rs->statem.adjacent_sp_restarting = 0;
            } else {
                if ( rs->statem.t19_running )
                    break;
                else
                    rs_timer_start(t19);
            }
            rs_tsrc_traffic_restart_allowed(rs);
            break;
        case RS_STATE_WAIT03:
            if ( /* Enough TRA message */ ) {
                rs_timer_stop(t20);
                rs_tsrc_t20_expired(rs);
                rs_tsrc_sending_status_phase(rs);   /*  Puts TSRC into "Wait 05"
                                                        so that TRA message is
                                                        sent. */
                rs_llsc_restart_ends(rs);
                rs_tsrc_restart_ends(rs);           /*  The status information is
                                                        sent after the linkset is
                                                        available at level 3. */
                rs_tspc_restart_ends(rs);
                rs_tlac_restart_ends(rs);
                rs_rtrc_restart_ends(rs);
                rs_rtpc_restart_ends(rs);
                rs_rsrt_restart_ends(rs);
                rs_rtac_restart_ends(rs);
                rs_hmrt_restart_ends(rs);
                rs_hmdc_restart_ends(rs);
                rs_hmdt_restart_ends(rs);
                rs->statem.tprc_state = RS_STATE_IDLE;
            }
            break;
    }
}

static inline void rs_tprc_signalling_point_restart_indication(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_IDLE:
            rs_tspc_restart_begins(rs);
            rs_tlac_restart_begins(rs);
            rs_hmrt_restart_begins(rs);
            rs_hmdt_restart_begins(rs);
            rs_hmdc_restart_begins(rs);
            rs_rtrc_restart_begins(rs);
            rs_rtpc_restart_begins(rs);
            rs_rsrt_restart_begins(rs);
            rs_rtac_restart_begins(rs);
            rs_timer_start(t20);
            if ( rs->config.stp_function ) {
                rs_timer_start(t18);
                rs->statem.tprc_state = RS_STATE_WAIT01;
            } else
                rs->statem.tprc_state = RS_STATE_WAIT03;
            break;
    }
}

static inline void rs_tprc_signalling_link_available(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT01:
            rs->statem.link_available = 1;
            rs->statem.links_available++;
            if ( /* Enough TRA messages? */ &&
                    rs->statem.links_available >= rs->config.sufficient_links
                    /* Sufficient links available */ ) {
                rs_timer_stop(t18);
                rs_llsc_restart_ends(rs);
                /* Any links still restoring are reported failed, but keep trying */
                rs_tsrc_sending_status_phase(rs);
                rs_tsrc_send_status(rs); /* The status infomction is sent after
                                            the linkset is available at level 3 */
                rs->statem.tprc_state = RS_STATE_WAIT02;
            }
            break;
    }
}

static inline void rs_tprc_traffic_restart_allowed(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT01:
            rs->statem.tra_received = 1;
            if ( /* Enough TRA messages? */ &&
                    rs->statem.links_available >= rs->config.sufficient_links
                    /* Sufficient links available */ ) {
                rs_timer_stop(t18);
                rs_llsc_restart_ends(rs);
                /* Any links still restoring are reported failed, but keep trying */
                rs_tsrc_sending_status_phase(rs);
                rs_tsrc_send_status(rs); /* The status infomction is sent after
                                            the linkset is available at level 3 */
                rs->statem.tprc_state = RS_STATE_WAIT02;
            }
            break;
    }
}

static inline void rs_tprc_signalling_link_unavailable(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT01:
            rs->statem.link_available = 0;
            rs->statem.links_available--;
            break;
    }
}

static inline void rs_tprc_stop_restart(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT01:
            rs_tspc_stop_restart(rs);
            rs_tlac_stop_restart(rs);
            rs_rtrc_stop_restart(rs);
            rs_rtpc_stop_restart(rs);
            rs_rsrt_stop_restart(rs);
            rs_rtac_stop_restart(rs);
            rs_hmrt_stop_restart(rs);
            rs_hmdc_stop_restart(rs);
            rs_hmdt_stop_restart(rs);
            rs_timer_stop(t18);
            rs_timer_stop(t20);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
        case RS_STATE_WAIT02:
            rs_tspc_stop_restart(rs);
            rs_tlac_stop_restart(rs);
            rs_rtrc_stop_restart(rs);
            rs_rtpc_stop_restart(rs);
            rs_rsrt_stop_restart(rs);
            rs_rtac_stop_restart(rs);
            rs_hmrt_stop_restart(rs);
            rs_hmdc_stop_restart(rs);
            rs_hmdt_stop_restart(rs);
            rs_timer_stop(t20);
            rs_tsrc_t20_expired(rs);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
        case RS_STATE_WAIT03:
            rs_llsc_stop_restart(rs);
            rs_tsfc_stop_restart(rs);
            rs_tlac_stop_restart(rs);
            rs_rtrc_stop_restart(rs);
            rs_rtpc_stop_restart(rs);
            rs_rsrt_stop_restart(rs);
            rs_rtac_stop_restart(rs);
            rs_hmrt_stop_restart(rs);
            rs_hmdc_stop_restart(rs);
            rs_hmdt_stop_restart(rs);
            rs_timer_stop(t20);
            rs_tsrc_t20_expired(rs);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
    }
}

static inline void rs_tprc_status_sent(rs_t *rs)
{
    switch ( rs->statem.tprc_state ) {
        case RS_STATE_WAIT02:
            rs_timer_stop(t20);
            rs_tsrc_t20_expired(rs);
            rs_tsrc_restart_ends(rs);
            rs_timer_start(t19); /* For all SPs to which a TRA message was sent */
            rs_llsc_restart_ends(rs);
            rs_tspc_restart_ends(rs);
            rs_tlac_restart_ends(rs);
            rs_rtrc_restart_ends(rs);
            rs_rtpc_restart_ends(rs);
            rs_rsrt_restart_ends(rs);
            rs_rtac_restart_ends(rs);
            rs_hmrt_restart_ends(rs);
            rs_hmdc_restart_ends(rs);
            rs_hmdt_restart_ends(rs);
            rs->statem.tprc_state = RS_STATE_IDLE;
            break;
    }
}

#endif  __MTP_TPRC_H__

