OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/ua/ua_sm.c


File /code/strss7/drivers/ua/ua_sm.c



#ident "@(#) $RCSfile: ua_sm.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2002/10/18 02:26:20 $"

static char const ident[] =
    "$RCSfile: ua_sm.c,v $ $Name:  $($Revision: 0.8.2.1 $) $Date: 2002/10/18 02:26:20 $";

/*
 *  =========================================================================
 *
 *  STATE MACHINE FUNCTIONS
 *
 *  =========================================================================
 *  These are some state machine functions which are rather complicated and
 *  need to be called from several places.  These include state transitioning
 *  for ASPs.
 */

/*
 *  SG Blocked
 *  -------------------------------------------------------------------------
 *  This function is called when an SGP encounters and error on a Routing
 *  Context or Interface Id.  It sends an ASPIA Ack to all connected ASPs for
 *  the affected routing context and moves the ASPs to the ASP_INACTIVE state
 *  for the affected AS.  The function is called with an SG queue.
 *
 *  What we are going to do here is send an ASPIA-Ack to all the ASPs for the
 *  specified AS and mark the AS AS-BLOCKED.  We should also send a NTFY
 *  AS-Inactive to each of the inactive ASPs in the AS.  This should freak the
 *  ASPs into resending ASPAC.  We unlink the stream and inform mangement.
 *  Either the stream will be restored before the ASPAC arrives or we will
 *  reject the ASPAC with an ERR message.  As the AS is marked locally as
 *  AS-BLOCKED any UA data messages received will be discarded.
 *
 *  For M2UA, setting AS-BLOCKED means that acknowledgements of data messages
 *  (Correlation Id Ack) and confirmations of MAUP messages will be
 *  immediately suspended.
 */
int ua_ss7_blocked(queue_t * q)
{
	gp_t *gp;
	mblk_t *mp, *np, *dp;
	static const char info[] = "Application Server blocked/failed at SG";
	ensure(Q_TYPE(q) & Q_TYPE_SS7, return -EFAULT);
	ensure(Q_MODE(q) & Q_MODE_SG, return -EFAULT);
	ensure(sg->spac_count, return -EFAULT);
	if (Q_UA(q) & Q_UA_M2UA) {
		mp = ua_send_aspia_ack(&sg->list->rc.id, 1, NULL, 0,
				       (caddr_t) info, info ? sizeof(info) - 1 : 0);
		np = ua_send_ntfy(UA_STATUS_AS_DOWN, NULL,
				  &sg->list->rc.id, 1, NULL, 0, (caddr_t) info,
				  info ? sizeof(info) - 1 : 0);

	} else {
		mp = ua_send_aspia_ack(NULL, 0, &sg->list->rc.id, 1,
				       (caddr_t) info, info ? sizeof(info) - 1 : 0);
		np = ua_send_ntfy(UA_STATUS_AS_DOWN, NULL,
				  NULL, 0, &sg->list->rc.id, 1, (caddr_t) info,
				  info ? sizeof(info) - 1 : 0);
	}
	if (!mp || !np) {
		if (mp)
			freemsg(mp);
		if (np)
			freemsg(np);
		return (-ENOBUFS);
	}
	for (gp = sg->gp; gp; gp = gp->sp_next) {
		if (gp->state & (ASP_ACTIVE | ASP_INACTIVE)) {
			if (!(dp = dupmsg(np)))
				return (-ENOBUFS);
			ensure(gp->sp->lp, continue);
			/* FIXME: need SCTP stream selector on message */
			putq(gp->sp->lp->q, dp);	/* send it */
		}
		if (gp->state & ASP_ACTIVE) {
			if (!(dp = dupmsg(mp)))
				return (-ENOBUFS);
			gp->state = ASP_INACTIVE;
			sg->spia_count++;
			sg->spac_count--;
			ensure(gp->sp->lp, continue);
			/* FIXME: need SCTP stream selector on message */
			putq(gp->sp->lp->q, dp);	/* send it */
		}
	}
	sg->state = AS_BLOCKED;
	freemsg(mp);		/* free original */
	freemsg(np);		/* free original */
	q_disable(q);
	return (0);
}

