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_asp.c


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



#ident "@(#) $RCSfile: ua_asp.c,v $ $Name:  $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:46 $"

static char const ident[] =
    "$RCSfile: ua_asp.c,v $ $Name:  $($Revision: 0.8.2.2 $) $Date: 2003/04/03 19:51:46 $";

#define __NO_VERSION__

#include <linux/config.h>
#include <linux/version.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>

#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/cmn_err.h>

#include "../debug.h"
#include "../bufq.h"

#include "../ua/ua_data.h"
#include "../ua/ua_msg.h"
//#include "../ua/ua_sm.h"

/*
 *  =========================================================================
 *
 *  UA Peer --> UA (ASP) Received Messages
 *
 *  =========================================================================
 *
 *  These are procedures for common UA received messages at the ASP.
 */
/*
 *  ASPS ASPUP Ack
 *  -------------------------------------------------------------------------
 *  ASP Identifier	Optional (But must be used sometimes)
 *  Info String		Optional
 */
static int ua_recv_aspup_ack(asp_t * asp, mblk_t * mp)
{
	int err;
	mblk_t *rp;
	pp_t *pp = (pp_t *) q->q_ptr;
	sp_t *sp = pp->u.sp;
	if (!sp || sp->state != ASP_STATE_WACK_ASPUP) {
		if (!(rp = ua_mgmt_err(SUA_ECODE_UNEXPECTED_MESSAGE)))
			return (-ENOBUFS);
		qreply(q, rp);
		return (-EINVALID);
	}
	/* 
	 *  Can we use ASP Identifier and Capabilities to show SGP identity
	 *  and capabilies?  Probably not.  Just check if the ASP is in the
	 *  ASP_STATE_WACK_ASPUP state and move it to the ASP_STATE_INACTIVE.
	 *  Recalculate the state of all configured AS.  It might be a good
	 *  idea not to "lock in" the AS state until we get an NTFY
	 *  (AS_STATE).
	 */
	if ((err = asp_recalc_as_state(sp)))
		return (err);
	sp->state = ASP_STATE_INACTIVE;
	freemsg(mp);
	return (0);
}

/*
 *  ASPS ASPDN Ack  (Watch this one for SUA and M3UA...)
 *  -------------------------------------------------------------------------
 */
static int ua_recv_aspdn_ack(asp_t * asp, mblk_t * mp)
{
	/* 
	 *  If we get this it does not matter that we are in what state.
	 *  if we are in ASP_STATE_WACK_ASPDN, then everything is fine.
	 *  However, if we are in any other state, we need to move to
	 *  the ASPDN state and then, errr.... Nope.  That's just M3UA.
	 */
	freemsg(mp);
	return (0);
}

/*
 *  ASPS HBEAT
 *  -------------------------------------------------------------------------
 *  Heartbeat Data	Optional
 */
static int ua_recv_hbeat_req(asp_t * asp, mblk_t * mp)
{
	/* 
	 *  This is a simple matter of turning around the heartbeat request.
	 *  We can just jam the message type and send it back.  Don't even
	 *  pull out the parameters.
	 */
	(void) q;
	(void) mp;
	return (-EOPNOTSUPP);
}

/*
 *  ASPS HBEAT Ack
 *  -------------------------------------------------------------------------
 *  Heartbeat Data	Optional
 */
static int ua_recv_hbeat_ack(asp_t * asp, mblk_t * mp)
{
	/* 
	 *  Check the heartbeat data.  There are a number of occasions for
	 *  which we send heartbeats.  There is a process waiting for the
	 *  response based on the heartbeat data or there is not.  This needs
	 *  be done in parallel for some applications (changeback).  We should
	 *  have a process list with ids from the data.  That way we could use
	 *  the data to index the function to call here...
	 *
	 *  Well..., normally we do this to flush an routing context traffic
	 *  flow.  If there is heartbeat data, extract the routing contexts
	 *  out of the heartbeat data and find AS in the AS_WACK_BEAT state.
	 */
	(void) q;
	(void) mp;
	return (-EOPNOTSUPP);
}

/*
 *  ASPT ASPAC Ack
 *  -------------------------------------------------------------------------
 *  Traffic Mode Type	Mandatory
 *  Routing Context	Optional
 *  INFO String		Optional
 */