/*
 *  AS State Recalc
 *  -------------------------------------------------------------------------
 *  An ASP has changed its state in this AS, so we need to recalculate the
 *  current state of the AS and take appropriate actions.
 */
static void ua_as_state_recalc(as_t * as)
{
	gp_t *gp;
	uint state = AS_DOWN;
	uint asps_ac = 0;
	uint asps_ia = 0;
	uint asps_dn = 0;
	for (gp = as->gp; gp; gp = gp->sp_next) {
		switch (gp->state & (ASP_DOWN | ASP_INACTIVE | ASP_ACTIVE)) {
		case ASP_DOWN:
			asps_dn++;
			break;
		case ASP_INACTIVE:
			asps_ia++;
			if (state == AS_DOWN)
				state = AS_INACTIVE;
			break;
		case ASP_ACTIVE:
			asps_ac++;
			state = AS_ACTIVE;
			break;
		}
	}
	if (state == AS_ACTIVE && asps_ac < as->min_count) {
		/* we don't have enough active asps */
		state = AS_INACTIVE;
		if (as->state == AS_ACTIVE) {
			/* need to send notify to all inactive ASPs */
			mblk_t *mp = msg_ntfy(UA_STATUS_AS_RESOURCE, as->iid);
			for (gp = as->list; gp; gp = gp->sp)
				if (gp->sp->state == ASP_INACTIVE)
					putq(WR(asp->q), dupmsg(mp));
			freemsg(mp);
		}
	}
	if (as->state == AS_ACTIVE && state != AS_ACTIVE) {
		/* we need to push this ASP to the pending state */
		state = AS_PENDING;
		/* 
		 *  FIXME: set pending timer for this AS so that messages will
		 *  only be collected for a time.
		 */
	}
	as->state = state;
	as->asps_ac = asps_ac;
	as->asps_ia = asps_ia;
	as->asps_dn = asps_dn;
	return;
}

/*
 *  ASP State Recalc
 *  -------------------------------------------------------------------------
 *  An ASP has changed state so we need to recalculate the current state of
 *  all of the AS of which the ASP is a part.
 */
static void ua_asp_state_recalc(asp_t * asp)
{
	gp_t *gp;
	/* for each of the AS which own this ASP */
	for (gp = asp->list; gp; gp = gp->node_next)
		ua_as_state_recalc(gp->node);
	return;
}

/*
 *  SSP goes INACTIVE/DOWN within an SP
 *  -------------------------------------------------------------------------
 *  An ASP/SGP/SPP has transitioned to the inactive (or down) state from the
 *  active state within an AS/SG/SP.  We must see what effect this has on the
 *  caching of data routing and on the overall state of the AS.
 */
static void ua_sp_spp_inactive(sp_t * spp, sp_t * sp)
{
	uint old_state = sp->state;
	switch (sp->tmode) {
	case UA_TMODE_OVERRIDE:
		switch (sp->state) {
		case AS_DOWN:
		case AS_ACTIVE:
		case AS_INACTIVE:
		case AS_PENDING:
		}
	case UA_TMODE_LOADSHARE:
		switch (sp->state) {
		case AS_DOWN:
		case AS_ACTIVE:
		case AS_INACTIVE:
		case AS_PENDING:
		}
	case UA_TMODE_BROADCAST:
		switch (sp->state) {
		case AS_DOWN:
		case AS_ACTIVE:
		case AS_INACTIVE:
		case AS_PENDING:
		}
	}
	/* inform all ASPs of any state changes */
	if (old_state != sp->state) {
		mblk_t *mp;
		uint status;
		switch (sp->state) {
		case AS_DOWN:
			status = UA_STATUS_AS_DOWN;
			break;
		case AS_ACTIVE:
			status = UA_STATUS_AS_ACTIVE;
			break;
		case AS_INACTIVE:
			status = UA_STATUS_AS_INACTIVE;
			break;
		case AS_PENDING:
			status = UA_STATUS_AS_PENDING;
			break;
		}
		for (gp = spp->list; gp; gp = gp->node_next) {
		sl_t *}
	}
	return;
}