static int ua_recv_aspac_ack(asp_t * asp, mblk_t * mp)
{
	int i;
	struct ua_parm *rc = &ua_parm_results.rc;
	ua_decode_parms(mp);
	if (rc->u.wptr && rc->len > 4) {
		int i;
		uint32_t *p = rc->u.wptr;
		for (i = 0, p = rc->u.wptr; i < (rc->len / 4) - 1; i++, p++) {
			uint32_t rcval = ntohl(*p++);
			/* 
			 *  Check for AS which belong to the ASP by routing
			 *  context.  Find AS in the AS_WACK_ASPAC state.
			 *  Move them to the AS_ACTIVE state.  I don't know
			 *  what the purpose of the returned traffic mode
			 *  type is...  Is this the mode of the SGP?
			 */
		}
	} else {
	}
	freemsg(mp);
	return (0);
}

/*
 *  ASPT ASPIA Ack
 *  -------------------------------------------------------------------------
 *  Routing Context	Optional
 *  INFO String		Optional
 */
static int ua_recv_aspia_ack(asp_t * asp, mblk_t * mp)
{
	int i;
	struct ua_parm *rc = &ua_parms.rc;
	ua_decode_parms(mp);
	if (rc->u.wptr && rc->len >= 4) {
		int i;
		uint32_t *p = rc->u.wptr;
		for (i = 0, p = rc->u.wptr; i < (rc->len / 4) - 1; i++, p++) {
			uint32_t rcval = ntohl(*p++);
			/* 
			 *  Find the RC in the list of AS which belong to this
			 *  ASP and see if it is in the state AS_STATE_WACK_ASPIA.
			 *  If it is, put it in the state AS_STATE_INACTIVE.
			 */
		}
	} else {
		/* 
		 *  RC was not provided.  This is the default routing context
		 *  case.  Do we only have one AS?  Only one AS in the
		 *  AS_STATE_WACK_ASPIA?
		 */
	}
	freemsg(mp);
	return (0);
}

/*
 *  MGMT ERR
 *  -------------------------------------------------------------------------
 *  Error Code		Mandatory
 *  Diagnostic Info	Optional
 */
static int ua_recv_err(asp_t * asp, mblk_t * mp)
{
	sp_t *sp = ((pp_t *) q->q_ptr)->u.sp;
	ua_decode_parms(mp);
	if (!ua_parms.ecode.u.wptr)
		return -EINVAL;
	switch (ua_parms.ecode.val) {
		/* 
		 *  These values are from ua-07.
		 */
	case 0x01:		/* Invalid Version */
	case 0x05:		/* Unsupported Traffic Handling Mode */
	case 0x08:		/* Invalid Routing Context */
		/* 
		 *  If I am trying something, give up.
		 */
	case 0x0c:		/* Unexpected Parameter */
		/* 
		 *  TODO: Might be because we a using an extension
		 *  that the other end doesn't recognize.  Go after
		 *  the diagnostics parameter and see if we get the
		 *  parameter.  Then see if we can discover features
		 *  of the other end from which parameter was
		 *  unexpected.
		 */
	default:
	case 0x02:		/* n/a */
	case 0x03:		/* Unexpected Message Class */
	case 0x04:		/* Invalid Message Type Class */
	case 0x06:		/* Unexpected Message */
	case 0x07:		/* Protocol Error */
	case 0x09:		/* Invalid Stream Identifier */
	case 0x0b:		/* Parameter Field Error */
	case 0x0d:		/* Duplicated Parameter */
	case 0x0e:		/* Error - ASP Identifier Required */
	case 0x0f:		/* Error - Invalid ASP Identifier */
	case 0x10:		/* Refused - ASP Identifier Required */
		/* 
		 *  Some of these can't happen (we always send
		 *  optional fields).  Don't give up.
		 */
	}
	/* 
	 *  TODO: Notify management.
	 */
	freemsg(mp);
	return (0);
/*
 *  MGMT ERR
 *  -------------------------------------------------------------------------
 *  IMPLEMENTATION NOTE:-  We want to report all errors to management.  Some
 *  errors are considered fatal errors.  That is we will stop all processes,
 *  and put everything associated with the ASP/SGP/SP into the Down state,
 *  even drop the SCTP association.
 */
	static int m3ua_err(asp_t * asp, mblk_t * mp) {
		m3ua_parms_t parms;
		parm_t *ecode = &parms->common.ecode;
		parm_t *diag = &parms->common.diag;

		m3ua_decode_parms(msg, &parms);

		if (!ecode->u.wptr) {
			/* missing mandatory parameter */
			return (-EINVAL);
		}
		switch (*ecode->u.wptr) {
		case UA_ECODE_INVALID_VERSION:
		case UA_ECODE_INVALID_IID_OR_NTWK_APP:
		case UA_ECODE_UNSUPPORTED_MESSAGE_CLASS:
		case UA_ECODE_UNSUPPORTED_MESSAGE_TYPE:
		case UA_ECODE_UNSUPPORTED_TRAFFIC_MODE:
		case UA_ECODE_UNEXPECTED_MESSAGE:
		case UA_ECODE_PROTOCOL_ERROR:
		case UA_ECODE_INVALID_ROUTING_CONTEXT:
		case UA_ECODE_INVALID_STREAM_IDENTIFIER:
		case UA_ECODE_INVALID_PARAMETER_VALUE:
		case M3UA_ECODE_REFUSED_MANAGEMENT_BLOCKING:
		case M3UA_ECODE_UNKNOWN_ROUTING_CONTEXT:
		case M3UA_ECODE_INVALID_ASPID:
		default:
			/* error invalid error???? */
			return (-EINVAL);
		}

		return (-EOPNOTSUPP);
	}
}

/*
 *  MGMT NTFY
 *  -------------------------------------------------------------------------
 *  Status		Mandatory
 *  ASP Identifier	Optional
 *  Routing Context	Optional
 *  Info String		Optional
 */
static int ua_recv_ntfy(asp_t * asp, mblk_t * mp)
{
	int i, err = 0;
	uint32_t *rc;
	struct ua_parm *rc = &ua_parm_results.rc;
	struct ua_parm *aspid = &ua_parm_results.aspid;
	sp_t *sp = ((pp_t *) q->q_ptr)->u.sp;
	ua_decode_parms(mp);
	if (!ua_parm_results.status.u.wptr)
		return -EINVAL;
	switch (ua_parm_results.status.val) {
	case 0x00010001:	/* Application Server Down (AS-Down) */
		err = ua_ntfy_as_state_change(q, rc, AS_STATE_DOWN);
		break;
	case 0x00010002:	/* Application Server Inactive (AS-Inactive) */
		err = ua_ntfy_as_state_change(q, rc, AS_STATE_INACTIVE);
		break;
	case 0x00010003:	/* Application Server Active (AS-Active) */
		err = ua_ntfy_as_state_change(q, rc, AS_STATE_ACTIVE);
		break;
	case 0x00010004:	/* Application Server Pending (AS-Pending) */
		err = ua_ntfy_as_state_change(q, rc, AS_STATE_PENDING);
		break;
	case 0x00020001:	/* Insufficient ASP resources active in AS */
		err = ua_ntfy_too_few_asps(q, rc, aspid);
		break;
	case 0x00020002:	/* Alternative ASP Active */
		err = ua_ntfy_alternate_asp(q, aspid);
		break;
	case 0x00020003:	/* ASP Failure */
		err = ua_ntfy_asp_failure(q, aspid);
		break;
	case 0x00020004:	/* Minimum ASP resources active in AS */
		err = ua_ntfy_as_vulnerable(q, rc);
		break;
	}
	if (err)
		return (err);
	freemsg(mp);
	return (0);
}

/*
 *  MGMT NTFY
 *  -------------------------------------------------------------------------
 *  IMPLEMENTATION NOTES:- Of these notifications, the changes in the state of
 *  an Application Server as viewed by the SGP can be tracked at the ASP/IPSP.
 *  Also, the change in state of specific ASP within the AS are indicated by
 *  other notifications.  We want to do two things with these notifications:
 *  first, record the state change so that if we are later interrogated by the
 *  application or layer management, we can report the current status of the
 *  AS and ASPs within it, second, we inform both the application and layer
 *  management of the state change.  We take no other action.  The reason we
 *  take no other action is because we ae ill-equipped with custom
 *  configuration information to determine within the kernel what the proper
 *  response of the system is to these notifications.  For example, if an we
 *  are om the ASP_INACTIVE state with respect to an Application Server and we
 *  get a NTFY(Minimum ASP resources available in AS) notification, the layer
 *  manager may choose to start an application and have it activate the ASP
 *  within the Application Server to reduce the vulnerability of the AS.
 *  Booting applications is not something to be performed here...
 *
 *  Actually, we don't care if the ASP Id or Routing Context is valid or not.
 *  Let the application or layer manager figure that out.
 */