/*
 *  SSP goes ACTIVE within an SP
 *  -------------------------------------------------------------------------
 *  An ASP/SGP/SPP has transitioned to the active state from the inactive (or
 *  down) state within an AS/SG/SP.  We must see what effect this has on the
 *  caching of data routing and on the overall state of the AS.
 */
static void ua_sp_spp_active(sp_t * spp, sp_t * sp)
{
	switch (sp->tmode) {
	case UA_TMODE_OVERRIDE:
		switch (sp->state) {
		case UA_AS_DOWN:
		case UA_AS_ACTIVE:
		case UA_AS_INACTIVE:
		case UA_AS_PENDING:
		}
	case UA_TMODE_LOADSHARE:
		switch (sp->state) {
		case UA_AS_DOWN:
		case UA_AS_ACTIVE:
		case UA_AS_INACTIVE:
		case UA_AS_PENDING:
		}
	case UA_TMODE_BROADCAST:
		switch (sp->state) {
		case UA_AS_DOWN:
		case UA_AS_ACTIVE:
		case UA_AS_INACTIVE:
		case UA_AS_PENDING:
		}
	}
	return;
}

/*
 *  SPP DOWN
 *  -------------------------------------------------------------------------
 *  This includes all of the actions require to transition an SPP to the down
 *  state from the current state at the serving SP.  For example, this
 *  includes all of the actions necessary to transition an ASP to the down
 *  state at an SG.  This function is called with the transport queue.
 */
static int ua_spp_down(queue_t * q)
{
	sp_t *sp = Q_SP(q);

	if (sp->state & ASP_DOWN)
		return (0);

	switch (Q_MODE(q)) {
	case Q_MODE_SG:
	case Q_MODE_AS:
	case Q_MODE_SP:
	}

	if (m2p->state == ASP_DOWN)
		return;

	/* inform management that an ASP has gone down */

	ua_asp_state_recalc(m2p);

	switch (m2p->state) {
	case UA_ASP_DOWN:
		/* already in down state: nothing to do */
		return;
	case UA_ASP_INACTIVE:
		ua_asp_state_recalc(m2p->node);
		/* trivial, just transition the state and inform management */
		break;
	case UA_ASP_ACTIVE:
		/* we must inform all owning SP of the loss of an active SPP */
	{
		sp_t *sp;
	}
		break;
	}
	m2p->state = UA_ASP_DOWN;
	return;
}

/*
 *  SPP UP
 *  -------------------------------------------------------------------------
 *  This includes all of the actions necessary to transition an SPP to the up
 *  state from the current state at the serving SP (with the exception of
 *  sending peer pdus).
 */
static void ua_spp_up(queue_t * q)
{
	sp_t *m2p = ((nsp_t *) q->q_ptr)->ua;
	sp_t *spp = m2p->list;
}

/*
 *  SPP ACTIVE
 *  -------------------------------------------------------------------------
 *  This includes all of the actions necessary to transition an SPP to the
 *  active state from the current state at the serving SP (with the exception
 *  of sending peer pdus).
 */
static void ua_spp_active(queue_t * q)
{
	sp_t *m2p = ((nsp_t *) q->q_ptr)->ua;
	sp_t *spp = m2p->list;
}

/*
 *  SPP INACTIVE
 *  -------------------------------------------------------------------------
 *  This includes all of the actions necessary to transition an SPP to the
 *  inactive state from the current state at the serving SP (with the
 *  exception of sending peer pdus).
 */
static void ua_spp_inactive(queue_t * q)
{
	sp_t *m2p = ((nsp_t *) q->q_ptr)->ua;
	sp_t *spp = m2p->list;
}

/*
 *  SPP BLOCKED
 *  -------------------------------------------------------------------------
 *  This includes all of the actions necessary to transition an SPP to the
 *  down state from the current state when the SPP is blocked (the transport
 *  provider has gone away).
 */