static int m3ua_ntfy(asp_t * asp, mblk_t * mp)
{
	int i;
	as_t *as;
	uint event, state;
	uint muxid = Q_MUXID(q);

	m3ua_parms_t parms;
	parm_t *rc = &parms->common.rc;
	parm_t *aspid = &parms->common.aspid;
	parm_t *status = &parms->common.status;

	if (Q_MODE(q) == Q_MODE_SG) {
		/* unexpected message, AS do not notify SG */
		return (-EINVAL);
	}
	if (!canput(m3ua_ctrlq))
		return (-EBUSY);
	m3ua_decode_parms(msg, &parms);
	if (!status->u.wptr) {
		/* missing mandatory parameter */
		return (-EINVAL);
	}
	if (rc->len > 0 && (rc->len & 0x3))
		/* badly formatted parameter */
		return (-EINVAL);
	switch (*status->u.wptr) {
	case UA_STATUS_AS_DOWN:
		event = ASE_DOWN;
		state = AS_DOWN;
		break;
	case UA_STATUS_AS_INACTIVE:
		event = ME_AS_INACTIVE;
		state = AS_INACTIVE;
		break;
	case UA_STATUS_AS_ACTIVE:
		event = ME_AS_ACTIVE;
		state = AS_ACTIVE;
		break;
	case UA_STATUS_AS_PENDING:
		event = ME_AS_PENDING;
		state = AS_PENDING;
		break;
	case UA_STATUS_AS_INSUFFICIENT_ASPS:
		event = ME_AS_CRITICAL;
		state = AS_CRITICAL;
		break;
	case UA_STATUS_ALTERNATE_ASP_ACTIVE:
		event = ME_ASP_OVERRIDE;
		state = -1;
		break;
	case UA_STATUS_ASP_FAILURE:
		event = ME_ASP_FAILURE;
		state = -1;
		break;
	case UA_STATUS_AS_MINIMUM_ASPS:
		event = ME_AS_VULNERABLE;
		state = AS_VULNERABLE;
		break;
	default:
		/* invalid status */
		return (-EINVAL);
	}
	if (!rc->u.wptr || rc->len < sizeof(uint32_t)) {
		/* No routing contexts in message, is it implied? */
		if (!(as = m3ua_as_default(q)))
			/* missing necessary routing context */
			return (-EINVAL);
		if (lm_as_event_ind(muxid, event, as->id, aspid->val))
			return (-ENOBUFS);
		if (state != -1)
			as->state = state;
		return (0);
	}
	for (i = 0; i < rc->len >> 2; i++) {
		if (!(as = m3ua_as_lookup(q, rc)))
			/* invalid routing context */
			continue;
		if (lm_as_event_ind(muxid, event, as->id, aspid->val))
			return (-ENOBUFS);
		if (state != -1)
			as->state = state;
	}
	return (0);

}

int (*ua_asp_mgmt[]) (asp_t *, mblk_t *) = {
	ua_recv_err,		/* UA_MGMT_ERR 0x0 */
	    ua_recv_ntfy	/* UA_MGMT_NTFY 0x1 */
};
int (*ua_asp_asps[]) (asp_t *, mblk_t *) = {
	NULL,			/* (reserved) 0x0 */
	    NULL,		/* UA_ASPS_ASPUP_REQ 0x1 */
	    NULL,		/* UA_ASPS_ASPDN_REQ 0x2 */
	    ua_recv_beat_req,	/* UA_ASPS_HBEAT_REQ 0x3 */
	    ua_recv_aspup_ack,	/* UA_ASPS_ASPUP_ACK 0x4 */
	    ua_recv_aspdn_ack,	/* UA_ASPS_ASPDN_ACK 0x5 */
	    ua_recv_beat_ack	/* UA_ASPS_HBEAT_ACK 0x6 */
};
int (*ua_asp_aspt[]) (asp_t *, mblk_t *) = {
	NULL,			/* (reserved) 0x0 */
	    NULL,		/* UA_ASPT_ASPAC_REQ 0x1 */
	    NULL,		/* UA_ASPT_ASPIA_REQ 0x2 */
	    ua_recv_aspac_ack,	/* UA_ASPT_ASPAC_ACK 0x3 */
	    ua_recv_aspia_ack	/* UA_ASPT_ASPIA_ACK 0x4 */
};


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

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

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