int ua_spp_blocked(queue_t * q)
{
	sp_t *sp = Q_SP(q);
	mblk_t *mp, *np, *dp;
	if (sp->state & ASP_DOWN)
		return (0);
	switch (Q_MODE(q)) {
	case Q_MODE_SG:
	{
		static const char info[] = "Broken Pipe to ASP";
		/* 
		 *  The SG should mark the ASP down and send NTFY("ASP
		 *  Failure") to any inactive ASPs in the AS, to allow
		 *  another ASP to take over from this blocked ASP.
		 */
		np = ua_send_ntfy(UA_STATUS_ASP_FAILURE, &sp->id,
				  NULL, 0, NULL, 0, (caddr_t) info, info ? sizeof(info) - 1 : 0);
		if (!np)
			return (-ENOBUFS);
	}
	case Q_MODE_AS:
	{
		static const char info[] = "Broken Pipe to ASP";
		/* 
		 *  The AS should 
		 */
	}
	case Q_MODE_SP:
	{
	}
	default:
		return (-EFAULT);
	}
	/* 
	 *  Change the state of the ASP within all ASs to ASP_DOWN.
	 */
	for (gp = sp->gp; gp; gp = gp->as_next) {
		as_t *as = gp->as;
		switch (gp->state) {
		case ASP_DOWN:
			continue;
		case ASP_INACTIVE:
			sp->aspia_count--;
			sp->aspdn_count++;
			gp->state = ASP_DOWN;
			break;
		case ASP_ACTIVE:
			sp->aspac_count--;
			sp->aspdn_count++;
			gp->state = ASP_DOWN;
		default:
			/* generate a SWERR */
			gp->state = ASP_DOWN;
			continue;
		}
		/* 
		 *  In each AS that the ASP has moved to ASP_DOWN,
		 *  recalculate the AS state and perform any changes.
		 */
		switch (as->state) {
		case AS_DOWN:
		case AS_INACTIVE:
		case AS_ACTIVE:
		case AS_PENDING:
		default:
		}
	}
	sp->state = ASP_DOWN;
}

/*
 *  FIXME:  Pulled these from old file.. figure out what to do with them...
 */
/*
 *  =========================================================================
 *
 *  ASP State Machine procedures
 *
 *  =========================================================================
 */
static int ua_ntfy_as_state_change(queue_t * q, struct ua_parm *rc, uint state)
{
	/* 
	 *  NOTE: we have to go thru all the RCs in the list
	 */
	/* 
	 *  An AS has changed state.  We should mirror the change in the AS
	 *  state and determine if there is any action that we should take.
	 *  If the AS is in AS_STATE_PENDING, we may want to go active.  If
	 *  the AS is in AS_STATE_INACTIVE we may want to go active.  If the
	 *  AS is AS_STATE_ACTIVE we may want to do something else.
	 */
}
static int ua_ntfy_too_few_asps(q, rc)
	queue_t *q;
	struct ua_parm *rc;		/* NULL if not specified */
{
	/* NOTE: we have to go thru all the rcs in the list */
}
static int ua_ntfy_alternate_asp(q, aspid)
	queue_t *q;
	struct ua_parm *aspid;		/* NULL if not specified */
{
	/* 
	 *  We have been overridden.  Perhaps we should say something to the
	 *  other asp which has (or may not) be identified.  It would be nice
	 *  to have the ASP Id here as well.  But it is not necessary.  All
	 *  that we know is that we have been overridden.  However, we are
	 *  still active, just not master.
	 */
}
static int ua_ntfy_asp_failure(q, rc, state)
	queue_t *q;
	struct ua_parm *aspid;		/* NULL if not specified */
{
	if (!aspid->u.wptr) {
		/* 
		 *  For ASP Failure we need to dig out the ASP Identifier.  If
		 *  it is not there, the notificiation is pretty much useless.
		 *  Unless we want to go auditing.
		 *
		 *  We want to return ERR Error - ASP Identifier Required
		 */
		return (-EINVAL);
	}
	/* 
	 *  Mark out mate ASP with the specified id as failed.  We may want to
	 *  take over its traffic if we are mirrored with it.
	 */

}
static int ua_ntfy_as_vulnerable(q, rc)
	queue_t *q;
	struct ua_parm *rc;		/* NULL if not specified */
{
	/* 
	 *  Some AS is running vulnerable.  We should only get this
	 *  notification when we are inactive.  We might want to activate
	 *  ourselves if we are next in line as a backup for the others.
	 */
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/drivers/ua/ua_sm.c

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: